Calculating Room Leasable area for Retail as per Indian NBC

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
5 Likes