Get Walls inside BoundingBox (Python)

Hello Dynamo Community :slight_smile:

I want to get all Elements inside a boundingbox, found some code here but have a hard time getting it to run.

I changed that code because it was made for working with a (active) view, but i want all walls in the model.
So if i use a boundingbox from element.boundingbox the python code will run but with no result.
If i build a boundingbox myselfe it wont even run because “input can´t be null”. Why is there adifference between those boundingboxes?

So I´m stuk and need some help. And can someone give me a good method to show my boundingbox in the dynamo 3d view?

here`s my code:

import clr
clr.AddReference('RevitAPI')
clr.AddReference('RevitNodes')
clr.AddReference('RevitServices')
import Revit
import RevitServices
from Autodesk.Revit.DB import *
from RevitServices.Persistence import DocumentManager
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)
doc = DocumentManager.Instance.CurrentDBDocument

#Preparing input from dynamo to revit
bb = IN[0].ToRevitType()
outline = Outline(bb.Min, bb.Max)
#filter = BoundingBoxIntersectsFilter(outline)
filter = BoundingBoxIsInsideFilter(outline)

collector = FilteredElementCollector(doc).WherePasses(filter)
collector.OfCategory(BuiltInCategory.OST_Walls).WhereElementIsNotElementType();

OUT = [e.ToDSType(True) for e in collector]

Appreciate any advice :slight_smile:

Ok, there was a mistake with my coordinates, the code works fine with an element.boundingbox:

But how to get it to work with a “self created” boundingbox ? :thinking:

still that strange error:

How are you creating the bounding box?

Should be something like:

bb = BoundingBoxXYZ() #makes a new BB with no dimension
bb.Min = XYZ(-10,-10,-10) #sets the BB’s min property to a new XYZ at -10,-10,-10
bb.Max = XYZ(10,10,10) #sets the BB’s max property to a new XYZ at 10,10,10

Hello Jacob,

I use the BoundingBox.byCorners node. The BB then is the input for the python code.

Hi,

I think this can help you:

When you use a dynamo node you need to convert the dynamo bbox to a revit bbox

2 Likes

hey jw,

I´m doing that with “bb = IN[0].ToRevitType()”
While it works for element.bb it doesn´t for bb.bycorners

I never had any issues with boundingboxes, since when are they so comnplicated? :smiley:
Will try your python method for sure

1 Like

In the link I send before you can build a box by points :slight_smile:

1 Like

it works with the XYZ method:

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

bb = BoundingBoxXYZ()
bb.Min = XYZ(-10,-10,-10)
bb.Max = XYZ(10,10,10)

OUT =  bb

All woking now :slight_smile: Thanks for all the help!

Hello

import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *


bb=[]
minpt=Point.ByCoordinates(-10,-10,-10)
maxpt=Point.ByCoordinates(10,10,10)
bb=BoundingBox.ByCorners(minpt, maxpt)

OUT = bb

cordially
christian.stan

1 Like

Ah - misinterpreted your question. Assuming no code changes in the Python node, the issue you are running into has to do with some additional parameters which are associated to bounding boxes when they are created by certain means. In particular the ContextCoordinateSystem.

This is about to get a bit technical, so hold onto your hat.

In the context of Dynamo, bounding boxes are always aligned to the global coordinate system, so the Z axis of any bounding box is aligned to the global Z, the X axis of a Bounding box is aligned to the global X, and the Y to the Y.

This is not the case in Revit, as bounding boxes can have a rotational transform applied to them. Revit utilizes that additional property to allow for creating the view extents for things like section views while keeping a simple 6 digits for defining the limits. Because of this a long while back the Dynamo team added a transform coordinate system property onto bounding box objects; these couldn’t interact with Dynamo geometry elements, but allowed for creation of bounding boxes for use in creation of sections and such. They also set up the bulk of the bounding box creation and query methods to ensure that the coordinate system was applied to the object’s ContextCoordianteSystem property, which is read only at this time.

Sadly, BoundingBox.ByCorners appears to have been missed, so no matter how it’s created (Python, DesignScript, or Nodes) we get a resulting object which cannot be converted to a Revit BoundingBoxXYZ object as the ContextCoordinateSystem property is null.

Fortunately there is a fix (besides the rebuilding of bounding boxes by the method which was noted above). While there isn’t a node, the method BoundingBox.ByCornersCoordinateSystem(Point, Point, CoordinateSystem) can be called via DesignScript or Python. As such we can check if a BB has a context coordinate system value, and if not regenerate the boundingbox with the property added.

That code might look something like this:

# Load DesignScript Library and the BoundingBox class using the bndBox alias
import sys, traceback, clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
from Autodesk.DesignScript.Geometry import BoundingBox as bndBox

# Load the Revit API including geometry and element conversion extensions
clr.AddReference('RevitAPI')
clr.AddReference('RevitNodes')
clr.AddReference('RevitServices')
import Revit
import RevitServices
from Autodesk.Revit.DB import *
from RevitServices.Persistence import DocumentManager
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)
doc = DocumentManager.Instance.CurrentDBDocument

#inputs and static variables
dsBBs = IN[0] 
rvtBBs = []
cs = CoordinateSystem.Identity() 
collections = []

for bb in dsBBs: #loops over the bounding boxes from the Dynamo environment
	try: #attempt to convert the DesignScript BB object to a Revit BB object
		rvtBBs.append(bb.ToRevitType()) #append the BB converted BB to the list of Revit bounding boxes
	except:
		b = bndBox.ByCornersCoordinateSystem(bb.MinPoint,bb.MaxPoint, cs) #recreate the DesignScript BB object with a CoordiatneSystem property value
		rvtBBs.append(b.ToRevitType()) #append the converted BB to the list of Revit bounding boxes

for bb in rvtBBs: #loops over the converted bounding boxes
	outline = Outline(bb.Min, bb.Max)
	#filter = BoundingBoxIntersectsFilter(outline)
	filter = BoundingBoxIsInsideFilter(outline)
	collector = FilteredElementCollector(doc).WherePasses(filter).OfCategory(BuiltInCategory.OST_Walls).WhereElementIsNotElementType().ToElements() #by using one line you can use the ToElements() method to remove the additional list iteration; this will likely be faster in most cases
	collections.append(collector)

OUT = collections

I have brought this to the attention of the development team, and they hope to issue a fix (along with some other updates to BoundingBox objects) in a future release.

3 Likes

Got the code also working for list input.

import clr
clr.AddReference('RevitAPI')
clr.AddReference('RevitNodes')
clr.AddReference('RevitServices')
import Revit
import RevitServices
from Autodesk.Revit.DB import *
from RevitServices.Persistence import DocumentManager
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)
doc = DocumentManager.Instance.CurrentDBDocument

#Preparing input from dynamo to revit
bbList = IN[0]
outlistlist = []

for bb in bbList:
	revbox=bb.ToRevitType()	
	outline = Outline(revbox.Min, revbox.Max)
	filter = BoundingBoxIntersectsFilter(outline)
	collector = FilteredElementCollector(doc).WherePasses(filter)
	collector.OfCategory(BuiltInCategory.OST_Walls).WhereElementIsNotElementType();
	outlist = []
	for e in collector:
		prototype = e.ToDSType(True) 
		outlist.append(prototype)
	outlistlist.append(outlist)
OUT = outlistlist

@jacob.small : Thanks for the explanaition!

2 Likes