Fill inside the builing and making it a single mass

Hello all,
I wanted to create a single mass of my whole building model in the revit, so i used a script which was available from the Dynamo fourm. Since I have an open loop in my building the script shows an error.
image

Can you Guys please help how to select also the pen loop through the dynamo. The scope is to create the whole model into a single mass element. for topographical purposes.

Hey,

I presume you’re trying to extract room solids and some of them are failing?

Unfortunately this is always a possibility, room geometry can be very complex and sometimes it just can’t be resolved. If you search the forum for the warning you received you will find a lot of results. The more recent Dynamo’s have an improved polycurve by joined curves node, so you can extract room boundaries, join polycurve and extrude the room parameter height… But even this can still fail.

If you are mostly interested in the relationships between spaces then you could extract ‘bounding boxes’ a simplified cube encompasing the spaces, the main down side to these are that they are not ‘axis aligned’.

Hope that helps,

Mark

It is not possible to use Element.Geometry for every element such as Curtain Walls. If you have anything like that you will get an error. You can compare your categories order and the result of element.geometry to understand which one is the problem.

What type of elements are you trying to access the geometry of?

You may want to utilize the building envelope analyzer class of the Revit API to get things more directly.

Hello Mark.Ackerley, thanks for your response. yes I was trying to extract the solid from both the rooms and elements to create my building model as a single element, for the purpose of volumetric calculations in topograpy (toposolid).
Also I tried the bounding box yes it is not axis aligned for some elements.

I tried it but the error is about the polycurve and Couldnt match it. But thank you for the response.

Hello jacob,
thanks for the response
To make it simple, I wanted my model to be filled inside and made a single mass element.

What is the desired end result once you have the single mass? Likely the ‘walls, roofs, foundations, and slabs’ from the API I linked above will get you what you need to generate the mass (adding windows and doors if you want that sort of stuff included).

I need to know more about ‘why’ to provide more help.

Having dealt with this at work, I can recommend focusing on walls only and their location lines. Hyperextend them slightly and try to use that to form loops per level. Classify your revit walls as external/internal so you can filter out non envelope walls. We used a workflow to make ceilings per level by walls, so in our case our goal was 1 loop per level.

@jacob.small to address the quizzical emoji, it’s a reverse block/stack moreorless - trying to build a repo of common project typologies in a few sectors as block/stack diagrams in a sample model to educate some basic ML forays (if my building is on X site and Y levels and Z planning controls what is my interpolated GFA etc.). Honestly we just found users do it manually faster for most jobs as the big ones are unruly anyway when it comes to clean edges.

:thinking:

My original emoji was in relation to automating the process via the Building Envelope Analyzer class… however now you got me thinking about automated block stack diagrams via Forma, Dynamo, and Generative Design.

1 Like

Yep wasn’t even aware of that class - one to play with… sounds too good to be true.

Jury is out, and how the model has been built will matter here - garbage in results in exponential garbage out.

The more and more I poke at stuff like this the more I realize that the many workarounds to ‘get stuff done quickly’ that are so prevalent that a lot of the good automation possibilities get broken.

1 Like

Hello Jacob,
My Idea is to create the single mass for the elements and then place it in the toposolid i have, so that it create the excavation volume in our project according to our terms. I am just a begginer in the Revit api. I will go through it. Thank you

This is interesting:

Not sure how it will perform on larger projects, but speed is fine by me for smaller stuff.

The Python Script
########################################
############## Properties ##############
########################################
__author__ = 'Jacob Small'
__version__ = '0.1.0'
__description__ = """ gets the solid mass of the building envelope """
__RevitBuilds__ = "2024.1"
__DynamoBuilds__ = "2.18.1"
__ReleaseNotes__ = """ - """
__Dependancies__ = "none"
__Copyright__ = "2024, Autodesk Inc."
__License__ = """Apache 3"""



########################################
### Configure the Python environment ###
########################################
### standard imports ###
import sys #add the sys class to the Python environment so we can work with the sys objects
import clr #add the CLR (common language runtime) class to the Python environment so we can work with .net libraries

### basic Dynamo imports ###
clr.AddReference('ProtoGeometry') #add the Dynamo geometry library to the CLR
from Autodesk.DesignScript import Geometry as DG #add the Dynamo geometry class using the alias DG, to ensure no overlap between class calls in Revit or Dynamo

### Dynamo Revit imports ###
clr.AddReference("RevitNodes") #add Dynamo's Revit nodes library to the clr
import Revit #import Dynamo's Revit node class
clr.ImportExtensions(Revit.Elements) #add the element conversion methods to the CLR
clr.ImportExtensions(Revit.GeometryConversion) #add the geometry conversion methods to the CLR
clr.AddReference("RevitServices") #add the Revit services library to the CLR
import RevitServices #import the Revit services class to the Python environment
from RevitServices.Persistence import DocumentManager #import the document manager class to the Python environment 
from RevitServices.Transactions import TransactionManager #import the transaction manager class to the Python environment 

### Revit API imports ###
clr.AddReference("RevitAPI") #add the Revit API to the CLR
import Autodesk #add the Autodesk class to the Python environment 
from Autodesk.Revit.DB import * #import every class of the main section of the Revit API to the Python environment
### trade specific Revit imports ###
from Autodesk.Revit.DB.Analysis import * #import every class of the Analysis API to the Dynamo environment


########################################
########### code begins here ###########
########################################
### global variables ###
doc = DocumentManager.Instance.CurrentDBDocument #the current Revit document
geoOpts = Options() #build a geometry options object
analyzerOpts = BuildingEnvelopeAnalyzerOptions() #build a building envelope analyzer options object
analyzerOpts.OptimizeGridCellSize = True #ensure we're using the optimal grid cell size so we're not over/under estimating envelope object
#analyzerOpts.GridCellSize = 3 #alternatively you can set this yourself by uncommenting this line and commenting the previous one
analyzerOpts.AnalyzeEnclosedSpaceVolumes = True #ensure we're analyizing everything
boundingElementsInDoc = [] #an empty list to hold the bounding elements
sldList = [] #an empty list to hold the solids
filter = ElementIsElementTypeFilter(True) #a filter to ensure we don't catch element types

### build the envelope analysis ###
envelopeAnalyzer = BuildingEnvelopeAnalyzer.Create(doc,analyzerOpts) #create the building envelope analysis
boundingElems = envelopeAnalyzer.GetBoundingElements() #get the bounding elements from the building envelope - those which make up the enclosure

### iterate over the bounding elements to get the solids ###
for e in boundingElems: #for every element in the bounding elements list
    linkId = e.LinkInstanceId #get the link element id
    if linkId == ElementId.InvalidElementId: #if the link element id was an invalid element id perform the offset lines below
        elem = doc.GetElement(e.HostElementId) #get the element from the id
        depends = [doc.GetElement(i) for i in elem.GetDependentElements(filter)] #get the dependant elements
        for elem in depends: #for every element in the dependent elements
            if elem not in boundingElementsInDoc: #if we haven't arleady processed the element perform the offset lines below
                boundingElementsInDoc.append(elem) #append the element to the list of elements
                eId = elem.Id.IntegerValue #get the element ID as an integer
                dynElem = Revit.Elements.ElementSelector.ByElementId(eId) #get the Dynamo for Revit reference to the element
                [sldList.append(sld) for sld in dynElem.Solids] #append the solids from the element to the solids list

### manipulate the solids to get a single solid element ###
sld = DG.Solid.ByUnion(sldList) #union the solids list into a single solid
bb = DG.BoundingBox.ByGeometry(sld) #get the bounding box of the solids
min = bb.MinPoint.Translate(-1000,-1000,-1000) #get the min point of the bounding box and move it out 1000 units
max = bb.MaxPoint.Translate(1000,1000,1000) #get the max point of the bounding box and move it out 1000 units
bb = DG.BoundingBox.ByCorners(min,max).ToCuboid() #build a new bounding box from the expanded min and max point and convert to a cuboid
voidSold = DG.Solid.Difference(bb,sld) #remove the building solid from the void
voids = [i for i in voidSold.Separate() if not i.DoesIntersect(min)] #separate the void geometry and remove the exterior void
slds = [sld] #generate a list of solids containing the building envelope solid
[slds.append(i) for i in voids] #append the void solids to the solids list
sld = DG.Solid.ByUnion(slds) #union the solids into a single solid representing the envelope, fenestration, and void space



########################################
##### Format and return the result #####
########################################
OUT = sld #return the solid to the Dynamo environment
3 Likes

Hi Jacob,

I was intruiged to see if this would work so i opened the sample Architectural model for Revit 2023, deleted some site objects and then ran your code but encountered the following error;

image
image

One of the elements which was found doesn’t have geometry. Perhaps a curtain wall? Changing the line which appends solids to the list to something like this should help, but it may suppress other warnings.

[sldList.append(sld) for sld in dynElem.Solids if sld != None] #append the solids from the element to the solids list

If that doesn’t work you’ll have to pull the solids first with a try statement or other tool, and then append the data to the list.

Don’t have the time to dig into this now as my previous effort was relevant to my work for a customer (single family homes, no curtain walls so I didn’t check those), but if someone wants to pick it up or ask again later feel free. :slight_smile: