Easy definition bounding box in RhinoCommon?

In RhinoCommon is there an easy way to get the bounding box of an InstanceDefinition whose content I can’t know beforehand ?

my guess - you have to iterate over all objects of the definition and union the boundingboxes

InstanceDefinition.GetObjects Method

BoundingBox.Union Method

Thanks Tom, I was thinking about a more “out-of-the-box” way but I will make my own recursive function.

I was digging in the API and did not find anything suitable.
maybe i arm wrong.
@dale should know better.

Hi @felix.mariotto,

There is no “out of the box” way of getting this. Why do you need it?

– Dale

Hi @dale !

I’m making a small plugin to make quick pave settings on jewelry models.

I made a nice custom conduit which for each instanceObject with a certain flag in userDictionary will draw a circle and a text label with the size of the stone over the instance :

Since the instance definition is available to the user, they could put anything inside or transform the content however they want (which is good I think), therefore I need to know the top Z position in the definition to know where to draw the text label. So far I just check the bbox of the first geometry, which is not ideal :

def getDefinitionZLimit() :
    
    definition = getDef()
    
    firstObject = definition.GetObjects()[0]
    
    if isinstance( firstObject, Rhino.DocObjects.BrepObject ) :
        
        brepGeom = firstObject.BrepGeometry
        
        bbox = brepGeom.GetBoundingBox( False )
        
        return bbox.Max.Z
    
    return 0

I’m quite new to RhinoCommon API so I’m struggling a bit.
It seems GeometryBase.GetBoundingBox is the only function to get a bounding box of anything ?

Does this do what you want?

import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino

def BlockDefinitionBoundingBox():
    blk_names=rs.BlockNames()
    if not blk_names: return
    
    blk_name=rs.ListBox(blk_names)
    if not blk_name: return
    
    blk_def=sc.doc.InstanceDefinitions.Find(blk_name)
    rhobjs=blk_def.GetObjects()
    #create 'empty' bounding box
    bbox=Rhino.Geometry.BoundingBox()
    for rhobj in rhobjs:
        #get each object's geometry and bounding box
        obj_bb=rhobj.Geometry.GetBoundingBox(True)
        #union with current bb (bbox)
        bbox.Union(obj_bb)
    sc.doc.Objects.AddBox(Rhino.Geometry.Box(bbox))
    sc.doc.Views.Redraw()
    
BlockDefinitionBoundingBox()

Note this gets the bounding box of the original block DEFINITION, not of any of its INSTANCES that might be in the document… There actually don’t need to be any instances in the file, just the definition. If you want an instance bounding box, that’s a different story.

Here is a quickie scriptlet that gets an instance geometry bounding box:

import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino

def GetBlockInstanceBB():
    msg="Select block instance for bounding box"
    blk_inst=rs.GetObject(msg,4096,preselect=True)
    if not blk_inst: return
    geo=rs.coercegeometry(blk_inst)  #InstanceReferenceGeometry
    bbox=geo.GetBoundingBox(True)
    if bbox.IsValid:
        sc.doc.Objects.AddBox(Rhino.Geometry.Box(bbox))
        sc.doc.Views.Redraw()
GetBlockInstanceBB()
1 Like

Hi Mitch, thank you for taking the time to answer.

My goal is indeed to get the bounding box of an object definition that may contain an object instance (of a definition that may itself contain an instance, etc… ).

I didn’t know the class InstanceReferenceGeometry, so I didn’t realize I could just use GetBoundingBox on an instance. I thought I had to write a recursive function that calls itself again everytime it encounters an instance object, while computing a local transformation matrix for the geometry contained within that instance, etc…

Much simpler like that, there is an out-of-the-box solution after all, thanks again !