Create Dimension Between Column Reference (Center) and Grid

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

create_columns_dimension

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
1 Like