I want to create a code where you choose two points on a Revit model and create a new dimension on every structural element that intersects with the initial points. I have a working code where you can choose the two points (That create an outline) and the program filters the desired structural elements, finds the intersection points, arranges them from smallest to largest and when trying to create the new dimensions, an error always comes up that states that there is an Invalid number of references when my ReferenceArray has 2 references. I have tried with references on the line (GetEndPointReference) and currently I store the reference of the faces that intersected the original points to use them. My code is the following:
import clr
clr.AddReference('RevitAPI')
clr.AddReference('RevitServices')
import RevitServices
import Autodesk.Revit.DB as DB
from Autodesk.Revit.UI import *
import Autodesk.Revit.UI.Selection
from RevitServices.Persistence import DocumentManager
doc = __revit__.ActiveUIDocument.Document
docui = __revit__.ActiveUIDocument
tolerancia = 10
try:
punto1 = docui.Selection.PickPoint("Selecciona la esquina inferior derecha")
punto2 = docui.Selection.PickPoint("Selecciona la esquina superior izquierda")
except Exception as e:
print("Error al seleccionar puntos:", e)
punto1 = None
punto2 = None
if punto1 and punto2:
direccion = "X" if abs(punto1.X - punto2.X) > abs(punto1.Y - punto2.Y) else "Y"
if punto1.X == punto2.X:
punto2 = DB.XYZ(punto2.X - 0.1, punto2.Y, punto2.Z)
if punto1.Y == punto2.Y:
punto2 = DB.XYZ(punto2.X, punto2.Y - 0.1, punto2.Z)
elements_list = []
outline = DB.Outline(punto1, punto2)
X = 0
Y = 0
Zmax = None
Zmin = None
if not outline.IsEmpty:
elementos_intersect = DB.FilteredElementCollector(doc) \
.OfCategory(DB.BuiltInCategory.OST_StructuralFraming) \
.WhereElementIsNotElementType() \
.WherePasses(DB.BoundingBoxIntersectsFilter(outline)) \
.ToElements()
print(len(elementos_intersect))
for element in elementos_intersect:
geometria = element.Geometry[DB.Options()]
if geometria:
boundbox = geometria.GetBoundingBox()
if boundbox:
if direccion == "X":
if abs(boundbox.Max.Y - boundbox.Min.Y) > abs(boundbox.Max.X - boundbox.Min.X):
elements_list.append(element)
Zmax = min(Zmax, boundbox.Max.Z) if Zmax is not None else boundbox.Max.Z
Zmin = max(Zmin, boundbox.Min.Z) if Zmin is not None else boundbox.Min.Z
print(element.Name)
X += 1
else:
if abs(boundbox.Max.X - boundbox.Min.X) > abs(boundbox.Max.Y - boundbox.Min.Y):
elements_list.append(element)
Zmax = min(Zmax, boundbox.Max.Z) if Zmax is not None else boundbox.Max.Z
Zmin = max(Zmin, boundbox.Min.Z) if Zmin is not None else boundbox.Min.Z
print(element.Name)
Y += 1
else:
print("No se pudo encontrar elementos")
altura = (Zmax + Zmin) * 0.5 if Zmax is not None and Zmin is not None else punto1.Z - 0.5
print(altura)
manager = DB.Transaction(doc, "Crear Cotas")
manager.Start()
if direccion == "X":
punto1alt = DB.XYZ(punto1.X, punto2.Y, altura)
punto2alt = DB.XYZ(punto2.X, punto2.Y, altura)
else:
punto1alt = DB.XYZ(punto2.X, punto1.Y, altura)
punto2alt = DB.XYZ(punto2.X, punto2.Y, altura)
linea = DB.Line.CreateBound(punto1alt, punto2alt)
manager.Commit()
print(X, Y)
print(Zmax, Zmin)
print(punto1, punto2)
print(punto1alt, punto2alt)
print(elements_list, len(elements_list))
intersection_points = []
referencias = {}
for elemento in elements_list:
geometrialen = 0
geo = elemento.Geometry[DB.Options()]
intersectResultArray = clr.Reference[DB.IntersectionResultArray]()
for geomObj in geo:
if isinstance(geomObj, DB.Solid):
for face in geomObj.Faces:
min_distance = float('inf')
result = face.Intersect(linea, intersectResultArray)
if result != DB.SetComparisonResult.Disjoint and intersectResultArray.Size > 0:
for i in range(intersectResultArray.Size):
point = intersectResultArray.get_Item(i).XYZPoint
intersection_points.append(point)
for edge_loop in face.EdgeLoops:
for edge in edge_loop:
curve = edge.AsCurve()
distance = curve.Distance(point)
if distance < min_distance:
min_distance = distance
closest_ref = curve.Reference
if direccion == "X":
referencias[point.X] = closest_ref
else:
referencias[point.Y] = closest_ref
print(len(intersection_points))
for l in range(len(intersection_points)):
print(intersection_points[l])
def sort_points(points):
return sorted(points, key=lambda p: (p.X, p.Y, p.Z))
def create_aligned_dimension(doc, line, ref1, ref2):
t = DB.Transaction(doc, "Create Aligned Dimension")
t.Start()
array = DB.ReferenceArray()
array.Append(ref1)
array.Append(ref2)
try:
dim = doc.Create.NewDimension(doc.ActiveView, line, array)
t.Commit()
return dim
except Exception as e:
t.RollBack()
print(e)
return None
def create_model_curve(doc, line, sketch_plane):
t = DB.Transaction(doc, "Create Model Curve")
t.Start()
try:
model_curve = doc.Create.NewModelCurve(line, sketch_plane)
t.Commit()
return model_curve
except Exception as e:
t.RollBack()
print(e)
return None
sorted_points = sort_points(intersection_points)
trans = DB.Transaction(doc, "Create SketchModel")
trans.Start()
plane = DB.Plane.CreateByNormalAndOrigin(DB.XYZ.BasisZ, sorted_points[0])
sketch_plane = DB.SketchPlane.Create(doc, plane)
trans.Commit()
for i in range(len(sorted_points) - 1):
if direccion == "X":
ref1 = referencias[sorted_points[i].X]
ref2 = referencias[sorted_points[i + 1].X]
else:
ref1 = referencias[sorted_points[i].Y]
ref2 = referencias[sorted_points[i + 1].Y]
line = DB.Line.CreateBound(sorted_points[i], sorted_points[i + 1])
modelcurve = create_model_curve(doc, line, sketch_plane)
dimension = create_aligned_dimension(doc, line, ref1, ref2)
print(line.Id)
print(dimension)
else:
print("No se encontraron los puntos")
Sorry for the Spanglish in naming of the variables and content of the promts.