Revit.Line intersects Revit.Plane and creates point?

I did a small test intersecting 600 curve elements with a single reference plane 10 times.

The standard Geometry.Intersect node performed quite quickly, returning the results between 123 and 166 ms, with an average of 139.

@c.poupin method returned results between 119ms and 158 ms, with an average of 136. Comparable to the Geometry intersect results.

Both of those methods require converting the Revit Elements to Dynamo geometry, which is included in the time. If geometry conversion is included in Cyril’s Python code things ran slower (though it could have been optimized better), returning results between 126 and 166 ms, with an average of 144ms.

A code block consisting of a.Curve.Intersect(plane.Plane); returned results comparable to the in-python geometry conversion.

But the fastest was to skip the geometry conversion, extract the data, and let Revit’s XYZ class do the heavy lifting. The code below executed between 61 and 91ms, with an average of 72.

Now a few things to note: if you reduce the dataset to say 100 lines, Geometry intersect won the day - consistently outperforming all other options including the Revit API method - the VM is a penalty for small actions, but scales up very well.

This is the direct Revit API intersection method I used.
########################################
############## Properties ##############
########################################
__author__ = 'Jacob Small'
__version__ = '0.1.0'
__description__ = "get the intersection of a line and a plane using the Revit API"
__RevitBuilds__ = "2025.1"
__DynamoBuilds__ = "2.18"
__ReleaseNotes__ = "based on the implementation found on ParametricZoo (https://www.parametriczoo.com/index.php/2020/03/07/plane-line-intersection-in-revit-api/), but with an added check to ensure the line crosses the plane"
__Dependancies__ = "none"



########################################
### Configure the Python environment ###
########################################
### standard Python imports ###
import sys #add the sys class to the Python environment so we can work with the sys objects
import clr #add the CLR (common language runtime) class to the Python environment so we can work with .net libraries

### Revit API imports ###
clr.AddReference("RevitAPI") #add the Revit API to the CLR
import Autodesk #add the Autodesk class to the Python environment 
from Autodesk.Revit.DB import Line, Plane, XYZ #import the relevant sectiosn of the Revit API to the Python environment



########################################
########### Code starts here ###########
########################################
### Get the line and plane geometry from the elements ###
lines = [UnwrapElement(i).GeometryCurve for i in IN[0]] #get the curves from the lines
plane = UnwrapElement(IN[1]).GetPlane() #get the plane from the reference plane

results = [] #empty list to hold the results

for line in lines: #for each line
    ### check for parallel relationship to the plane, and get the distance from the start and end point to the plane ###
    parallelTest = line.Direction.DotProduct(plane.Normal) #if the dot product of the direction (a normalized vector) and the normal (another normalized vector) is zero, the plane and the line are parallel
    v1 = plane.Origin.Subtract(line.GetEndPoint(0)) #subtract the start point from the origin of the plane
    startTest  = v1.DotProduct(plane.Normal) #get the dot product from the subtracted vector and the normal of the plane. if this is the same sign for the start and end point the line doesn't cross the plane.
    v2 = plane.Origin.Subtract(line.GetEndPoint(1)) #subtract the4 end point from the origin of the plane
    endTest = v2.DotProduct(plane.Normal) #get the dot product from the subtracted vector and the normal of the plane
    if parallelTest < 0.0000001: #line is parallel to the plane 
        if abs(startTest) < 0.0000001: #check if the start point is on the plane - if so the intersection is the line itself
            results.append("Line is on the plane") #append message for user to the result
        else: #if not, the intersection is null
            results.append("Line is parallel to plane") #append message for user to the result
    else: #line isn't parallel to the plane and still may or may not intersect
        startSign = startTest>=0 #get the sign of the start test
        endSign = endTest>=0 #get the sign of the end test
        if startSign == endSign: #if the sign of the start test and end test are the same both on the same side of the plane and the line doesn't intersect thep lane
            results.append("Line does not cross plane") #append message for user to the result
        else: #otherwise we finally have a working intersection result
            param = startTest / parallelTest #get the start test as a percentage of the parallel test - vectors are fun!
            vect = line.Direction.Multiply(param) #get the direction of the line and multiply by the parameter to scale the vector
            pnt = line.GetEndPoint(0).Add(vect) #move the start point by the vector
            results.append(pnt)#append the point to the results



########################################
##### Return the results to Dynamo #####
########################################
OUT = results #return the results to the Dynamo environment
3 Likes