Hi, I’m using a python script to take elements (in this case furniture), and have them move to match the location of the nearest wall. The furniture only needs to move along the x axis since the walls are only going to be moving a few inches along the x axis. I have the two furniture elements as IN[0], the walls as IN[1], and a distance parameter as IN[2] so the elements are looking for walls within that distance. I copied the python script down below and i’m not sure where i’ve gone wrong but i keep getting the error “Warning: IronPythonEvaluator.EvaluateIronPythonScript operation failed.
invalid syntax”. Any help is greatly appreciated!!
import clr
clr.AddReference('RevitServices')
clr.AddReference('RevitAPI')
clr.AddReference('RevitNodes')
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
# Inputs from Dynamo
elements = UnwrapElement(IN[0]) # First input - elements to move (e.g., furniture)
walls = UnwrapElement(IN[1]) # Second input - walls
distance_threshold = IN[2] # Third input - distance threshold from a number slider
doc = DocumentManager.Instance.CurrentDBDocument
def get_element_location(element):
"""Get the location point of a given element (handles furniture elements)."""
loc = element.Location
if isinstance(loc, LocationPoint):
return loc.Point
elif isinstance(loc, LocationCurve):
curve = loc.Curve
return curve.Evaluate(0.5, True) # Midpoint of the curve
return None
def get_element_orientation(element):
"""Get the orientation of an element based on its facing direction."""
facing_orientation = None
if hasattr(element, 'FacingOrientation'):
facing_orientation = element.FacingOrientation
return facing_orientation
def get_wall_interior_face(wall):
"""Get the interior face of a wall."""
options = Options()
geometry_element = wall.get_Geometry(options)
for geom_obj in geometry_element:
solid = geom_obj if isinstance(geom_obj, Solid) else None
if solid:
for face in solid.Faces:
# Assume the interior face is the one whose normal points inward
normal = face.ComputeNormal(UV(0.5, 0.5)) # Get the normal at the midpoint of the face
if normal.Z == 0: # Avoid horizontal faces (top or bottom)
return face, normal
return None, None
def distance_between_points(point1, point2):
"""Calculate the distance between two XYZ points."""
return point1.DistanceTo(point2)
def move_element_to_wall(element, move_vector):
"""Move an element by a given vector."""
TransactionManager.Instance.EnsureInTransaction(doc)
element.Location.Move(move_vector)
TransactionManager.Instance.TransactionTaskDone()
moved_elements = []
# Loop through each element
for element in elements:
element_loc = get_element_location(element)
element_orientation = get_element_orientation(element)
if element_loc is None or element_orientation is None:
print(f"Skipping element {element.Id}: No valid location or orientation")
continue # Skip if no valid location or orientation is found
closest_wall = None
closest_distance = float("inf")
best_move_vector = None
# Loop through each wall to find the closest wall with matching orientation
for wall in walls:
face, wall_normal = get_wall_interior_face(wall)
if face is None or wall_normal is None:
print(f"Skipping wall {wall.Id}: No valid face or normal")
continue # Skip if no valid wall face or normal is found
# Check if the element's orientation is aligned with the wall's face normal
if element_orientation.IsAlmostEqualTo(wall_normal, 0.1): # Adjust tolerance as needed
wall_face_center = face.Evaluate(UV(0.5, 0.5)) # Get the center of the wall face
dist = distance_between_points(element_loc, wall_face_center)
# Debugging outputs
print(f"Element: {element.Id}, Wall: {wall.Id}, Distance: {dist}, Threshold: {distance_threshold}")
# Check if the distance is within the specified threshold
if dist < closest_distance and dist <= distance_threshold:
closest_distance = dist
# Only move along the X-axis to match the wall face
best_move_vector = XYZ(wall_face_center.X - element_loc.X, 0, 0) # Adjust Y and Z to 0
closest_wall = wall
# If we found a suitable wall, move the element
if closest_wall and best_move_vector:
move_element_to_wall(element, best_move_vector)
moved_elements.append(element)
print(f"Moved element {element.Id} to wall {closest_wall.Id}")
# Output the moved elements
OUT = moved_elements ```