Intersecting line with BoundingBox
-
The Geom module helps us to intersect lines with lines, lines with planes, planes with planes.
Has anyone needed to cast rays into bounding boxes? I would prefer using API methods before implementing something on my own.
It seems SketchUp gives us only raytests for testing against DrawingElements, but not for pure geometry. -
I think you just have to define the planes of the bounding box and use those planes. Will that work?
-
The intersection, which will be at the edge of the bounding box, will be considered inside?
No accuracy issues? -
You'll also have to watch out for a line that goes through a corner of the box, but not the corner there the planes have been setup. That will in fact intersect your bounding box, but won't show up as an intersection unless you define all 6 planes.
-
As for what I tested, points on the sides of the bounding box are considered inside (
BoundingBox.contains?
is true).I believe it should work with 3 instead of 6 planes, since the planes are infinite (bigger than the sides of the box).
An infinite straight line must intersect with any 3 orthogonal planes. If the line is a ray (half infinite), there is the case that it does not intersect the planes if it points away from the plane's intersection. In that case the line either starts in the box or it is completely outside. -
Maybe this condition isn't a problem for your script, but here is a case where a line starts outside the bounding box, intersects the bounding box, but would return false if you only test it against 3 planes of the bounding box. (hopefully that graphic makes some sense )
-
Ah, yes, you are right. I get an intersection with the plane on the left, but the intersection point is not in the bounding box.
-
Chris got his thinking hat on!
-
Yes sir! My new hat makes me feel very smart (and slightly Norwegian!).
-
I hadn't considered that because planes are infinite, but it works well combined with BoundingBox.contains?
def intersect_line_boundingbox(line, bb) # Intersect with 6 planes of the bounding box's sides. p0 = bb.corner(0) p1 = bb.corner(7) [ [p0, X_AXIS], [p0, Y_AXIS], [p0, Z_AXIS], [p1, X_AXIS], [p1, Y_AXIS], [p1, Z_AXIS] ].each{|plane| intersection = Geom;;intersect_line_plane(line, plane) # Stop when the intersection point is inside the bounding box. return intersection if bb.contains?(intersection) # else continue } # No intersection (because bb is aside line or behind line start). return nil end
There is certainly room for optimization (ie. maybe less than 6 planes, or checking whether BB is behind line start).
I first had the code with an infinite straight line (starting from -infinity) and only one intersection with a plane but that failed due to precision errors.
Advertisement