Hi,
I have some code that I’d like to modify to use surfaces instead of rooms. Could someone help me with this? I’m not very familiar with programming in Dynamo/Python.
import clr
import sys
import os
localapp = os.getenv(r'LOCALAPPDATA')
sys.path.append(os.path.join(localapp, r'python-3.8.10-embed-amd64\Lib\site-packages'))
import System
#
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import Autodesk.DesignScript.Geometry as DS
# Import Revit API
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
import numpy as np
def cosine_similarity(point, vector):
dot_prod = point.DotProduct(vector)
mag_point = point.GetLength()
mag_vector = vector.GetLength()
# avoid division by zero if the magnitude is zero
if mag_point == 0 or mag_vector == 0:
return 0
return dot_prod / (mag_point * mag_vector)
# Preparing input from Dynamo to Revit (a list of rooms)
rooms = [UnwrapElement(room) for room in IN[0]] # Unwrap the list of rooms
out = []
lst_debug = []
DEBUG = False
# Iterate over each room
for room in rooms:
bound_opt = SpatialElementBoundaryOptions()
bound_opt.SpatialElementBoundaryLocation = SpatialElementBoundaryLocation.Finish
room_curves = [s.GetCurve() for lst_segments in room.GetBoundarySegments(bound_opt) for s in lst_segments]
ds_room_curves = [c.ToProtoType() for c in room_curves]
# Coordinates system (vectors) orientation of the room
lst_vector_ray = [XYZ.BasisX, XYZ.BasisY]
# Get min point start
ptstart = room.get_BoundingBox(None).Min
ptstart = XYZ(ptstart.X, ptstart.Y, room_curves[0].GetEndPoint(0).Z)
ptend = room.get_BoundingBox(None).Max
ptend = XYZ(ptend.X, ptend.Y, room_curves[0].GetEndPoint(0).Z)
max_size = max([ptend.Y - ptstart.Y, ptend.X - ptstart.X])
# Scan with vector_ray_A and then vector_ray_B
for idx, vector_ray in enumerate(lst_vector_ray):
rayA = DB.Line.CreateUnbound(ptstart, vector_ray)
# Offset ray each scan iteration
for step in np.arange(0, max_size, 0.0033):
perpendicular_vector = lst_vector_ray[abs(idx-1)] # Auto-switch between the inverse of idx
ray_curve = rayA.CreateOffset(step, perpendicular_vector.CrossProduct(vector_ray))
# DEBUG to ensure the ray location is correct drawing a small line of ray
if DEBUG:
line_bound = ray_curve.Clone()
line_bound.MakeBound(0.1, 3.9)
ds_line_bound = line_bound.ToProtoType()
lst_debug.append(ds_line_bound)
temp = []
# Try to find room boundaries intersection
for bound_curve in room_curves:
outResultArray = IntersectionResultArray()
comparisonResult, outResultArray = ray_curve.Intersect(bound_curve, outResultArray)
if comparisonResult == SetComparisonResult.Overlap:
lst_intersect_pts = [i.XYZPoint for i in outResultArray]
temp.extend(lst_intersect_pts)
# Sort points by vector
sorted_points = sorted(temp, key=lambda p: cosine_similarity(p, vector_ray))
# Iterate over pair points
sorted_points = iter(sorted_points)
for pta, ptb in zip(sorted_points, sorted_points):
if 0.1 < pta.DistanceTo(ptb) <= 1.8 * 3.281: # If distance between points is under 1.8m
line_bad_part_area = DB.Line.CreateBound(pta, ptb)
out.append(line_bad_part_area.ToProtoType()) # Append the result for each room
# Output all the lines found in all rooms
OUT = out