Showing results for 
Search instead for 
Did you mean: 

Compute Model Bounds for some objects not all objects


Is there an NXOpen command that does the same thing as:


but allows me to specify the objects to consider, rather than returning a bounding box that is large enough for all displayable objects? 

There is a function for adjusting the scale on a view taking particular objects into account, that is called:


but the resulting view extents calculated are dependent on the aspect ratio of the window being displayed. 

What I'm trying to do is keep PMI annotations away from the area required to display the model, and I have working functions that convert the bounding box in Model Space to the corners of a rectangular frame in view space.  But I found that once I add any PMI, it gets included in the results of the bounding box!  I want to be able to re-calculate the required PMI keep-out zone whenever the model changes, so I can't just get numbers once and trust them forever. 

I already created a working function to get the objectsToConsider, which for my purposes is all solid bodies and all components in the work part.  If there was a way to apply that as a filter to ComputeModelBounds, that would be perfect.


Re: Compute Model Bounds for some objects not all objects

Gears Esteemed Contributor Gears Esteemed Contributor
Gears Esteemed Contributor

The .AskBoundingBox (.AskBoundingBoxAligned, .AskBoundingBoxExact) method will compute the bounding box of a given object.

Re: Compute Model Bounds for some objects not all objects


That should work, thanks!  It looks like this (NXOpen.UF.ModlGeneral.AskBoundingBox) only works on one object at a time - so I would need to iterate over all of the objects to consider.  And of course it doesn't report the values in the same order as the (NXOpen.UF.Disp.ComputeModelBounds) results, that would be too convenient.

Re: Compute Model Bounds for some objects not all objects




        'calc bounding box
        Dim llc() As Double = {5000000, 5000000, 5000000}
        Dim urc() As Double = {-5000000, -5000000, -5000000}
        CalculateBox(lstFacetedBodiesInPart.ToArray, llc, urc, False) 'calc total box of filteredobjects objects (filtered by checkobjecttype function)
Sub CalculateBox(ByRef objs() As DisplayableObject, ByRef llc() As Double, ByRef urc() As Double, blnShowComponentBoxes As Boolean)

        Dim minmax(5) As Double
        'loop through all filtered objects
        For Each obj As DisplayableObject In objs

                ufs.Modl.AskBoundingBox(obj.Tag, minmax)

                For ii As Integer = 0 To 2
                    If minmax(ii) < llc(ii) Then llc(ii) = minmax(ii)
                For ii As Integer = 0 To 2
                    If minmax(ii + 3) > urc(ii) Then urc(ii) = minmax(ii + 3)

                ' show each assembly level body bounding box
                If blnShowComponentBoxes Then
                    Dim tlc() As Double = {minmax(0), minmax(1), minmax(2)}
                    Dim trc() As Double = {minmax(3), minmax(4), minmax(5)}
                    DrawBox(tlc, trc, , 36) ' 36 = Green
                    'EchoBoundingBoxValues(tlc, trc, obj)
                End If

            Catch ex As NXException
                EchoError(ex, "Can not calculate Bounding Box from : " & obj.JournalIdentifier, 0)
            End Try
            'End If

    End Sub
Frederik Verscheure
Evolve Consulting bvba
Freelance NX & Teamcenter consultant

Re: Compute Model Bounds for some objects not all objects


Here's what I wrote yesterday in Python.  It does the rotation into View Space before checking if the bounding box grows the boundaries.  That way it doesn't need to keep track of Z at all, which is always 0 in View Space.  It is neat to see the similarities between our approaches:

def matrixProduct3B3x3B1(list3B3, list3B1):
    x, y, z = list3B1
    a, b, c, p, q, r, u, v, w = list3B3    
    i = a*x + b*y + c*z
    j = p*x + q*y + r*z
    k = u*x + v*y + w*z
    resultList3B1 = [i, j, k]

People might wonder why I wrote the matrix multiplication function above - basically I need to keep the scripts to bare Python 3.3.2 so that they can be run by anone with NX10 installed.  I only need this one type of matrix multiplication, so this was the easiest way to get it done.


def findExtentsOfViewsMBD0MBD2(self):
    noIssuesFlag = True
    minXMBD0 = 100000.0
    maxXMBD0 = -100000.0
    minYMBD0 = 100000.0
    maxYMBD0 = -100000.0
    minXMBD2 = 100000.0
    maxXMBD2 = -100000.0
    minYMBD2 = 100000.0
    maxYMBD2 = -100000.0
    viewMBD0 = self.theWorkPart.Views.FindObject('MBD0')
    viewMBD2 = self.theWorkPart.Views.FindObject('MBD2')
    rotMatrixMBD0 = [viewMBD0.Matrix.Xx, viewMBD0.Matrix.Xy,
                     viewMBD0.Matrix.Yx, viewMBD0.Matrix.Yy,
                     viewMBD0.Matrix.Zx, viewMBD0.Matrix.Zy,
    rotMatrixMBD2 = [viewMBD2.Matrix.Xx, viewMBD2.Matrix.Xy,
                     viewMBD2.Matrix.Yx, viewMBD2.Matrix.Yy,
                     viewMBD2.Matrix.Zx, viewMBD2.Matrix.Zy,
    solidsAndComponentsToFit = []
    for eachBody in self.allSolidBodies:
    for eachItem in solidsAndComponentsToFit:
            thisBB = self.theUFSession.ModlGeneral.AskBoundingBox(eachItem.Tag)
            noIssuesFlag = False
        negX, negY, negZ, posX, posY, posZ = thisBB
        cornerVertsModelSpace = [[negX, negY, negZ],
                                 [posX, negY, negZ],
                                 [negX, posY, negZ],
                                 [posX, posY, negZ],
                                 [negX, negY, posZ],
                                 [posX, negY, posZ],
                                 [negX, posY, posZ],
                                 [posX, posY, posZ]]        
        for oneCorner in cornerVertsModelSpace:
            X0, Y0, Z0 = matrixProduct3B3x3B1(rotMatrixMBD0, oneCorner)
            X2, Y2, Z2 = matrixProduct3B3x3B1(rotMatrixMBD2, oneCorner)
            if X0 < minXMBD0: minXMBD0 = X0
            if X0 > maxXMBD0: maxXMBD0 = X0
            if Y0 < minYMBD0: minYMBD0 = Y0
            if Y0 > maxYMBD0: maxYMBD0 = Y0
            if X2 < minXMBD2: minXMBD2 = X2
            if X2 > maxXMBD2: maxXMBD2 = X2
            if Y2 < minYMBD2: minYMBD2 = Y2
            if Y2 > maxYMBD2: maxYMBD2 = Y2
    minXMBD0 = (math.floor(minXMBD0*100))/100
    maxXMBD0 = (math.ceil(maxXMBD0*100))/100
    minYMBD0 = (math.floor(minYMBD0*100))/100
    maxYMBD0 = (math.ceil(maxYMBD0*100))/100
    minXMBD2 = (math.floor(minXMBD2*100))/100
    maxXMBD2 = (math.ceil(maxXMBD2*100))/100
    minYMBD2 = (math.floor(minYMBD2*100))/100
    maxYMBD2 = (math.ceil(maxYMBD2*100))/100
    extentsMBD0 = [minXMBD0, maxXMBD0, minYMBD0, maxYMBD0]
    extentsMBD2 = [minXMBD2, maxXMBD2, minYMBD2, maxYMBD2]
    return(extentsMBD0, extentsMBD2, noIssuesFlag)

 Much of the end of the function is to round the dimensions to the nearest appropriate hundreth of an inch.  I needed to make sure that the left extent went more left and the right extent went more right, same with top and bottom.

Re: Compute Model Bounds for some objects not all objects

Gears Esteemed Contributor Gears Esteemed Contributor
Gears Esteemed Contributor

FWIW, the NXOpen API provides some matrix functions, including vector/matrix multiplication.

Re: Compute Model Bounds for some objects not all objects


This seems to only offer vector*matrix, and I think the rotation matrix needs to be applied as matrix*vector to get the correct (expected) answer?  There is an option to transpose the matrix during multiplication, and I guess I could transpose the vector before multiplication and then transpose the result afterwards.  But at that point I've written an extra function anyway to do those gyrations...


Unless I'm missing something built in to another module again?