Overview

The RoseBoundingBox class describes an axis-aligned bounding box. This box is formed by a pair of XY planes at the maximum and minimum Z coordinates, XZ planes at the max/min Y coordinates, and YZ planes at the max/min X coordinates. The class holds a pair of points that contain the maximum and minimum coordinate values, Use RoseBoundingBox2D if you need the bounds of a 2D planar region.

You can compute the boolean union of two bounding boxes with the update() function and compute the boolean intersection of two volumes with the rose_bounds_intersect() function.

Array Member

public:
	double m[6];

The class has a public array member which holds the limits of the bounding box in the X, Y, and Z directions. The first three elements are the coordinates of the corner of the box closest to the origin and the second three are the corner furthest from the origin. An empty box is indicated by setting the first element to ROSE_NULL_REAL.

RoseBoundingBox bb;

// completely equivalent
if (ROSE_FLOAT_IS_NULL(bb.m[0]))
    printf("Bounds are empty\n");

if (bb.is_empty())
    printf("Bounds are empty\n");
   
printf ("min corner is %g, %g, %g\n", bb.m[0], bb.m[1], bb.m[2]);
printf ("max corner is %g, %g, %g\n", bb.m[3], bb.m[4], bb.m[5]);

printf ("min corner is %g, %g, %g\n", bb.minpt().x(), bb.minpt().y(), bb.minpt().z());
printf ("max corner is %g, %g, %g\n", bb.maxpt().x(), bb.maxpt().y(), bb.maxpt().z());

centerpt()

RosePoint centerpt() const;

The centerpt() function returns the calculated center point of the bounding box. This function returns (0,0,0) if the box is empty.

clear()

void clear()

The clear() function resets the bounding box so that the maximum and minimum points are undefined and is_empty() returns true. In the limit array, an empty box is indicated by setting the first element to ROSE_NULL_REAL.

contains()

int contains (
        const double val[3],
        double tol=0
        ) const;
	
int contains (
        double x, double y, double z,
        double tol=0
        ) const;
	
int contains (
        const RosePoint& val,
        double tol=0
        ) const;
	
int contains (
        ListOfDouble * lst,
        double tol=0
        ) const;
	
int contains (
	const RoseReal3DArray& val,
	double tol=0
	) const;
	
int contains (
        const RoseBoundingBox& val,
        double tol=0
        ) const;

The contains() function returns true if a point in space exists within the volume of the bounding box. The point can be passed as an array, separate coordinates, a RosePoint or a ListOfDouble.

The version that accepts a list of points as a a RoseReal3DArray returns true only if all of the points in the list are completely enclosed within the bounds of the current box. It returns false if the list is empty or if any point lies outside of the box.

The function also has an overload that accepts a second bounding box and returns true only if the second box is completely enclosed within the bounds of the current box. By default, strict numeric comparison is used to determine whether the point or box is contained. If numbers are exactly equal, the function returns true.

If the optional tol value is given, the function checks with a box that extends tol further on each side. The value can be negative if you need to shrink the box. The intersects() function has more discussion about the maximum separation distance when doing toleranced comparison.

// define box -1,-1,-1 to 10,10,10
RoseBoundingBox bb;	
bb.update(-1, -1, -1);
bb.update(10,10,10);

// clearly inside ==> true
bb.contains(0,0,0);

// slightly outside ==> false
bb.contains(10.1,10.1,10.1);

// slightly outside, but add 0.5 all around ==> true
bb.contains(10.1,10.1,10.1, 0.5);

// exactly on bounds ==> true
bb.contains(-1,-1,-1);

diagonal()

double diagonal() const;

The diagonal() function returns the space diagonal of the bounding box, which is the distance between the minpt() and the maxpt(). This function returns zero if the box is empty or if the box contains a single point in space.

intersects()

int intersects (
	const RoseReal3DArray& val,
	double tol=0
	) const;
	
int intersects (
	const RoseBoundingBox& val,
	double tol=0
	) const;

The intersects() function returns true if the bounding box overlaps a second bounding box. By default, strict numeric comparison is used to determine whether there is any overlap. If numbers are exactly equal, the function returns true.

The version that accepts a list of points as a a RoseReal3DArray returns true if any point in the list is contained within the bounds of the current box. It returns false if the list is empty or if all points are outside of the box.

If the optional tol value is given, the function uses a box that extends tol further on each side when checking for overlap with the second bounding box. The value can be negative if you need to shrink the box.

Note that the boxes might be slightly further than tol away. If they overlap corner to corner, the closest points could be up to tol*ROSE_SQRT_3 apart.

// define box -1,-1,-1 to 10,10,10
RoseBoundingBox bb;	
bb.update(-1, -1, -1);
bb.update(10,10,10);

// define box 10,10,10.1 to 12,12,12
RoseBoundingBox b2;
b2.update(10, 10, 10.1);
b2.update(12, 12, 12);

// slightly outside ==> false
bb.intersects(b2);

// slightly outside, but add 0.5 all around ==> true
bb.intersects(b2, 0.5);

is_empty()

int is_empty() const;

The is_empty() function returns if the bounding box does not describe a volume. The maximum and minimum points of an empty box are undefined. In the limit array, an empty box is indicated by setting the first element to ROSE_NULL_REAL. Boxes are empty when they are first created or when the clear() function has been called. The result of rose_bounds_intersect() is also set to empty when the input boxes do not overlap.

longside()

double longside() const;

The longside() function returns the length of the longest side of the bounding box and shortside() returns the length of the shortest side. This function returns zero if the box is empty or if the box contains a single point in space.

maxpt()

RosePoint& maxpt();
const RosePoint& maxpt() const;

The maxpt() function returns the corner of the bounding box furthest from the origin. The minpt() function returns the point closest to the origin. Each corner is a reference to either a constant or an updatable RosePoint. These two points define the limits of the bounding box in the X, Y, and Z directions. The top of the box is parallel to the XY plane at Z = maxpt.z(), the bottom of the box is the plane at Z = minpt.z(), and so on for the planes along the other axes.

If the bounding box is_empty() these functions will not return useful values.

The minx(), miny(), minz(), maxx(), maxy(), and maxz() functions are shortuts to each of the individual coordinates.

RoseBoundingBox bb;
printf ("Low X Face = YZ plane at X=%g\n", bb.minpt().x());
printf ("High X Face = YZ plane at X=%g\n", bb.maxpt().x());

printf ("Low Y Face = XZ plane at Y=%g\n", bb.minpt().y());
printf ("High Y Face = XZ plane at Y=%g\n", bb.maxpt().y());

printf ("Low Z Face = XY plane at Y=%g\n", bb.minpt().z());
printf ("High Z Face = XY plane at Y=%g\n", bb.maxpt().z());

// version with quick functions for each coordinate
//
printf ("Low X Face = YZ plane at X=%g\n", bb.minx());
printf ("High X Face = YZ plane at X=%g\n", bb.maxx());

printf ("Low Y Face = XZ plane at Y=%g\n", bb.miny());
printf ("High Y Face = XZ plane at Y=%g\n", bb.maxy());

printf ("Low Z Face = XY plane at Y=%g\n", bb.minz());
printf ("High Z Face = XY plane at Y=%g\n", bb.maxz());


// Normally update() is used to adjust the size of the box, 
// but you can change the coordinates manually if needed.
//
bb.minpt().x(57.2);
bb.maxpt().x(175.9);

maxx/y/z()

double maxx() const;
double maxy() const;
double maxz() const;

double maxx(double v);
double maxy(double v);
double maxz(double v);

The maxx(), maxy(), and maxz() functions get or set the coordinates of the corner of the bounding box furthest from the origin. See maxpt() for discussion and examples.

minpt()

RosePoint& minpt();
const RosePoint& minpt() const;

The minpt() function returns the corner of the bounding box closest to the origin. The corner is a reference to either a constant or an updatable RosePoint. See maxpt() for discussion and examples.

minx/y/z()

double minx() const;
double miny() const;
double minz() const;

double minx(double v);
double miny(double v);
double minz(double v);

The minx(), miny(), and minz() functions get or set the coordinates of the corner of the bounding box closest to the origin. See maxpt() for discussion and examples.

shortside()

double shortside() const;

The shortside() function returns the length of the shortest side of the bounding box and longside() returns the length of the longest side. This function returns zero if the box is empty or if the box contains a single point in space.

update()

void update (const double val[3]);
void update (const double val[3], const double xf[16]);
void update (const double val[3], const RoseXform& xf); 

void update (double x,double y,double z);
void update (double x,double y,double z, const double xf[16]);
void update (double x,double y,double z, const RoseXform& xf);

void update (const RosePoint& val);
void update (const RosePoint& val, const RoseXform& xf);

void update (ListOfDouble * lst);
void update (ListOfDouble * lst, const double xf[16]);
void update (ListOfDouble * lst, const RoseXform& xf);

void update (const RoseReal3DArray& val);
void update (const RoseReal3DArray& val, const double xf[16]);
void update (const RoseReal3DArray& val, const RoseXform& xf); 

void update (const RoseBoundingBox * val);
void update (const RoseBoundingBox& val);
void update (const RoseBoundingBox& val, const double xf[16]);
void update (const RoseBoundingBox& val, const RoseXform& xf); 

The update() function extends a bounding box as needed to include a point in space. The point can be passed as an array, separate coordinates, a RosePoint or a ListOfDouble. You can pass a collection of points as a RoseReal3DArray. If a transform is provided, it will be applied to the point before computing the updated box.

The function also has overloads that accept a second bounding box and computes the union with the current bounding box. If a transform is provided, it will be applied to the entire volume of the second box before computing the updated volume.

RoseBoundingBox bb;	// box is empty

bb.update(1,2,3);	// box 1,2,3  to  1,2,3
bb.update(4,5,6);	// box 1,2,3  to  4,5,6
bb.update(0, 1, 2);	// box 0,1,2  to  4,5,6
bb.update(1,2,3);	// box unchanged

RoseBoundingBox bb2;
bb2.update(0,0,0);	// second box for intersect
bb2.update(1,1,1);

bb.update(bb2);		// box 0,0,0  to  4,5,6

When using a transform, the bounding box will contain the transformed point values.

RoseXform xf;
RoseDirection minux_xaxis (-1, 0, 0);
RoseDirection zaxis (0, 0, 1);
RosePoint loc(10, 20, 30);

// Set rotation to 180deg counterclockwise about the Z axis.
// The Y direction will be (0, -1, 0)   Finish by setting the
// translation portion to (10, 20, 30)
xf.put_dirs(zaxis, minux_xaxis);      
xf.origin(loc);
	    
RoseBoundingBox bb;
bb.update(10,2,3, xf);	// box 0, 18, 33 to 0, 18, 33
bb.update(11,3,9, xf);	// box -1, 17, 33 to 0, 18, 39
bb.update(9,1,2, xf);	// box -1, 17, 32 to 1, 19, 39
bb.update(10,2,3, xf);	// box -1, 17, 32 to 1, 19, 39