How to Split Structural Columns by Levels in Revit Using Dynamo!! [REVIT 2021]

 In this video, you will learn how to split structural columns by levels without using the out-of-the-box command or manually but using Dynamo!!


Python Script:

import clr

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

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc =  DocumentManager.Instance.CurrentDBDocument
 
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)
 
clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import *

# Convert to list if not list...
def tolist(obj1):
    if hasattr(obj1,"__iter__"): return obj1
    else: return [obj1]

# Gets the centreline of the column...
def GetColumnCentreline(e):    
    crv = None    
    fs = e.Symbol
    fm = fs.Family    
    if not fm.GetType() == DirectShape:
        if not fm.IsInPlace:
            if e.IsSlantedColumn:
                try:
                    crv = e.Location.Curve.ToProtoType()
                except:
                    return
            else:
                loc = e.Location.Point.ToPoint()
                
                bLev = (e.Document.GetElement(e.get_Parameter(BuiltInParameter.FAMILY_BASE_LEVEL_PARAM).AsElementId()).Elevation + e.get_Parameter(BuiltInParameter.FAMILY_BASE_LEVEL_OFFSET_PARAM).AsDouble()) * ft2mm
                tLev = (e.Document.GetElement(e.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_PARAM).AsElementId()).Elevation + e.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_OFFSET_PARAM).AsDouble()) * ft2mm
                
                crv = geom.Line.ByStartPointEndPoint(geom.Point.ByCoordinates(loc.X,loc.Y,bLev), geom.Point.ByCoordinates(loc.X,loc.Y,tLev))
    return crv

# Convert Level to DS Plane...
def LevelToPlane(l):
    pt = geom.Point.ByCoordinates(0,0,round(l.Elevation * ft2mm,0)+offset)
    n = geom.Vector.ZAxis()
    return geom.Plane.ByOriginNormal(pt,n)

# Get the nearest Level above in list of Levels to gien Elevation...
def NearestLevelAbove(elev,lvls):
    lvlAbv = None
    for l in lvls:
        if round(l.Elevation*ft2mm,0) > elev:
            lvlAbv = l
            break            
    return lvlAbv

# Get the nearest Level in list of Levels to gien Elevation...
def NearestLevel(elev, lvls):
    return min(lvls, key=lambda x:abs(round(x.Elevation*ft2mm,0)-elev))

# Calculates the location to split column with parameterised column length (between 0 & 1)...
def CalculateSplitParameter(col,lvls):
    # Switch out for mathematical method to speed up computation...

    # abs(NewColBaseElevation-LevelAboveElevation)/NewCol length should give split parameter...
    if col:
        crv = GetColumnCentreline(col)
        elev = round(crv.StartPoint.Z,0)
        l = NearestLevelAbove(elev,lvls)        
        
        x = geom.Geometry.Intersect(crv,LevelToPlane(l))
        if x:
            x = x[0]
            return geom.Curve.ParameterAtPoint(crv,x)
                
    return None

# IN Variables...
run = tolist(IN[0])[0]
columns = tolist(UnwrapElement(IN[1]))
lvls = tolist(UnwrapElement(IN[2]))
offset = 0
if IN[3]:
    offset = tolist(IN[3])[0]


# OUT Variables...
outList = []

# Main Body...
if run:
    ft2mm = 304.8
    lvls = sorted(lvls, key=lambda x: x.Elevation)
    
    # Start Transaction to allow for Document modification...
    TransactionManager.Instance.EnsureInTransaction(doc)
    for c in columns:
        # Ensure only Structural Columns are used (modify if Arch Columns category is required)
        if c.Category.Name == Category.GetCategory(doc,BuiltInCategory.OST_StructuralColumns).Name:
            arr = []
            arr.append(c)
            newCol = None
            crv = GetColumnCentreline(c)
            
            bLvlIndex = lvls.index(NearestLevel(crv.StartPoint.Z,lvls))
            tLvlIndex = lvls.index(NearestLevel(crv.EndPoint.Z,lvls))
            
            i = bLvlIndex
            while i <= tLvlIndex:
                try:    
                    if not newCol:
                        p = CalculateSplitParameter(c,lvls)
                        newCol = doc.GetElement(c.Split(p))
                        arr.append(newCol)            
                    else:
                        p = CalculateSplitParameter(newCol,lvls)
                        newCol = doc.GetElement(newCol.Split(p))
                        arr.append(newCol)
                except Exception, ex:
                    arr.append(ex.message)
                i = i+1        
            outList.append(arr)
        else:
            outList.append("Element is not of Category Structural Column")            
        
    TransactionManager.Instance.TransactionTaskDone()
    OUT = outList
else:
    OUT = "Please set Run to True"
Post a Comment (0)
Previous Post Next Post