faces references are sometimes FamilySymbol references, instance references are required for dimensions

import clr
import sys
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)
#import transactionManager and DocumentManager (RevitServices is specific to Dynamo)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
import itertools
def get_grids_intersections():
"""find all intersection of grids"""
data = []
grids = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Grids).WhereElementIsNotElementType().ToElements()
for gd_a, gd_b in itertools.combinations_with_replacement(grids, 2):
resultArray = IntersectionResultArray()
setComparisonResult, resultArray = gd_a.Curve.Intersect(gd_b.Curve, resultArray)
if setComparisonResult == SetComparisonResult.Overlap:
data.append([gd_a, gd_b, resultArray.get_Item(0).XYZPoint ])
return data
def get_vertical_faces(c):
"""get vertical faces"""
opt=Options()
opt.ComputeReferences = True
for geo in c.get_Geometry(opt):
if isinstance(geo, GeometryInstance):
for geoI in geo.GetInstanceGeometry():
if isinstance(geoI, DB.Solid) and geoI.Volume > 0:
return [f for f in geoI.Faces if abs(f.FaceNormal.Z) < 0.01]
return []
def fix_Instance_Reference(reference):
""" fix dimension for dimension"""
owner_elem = doc.GetElement(reference)
print(f"{owner_elem=}")
if isinstance(owner_elem, DB.FamilySymbol):
curent_stableRef = reference.ConvertToStableRepresentation(doc)
if ":INSTANCE:" in curent_stableRef:
full_ref = reference
else:
full_stableRef = f"{column.UniqueId}:0:INSTANCE:{curent_stableRef}"
full_ref = DB.Reference.ParseFromStableRepresentation(doc, full_stableRef)
return full_ref
else:
return reference
def create_dimension(column, grid, offset=3):
"""create dimension beetween column Reference and the nearest grid"""
loc_column = column.Location.Point
grid_direction = grid.Curve.Direction.Normalize()
# grid_ref = Reference.ParseFromStableRepresentation(doc, grid.UniqueId)
# OR
grid_ref = Reference(grid)
#
base_line = DB.Line.CreateUnbound(loc_column, grid_direction.CrossProduct(XYZ.BasisZ))
#
lst_parallal_Faces = [f for f in get_vertical_faces(column) if abs(grid_direction.DotProduct(f.FaceNormal)) < 0.01]
# select the good reference plane
for referenceType in [FamilyInstanceReferenceType.CenterLeftRight, FamilyInstanceReferenceType.CenterFrontBack]:
for ref in column.GetReferences(referenceType):
ref_array = ReferenceArray()
ref_array.Append(fix_Instance_Reference(ref))
ref_array.Append(fix_Instance_Reference(grid_ref))
for f in lst_parallal_Faces:
ref_array.Append(fix_Instance_Reference(f.Reference))
#
dim = doc.Create.NewDimension(doc.ActiveView, base_line, ref_array)
doc.Regenerate()
# check if dimension is correct
if all(s.Value > 0.01 for s in dim.Segments):
# apply offset
if abs(grid_direction.CrossProduct(XYZ.BasisX).GetLength()) < 0.1:
dim.Location.Move(XYZ.BasisX.Multiply(offset * -1))
else:
dim.Location.Move(XYZ.BasisY.Multiply(offset))
return dim
else:
# delete the bad dimension and continue
print("deleted")
doc.Delete(dim.Id)
return None
column = UnwrapElement(IN[0])
data_interSect_grid = get_grids_intersections()
# get the nearest grid intersection and unpack the result
gridA, gridB, intersectPt = sorted(data_interSect_grid, key=lambda tupl_data : tupl_data[2].DistanceTo(column.Location.Point))[0]
TransactionManager.Instance.EnsureInTransaction(doc)
outdims = [create_dimension(column, g) for g in [gridA, gridB,]]
TransactionManager.Instance.TransactionTaskDone()
OUT = outdims