Overview

The RoseBoundingBox2D class describes an axis-aligned rectangle in the XY plane or UV space. The rectangle is formed by vertical and horizontal lines at the upper and lower coordinates. The class holds a pair of points that contain the maximum and minimum 2D coordinate values. The class holds a pair of points that contain the maximum and minimum coordinate values, Use RoseBoundingBox to describe the bounds of a 3D volume.

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

Array Member

public:
	double m[4];

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

RoseBoundingBox2D 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\n", bb.m[0], bb.m[1]);
printf ("max corner is %g, %g\n", bb.m[2], bb.m[3]);

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

// aliases for UV space
printf ("min corner is %g, %g\n", bb.minpt().u(), bb.minpt().v());
printf ("max corner is %g, %g\n", bb.maxpt().u(), bb.maxpt().v());

centerpt()

RosePoint2D centerpt() const;

The centerpt() function returns the calculated center point of the bounding rectangle. 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[2],
        double tol=0
        ) const;

int contains (
        double x, double y
        double tol=0
        ) const;

int contains (
        const RosePoint2D& val,
        double tol=0
        ) const;

int contains (
        ListOfDouble * lst,
        double tol=0
        ) const;

int contains (
	const RoseReal2DArray& val,
	double tol=0
	) const;
	
int contains (
        const RoseBoundingBox2D& val,
        double tol=0
        ) const;

The contains() function returns true if a 2D point exists within the bounding rectangle. The point can be passed as an array, separate coordinates, a RosePoint2D or a ListOfDouble.

The version that accepts a list of points as a a RoseReal2DArray 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 area 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 to 10,10
RoseBoundingBox2D bb;	
bb.update(-1, -1);
bb.update(10,10);

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

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

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

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

diagonal()

double diagonal() const;

The diagonal() function returns the diagonal of the bounding rectangle, 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 RoseReal2DArray& val,
	double tol=0
	) const;
	
int intersects (
	const RoseBoundingBox2D& val,
	double tol=0
	) const;

The intersects() function returns true if the bounding rectangle overlaps a second rectangle. 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 RoseReal2DArray 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 rectangle. 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_2 apart.

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

// define box 10,10.1 to 12,12
RoseBoundingBox2D b2;
b2.update(10, 10.1);
b2.update(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 area. 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_bounds2d_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 rectangle 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()

RosePoint2D& maxpt();
const RosePoint2D& maxpt() const;

The maxpt() function returns the corner of the rectangle 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 RosePoint2D. These two points define the limits of the rectangle in the X and Y directions. The top of the box is parallel to the X axis at Y = maxpt.y(), the bottom of the box is the line at Y = minpt.y(), and similarly for the sides of the rectangle.

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

The minx(), miny(), maxx(), and maxy() functions are shortuts to each of the individual coordinates. The minu(), minv(), maxu(), and maxv() shortcuts are also available for work in UV space.

RoseBoundingBox2D bb;
printf ("Low X Edge at X=%g\n", bb.minpt().x());
printf ("High X Edge at X=%g\n", bb.maxpt().x());

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

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

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


// 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/u/v()

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

double maxu() const; 
double maxv() const;

void maxx(double v);
void maxy(double v);

void maxu(double v);
void maxv(double v);

The maxx() and maxy() functions get or set the coordinates of the corner of the bounding rectangle furthest from the origin. The maxu() / maxv() functions are aliases for working in UV space. See maxpt() for discussion and examples.

minpt()

RosePoint2D& minpt();
const RosePoint2D& minpt() const;

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

minx/y/u/v()

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

double minu() const; 
double minv() const;

void minx(double v);
void miny(double v);

void minu(double v);
void minv(double v);

The minx() and miny() functions get or set the coordinates of the corner of the bounding rectangle closest to the origin. The minu() / minv() functions are aliases for working in UV space. See maxpt() for discussion and examples.

shortside()

double shortside() const;

The shortside() function returns the length of the shortest side of the bounding rectangle 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[2]);
void update (const double val[2], const double xf[9]);
void update (const double val[2], const RoseXform2D& xf); 

void update (double x,double y);
void update (double x,double y, const double xf[9]);
void update (double x,double y, const RoseXform2D& xf);

void update (const RosePoint2D& val);
void update (const RosePoint2D& val, const RoseXform2D& xf);

void update (ListOfDouble * lst);
void update (ListOfDouble * lst, const double xf[9]);
void update (ListOfDouble * lst, const RoseXform2D& xf);

void update (const RoseReal2DArray& val);
void update (const RoseReal2DArray& val, const double xf[9]);
void update (const RoseReal2DArray& val, const RoseXform2D& xf); 

void update (const RoseBoundingBox2D& val);
void update (const RoseBoundingBox2D& val, const double xf[9]);
void update (const RoseBoundingBox2D& val, const RoseXform2D& xf); 

The update() function extends a bounding rectangle as needed to include a point in space. The point can be passed as an array, separate coordinates, a RosePoint2D or a ListOfDouble. You can pass a collection of points as a RoseReal2DArray. 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 area of the second box before computing the updated area.

RoseBoundingBox2D bb;	// box is empty

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

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

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

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

RoseXform2D xf;
RoseDirection2D minux_xaxis (-1, 0);
RosePoint2D loc(10, 20);

// 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)
xf.put_dirs(minux_xaxis);      
xf.origin(loc);
	    
RoseBoundingBox2D bb;
bb.update(10,2, xf);	// box 0, 18 to 0, 18
bb.update(11,3, xf);	// box -1, 17 to 0, 18
bb.update(9,1, xf);	// box -1, 17 to 1, 19
bb.update(10,2, xf);	// box -1, 17 to 1, 19