Apr 3, 2024

Create 3D BoundingBox by using DirectShape

Learn how to create a DirectShpae from element's BoundingBox to better understand the geometry when you need it.

How To Visualize a BoundingBox with Revit API?

If you start using BoundingBox, and something doesn't add up, then it's a good point to visualize your bounding box to better understand the issue. If you use Dynamo then you can simply get a preview in the Dynamo Viewer.

However, if you use pyRevit, then it gets a bit tricky. However, there is a way out by converting bounding box into a solid geometry. And for that we need to use DirectShape class from Revit API, so we can create this solid in the project.

To do that we need to do the following steps:

Let's look how to make it happen

Get BoundingBox

For this example, I will just get my current selection from Revit's UI. But please adjust it to your own needs.

Here is how to get selected elements and retrieve their BoundingBox.

#⬇️ IMPORTS
from Autodesk.Revit.DB import *

#Import .NET List
import clr
clr.AddReference('System')
from System.Collections.Generic import List


#📦 VARIABLES
uidoc = __revit__.ActiveUIDocument
doc   = __revit__.ActiveUIDocument.Document

# Get Selected Elements
selected_elems = [doc.GetElement(elId) for elId in uidoc.Selection.GetElementIds()]

# Get BoundingBoxes
for elem in selected_elems:
    bbox = elem.get_BoundingBox(None)

Create Solid from BoundingBox

Now we need to convert BoundingBox to a Solid object, so we can construct a DirectShape .

Since BoundingBoxes are simple boxes, we can use CreateExtrusionGeometry method to create it. We just need to create an outline by using its Min and Max points.

Here is function that can do that for you:

def solidBoundingBox(elem):
    bbox = elem.get_BoundingBox(None)

    # Lower Corner Points from BoundingBox
    pt0 = XYZ(bbox.Min.X, bbox.Min.Y, bbox.Min.Z)
    pt1 = XYZ(bbox.Max.X, bbox.Min.Y, bbox.Min.Z)
    pt2 = XYZ(bbox.Max.X, bbox.Max.Y, bbox.Min.Z)
    pt3 = XYZ(bbox.Min.X, bbox.Max.Y, bbox.Min.Z)
    
    # Create Edges of the BoundingBox
    edge0 = Line.CreateBound(pt0, pt1)
    edge1 = Line.CreateBound(pt1, pt2)
    edge2 = Line.CreateBound(pt2, pt3)
    edge3 = Line.CreateBound(pt3, pt0)
    
    # Create CurveLoop from Edges
    edges  = [edge0, edge1, edge2, edge3]
    baseLoop = CurveLoop.Create(edges)
    loopList = [baseLoop]

  
    # Create Solid
    height = bbox.Max.Z - bbox.Min.Z
    preTransformBox = GeometryCreationUtilities.CreateExtrusionGeometry(loopList, XYZ.BasisZ, height)

    # Make sure BoundingBox has the same Transform 
    transformBox = SolidUtils.CreateTransformed(preTransformBox, bbox.Transform)

    return transformBox

Create Direct Shape

Now, once you have your Solid geometry it's very easy to create a direct shape.

Here is the code snippet:

#🔓 Start a transaction
t = Transaction(doc, 'Create DirectShape from BoundingBox')
t.Start()

for el in selection:
    # Convert Element's BoundingBox to Solid
  
    solid = solidBoundingBox(el)

    # Create a DirectShape
    ds = DirectShape.CreateElement(doc, ElementId(BuiltInCategory.OST_GenericModel))
    ds.SetShape([solid])
    
t.Commit()


Final Snippet

Here is the whole code put together so there are no misunderstandings. You can even use Revit Python Shell to test it.



#⬇️ IMPORTS
from Autodesk.Revit.DB import *

#Import .NET List
import clr
clr.AddReference('System')
from System.Collections.Generic import List


#📦 VARIABLES
uidoc = __revit__.ActiveUIDocument
doc   = __revit__.ActiveUIDocument.Document

#👉 Get Selected Elements
selected_elems = [doc.GetElement(elId) for elId in uidoc.Selection.GetElementIds()]

#🔓 Start a transaction
t = Transaction(doc, 'Create DirectShape from BoundingBox')
t.Start()
def solidBoundingBox(elem):
    bbox = elem.get_BoundingBox(None)

    # Lower Corner Points from BoundingBox
    pt0 = XYZ(bbox.Min.X, bbox.Min.Y, bbox.Min.Z)
    pt1 = XYZ(bbox.Max.X, bbox.Min.Y, bbox.Min.Z)
    pt2 = XYZ(bbox.Max.X, bbox.Max.Y, bbox.Min.Z)
    pt3 = XYZ(bbox.Min.X, bbox.Max.Y, bbox.Min.Z)
    
    # Create Edges of the BoundingBox
    edge0 = Line.CreateBound(pt0, pt1)
    edge1 = Line.CreateBound(pt1, pt2)
    edge2 = Line.CreateBound(pt2, pt3)
    edge3 = Line.CreateBound(pt3, pt0)
    
    # Create CurveLoop from Edges
    edges  = [edge0, edge1, edge2, edge3]
    baseLoop = CurveLoop.Create(edges)
    loopList = [baseLoop]

  
    # Create Solid
    height = bbox.Max.Z - bbox.Min.Z
    preTransformBox = GeometryCreationUtilities.CreateExtrusionGeometry(loopList, XYZ.BasisZ, height)

    # Make sure BoundingBox has the same Transform 
    transformBox = SolidUtils.CreateTransformed(preTransformBox, bbox.Transform)

    return transformBox


for el in selection:
    solid = solidBoundingBox(el)
    
    # Create a DirectShape
    ds = DirectShape.CreateElement(doc, ElementId(BuiltInCategory.OST_GenericModel))
    ds.SetShape([solid])
    
t.Commit()

Join Newsletter

📩 You will be added to Revit API Newsletter

Join Us!

which is already read by 7400+ people!

Ready to become Revit Hero for your office? Learn Revit API!

Join this comprehensive course that will guide you step by step on how to create your dream tools for Revit that save time.