Internal error when creating columns stirrup rebars

Hi All, @c.poupin

I’m attempting to create stirrup rebars for the columns shown in the image below. However, I received an internal error message, and I’m not sure what caused it. Could it be related to a RebarHookOrientation issue when the column is transformed?

Please check my attached code:

import clr
import sys
import System
from System.Collections.Generic import IList, List

clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.Structure import StructuralType, RebarBarType, RebarShape, RebarHookType,Rebar, RebarHookOrientation, RebarStyle, RebarCoverType

clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)

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

doc = DocumentManager.Instance.CurrentDBDocument


# get covers parameters by face 
cover_faces = {
    "Top": BuiltInParameter.CLEAR_COVER_TOP,
    "Bottom": BuiltInParameter.CLEAR_COVER_BOTTOM,
    "Other": BuiltInParameter.CLEAR_COVER_OTHER
}

cover_types = list(FilteredElementCollector(doc).OfClass(RebarCoverType).ToElements())

# get existing covers type
def get_cover_type(distance):

    for ct in cover_types:
        if abs(ct.CoverDistance - distance) < 1e-6:
            return ct
    name = "Enrobage_{} cm".format(distance / 0.0328084)
    new_ct = RebarCoverType.Create(doc, name, distance)
    cover_types.append(new_ct)
    return new_ct

# set covers distance from user input
def set_column_covers(column, top, btm, side):
    # Convert cm → feet
    cover_cm = {"Top": top, "Bottom": btm, "Other": side}
    cover_ft = {face: cover_cm[face] * 0.0328084 for face in cover_cm}

    # Assign covers
    for face, bip in cover_faces.items():
        param = column.get_Parameter(bip)
        if param and param.StorageType == StorageType.ElementId:
            ct = get_cover_type(cover_ft[face])
            if ct:
                param.Set(ct.Id)

# get updated covers from user input
def get_column_covers(column):
    
    result = {}
    for face, bip in cover_faces.items():
        param = column.get_Parameter(bip)
        if param and param.StorageType == StorageType.ElementId:
            ct = doc.GetElement(param.AsElementId())
            if isinstance(ct, RebarCoverType):
                result[face] = ct.CoverDistance
    return result
    
# get solid geometry from column
def get_solid(column):
    options = Options()
    options.IncludeNonVisibleObjects = False
    options.DetailLevel = ViewDetailLevel.Fine
    geoElement = column.get_Geometry(options)
    for g in geoElement:
        if isinstance(g, GeometryInstance):
            inst_geo = g.GetInstanceGeometry()
    return next((g for g in inst_geo if isinstance(g, Solid) and g.Volume > 0), None)
    
# define stirrups curves for the column
def stirrup_curves(column, solid, covers):
    curves = []
    side_cover = covers.get("Other")
    btm_cover = covers.get("Bottom")
    base_face = next((f for f in solid.Faces if f.FaceNormal.IsAlmostEqualTo(XYZ.BasisZ.Negate())), None)
    norm = base_face.FaceNormal
    curveloop = base_face.GetEdgesAsCurveLoops()[0]
    curveloop1 = CurveLoop.CreateViaOffset(curveloop, side_cover, norm.Negate())
    trans = Transform.CreateTranslation(XYZ.BasisZ.Multiply(btm_cover))
    curveloop1 = CurveLoop.CreateViaTransform(curveloop1, trans)
    for c in curveloop1:
        curves.append(c)    
    return curves


columns = list(FilteredElementCollector(doc)\
    .OfCategory(BuiltInCategory.OST_StructuralColumns)\
    .WhereElementIsNotElementType()\
    .ToElements())

offset_curves = []

with Transaction(doc, "Set columns Covers") as t:
    t.Start()
    for c in columns:
        set_column_covers(c, 4.5, 6, 3.5)
    t.Commit()

rebar_types = (FilteredElementCollector(doc)
        .OfCategory(BuiltInCategory.OST_Rebar)
        .WhereElementIsElementType()
        .WherePasses(ElementClassFilter(RebarBarType))
        .ToElements())
        
rebar_shapes = (FilteredElementCollector(doc)
        .OfCategory(BuiltInCategory.OST_Rebar)
        .WhereElementIsElementType()
        .WherePasses(ElementClassFilter(RebarShape))
        .ToElements())

#shape_00 = next((s for s in rebar_shapes if s.Name == "00"), None)


bar_type = next((r for r in rebar_types if r.LookupParameter('Diamètre de barre').AsValueString() == "12 mm"), None)

bar_type1 = next((r for r in rebar_types if r.LookupParameter('Diamètre de barre').AsValueString() == "6 mm"), None)


hook_types = FilteredElementCollector(doc) \
    .OfCategory(BuiltInCategory.OST_Rebar) \
    .WhereElementIsElementType() \
    .WherePasses(ElementClassFilter(RebarHookType)) \
    .ToElements()

hook_90 = next((h for h in hook_types if Element.Name.GetValue(h) == "Standard - 90 deg"), None)

hook_135 = next((h for h in hook_types if Element.Name.GetValue(h) == "Standard - 135 deg"), None)



with Transaction(doc, "create stirrups") as t:
    t.Start()
    for col in columns:
        solid = get_solid(col)
        covers = get_column_covers(col)
        top_cover, btm_cover, side_cover = covers["Top"], covers["Bottom"], covers["Other"]
        curvs = stirrup_curves(col, solid, covers)
        L = col.LookupParameter('Longueur').AsDouble()
        s = 0.15 * 0.3048
        d = L - top_cover - btm_cover
        stirup_curves = List[Curve](curvs)
        rebar = Rebar.CreateFromCurves(
            doc,
            RebarStyle.StirrupTie,
            bar_type1, 
            hook_135, 
            hook_135, 
            col,          
            XYZ.BasisZ,        
            curvs,      
            RebarHookOrientation.Left,
            RebarHookOrientation.Left,
            True,
            True
            )
        rebar.GetShapeDrivenAccessor().SetLayoutAsMaximumSpacing(s, d, True, True, True)    
            
    t.Commit()

OUT = 0

PS: I’m using Revit 2023 and Ironpython 2.7 engine

Any help would be appreciated

Thanks.

No one can help me??

Hi,

works well on my side

Unable to reproduce the bug, can you share a simple rvt file ?

1 Like

@c.poupin

Here my model file

columns_rebars.rvt (6.3 MB)

Furthermore, as I descibed in the image below, could you confirm whether I should tick “Include hooks in Rebar Shape definition” ? (In other examples especialy for longitidunal rebars creation, I noticed that if this option is unchecked, I get incorrect hook orientations compared to those defined in my code!)

Which Rebar shape is generated in your case?

Thanks.

I’m getting the same error with your file. I can’t say where it’s coming from, maybe it’s an API bug.

1 Like

Hi @c.poupin

Is this shape obtained from my file or yours? If it’s your file, you can see from the Properties tab that hooks are not taken into account for the generated shape….You can also check in the Rebar Shapes browser that ‘Shape 31’ does not contain hooks! So, the issue is not completely fixed because Revit does not resolve the shape correctly when hooks are not taken into account!?

Thanks.

@jacob.small @Mike.Buttery

Have you an idea how to solve this issue?

Thanks.

Not offhand - posting a model and your current .dyn would help.

1 Like

@jacob.small

My model is attached above

for dyn file you would just “copy/past” my code above into a python script then run it

PS: as I mentioned above I’m using Revit 2023 with IronPython 2.7 engine within Dynamo

Thanks.

Ah! I saw that earlier this week and chose to not reply as I won’t touch IP 2.7 anymore. Too risky.

You shocked me! What risk are you talking about regarding IP 2.7 usage? Does that mean I’m at risk using IP 2.7? Could you explain more?

Python 2.7 is unsupported/End of Life since 2019 which is the base of IronPython2 and will not get any security updates. This is outside of Autodesks hands!

Therefore as zero days are found they wont be fixed, and this means your system will be vulnerable.

Status of Python versions

1 Like

What @Brendan_Cassidy said is spot on, but you should also look over the link below as it’ll give a bunch more insight. For you to not have seen this one coming you’d have to basically not read any of my posts that mention Python here or anywhere else on social media. Note this also impacts PyRevit heavily.

(using an archive version as dynamobim.org is down for now due to errors the host is having)

2 Likes

I finally managed to solve the issue, and I now get the stirrups for columns with the desired hooks, as shown in the image below.

The problem was caused by this incorrect line, where I overlooked the hook Style. It was set to Standard, which didn’t match RebarStyle.StirrupTie as defined in the main function for rebar creation:

hook_135 = next((h for h in hook_types if Element.Name.GetValue(h) == "Standard - 135 deg"), None)

Additionally, since the orientation of the CurveLoop extracted from the column (and used for stirrup creation) was counter-clockwise, the RebarHookOrientation needed to be set to Right instead of Left.

Here my updated code:

import clr
import sys
import System
from System.Collections.Generic import IList, List

clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.Structure import StructuralType, RebarBarType, RebarShape, RebarHookType,Rebar, RebarHookOrientation, RebarStyle, RebarCoverType

clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)

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

doc = DocumentManager.Instance.CurrentDBDocument



cover_faces = {
    "Top": BuiltInParameter.CLEAR_COVER_TOP,
    "Bottom": BuiltInParameter.CLEAR_COVER_BOTTOM,
    "Other": BuiltInParameter.CLEAR_COVER_OTHER
}

cover_types = list(FilteredElementCollector(doc).OfClass(RebarCoverType).ToElements())

def get_cover_type(distance):

    for ct in cover_types:
        if abs(ct.CoverDistance - distance) < 1e-6:
            return ct
    name = "Enrobage_{} cm".format(distance / 0.0328084)
    new_ct = RebarCoverType.Create(doc, name, distance)
    cover_types.append(new_ct)
    return new_ct

def set_column_covers(column, top, btm, side):
    # Convert cm → feet
    cover_cm = {"Top": top, "Bottom": btm, "Other": side}
    cover_ft = {face: cover_cm[face] * 0.0328084 for face in cover_cm}

    # Assign covers
    for face, bip in cover_faces.items():
        param = column.get_Parameter(bip)
        if param and param.StorageType == StorageType.ElementId:
            ct = get_cover_type(cover_ft[face])
            if ct:
                param.Set(ct.Id)

def get_column_covers(column):
    
    result = {}
    for face, bip in cover_faces.items():
        param = column.get_Parameter(bip)
        if param and param.StorageType == StorageType.ElementId:
            ct = doc.GetElement(param.AsElementId())
            if isinstance(ct, RebarCoverType):
                result[face] = ct.CoverDistance
    return result



def get_solid(column):
    options = Options()
    options.IncludeNonVisibleObjects = False
    options.DetailLevel = ViewDetailLevel.Fine
    geoElement = column.get_Geometry(options)
    for g in geoElement:
        if isinstance(g, GeometryInstance):
            inst_geo = g.GetInstanceGeometry()
    return next((g for g in inst_geo if isinstance(g, Solid) and g.Volume > 0), None)

    
def stirrup_curves(column, solid, covers):
    curves = []
    side_cover = covers.get("Other")
    btm_cover = covers.get("Bottom")
    base_face = next((f for f in solid.Faces if f.FaceNormal.IsAlmostEqualTo(XYZ.BasisZ.Negate())), None)
    norm = base_face.FaceNormal
    curveloop = base_face.GetEdgesAsCurveLoops()[0]
    curveloop1 = CurveLoop.CreateViaOffset(curveloop, side_cover, norm.Negate())
    trans = Transform.CreateTranslation(XYZ.BasisZ.Multiply(btm_cover))
    curveloop1 = CurveLoop.CreateViaTransform(curveloop1, trans)
    for c in curveloop1:
        curves.append(c)    
    return curves



columns = list(FilteredElementCollector(doc)\
    .OfCategory(BuiltInCategory.OST_StructuralColumns)\
    .WhereElementIsNotElementType()\
    .ToElements())

with Transaction(doc, "Set columns Covers") as t:
    t.Start()
    for c in columns:
        set_column_covers(c, 4.5, 6, 3.5)
        
    t.Commit()

rebar_types = (FilteredElementCollector(doc)
        .OfCategory(BuiltInCategory.OST_Rebar)
        .WhereElementIsElementType()
        .WherePasses(ElementClassFilter(RebarBarType))
        .ToElements())
        
rebar_shapes = (FilteredElementCollector(doc)
        .OfCategory(BuiltInCategory.OST_Rebar)
        .WhereElementIsElementType()
        .WherePasses(ElementClassFilter(RebarShape))
        .ToElements())
        
         
bar_type = next((r for r in rebar_types if r.LookupParameter('Diamètre de barre').AsValueString() == "6 mm"), None)

hook_types = list(FilteredElementCollector(doc)
                  .OfClass(RebarHookType)
                  .ToElements())

hook_types = [hk for hk in hook_types if hk.Style == RebarStyle.StirrupTie]


hook_135 = next((h for h in hook_types if Element.Name.GetValue(h) == "Etrier/épingle - 135 deg."), None)


columns_stirrups= []

with Transaction(doc, "create stirrups") as t:
    t.Start()
    
    for col in columns:
        solid = get_solid(col)
        covers = get_column_covers(col)
        top_cover, btm_cover, side_cover = covers["Top"], covers["Bottom"], covers["Other"]
        curvs = stirrup_curves(col, solid, covers)
        L = col.LookupParameter('Longueur').AsDouble()
        s = 0.15 / 0.3048
        d = L - top_cover - btm_cover
        stirup_curves = List[Curve](curvs)
        rebar = Rebar.CreateFromCurves(
            doc,
            RebarStyle.StirrupTie,
            bar_type, 
            hook_135, 
            hook_135, 
            col,          
            XYZ.BasisZ,        
            stirup_curves,      
            RebarHookOrientation.Right,
            RebarHookOrientation.Right,
            True,
            True
            )
           
        rebar.GetShapeDrivenAccessor().SetLayoutAsMaximumSpacing(s, d, True, True, True)    
        
        columns_stirrups.append(rebar)   

    t.Commit()
	
OUT = columns_stirrups

Since you mentioned pyRevit, I should point out that most of my work is done in pyRevit, and I only use Dynamo occasionally to visualize outputs from certain codes I want to check. I would have preferred to use a secure Python engine within pyRevit, but I’m currently limited to working with the IronPython 2.7 engine.

Thanks.

Beyond the risk of using old libraries with vulnerabilities such as urllib2, there will come a time when IronPython2.7 (no longer maintained by the IronPython team) will no natively longer work on future versions of Net Core.

Take advantage of the transition to Net 8 to migrate to PythonNet3 or IronPython3, whether on Dynamo or PyRevit.

This is an example of a security issue

2 Likes

You’re only stuck there as you’ve chose that ecosystem. There is nothing PyRevit does which you can’t do with another tool.

2 Likes