Curves or lines from room.GetboundarySegments

Hi i’m trying to create area based on the boundaries of rooms from a linked model.

But i’m having trouble converting the room.GetboundariySegments to curves/lines to be able to use them for the are boundray creation.
anybody having any idea?

the problem seems the be that the segments can be in list in list (in list) depending on wheter or not the room has multiple boundarieloops.

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

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

from CMRPGUI import *

# Doc & App
# -----------------------------------------------------------------------
doc = revit.doc
uidoc = revit.uidoc

def areatoroom(doc):
        # lists
        # -----------------------------------------------------------------------
        room_names, room_numbers, room_boundaries, room_Id, room_lvls = [], [], [], [], []
        room_views = []
        linked_lvl_name = []
        
        lvls_ex = FilteredElementCollector(doc).OfClass(Level).ToElements()
        lvls_ex_names = [lvl.Name for lvl in lvls_ex]
        
        options = SpatialElementBoundaryOptions()
        options.SpatialElementBoundaryLocation = SpatialElementBoundaryLocation.Finish
        
        # Select link document & the linked-rooms
        # -----------------------------------------------------------------------
        links = link_selection(doc)
        for link in links:
                link = link.GetLinkDocument()
                rooms = FilteredElementCollector(link).OfCategory(BuiltInCategory.OST_Rooms).ToElements()
                # Get rooms information from linked model
                # -----------------------------------------------------------------------
                for room in rooms:
                        room_Id.append(room.UniqueId)
                        room_names.append(Element.Name.GetValue(room))
                        room_numbers.append(room.Number)
                        # boundaries information - curves
                        room_segments = []
                        lines = []
                        room_segments.append(room.GetBoundarySegments(Options))
                        for segment in room_segments:
                                for curve in segment:
                                        if isinstance(curve, lines):
                                                lines.append(curve)
                        room_boundaries.append(lines)
                        # lvl information
                        lvl_Id = (room.LevelId)
                        lvl = link.GetElement(lvl_Id)
                        linked_lvl_name.append(lvl.Name)
                # Get corresponding lvls from the analysismodel
                # -----------------------------------------------------------------------
                room_lvls = [lvls_ex[lvls_ex_names.index(name)] for name in linked_lvl_name]
                room_lvl_ref = [lvl.GetPlaneReference for lvl in room_lvls]
                # Get corresponding view of lvl
                # -----------------------------------------------------------------------
                for view in FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Views):
                        # Check if the view name starts with "13_"
                        if view.Name.startswith("13_"):
                                level_name = view.Name.replace("13_", "")
                                # Check if the level name is in the list of level names
                                if level_name in lvls_ex_names:
                                        room_views.append(view)
                print(room_views)
                # New boundary lines
                # -----------------------------------------------------------------------
                room_boundaries.NewAreaBoundaryLine(room_lvl_ref, room_boundaries, room_views)

areatoroom(doc)

Can you show this running with the inputs and outputs? The boundary structure should be the same regardless of how many boundary loops there are.

One thing I notice right off the bat is the redundancy with your room_segments portion. You make this an empty list that you append to (adding a list level) and then iterate through (the list of boundaries) so I think you end up being one level off. Just make room_segments a variable and set it equal to room.GetBoundarySegments(Options). That should hopefully make things less confusing.

Solved it, already :slight_smile:

for those intressed, i needed to go one layer deeper:

for room in rooms:
                        room_Id.append(room.UniqueId)
                        room_names.append(Element.Name.GetValue(room))
                        room_numbers.append(room.Number)
                        # boundaries information - curves
                        room_segments = []
                        lines = []
                        room_segments.append(room.GetBoundarySegments(options))
                        for segment in room_segments:
                                for subsegment in segment:
                                        for curve in subsegment:
                                                lines.append(curve.GetCurve())
                        room_boundaries.append(lines)
1 Like

Same thing. You have to go one level deeper because you’re (unnecessarily) adding an extra level. Appending to a list here is pointless because you only do it once and then reset the list.

i needed the extra list lvl so that aligned with the rooms they belong to.
one lvl less and a room with 2 boundaries loops would be in trouble (as i see it).
the only input i use is the current doc and from the selection window one linked document

The whole script works fine now :):

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

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

from CMRPGUI import *

# Doc & App
# -----------------------------------------------------------------------
doc = revit.doc
uidoc = revit.uidoc

def roomtoarea(doc):
        # lists
        # -----------------------------------------------------------------------
        room_names, room_numbers, room_boundaries, room_Id, room_lvls = [], [], [], [], []
        room_views = []
        linked_lvl_name = []
        
        lvls_ex = FilteredElementCollector(doc).OfClass(Level).ToElements()
        lvls_ex_names = [lvl.Name for lvl in lvls_ex]
        
        options = SpatialElementBoundaryOptions()
        options.SpatialElementBoundaryLocation = SpatialElementBoundaryLocation.Finish
        
        # Select link document & the linked-rooms
        # -----------------------------------------------------------------------
        links = link_selection(doc)
        for link in links:
                link = link.GetLinkDocument()
                rooms = FilteredElementCollector(link).OfCategory(BuiltInCategory.OST_Rooms).ToElements()
                # Get rooms information from linked model
                # -----------------------------------------------------------------------
                for room in rooms:
                        room_Id.append(room.UniqueId)
                        room_names.append(Element.Name.GetValue(room))
                        room_numbers.append(room.Number)
                        # boundaries information - curves
                        room_segments = []
                        lines = []
                        room_segments.append(room.GetBoundarySegments(options))
                        for segment in room_segments:
                                for subsegment in segment:
                                        for curve in subsegment:
                                                lines.append(curve.GetCurve())
                        room_boundaries.append(lines)
                        # lvl information
                        lvl_Id = (room.LevelId)
                        lvl = link.GetElement(lvl_Id)
                        linked_lvl_name.append(lvl.Name)
                # Get corresponding lvls from the analysismodel
                # -----------------------------------------------------------------------
                room_lvls = [lvls_ex[lvls_ex_names.index(name)] for name in linked_lvl_name]
                lvl_ref = [lvl.Id for lvl in room_lvls]
                room_sketchplane = []
                with Transaction(doc, "Create SketchPlanes form levels") as t:
                        t.Start()
                        for i in lvl_ref:
                                room_sketchplane.append(SketchPlane.Create(doc, i))
                        t.Commit()
                # Get corresponding view of lvl
                # -----------------------------------------------------------------------
                for lvl in linked_lvl_name:
                        for view in FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Views):
                                # Check if the view name starts with "13_"
                                if view.Name.startswith("13_"):
                                        level_name = view.Name.replace("13_", "")
                                        # Check if the level name is in the list of level names
                                        if level_name == lvl:
                                                room_views.append(view)
                # New boundary lines
                # -----------------------------------------------------------------------
                with Transaction(doc, "Create area boundaries") as t:
                        t.Start()
                        for boundary, plane, view in zip(room_boundaries, room_sketchplane, room_views):
                                for line in boundary:
                                        doc.Create.NewAreaBoundaryLine(plane, line, view)
                        t.Commit()

roomtoarea(doc)

maybe u have a point.
because at the end i go also a lvl lower to make make boundaries themselfs … hmm

room_segments = []
lines = []
room_segments.append(room.GetBoundarySegments(options))
      for segment in room_segments:
              for subsegment in segment:
                      for curve in subsegment:
                              lines.append(curve.GetCurve())

Only because you’re adding an extra level by appending to a list instead of just using the returned value.

lines = []
room_segments = room.GetBoundarySegments(options)
for segment in room_segments:
        for curve in segment:
                lines.append(curve.GetCurve())

If you just use room_segments as the list that gets returned you don’t have to deal with the extra level.

Appending to a list here is unnecessary because the list only exists within the loop of a single room. So you’re only adding a single element and then starting over.

2 Likes

thx for the tip @Nick_Boyts !!!
A new lesson learned today ^^!
i didn’t think of the fact that the first empty list would create an extra layer.

is it bettre in general to approach list first as variables rather then empty lists?
i’m still a beginner so thx for your advice :smiley: !

1 Like

It’s not really a matter of variable vs empty list. It’s going to be a variable regardless. It’s just whether you’re adding to the structure or keeping it the same.

It’s really about the list structure you need. If you need a list then you need to create one and append to it. If you don’t, then you don’t.

1 Like