Filled Region from Room Boundary

I am trying to figure out if there is a way to create a filled region through a room boundary? Following a video on Autodesk University’s website, I was able to put together a script that creates a floor from a room boundary. I was hoping I may be able to use this as a base and make modifications to create a filled region, but i have not been able to find any feeds on here, or links elsewhere that say creating a filled region in dynamo is even possible. Attached is the file I have started with.IN2016002_Create Floor from Room - Dyn. 0.9.1

1 Like

Hi Robert,

Yes it is possible. How? See below. Good Luck!

Untitled1

Thank you Kulkul for your help. I was able to set everything up, and run the script, but kept getting an error message with the python script node. I double checked the Script twice but cannot seem to see any differences or error in my script. I tried running this in another revit file thinking something may be wrong with my base file, but still getting the same error. The image below is the error message I keep getting and what i put into the python script. I’ve also attached my dynamo file. IN2016002_Filled Region Attempt - Dyn. 0.9.1

Edit Python

1 Like

There are 2 things which i noticed your connecting elements to Python IN [0] instead of Curves. Second thing is why are you getting “Empty List” at “FilterByboolMask”.

follow my screenshot properly. Good Luck!

Something similar:

import clr
 
 clr.AddReference("RevitAPI")
 from Autodesk.Revit.DB import *
 
 clr.AddReference("RevitServices")
 from RevitServices.Persistence import DocumentManager
 from RevitServices.Transactions import TransactionManager
 
 doc =  DocumentManager.Instance.CurrentDBDocument
 
 roomsList =  UnwrapElement(IN[0])
 filledRegionName = IN[1]
 
 for fr in FilteredElementCollector(doc).OfClass(FilledRegionType):
     if Element.Name.GetValue(fr) == filledRegionName:
         filledRegion = fr
         break     
 
 viewId = doc.ActiveView.Id
 
 TransactionManager.Instance.EnsureInTransaction(doc)
 
 regions = []
 for room in roomsList:  
     if room.Area > 0:
         roomBoundaries = room.GetBoundarySegments(SpatialElementBoundaryOptions())            
         curveLoopList = []
         roomCurves = CurveLoop()
         for roomBoundary in roomBoundaries:
             for boundarySegment in roomBoundary:
                 roomCurves.Append(boundarySegment.Curve)
         curveLoopList.Add(roomCurves)
 
         region = FilledRegion.Create(doc,filledRegion.Id,viewId, curveLoopList)
         regions.append(region)    
     
 TransactionManager.Instance.TransactionTaskDone()
 
 OUT = regions

FilledRegions

Hi Organon, thanks for posting this! It’s working nicely with both curves and lines, and responds well to unit changes in the Revit document. I plan on adapting this (given my sketchy Python skills) to create filled regions from slab boundaries instead of room boudaries.

I did notice though that when you run again after changing the walls in your example, that new filled regions are created instead, leaving the old ones behind. Why aren’t the original filled regions adjusted instead? I guess I was expecting the same behavior we get when creating Revit geometry via Dynamo where such geometry responds to graph changes, instead of recreating objects. Why would this be any different? Thanks again.

Well, looking a bit more at the Phyton code, I understand that filled regions are being created from boundaries and I think anything created via Python cannot really be updated without explicitly coding for that to happen (ex: store element IDs of created elements in a list together with ID of elements where the boundary was extracted from and each time the graph updates, look up the element and edit the curve loop instead of creating a new object; if there is a new object and no corresponding filled region, then create a new one, and also delete orphaned filled regions). What I was after now seems to be a lot more complicated than expected…the story of my Dynamo life :slight_smile: I suspect if there was native node that created filled regions, that this behavior might have been built-in.

Hi @Kulkul

I’ve followed without any differences, my filterbool shows correctly and nodes are connected correctly, etc. When I run, it gives me the error:

AttributeError: ‘FilledRegionType’ object has no attribute ‘ID’

Pointing to the line of code:
region = FilledRegion.Create(doc,frt[0].ID,activeViewId,profileLoops)

Any ideas?

try Id (capital I lower case d)

@Mostafa_El_Ayoubi

Thanks for catching that small syntax difference. I triple checked the code again and everything is verbatim including case. However now when I execute the script, dynamo hangs and does not respond. Something seems to be wrong. I am stumped as I am sure I have everything correct.

can you share your code here?

@Mostafa_El_Ayoubi

Thanks man I appreciate the help. Just in case you need further info:
Revit 2015, DYN 1.1

I am simply running this on a simple square room enclosed by walls in a floor plan view.

CODE:

import clr
clr.AddReference(‘ProtoGeometry’)
from Autodesk.DesignScript.Geometry import *

Import DocumentManager and TransactionManager

clr.AddReference(“RevitServices”)
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

Import RevitAPI

clr.AddReference(“RevitAPI”)
import Autodesk
from Autodesk.Revit.DB import *

doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application

def lineFromCrv(crv):
start = crv.StartPoint
end = crv.EndPoint
a = XYZ(start.X,start.Y,start.Z)
b = XYZ(end.X,end.Y,end.Z)
return Autodesk.Revit.DB.Line.CreateBound(a,b)

regions = []
activeViewId = doc.ActiveView.Id;

TransactionManager.Instance.EnsureInTransaction(doc)

frt = UnwrapElement( IN[1] )

for bound in IN[0]:
profileLoops = []
profileLoop = CurveLoop()
#create filled region
for crv in bound:
profileLoop.Append(lineFromCrv(crv))
profileLoops.Add(profileLoop)
region = FilledRegion.Create(doc,frt[0].Id,activeViewId,profileLoops)
regions.Add(region)

#End Transaction
TransactionManager.Instance.TransactionTaskDone()

#Assign your outputs to the OUT variable
OUT = regions

Yes, that’s right.

We can´t see the indentation of the blocks of code. By the way, this is another solution:

import clr

clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import *

clr.AddReference("RevitServices")
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

doc =  DocumentManager.Instance.CurrentDBDocument

roomsList =  UnwrapElement(IN[0])
filledRegionName = IN[1]

for fr in FilteredElementCollector(doc).OfClass(FilledRegionType):
    if Element.Name.GetValue(fr) == filledRegionName:
        filledRegion = fr
        break     

viewId = doc.ActiveView.Id

TransactionManager.Instance.EnsureInTransaction(doc)

regions = []
for room in roomsList:  
    if room.Area > 0:
        roomBoundaries = room.GetBoundarySegments(SpatialElementBoundaryOptions())            
        curveLoopList = []
        roomCurves = CurveLoop()
    	for roomBoundary in roomBoundaries:
            for boundarySegment in roomBoundary:
    		    roomCurves.Append(boundarySegment.GetCurve())
        curveLoopList.Add(roomCurves)

    	region = FilledRegion.Create(doc,filledRegion.Id,viewId, curveLoopList)
        regions.append(region)
        
TransactionManager.Instance.TransactionTaskDone()

OUT = regions
1 Like

Thank you @Organon I don’t doubt your solution and Ive tried it too but it seems to hang as well. Are there any thoughts on what may be causing this? Is there something I am fundamentally missing, perhaps an additional package or download?

I really don’t know. Sorry.

@Organon

I am testing to see if any calculations are throwing the script off and attempting to simply the script to accepting a polyline or list of curves as IN[0] as the boundary and the filtered filled region type like “Diagonal Up” as IN[1]. See below:

import clr

clr.AddReference(“RevitAPI”)
from Autodesk.Revit.DB import *

clr.AddReference(“RevitServices”)
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

doc = DocumentManager.Instance.CurrentDBDocument

curveLoopList = IN[0]
filledRegionName = IN[1]

for fr in FilteredElementCollector(doc).OfClass(FilledRegionType):
if Element.Name.GetValue(fr) == filledRegionName:
filledRegion = fr
break

viewId = doc.ActiveView.Id

TransactionManager.Instance.EnsureInTransaction(doc)

regions=[]
region = FilledRegion.Create(doc,filledRegion.Id,viewId, curveLoopList)
regions.append(region)

TransactionManager.Instance.TransactionTaskDone()

OUT = regions


I am wondering how to get this to work with an input of curves.

Hi @Dynamonkey
This topic is already solved. Could you please create a new topic with complete screenshot’s of your query. Thanks :slight_smile:

Hi There!

I’d like to do something similar.

We have an Interior design sub-consultant who has done all their finish floors with filled regions.

Can the process of using rooms to create filled regions be used to create floors from fille region types?

Regards,

Hi,
The script seems to run OK when used on an Imperial Units Revit file, but when run on a Metric file, the regions are scaling up. Any suggestions why?