getOBB Function

Hi,

I’m attempting to get the OBB for a set of parts, but I’m not getting expected values from using getOBB.

I’ve tried this with more parts, but as an example if I use it on a single part located at the translation point: 11283.1,-1297.43,2225.06

I get this return:
pxz.geom.OBB(pxz.geom.Point3(22556.07639095168, 4418.216988201847, 2558.437568865675), pxz.geom.Point3(3.663600502432114, -18.692777221409962, 47.057729049575684), pxz.geom.Point3(9.040980636295075, -0.7059574012008597, -0.9842983621514242), pxz.geom.Point3(10.087270977685899, 83.84314311238376, 32.519747459729196))

The object is listed in documentation as returning a corner and the 3 axis. The axis look essentially correct to me as it is a relatively small part, but shouldn’t the corner be near the part’s translation?

I run this prior to getting the OBB to correct for scaling issues between parts (I think):

scene.resetTransform(1, True, False, False)
for occurrence in scene.getPartOccurrences():
	scene.movePivotPointToOccurrenceCenter([occurrence], False)

Is my conception about what I am doing incorrect?

Hello,

Is [11283.1, -1297.43, 2225.06] the translation after running your script?
If so it should indeed correspond to the center of your occurrence bounding box. Having the corner so far off (around 11 or 12m) is weird.

Can you try running this script and check what it returns?

def center(pt1, pt2):
	return geom.Point3((pt1.x + pt2.x)/2, (pt1.y + pt2.y)/2, (pt1.z + pt2.z)/2)

aabb = scene.getAABB([occurrence])
print(center(aabb.low, aabb.high))

That is the translation of the part before and after running the script. All my script does right now is get the OBB.

Here’s the return from your script:
[2024/10/16 13:24:53] executing command scene.getAABB
[2024/10/16 13:24:53] occurrences: [961755]
[2024/10/16 13:24:53] Command execution time : 0.000 s
[2024/10/16 13:24:53] pxz.geom.Point3(11283.1, 2225.06, 1297.4300000000003)

I’m sorry. I just realized that I misunderstood what you meant AND I also made a mistake. I had not yet run that script that resets the pivot points. After running it the translation of that part is actually: [11283.1,2225.06,1297.43]

If I run your script after that I get:
[2024/10/16 13:42:58] executing command scene.getAABB
[2024/10/16 13:42:58] occurrences: [961755]
[2024/10/16 13:42:58] Command execution time : 0.000 s
[2024/10/16 13:42:58] pxz.geom.Point3(11283.1, 2225.06, 1297.4300000000003)

Getting the OBB for that same part after the pivot resets gives:
[2024/10/16 13:45:06] pxz.geom.Point3(22556.034997970815, 4418.220061857224, 2558.440436311508)

The translation you see in the UI is local to its parent (local coordinates).
Because you reset all the occurrences using scene.resetTransform(1, True, ...) and move the pivot point to the occurrence center now it matches the global translation in world coordinates.

It seems to match the AABB center so that’s good.

But the OBB corner is off. So maybe the part is not that small… Can you print the aabb.high and aabb.low values as well so we can check that?

Can you also share a screenshot of the geometry?

Here’s a slight modification of your script:

def center(pt1, pt2):
	return geom.Point3((pt1.x + pt2.x)/2, (pt1.y + pt2.y)/2, (pt1.z + pt2.z)/2)

aabb = scene.getAABB([961759])
obb = scene.getOBB([961759])
print(center(aabb.low, aabb.high))
print(obb)

This returns:
[2024/10/16 14:18:22] executing command scene.getAABB
[2024/10/16 14:18:22] occurrences: [961755]

[2024/10/16 14:18:22] Command execution time : 0.000 s
[2024/10/16 14:18:22]
[2024/10/16 14:18:22] executing command scene.getOBB
[2024/10/16 14:18:22] occurrences: [961755]
[2024/10/16 14:18:22] Command execution time : 0.008 s

[2024/10/16 14:18:22] pxz.geom.Point3(11283.141392980864, 2225.056926344623, 1297.4271325541663)
[2024/10/16 14:18:22] pxz.geom.OBB(pxz.geom.Point3(22556.07639095168, 4418.216988201847, 2558.437568865675), pxz.geom.Point3(3.663600502432114, -18.692777221409962, 47.057729049575684), pxz.geom.Point3(9.040980636295075, -0.7059574012008597, -0.9842983621514242), pxz.geom.Point3(10.087270977685899, 83.84314311238376, 32.519747459729196))

Unfortunately I can’t share a screenshot of the geometry, but here is the translation data. There is an occurrence component attached to the part as well so not sure if that might be affecting anything…

Could you print aabb.low and aabb.high as well (you only printed the center between these two points)? I’d like to check something.

Another way to debug visually the obb is to use the algo.replaceByBox function with an obb box type.

Also, why do you need the obb in the first place? Maybe we can find another way to achieve what you want to do.

Here is low then high:
[2024/10/16 17:45:02] pxz.geom.Point3(11277.680015463042, 2182.289130854579, 1267.5261161890528)
[2024/10/16 17:45:02] pxz.geom.Point3(11288.602770498686, 2267.8247218346673, 1327.32814891928)

I need to find a series of parts within the OBB. I tried with AABB first, but that was grabbing more parts then I wanted.

Ok I reproduced the issue. I think it is caused by the transforms on the Part components.

Can you try applying a scene.resetPartTransform after your scene.resetTransform? It will remove the Part components transforms.

I actually have to run that for each part after moving the pivot point but it seems to have fixed the problem!

scene.resetTransform(1, True, False, False)
for occurrence in scene.getPartOccurrences():
	scene.movePivotPointToOccurrenceCenter([occurrence], False)
	scene.resetPartTransform(occurrence)

Now that I have that I actually do want to create a box representing the OBB on the screen. I’m doing this right now:

cubeOccurrence = scene.createCube(obbWidth, obbHeight, obbDepth, 1, True)
scene.setParent(cubeOccurrence, scene.getRoot())

That creates a box at the origin. Is there a function that can move the transform of that cube to a new position?

You can manipulate the local matrix (Translation, Rotation, Scale) with this function: scene.setLocalMatrix(occurrence, matrix) Class Scene

To build such matrix, you can use: geom.fromTRS(T, R, S) → geom.Matrix4 Class Geom

I tried this:

cubeOccurrence = scene.createCube(obbWidth, obbHeight, obbDepth, 1, True)
scene.setParent(cubeOccurrence, scene.getRoot())
cubeTranslation = pxz.geom.Point3(obbCenter.x,obbCenter.y,obbCenter.z)
cubeRotation = pxz.geom.Point3(0,0,0)
cubeScale = pxz.geom.Point3(1,1,1)
cubeTranslation = pxz.geom.Point3(obbCenter.x,obbCenter.y,obbCenter.z)
cubeMatrix = pxz.geom.fromTRS(cubeTranslation, cubeRotation, cubeScale)
geom.applyTransform(cubeOccurrence,cubeMatrix)

However, I get this error:
[2024/10/17 11:26:15] Traceback (most recent call last):
[2024/10/17 11:26:15] File “”, line 17, in
[2024/10/17 11:26:15] pxz.geom.Error: Matrix Transformation for this type of entity (Occurrence) is not supported yet

I was mistakenly using geom.applyTransform which isn’t even a function. Scene.applyTransformation correctly sets the position.

scene.setLocalMatrix would be more appropriate here.

scene.applyTransformation applies the translation/rotation/scale to the current occurrence translation/rotation/scale and works in your case because the current occurrence transform is set to identity (centered on origin, with no rotation and a unit scale).

Coming back to this topic, can you describe what exactly the return of the getOBB function is? The OBB type is listed as containing a point3 of corner and three vector3’s of xAxis, yAxis, and zAxis. The way I have been thinking about this would be that the corner is the corner of the box with the lowest x, y, z values and each vector is normal to the surface of each side of the box and ends on the plane that makes that side. Is that a correct way to interpret that?

Corner is the corner of the box with the lowest x, y, z

Yes.
xAxis, yAxis, zAxis are vectors going from this point to 3 other corners of the box. You can deduce the 8 corners from them.