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) – XYZ coordinates of the points.

Returns

array – XYZ coordinates of 8 points defining a box.

Raises

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 = numpy.random.rand(10000, 3)
>>> bottom = numpy.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 = numpy.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 = numpy.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.

>>> 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