I’m trying to figure out how to tell if a point is in a solid. I know there are node out there that can do this but can’t find any that allow me to see their code. I’ve checked the API but can only find the ability to check with curves. Does anyone know how the nodes do it? I was considering:
Create a new point based off the original with a small offset
You can make two lines from the point and intersection for point is only true if both lines intersect. This will not give a true result if the point is on the face of the solid but only if it is really “inside”.
Another easy approach to also consider points on faces:
Check for intersection with two curves.
If a curve intersects and the start parameter of the intersection curve on the original curve is 0, then intersection of point is true.
Utilizing the startparameter of the segmentextents of the intersection result is pretty much like using the point itself…
I recommend making a small line from the XYZ (say 1mm long, on the X axis), and then intersecting the curve with the solid using this method.
From there you can parse all the curve segments, and project the original XYZ onto each resulting curve. If the projected XYZ is almost equal to the original XYZ, the point touches or is inside the solid.
Thanks for the posts everyone. I’m currently testing another idea. I can get the elements directly rather than using their GetSpatialElementCalculationPoint. I’m using ElementIntersectsSolidFilter and I’m getting elements! I need to double check the lists and see if any elements show up in multiple solids before I move on. If not I’m going to try creating the small line.
Hi, was browsing by this form, and may have something to add to something to the discussion. Below is a algorithm based on the Revit API, which checks for point inclusion in all kinds of solids, also including torus-like shapes
import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import XYZ, Line, SolidCurveIntersectionOptions, SolidCurveIntersectionMode
def point_inclusion(xyz, solid):
bounding_box = solid.GetBoundingBox()
# Make a point which is guaranteed to be outside the solid
max = bounding_box.Max
max += bounding_box.Transform.Origin # Adjust for bounding box origin transformation, if bounding box has a more complex transformation, this will need to be accounted for as well
max += XYZ(1, 1, 1) # Just in case
line = Line.CreateBound(xyz, max)
intersection_options = SolidCurveIntersectionOptions()
intersection_options.ResultType = SolidCurveIntersectionMode.CurveSegmentsInside
intersection_result_inside = solid.IntersectWithCurve(line, intersection_options)
intersection_options.ResultType = SolidCurveIntersectionMode.CurveSegmentsOutside
intersection_result_outside = solid.IntersectWithCurve(line, intersection_options)
return (intersection_result_inside.SegmentCount + intersection_result_outside.SegmentCount) % 2 == 0 # See Jordan curve theorem
another quicker way is to make a boundingbox from the solid and check is the point inside this boundingbox
this is a quick filter which perform faster
BoundingBoxContainsPointFilter