I got the piping to work in both Revit 2024 & 2026 but not for ductwork, Any suggestions please? This is the error I’m getting “AttributeError : module ‘clr’ has no attribute ‘Reference’ [’ File “”, line 65, in \n’]”
Hi, welcome to the forums.
Can you post the script that you’re currently working with? There’s a lot of guesswork that can get eliminated if we could simply just read it.
And add the fire rating into it, could be helpfull
Hi Robert, I can not upload any documents or scripts as I am a new member. Here is the Python script import clr
import clr
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
doc = DocumentManager.Instance.CurrentDBDocument
# Inputs are lists of elements from the canvas nodes
ducts = UnwrapElement(IN[0]) if isinstance(IN[0], list) else [UnwrapElement(IN[0])]
walls = UnwrapElement(IN[1]) if isinstance(IN[1], list) else [UnwrapElement(IN[1])]
family_type = UnwrapElement(IN[2])
placed_elements = [ ]
TransactionManager.Instance.EnsureInTransaction(doc)
if not family_type.IsActive:
family_type.Activate()
doc.Regenerate()
def extract_solids(geom_element):
solids = [ ]
if geom_element is None:
return solids
for geom_obj in geom_element:
if isinstance(geom_obj, Solid) and geom_obj.Volume > 0:
solids.append(geom_obj)
elif isinstance(geom_obj, GeometryInstance):
solids.extend(extract_solids(geom_obj.GetInstanceGeometry()))
return solids
for duct in ducts:
if not duct or not hasattr(duct, 'Location') or not duct.Location:
continue
duct_line = duct.Location.Curve
# Safely extract width and height from the MEPCurve class directly.
try:
duct_width = duct.Width
duct_height = duct.Height
except AttributeError:
# Fallback if it is a round duct or lacks the standard properties
try:
duct_width = duct.Diameter
duct_height = duct.Diameter
except AttributeError:
continue
for wall in walls:
if not wall:
continue
opt = Options()
opt.ComputeReferences = True
opt.DetailLevel = ViewDetailLevel.Fine
wall_solids = extract_solids(wall.get_Geometry(opt))
for wall_solid in wall_solids:
results = clr.Reference[IntersectionResultArray]()
intersect = wall_solid.IntersectWithCurve(duct_line, results)
if intersect == SetComparisonResult.Overlap and results.Value.Count > 0:
inter_point = results.Value[0].XYZPoint
closest_face = None
min_dist = float('inf')
for face in wall_solid.Faces:
proj = face.Project(inter_point)
if proj:
dist = proj.Distance
if dist < min_dist:
min_dist = dist
closest_face = face
if closest_face and closest_face.Reference:
ref = closest_face.Reference
proj_result = closest_face.Project(inter_point)
face_normal = closest_face.ComputeNormal(proj_result.UVPoint)
duct_dir = duct_line.Direction
if abs(duct_dir.DotProduct(face_normal)) > 0.999:
if abs(face_normal.Z) < 0.999:
placement_dir = XYZ.BasisZ.CrossProduct(face_normal).Normalize()
else:
placement_dir = XYZ.BasisX.CrossProduct(face_normal).Normalize()
else:
placement_dir = duct_dir.Subtract(face_normal.Multiply(duct_dir.DotProduct(face_normal))).Normalize()
# Place the face-based family instance
new_instance = doc.Create.NewFamilyInstance(ref, inter_point, placement_dir, family_type)
# Extract wall thickness
wall_type = doc.GetElement(wall.GetTypeId())
wall_thickness = wall_type.Width
# Set dimensions on the family
param_w = new_instance.LookupParameter("Void Width")
param_h = new_instance.LookupParameter("Void Height")
param_l = new_instance.LookupParameter("Sleeve Length")
if param_w: param_w.Set(duct_width)
if param_h: param_h.Set(duct_height)
if param_l: param_l.Set(wall_thickness)
placed_elements.append(new_instance)
TransactionManager.Instance.TransactionTaskDone()
OUT = placed_elements
I created a void form for the piping and a separate one for ducting. The piping one works 100%.
Manually made you a member, so you can post now. One of the fun aspects of my admin super powers!
Thank you so much. Will upload first thing in the morning.
Hi
Dynamo script anf family attached
(attachments)
Duct Penetrations.rfa (548 KB)
PR Eng Rectangular_Penetrations.dyn (14.3 KB)
You need to update the code for PythonNet3 (your current syntax is that of IronPython); the “out” and “ref” parameters appear as normal arguments in PythonNet.
read this article
