Placing dimensions in Revit using Dynamo and Python Air Terminals

Hello all,

I would like to place dimensions between Separation lines and the reference lines (X and Y) of Air Terminals.

The goal is to place dimensions from the nearest separation line (for spaces) to the X or Y reference line of the air terminal.

I have a Python script to use in a Dynamo node but to let this work, I have to change the family of the air terminal and delete the reference lines wich I’d rather not.

Herewith the previous Python script.

Many thanks in advance :slight_smile: (special thanks to Søren Villadsen who helped me the last time!!)…

import clr

clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import *

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

doc = DocumentManager.Instance.CurrentDBDocument
active_view = doc.ActiveView

input_in0 = IN[0]
elements = UnwrapElement(input_in0) if isinstance(input_in0, list) else [UnwrapElement(input_in0)]

def get_best_reference(el):
    for name in ["Center (Left/Right)", "Center (Front/Back)", "Centerline", "Center"]:
        try:
            ref = el.GetReferenceByName(name)
            if ref: 
                return ref
        except: 
            continue

    opt = Options()
    opt.ComputeReferences = True
    opt.IncludeNonVisibleObjects = True
    opt.View = active_view
    geo = el.get_Geometry(opt)
    
    if geo:
        for obj in geo:
            if isinstance(obj, GeometryInstance):
                for inst_obj in obj.GetInstanceGeometry():
                    if hasattr(inst_obj, "Reference") and inst_obj.Reference:
                        return inst_obj.Reference
            elif hasattr(obj, "Reference") and obj.Reference:
                return obj.Reference
    return None


all_curves = FilteredElementCollector(doc, active_view.Id).OfClass(CurveElement).ToElements()
output_dimensions = []

if elements:
    TransactionManager.Instance.EnsureInTransaction(doc)
    for el in elements:
        if not el: 
            continue
        try:
            if hasattr(el.Location, "Point"):
                ref_pt = el.Location.Point
            else: 
                continue

            e_ref = get_best_reference(el)
            if not e_ref: 
                continue

            hits_x = []
            hits_y = []

            for curve_el in all_curves:
                c_geom = curve_el.GeometryCurve
                if c_geom.Reference is None: 
                    continue
                
                proj = c_geom.Project(ref_pt)
                if not proj: 
                    continue
                
                target_pt = proj.XYZPoint
                dist = proj.Distance
                to_hit_vec = (target_pt - ref_pt).Normalize()

                if abs(to_hit_vec.X) > abs(to_hit_vec.Y):
                    hits_x.append({'dist': dist, 'ref': c_geom.Reference, 'pt': target_pt, 'geom': c_geom})
                else:
                    hits_y.append({'dist': dist, 'ref': c_geom.Reference, 'pt': target_pt, 'geom': c_geom})

            for bucket in [hits_x, hits_y]:
                if not bucket: 
                    continue
                
                closest = sorted(bucket, key=lambda d: d['dist'])[0]
                ref_array = ReferenceArray()
                ref_array.Append(e_ref)
                ref_array.Append(closest['ref'])
                
                proj_result = closest['geom'].Project(closest['pt'])
                raw_param = proj_result.Parameter
                derivatives = closest['geom'].ComputeDerivatives(raw_param, False)
                tangent = derivatives.BasisX.Normalize()
                normal_vec = XYZ(-tangent.Y, tangent.X, 0)
                
                try:
                    dim_line = Line.CreateUnbound(ref_pt, normal_vec)
                    output_dimensions.append(doc.Create.NewDimension(active_view, dim_line, ref_array))
                except:
                    dim_line = Line.CreateBound(ref_pt, closest['pt'])
                    output_dimensions.append(doc.Create.NewDimension(active_view, dim_line, ref_array))

        except Exception as e:
            output_dimensions.append(str(e))

    TransactionManager.Instance.TransactionTaskDone()

OUT = output_dimensions

Hi @johanQZGZ7 thanks… yeah have to admit i havent goin deep into it, but if i remember you dont delete any reference just set the reference to none right?..guees the key is in the family itself, basic not a python/dynamo thing but more how the diffuser family is build…try play around with that instead…PS seems the family comes from some webside, and probably build, with strange hidden parameters and strange stuff…i recommend build them self so we have full control whats happend