# oriented_bounding_box_numpy

compas.geometry.oriented_bounding_box_numpy(points)[source]

Compute the oriented minimum bounding box of a set of points in 3D space.

Parameters

points (array_like[point]) – XYZ coordinates of the points.

Returns

list[[float, float, float]] – XYZ coordinates of 8 points defining a box.

Raises
• AssertionError – If the input data is 2D.

• QhullError – If the data is essentially 2D.

Notes

The oriented (minimum) bounding box (OBB) of a given set of points is computed using the following procedure:

1. Compute the convex hull of the points.

2. For each of the faces on the hull:

1. Compute face frame.

2. Compute coordinates of other points in face frame.

3. Find “peak-to-peak” (PTP) values of point coordinates along local axes.

4. Compute volume of box formed with PTP values.

3. Select the box with the smallest volume.

Examples

Generate a random set of points with $$x \in [0, 10]$$, $$y \in [0, 1]$$ and $$z \in [0, 3]$$. Add the corners of the box such that we now the volume is supposed to be $$30.0$$.

>>> points = np.random.rand(10000, 3)
>>> bottom = np.array([[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [1.0, 1.0, 0.0]])
>>> top = np.array([[0.0, 0.0, 1.0], [1.0, 0.0, 1.0], [0.0, 1.0, 1.0], [1.0, 1.0, 1.0]])
>>> points = np.concatenate((points, bottom, top))
>>> points[:, 0] *= 10
>>> points[:, 2] *= 3


Rotate the points around an arbitrary axis by an arbitrary angle.

>>> from compas.geometry import Rotation
>>> from compas.geometry import transform_points_numpy
>>> R = Rotation.from_axis_and_angle([1.0, 1.0, 0.0], 0.3 * 3.14159)
>>> points = transform_points_numpy(points, R)


Compute the volume of the oriented bounding box.

>>> from compas.geometry import length_vector, subtract_vectors, close
>>> bbox = oriented_bounding_box_numpy(points)
>>> a = length_vector(subtract_vectors(bbox[1], bbox[0]))
>>> b = length_vector(subtract_vectors(bbox[3], bbox[0]))
>>> c = length_vector(subtract_vectors(bbox[4], bbox[0]))
>>> close(a * b * c, 30.)
True