Shaft boundaries

Hi everybody,

I’m trying to retrieve shaftboundaries from shafts in a linked model.
right now i got to the point that i get the curves but the is a “small” problem…
The revit-api retrieves both the boundaries and the symbolic lines…
image

I found this out by replicating my script in dynamo to be able to see the lines in ‘action’:

When i then take the first 4 lines (to make a rectangle) it works for most of the shaft but not all.
And this will not works for shaft wich are not rectangles!

Anybody got any ideas on how to solve this? and split the lines up between symbolic and boundary?

big thx in advance :slight_smile:

Below my python script for pyrevit:

import sys
sys.path.append(r'H:\\_GROEPEN\\CAD\\DEV\\Tools\\CMRP')

from pyrevit import script
from pyrevit import UI
from pyrevit import revit
from Autodesk.Revit.UI import *
from Autodesk.Revit.UI.Selection import *
from Autodesk.Revit.DB import *

from CMRPGUI import *
from CMRP import *

# Doc & App
# -----------------------------------------------------------------------
doc = revit.doc
uidoc = revit.uidoc
# link_f = settings_read_link('model_rooms')
link_f = link_selection(doc)
link = link_f[0].GetLinkDocument()
print(link.Title)

# Retrieve rooms and there locations
shaft_Id, shaft_curves, shaft_nums = [], [], []
shaft_botlvls, shaft_toplvls = [], []
shaft_botlvls_name, shaft_toplvls_name = [], []
shaft_botoffsets, shaft_topoffsets = [], []

# Create DirectShapeType for Generic elements
def get_custom_parameter(shaft, param_name):
    param = shaft.LookupParameter(param_name)
    if param:
        if param.StorageType == StorageType.String:
            return param.AsString()
        elif param.StorageType == StorageType.Integer:
            return param.AsInteger()
        elif param.StorageType == StorageType.Double:
            return param.AsDouble()
        elif param.StorageType == StorageType.ElementId:
            return param.AsElementId()
    else:
        return None

# Start a new transaction to create Mass elements
shaft_num = 1
shafts = FilteredElementCollector(link).OfCategory(BuiltInCategory.OST_ShaftOpening).ToElements()

lvls_ex = FilteredElementCollector(doc).OfClass(Level).ToElements()
lvls_ex_names = [lvl.Name for lvl in lvls_ex]

for shaft in shafts:
    shaft_Id.append(shaft.UniqueId)
    print(shaft.UniqueId)
    shaft_curves.append(shaft.BoundaryCurves)
    print(shaft.BoundaryCurves)
    for i in shaft.BoundaryCurves:
        print(i)
    
    # Base lvl
    base_constraint_id = shaft.get_Parameter(BuiltInParameter.WALL_BASE_CONSTRAINT).AsElementId()
    shaft_botlvls_name.append(link.GetElement(base_constraint_id).Name) 
    print(shaft_botlvls_name)
    
    # Base-offset
    param = shaft.LookupParameter('Base Offset')
    shaft_botoffsets.append(param.AsValueString())

    # Top lvl
    base_constraint_id = shaft.get_Parameter(BuiltInParameter.WALL_HEIGHT_TYPE).AsElementId()
    shaft_toplvls_name.append(link.GetElement(base_constraint_id).Name)
    
    # Top-offset
    param = shaft.LookupParameter('Top Offset')
    shaft_topoffsets.append(param.AsValueString())

    shaft_nums.append(shaft_num + 1)
    
    # mass_element.Category = Category.GetCategory(doc, mass_category)
    print('--------------------------------------------------------------------------------------------')

print(shaft_curves)
botlvls = [lvls_ex[lvls_ex_names.index(name)] for name in shaft_botlvls_name]
toplvls = [lvls_ex[lvls_ex_names.index(name)] for name in shaft_toplvls_name]


with Transaction(doc, "Shaftmasses") as t:
    t.Start()
                
    for curves, botlvl, toplvl, botoff, topoff, Id, num in zip(shaft_curves, botlvls, toplvls, shaft_botoffsets, shaft_topoffsets, shaft_Id, shaft_nums):
        shaft = doc.Create.NewOpening(botlvl, toplvl, curves)
        
        shaft.Name = num
        print(shaft)
        param = shaft.LookupParameter('CMRP_UniqueId')
        param.Set(Id)
    t.Commit()

For those looking for the solution to this problem i solved it with the code below.
the clue is in the fact that u don’t need to use BoudanryCurves (wich sounds logical) but the SketchId.
Then retrieve the profile from the sketch.

this code was for testing purposes in dynamo but also aplies in python(pyrevit):

# Load the Python Standard and DesignScript Libraries
import sys
import clr
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import Autodesk.DesignScript.Geometry as DS
import Revit
clr.ImportExtensions(Revit.GeometryConversion)

link = IN[0]

shafts = FilteredElementCollector(link).OfCategory(BuiltInCategory.OST_ShaftOpening).ToElements()
# Place your code below this line
shaft_curves =[]

for shaft in shafts:
    sketch = link.GetElement(shaft.SketchId)
    profile = sketch.Profile
    curves = []
    for profile_curve in profile:
        for curve in profile_curve:
            curves.append(curve.ToProtoType())
    shaft_curves.append(curves)
 
# Assign your output to the OUT variable.
OUT = shaft_curves
2 Likes