Skip to content

Adding Minimum Bounding Sphere functionality#7511

Open
Pemar743 wants to merge 22 commits into
isl-org:mainfrom
Pemar743:MinBoundSphere
Open

Adding Minimum Bounding Sphere functionality#7511
Pemar743 wants to merge 22 commits into
isl-org:mainfrom
Pemar743:MinBoundSphere

Conversation

@Pemar743

Copy link
Copy Markdown

Add Minimum Bounding Sphere support to Open3D

Type

  • Bug fix (non-breaking change which fixes an issue): Fixes #
  • New feature (non-breaking change which adds functionality). Resolves #
  • Breaking change (fix or feature that would cause existing functionality to not work as expected) Resolves #

Motivation and Context

This change introduces support for computing Minimum Bounding Spheres. While Open3D currently supports axis-aligned and oriented bounding volumes, it lacks a native spherical bounding representation.

Recently, support for an Oriented Bounding Ellipsoid was introduced in Open3D (PR #7377), extending the available set of bounding primitives beyond boxes.

Bounding spheres complement these existing and emerging primitives by providing a simple, robust, and computationally efficient bounding volume.

Bounding spheres are useful in many applications, including:

  • Fast spatial queries and collision detection
  • Geometry simplification and approximation
  • Robust bounding representations for noisy or irregular data

This feature adds both approximate and exact methods for computing bounding spheres, giving users flexibility depending on performance and accuracy requirements.

Checklist:

  • I have run python util/check_style.py --apply to apply Open3D code style to my code.
  • This PR changes Open3D behavior or adds new functionality.
    • Both C++ (Doxygen) and Python (Sphinx / Google style) documentation is updated accordingly.
    • I have added or updated C++ and / or Python unit tests OR included test results here.
  • I will follow up and update the code if CI fails.
  • For fork PRs, I have selected Allow edits from maintainers.

Description

This PR adds a complete implementation of Minimum Bounding Sphere (BS) support across both legacy and tensor geometry APIs in Open3D.

Key Features:

  • Implementation of exact bounding sphere computation using Welzl’s algorithm
  • Support for fast and approximate bounding sphere computation using Ritter's method
  • Integration into both legacy API and Tensor:
    • PointCloud
    • TriangleMesh
    • LineSet
  • Both legacy and tensor implementations follow consistent APIs and produce comparable results across geometry types.
  • Exposure through both:
    • C++ API
    • Python bindings (pybind)

API Changes:

  • Added BoundingSphere class:
  • CreateFromPoints methods expose a flag to select between exact (Welzl) and approximate (Ritter) algorithms

Implementation Details:

  • Added kernel implementation in:
    • cpp/open3d/t/geometry/kernel/MinimumBS.*
  • Robustness for edge cases (e.g., coplanar points, degenerate inputs)

Testing:

  • Added unit tests for:
    • General point sets
    • Degenerate configurations (coplanar / minimal cases)
  • Verified correctness and robustness across different geometries

Exact Bounding Sphere

example_exact_Bounding_sphere_Monkey

Approximate Bounding Sphere

example_approx_Bounding_sphere_Armadillo

Exact and Approximate Bounding Sphere

example_approx_and_exact_Bounding_sphere_Bunny

Notes:

  • The implementation is non-breaking and consistent with existing Open3D design patterns
  • CI workflow files were preserved to ensure compatibility with upstream testing

Example usage

import open3d as o3d

mesh_path = o3d.data.MonkeyModel().path
mesh = o3d.io.read_triangle_mesh(mesh_path)
mesh.compute_triangle_normals()
# sphere = mesh.get_bounding_sphere(exact=False)
sphere = mesh.get_bounding_sphere()
print(f"Volume: {sphere.volume()}")
sphere.color = (0, 0.44, 0.77)

sphere_lines = o3d.geometry.LineSet.create_from_bounding_sphere(sphere)
o3d.visualization.draw([mesh, sphere_lines])

Pemar743 added 21 commits June 12, 2026 11:55
…CreateFromBoundnigSphere methods - the user can scale afterwards if scaling wanted
…CreateFromBoundnigSphere methods - the user can scale afterwards if scaling wanted v2
… update documentation and example usage in pybind interface
…pdate related documentation and method signatures
@update-docs

update-docs Bot commented Jun 12, 2026

Copy link
Copy Markdown

Thanks for submitting this pull request! The maintainers of this repository would appreciate if you could update the CHANGELOG.md based on your changes.

@ssheorey

Copy link
Copy Markdown
Member

Hi @Pemar743, how does this add new functionality over the minimum bounding ellipsoid? You can always convert the minimum bounding ellipsoid to a min bounding sphere by just setting all radii the max ellipsoid radius.

@Pemar743

Copy link
Copy Markdown
Author

Hi @ssheorey, from experience the bounding sphere is both tighter (although marginal in many cases) and it can be orders quicker to compute.

Example BunnyMesh Execution Times

Oriented Bounding Ellipsoid: 16766.952 ms
Approx Sphere: 0.411 ms
Exact Sphere: 44.741 ms

@Pemar743

Copy link
Copy Markdown
Author

Hi @ssheorey, they also produce different radii and centers.
Bunny
example_BS_and_OBE_Bunny

Cylinder
example_BS_and_OBE_Cylinder

Bunny Execution Times

Oriented Bounding Ellipsoid: 19750.351 ms
Exact Sphere: 60.783 ms

Bunny Metrics

Ellipsoid center: [-0.03425542 0.10323097 -0.0008773996]
Ellipsoid radii: [0.07972044 0.11715594 0.06445691]

Sphere center: [-0.019763147 0.10807039 -0.010968389]
Sphere radius: [0.10015704]

import time
import open3d as o3d

dataset = o3d.data.BunnyMesh()

mesh = o3d.io.read_triangle_mesh(dataset.path)
mesh.compute_vertex_normals()

print("Mesh loaded.")

mesh_t = o3d.t.geometry.TriangleMesh.from_legacy(mesh)

t0 = time.perf_counter()
obe = mesh_t.get_oriented_bounding_ellipsoid()
t1 = time.perf_counter()
obe_time_ms = (t1 - t0) * 1000.0
obe.set_color((0.0, 0.8, 0.0))

t0 = time.perf_counter()
bs_exact = mesh_t.get_bounding_sphere(exact=True)
t1 = time.perf_counter()
bs_exact_time_ms = (t1 - t0) * 1000.0

bs_exact.set_color((0.0, 0.0, 0.8))

print("\nExecution Times")
print("----------------------------")
print(f"Oriented Bounding Ellipsoid: {obe_time_ms:.3f} ms")
print(f"Exact Sphere:  {bs_exact_time_ms:.3f} ms")

print("\nMetrics")
print("----------------------------")
print(f"Ellipsoid center: {obe.center}")
print(f"Ellipsoid radii: {obe.radii}")
print(f"Sphere center: {bs_exact.center}")
print(f"Sphere radius: {bs_exact.radius}")

ellipsoid_lines = (
        o3d.t.geometry.LineSet.create_from_oriented_bounding_ellipsoid(obe)
    )

bounding_sphere_lines_exact = (
    o3d.t.geometry.LineSet.create_from_bounding_sphere(bs_exact, resolution=20)
)

o3d.visualization.draw_geometries([
mesh_t.to_legacy(),
ellipsoid_lines.to_legacy(),
bounding_sphere_lines_exact.to_legacy(),
    ])

@Pemar743

Copy link
Copy Markdown
Author

Hi @ssheorey, just following up to see if my previous comments helped clarify the distinction between the min bounding sphere and the min bounding ellipsoid?
I believe this PR complements the existing bounding primitives - happy to explain further if needed.
Thanks for your time

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants