I want to modify a script that I am working on such that it ends a loop when there is an intersection/collision (I'm not sure how best to describe the actual intersection event in this particular situation since the objects are inside each other) between two planes (plane A and plane B). The loop rotates plane A and at a certain degree of rotation plane A intersects plane B, which is static.
I've seen/tried to use solutions that involve BHVtree but I haven't been able to get them working. I've also tried boolean operations (intersect, subtract, etc), but they don't seem to do anything differently from when the objects intersect (or 'stop intersecting'?).
I am working with primative 2d planes and plane A is inside plane B. In the below wireframe images, the 'yellow' selected object and the 'red' selected object are what I am referring to as plane A and plane B, respectively.
This image shows a given rotation in which plane A DOES NOT intersect with plane B
This image shows a second rotation in which plane A DOES intersect with plane B. I would like to be able to identity when this event occurs within my script.
UPDATED: Based on batFINGER's suggestion, I looked into intersect_line_sphere_2d from mathutils.geometry. Thank you very much for pointing me to it.
I wrote a script based on that particular function, which works but not correctly. I think my math/trig is off somewhere because the angle reported is larger than expected, and the angle should decrease as the scale is increased.
Below is the script:
# testing script for predicting rotation-based collision angle thresholds # output is not correct. Increasing scale should give lower roll angle tolerance, also roll angle values are not accurate as compared by other methods. Code needs to be adjusted. #-------- # imports #-------- import bpy import numpy as np from math import cos from math import sin import mathutils from mathutils.geometry import intersect_line_sphere_2d #---------- # functions #---------- # function converts from degrees to radians def radians(num): result = (num) * (np.pi/180) return result # function converts from radians to degrees def degrees(num): result = (num) * (180/np.pi) return result #---------- # variables #---------- relativeRadius = 0.3 #relevant for actual objects being tested scalePercentage = 0.80 #percentage radiusOne=relativeRadius*0.1 #relevant to actual objects being tested leftAdjustment = (radiusOne)*(1-scalePercentage)*(0.5) #relevant to placement of actual object theta = 225.0 #represents starting point on the circumference of the rotational pathway, e.g., bottom left corner of square radTheta = radians(theta) #convert to radians for trig functions # variables for the intersect_line_sphere_2d function lineA = mathutils.Vector (( -radiusOne+leftAdjustment, -radiusOne)) #bottom left and moved to the right to compensate for the left adjustment that is typically applied to the actual object lineB = mathutils.Vector (( -radiusOne+leftAdjustment, radiusOne)) #top left and moved to the right to compensate for the left adjustment that is typically applied to the actual object xPos=cos(radTheta)*radiusOne yPos=sin(radTheta)*radiusOne locationCircle = mathutils.Vector ((xPos, yPos)) radiusCircle = 0.0000001 #very small to make it a 2d 'point' rather than a circle #amount of change in degrees for testing roll angle tolerance incrementsInDegrees= 0 incrementInRadians= radians(incrementsInDegrees) numberOfTests=0 #added in case scale is TOO SMALL in which case the loop would continue without end and probably crash blender; an alternative would be to just use something like a 90 degree angle check as security against an infinite loop #---------- # main loop: #---------- #set beginning of intersect_line_ function to starting position of object bottom left corner i = intersect_line_sphere_2d(lineA, lineB, locationCircle, radiusCircle) while i == None and i == None and numberOfTests < 50000: numberOfTests += 1 incrementsInDegrees += 0.01 incrementInRadians= radians(incrementsInDegrees) xPos = cos(radTheta-incrementInRadians)*radiusOne yPos = sin(radTheta-incrementInRadians)*radiusOne locationCircle = mathutils.Vector ((xPos, yPos)) i = intersect_line_sphere_2d(lineA, lineB, locationCircle, radiusCircle) #-------------------------- # print results to console: #-------------------------- rollAngleToleranceInDegrees = str(incrementsInDegrees) numberOfAnglesAttempted = str(numberOfTests) print("roll angle tolerance is: %s" % (rollAngleToleranceInDegrees)) print("number of angles attempted: %s" % (numberOfAnglesAttempted))