#7558·Open3D

geometry::OrientedBoundingBox::Transform() always throws, even for a rigid transform

Author: simonschlaepferCreated Sep 10, 2026Updated Sep 10, 2026

Checklist

  • I have searched for similar issues. The closest one is #4875, which reports the same limitation as a question and is still open.
  • For Python issues, I have tested with the latest development wheel. That page currently lists no wheel links, so I reproduced with 0.19.0 from PyPI and confirmed the code path is unchanged on main at 1a9eb990f9, see the permalink below.
  • I have checked the release documentation and the latest documentation (for main branch).

Describe the issue

geometry::OrientedBoundingBox::Transform() always raises, even for a plain rigid transform:

https://github.com/isl-org/Open3D/blob/1a9eb990f9a20936c30c428568c602bdef760744/cpp/open3d/geometry/BoundingVolume.cpp#L154-L160

An oriented bounding box is stored as a center, a rotation matrix and an extent, so it is closed under any similarity transform (rotation, uniform scale, translation): only the center and the rotation move, and the extent scales. That is exactly the case that matters in practice, where a box is carried between coordinate frames next to the point cloud it bounds:

cpp
cloud.Transform(target_T_source);
box.Transform(target_T_source);  // throws

Three things make the current behavior surprising:

  1. Every other Geometry3D accepts Transform(), so a box cannot be moved through generic code that transforms a geometry.
  2. The tensor API already implements it, as Rotate() followed by Translate(), so the legacy and tensor APIs disagree on the same operation: https://github.com/isl-org/Open3D/blob/1a9eb990f9a20936c30c428568c602bdef760744/cpp/open3d/t/geometry/BoundingVolume.cpp#L464-L478
  3. The suggested workaround ("Call Translate, Scale, and Rotate") is easy to get wrong, because Rotate(R) rotates about the box center by default while Transform() rotates about the origin. #4875 is exactly that mistake, and the usual fix people land on is to rebuild the box by hand:
    cpp
    OrientedBoundingBox transformed(transform * box.center_,
                                    transform.rotation() * box.R_, box.extent_);

geometry::OrientedBoundingEllipsoid::Transform() on main has the same body and the same limitation.

A general affine transform genuinely cannot be supported, since shear or non-uniform scale turns the box into a parallelepiped and the ellipsoid into a general quadric. Those cases should keep raising. The similarity case should not.

Steps to reproduce the bug

python
import numpy as np
import open3d as o3d

box = o3d.geometry.OrientedBoundingBox([1, 2, 3], np.eye(3), [2, 4, 6])

transformation = np.eye(4)
transformation[:3, 3] = [1, 0, 0]  # translate by 1 along x

box.transform(transformation)

Error message

Traceback (most recent call last):
  File "<string>", line 5, in <module>
RuntimeError: [Open3D Error] (virtual open3d::geometry::OrientedBoundingBox& open3d::geometry::OrientedBoundingBox::Transform(const Matrix4d&)) /root/Open3D/cpp/open3d/geometry/BoundingVolume.cpp:58: A general transform of an OrientedBoundingBox is not implemented. Call Translate, Scale, and Rotate.

Expected behavior

A similarity transform is applied to the box: center_ is mapped by the transform, R_ is premultiplied by its rotation part and extent_ is multiplied by its uniform scale. The corners of the result are then the transformed corners of the original box, which is what transforming a point cloud of those corners with the same matrix gives.

A transform with shear, non-uniform scale, mirroring or a projective part keeps raising, with a message that names which part is not supported.

Open3D, Python and System information

markdown
- Operating system: Ubuntu 24.04 64-bit
- Python version: 3.12.3
- Open3D version: 0.19.0, and the source of `main` at 1a9eb990f9a20936c30c428568c602bdef760744
- System architecture: x86_64
- Is this a remote workstation?: no
- How did you install Open3D?: pip, and separately built from source for the C++ side
- Compiler version (if built from source): gcc 13.3

Additional information

I have a fix ready and will open a PR that implements Transform() for similarity transforms on both OrientedBoundingBox and OrientedBoundingEllipsoid, reusing the existing Rotate(), Scale() and Translate() primitives, with C++ and Python unit tests for the supported and the rejected cases.