Hi,
- DB.CurveLoop.CreateViaOffset method can be used to create custom offsets for each curve, and we can find the bounding element (wall) for each boundary segment.
python code (need to adapt if necessary)
import clr
import sys
import System
from System.Collections.Generic import List, IList, Dictionary, HashSet
#
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import Autodesk.DesignScript.Geometry as DS
#import Revit API
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
#import transactionManager and DocumentManager (RevitServices is specific to Dynamo)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
doc = DocumentManager.Instance.CurrentDBDocument
class CustomRoom:
def __init__(self, room):
self._room = room
s_opt = SpatialElementBoundaryOptions()
s_opt.SpatialElementBoundaryLocation = SpatialElementBoundaryLocation.Center
self._outsegments = max(self._room.GetBoundarySegments(s_opt), key=lambda loop : sum(l.GetCurve().Length for l in loop))
@property
def OutCurveLoop(self):
return CurveLoop.Create(List[DB.Curve]([x.GetCurve() for x in self._outsegments]))
@property
def Room(self):
return self._room
@property
def LeasableSurface(self):
lst_offset = List[System.Double]()
for curve in self.OutCurveLoop:
# get the associated wall via the segment.
assoc_segment = next((s for s in self._outsegments if s.GetCurve().Intersect(curve) == SetComparisonResult.Equal), None)
assoc_wall = doc.GetElement(assoc_segment.ElementId)
# if interior wall do no offset
if assoc_wall.GetTypeId() in lst_walls_type_partition_Ids:
lst_offset.Add(0)
# if exterior wall offset it
else:
lst_offset.Add(assoc_wall.Width / 2)
# offset curveloop
extendLoop = DB.CurveLoop.CreateViaOffset(self.OutCurveLoop, lst_offset, XYZ.BasisZ)
# create Surface
return DS.PolyCurve.ByJoinedCurves([c.ToProtoType() for c in extendLoop], 0.001, False, 0).Patch()
def toList(x):
if isinstance(x, (list, dict)) or \
(hasattr(x, "GetType") and x.GetType().GetInterface("ICollection") is not None):
return x
else : return [x]
#Preparing input from dynamo to revit
lst_rooms = toList(UnwrapElement(IN[0]))
lst_walls_type_partition = toList(UnwrapElement(IN[1]))
lst_walls_type_partition_Ids = [x.Id for x in lst_walls_type_partition]
out = []
for room in lst_rooms:
if room.Area > 0.001: # edit 25/06/2025
c_room = CustomRoom(room)
out_surf = c_room.LeasableSurface
out.append([c_room.Room, out_surf, out_surf.PerimeterCurves(), out_surf.Area])
OUT = out
