Converting 'out' arguments to Python

I’m in the process of converting this script into Python, and I have hit a wall.

Particularly, in the curve.Intersect function, the function passes an argument by-reference, instead of by-value, using the ‘out’ functionality of C Sharp, which isn’t available in Python. This Iron Python page suggests two solutions, but I have not been able to implement either of them successfully. I favor the implicit approach, but if I have to use the explicit approach, how can I pass Array[Type] into clr.Reference[]?

See my attempts below. The code ought to work if you have at least two gridlines set up in your project. Search for the word ‘Attempt’ to see where I’m struggling.

import clr
import array
from pyrevit import DB, revit, script, forms
from rpw import ui

doc = revit.doc
output = script.get_output()
selection = ui.Selection()

from Autodesk.Revit.UI import TaskDialog

# Function to find the nearest intersection point
def get_nearest_intersection_point():
    selected_ids = selection.GetElementIds()
    
    # Get intersection points from the get_intersections function
    intersection_points = get_intersections(doc)
    intersection = "??"
    
    for selected_id in selected_ids:
        elem = doc.GetElement(selected_id)
        elem_point = elem.Location.Point
        
        xyz = DB.XYZ(elem_point.X, elem_point.Y, 0)
        distance_min = 0
        distance = 0
        
        # Find the minimum distance to an intersection point
        first_intersection = list(intersection_points.values())[0]
        distance_min = xyz.DistanceTo(first_intersection)
        
        for key, point in intersection_points.items():
            distance = xyz.DistanceTo(point)
            if distance < distance_min:
                distance_min = distance
                intersection = key
        
        distance_in_meter = distance_min / 3.281  # Convert to meters
        TaskDialog.Show("Intersection", intersection)

# Function to build a dictionary of intersection points
def get_intersections(doc):
    coordinate = None
    coord_a = None
    coord_b = None
    coord_c = None
    intersection_points = {}
    
    # Collect all grid elements
    grids = DB.FilteredElementCollector(doc).OfCategory(DB.BuiltInCategory.OST_Grids).WhereElementIsNotElementType().ToElements()
    ref_grid = DB.FilteredElementCollector(doc).OfCategory(DB.BuiltInCategory.OST_Grids).WhereElementIsNotElementType().ToElements()
    
    # Loop through all grid elements
    for elem_1 in grids:
        coord_a = elem_1.Name
        c1 = elem_1.Curve
        ref_grid.Remove(elem_1)
        
        for elem_2 in ref_grid:            
            coord_b = elem_2.Name
            c2 = elem_2.Curve

            # Check if the two grid lines intersect

			## Attempt 1 - Returns TypeError: 'SetComparisonResult' object is not iterable
			# result, results = c1.Intersect(c2)
            
			## Attempt 2 - Returns TypeError: expected StrongBox[IntersectionResultArray], got IntersectionResultArray
			# results = DB.IntersectionResultArray()
            # result = c1.Intersect(c2, results)
            
			## Attempt 3 - Returns TypeError: expected Array[Type], got IntersectionResultArray
            results = clr.Reference[DB.IntersectionResultArray()]()
            result = c1.Intersect(c2, results)

            print(result)
            print(results)
            
            if result != DB.SetComparisonResult.Overlap:
                continue
            
            if results is None or results.Size != 1:
                continue
            
            for i in range(results.Size):
                i_result = results.get_Item(i)
                coord_c = str(i)
                coordinate = "{},{}-{}".format(coord_a,coord_b, coord_c)
                point = i_result.XYZPoint
                intersection_points[coordinate] = point
    
    return intersection_points

# Call the get_nearest_intersection_point function
get_nearest_intersection_point()

I managed to work it out; it was a syntax issue:

       results = clr.Reference[DB.IntersectionResultArray](DB.IntersectionResultArray())
       result = c1.Intersect(c2, results)

Although I’m still curious about why the implicit approach did not work.

1 Like