Files
opennurbs/opennurbs_bounding_box.h
Bozo The Builder 53fe7bc7ef Sync changes from upstream repository
Co-authored-by: Andrew Le Bihan <andy@mcneel.com>
Co-authored-by: Dale Fugier <dale@mcneel.com>
Co-authored-by: Dale Lear <dalelear@mcneel.com>
Co-authored-by: Greg Arden <greg@mcneel.com>
Co-authored-by: Jussi <jussi@mcneel.com>
Co-authored-by: Lowell <lowell@mcneel.com>
Co-authored-by: Rajaa Issa <rajaa@mcneel.com>
Co-authored-by: Steve Baer <steve@mcneel.com>
Co-authored-by: alain <alain@mcneel.com>
Co-authored-by: chuck <chuck@mcneel.com>
Co-authored-by: piac <giulio@mcneel.com>
2021-05-13 04:27:38 -07:00

915 lines
26 KiB
C++

/* $NoKeywords: $ */
/*
//
// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved.
// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
// McNeel & Associates.
//
// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
// MERCHANTABILITY ARE HEREBY DISCLAIMED.
//
// For complete openNURBS copyright information see <http://www.opennurbs.org>.
//
////////////////////////////////////////////////////////////////
*/
#if !defined(ON_BOUNDING_BOX_INC_)
#define ON_BOUNDING_BOX_INC_
////////////////////////////////////////////////////////////////
//
// ON_BoundingBox - axis aligned bounding box
//
class ON_CLASS ON_BoundingBox
{
public:
static const ON_BoundingBox EmptyBoundingBox; // ((1.0,0.0,0.0),(-1.0,0.0,0.0))
static const ON_BoundingBox UnsetBoundingBox; // all coordinates are ON_UNSET_VALUE
static const ON_BoundingBox NanBoundingBox; // all coordinates are ON_DBL_QNAN
ON_BoundingBox() ON_NOEXCEPT; // creates EmptyBoundingBox
~ON_BoundingBox() = default;
ON_BoundingBox(const ON_BoundingBox&) = default;
ON_BoundingBox& operator=(const ON_BoundingBox&) = default;
explicit ON_BoundingBox(
const ON_3dPoint&, // min corner of axis aligned bounding box
const ON_3dPoint& // max corner of axis aligned bounding box
);
// OBSOLETE
// temporary - use ON_ClippingRegion - this function will be removed soon.
int IsVisible(
const ON_Xform& bbox2c
) const;
// OBSOLETE
void Destroy(); // set this = ON_BoundingBox::EmptyBoundingBox
// operator[] returns min if index <= 0 and max if indes >= 1
ON_3dPoint& operator[](int);
const ON_3dPoint& operator[](int) const;
ON_3dPoint Min() const;
ON_3dPoint Max() const;
ON_3dVector Diagonal() const; // max corner - min corner
ON_3dPoint Center() const;
ON_3dPoint Corner( // 8 corners of box
int, // x_index 0 = Min().x, 1 = Max().x
int, // y_index 0 = Min().y, 1 = Max().y
int // z_index 0 = Min().z, 1 = Max().z
) const;
bool GetCorners(
ON_3dPointArray& box_corners // returns list of 8 corner points
) const;
bool GetCorners(
ON_3dPoint box_corners[8] // returns list of 8 corner points
) const;
/*
Parameters:
edges[] - out
12 edge lines. If the bounding box has no height, width or depth,
then the corresponding edges will have the same "from" and "to"
points.
Returns:
If the bounding box is valid, then true is returned and
12 line segments, some possibly a single point, are returned.
Otherwise false is returned and 12 line segments with "from"
and "to" points set to ON_3dPoint::UnsetPoint are returned.
*/
bool GetEdges(
ON_Line edges[12] // returns list of 12 edge segments
) const;
// OBSOLETE IsValid() = IsNotEmpty()
bool IsValid() const; // empty boxes are not valid
bool IsSet() const; // every coordinate is a finite, valid double, not ON_UNSET_VALUE and not ON_UNSET_POSITIVE_VALUE
bool IsUnset() const; // some coordinate is ON_UNSET_VALUE or ON_UNSET_POSITIVE_VALUE
bool IsNan() const; // some coordinate is a NAN
bool IsUnsetOrNan() const; // = IsUnset() or IsNan()
bool IsEmpty() const; // (m_min.x > m_max.x || m_min.y > m_max.y || m_min.z > m_max.z) && IsSet();
bool IsNotEmpty() const; // (m_min.x <= m_max.x && m_min.y <= m_max.y && m_min.z <= m_max.z) && IsSet()
bool IsPoint() const; // (m_min.x == m_max.x && m_min.y == m_max.y && m_min.z == m_max.z) && IsSet()
void Dump(class ON_TextLog&) const;
/*
Description:
Test a bounding box to see if it is degenerate (flat)
in one or more directions.
Parameters:
tolerance - [in] Distances <= tolerance will be considered
to be zero. If tolerance is negative (default), then
a scale invarient tolerance is used.
Returns:
@untitled table
0 box is not degenerate
1 box is a rectangle (degenerate in one direction)
2 box is a line (degenerate in two directions)
3 box is a point (degenerate in three directions)
4 box is not valid
*/
int IsDegenerate(
double tolerance = ON_UNSET_VALUE
) const;
//////////
// ON_BoundingBox::Transform() updates the bounding box
// to be the smallest axis aligned bounding box that contains
// the transform of the eight corner points of the input
// bounding box.
bool Transform( const ON_Xform& );
double Tolerance() const; // rough guess at a tolerance to use for comparing
// objects in this bounding box
// All of these Set() functions set or expand a box to enclose the points in the arguments
// If bGrowBox is true, the existing box is expanded, otherwise it is only set to the current point list
bool Set(
int dim,
bool is_rat,
int count,
int stride,
const double* point_array,
int bGrowBox = false
);
bool Set(
const ON_3dPoint& point,
int bGrowBox = false
);
bool Set(
const ON_2dPoint& point,
int bGrowBox = false
);
bool Set(
const ON_SimpleArray<ON_4dPoint>& point_array,
int bGrowBox = false
);
bool Set(
const ON_SimpleArray<ON_3dPoint>& point_array,
int bGrowBox = false
);
bool Set(
const ON_SimpleArray<ON_2dPoint>& point_array,
int bGrowBox = false
);
bool Set(
int dim,
bool is_rat,
int count,
int stride,
const float* point_array,
int bGrowBox = false
);
bool Set(
const ON_3fPoint& point,
int bGrowBox = false
);
bool Set(
const ON_2fPoint& point,
int bGrowBox = false
);
bool Set(
const ON_SimpleArray<ON_4fPoint>& point_array,
int bGrowBox = false
);
bool Set(
const ON_SimpleArray<ON_3fPoint>& point_array,
int bGrowBox = false
);
bool Set(
const ON_SimpleArray<ON_2fPoint>& point_array,
int bGrowBox = false
);
bool IsPointIn(
const ON_3dPoint& test_point, // point to test
int bStrictlyIn = false
// true to test for strict ( min < point < max )
// false to test for (min <= point <= max)
//
) const;
//////////
// Point on or in the box that is closest to test_point.
// If test_point is in or on the box, the test_point is returned.
ON_3dPoint ClosestPoint(
const ON_3dPoint& test_point
) const;
/*
Description:
Quickly find a lower bound on the distance
between the point and this bounding box.
Parameters:
P - [in]
Returns:
A distance that is less than or equal to the shortest
distance from the line to this bounding box.
Put another way, if Q is any point in this bounding box,
then P.DistanceTo(Q) >= MinimumDistanceTo(bbox).
*/
double MinimumDistanceTo( const ON_3dPoint& P ) const;
/*
Description:
Quickly find an upper bound on the distance
between the point and this bounding box.
Parameters:
P - [in]
Returns:
A distance that is greater than or equal to the
longest distance from the point P to this bounding box.
Put another way, if Q is any point in this bounding box,
then P.DistanceTo(Q) <= MaximumDistanceTo(bbox).
*/
double MaximumDistanceTo( const ON_3dPoint& P ) const;
/*
Description:
Quickly find a lower bound on the distance
between this and the other bounding box.
Parameters:
other - [in]
Returns:
A distance that is less than or equal to the shortest
distance between the bounding boxes.
Put another way, if Q is any point in this bounding box
and P is any point in the other bounding box,
then P.DistanceTo(Q) >= MinimumDistanceTo(bbox).
*/
double MinimumDistanceTo( const ON_BoundingBox& other ) const;
/*
Description:
Quickly find an upper bound on the distance
between this and the other bounding box.
Parameters:
other - [in]
Returns:
A distance that is greater than or equal to the longest
distance between the bounding boxes.
Put another way, if Q is any point in this bounding box
and P is any point in the other bounding box,
then P.DistanceTo(Q) <= MaximumDistanceTo(bbox).
*/
double MaximumDistanceTo( const ON_BoundingBox& other ) const;
/*
Description:
Quickly find a lower bound on the distance
between the line segment and this bounding box.
Parameters:
line - [in]
Returns:
A distance that is less than or equal to the shortest
distance from the line to this bounding box.
Put another way, if Q is any point on line
and P is any point in this bounding box, then
P.DistanceTo(Q) >= MinimumDistanceTo(bbox).
*/
double MinimumDistanceTo( const ON_Line& line ) const;
/*
Description:
Quickly find a tight lower bound on the distance
between the plane and this bounding box.
Parameters:
plane - [in]
Returns:
The minimum distance between a point on the plane
and a point on the bounding box.
See Also:
ON_PlaneEquation::MimimumValueAt
ON_PlaneEquation::MaximumValueAt
*/
double MinimumDistanceTo( const ON_Plane& plane ) const;
double MinimumDistanceTo( const ON_PlaneEquation& plane_equation ) const;
/*
Description:
Quickly find an upper bound on the distance
between the line segment and this bounding box.
Parameters:
line - [in]
Returns:
A distance that is greater than or equal to the
longest distance from the line to this bounding box.
Put another way, if Q is any point on the line
and P is any point in this bounding box, then
P.DistanceTo(Q) <= MaximumDistanceTo(bbox).
*/
double MaximumDistanceTo( const ON_Line& line ) const;
/*
Description:
Quickly find a tight upper bound on the distance
between the plane and this bounding box.
Parameters:
plane - [in]
Returns:
A distance that is equal to the longest distance from
the plane to this bounding box. Put another way,
if Q is any point on the plane and P is any point
in this bounding box, then
P.DistanceTo(Q) <= MaximumDistanceTo(bbox) and there
is at least one point on the bounding box where the
distance is equal to the returned value.
See Also:
ON_PlaneEquation::MaximumValueAt
*/
double MaximumDistanceTo( const ON_Plane& plane ) const;
double MaximumDistanceTo( const ON_PlaneEquation& plane_equation ) const;
/*
Description:
Quickly determine if the shortest distance from
the point P to the bounding box is greater than d.
Parameters:
d - [in] distance (> 0.0)
P - [in]
Returns:
True if if the shortest distance from the point P
to the bounding box is greater than d.
*/
bool IsFartherThan( double d, const ON_3dPoint& P ) const;
/*
Description:
Quickly determine if the shortest distance from the line
to the bounding box is greater than d.
Parameters:
d - [in] distance (> 0.0)
line - [in]
Returns:
True if the shortest distance from the line
to the bounding box is greater than d. It is not the
case that false means that the shortest distance
is less than or equal to d.
*/
bool IsFartherThan( double d, const ON_Line& line ) const;
/*
Description:
Quickly determine if the shortest distance from the plane
to the bounding box is greater than d.
Parameters:
d - [in] distance (> 0.0)
plane - [in]
Returns:
True if the shortest distance from the plane
to the bounding box is greater than d, and false
if the shortest distance is less than or equal to d.
*/
bool IsFartherThan( double d, const ON_Plane& plane ) const;
/*
Description:
Quickly determine if the shortest distance from the plane
to the bounding box is greater than d.
Parameters:
d - [in] distance (> 0.0)
plane_equation - [in] (the first three coefficients
are assumed to be a unit vector.
If not, adjust your d accordingly.)
Returns:
True if the shortest distance from the plane
to the bounding box is greater than d, and false
if the shortest distance is less than or equal to d.
*/
bool IsFartherThan( double d, const ON_PlaneEquation& plane_equation ) const;
/*
Description:
Quickly determine if the shortest distance this bounding
box to another bounding box is greater than d.
Parameters:
d - [in] distance (> 0.0)
other - [in] other bounding box
Returns:
True if if the shortest distance from this bounding
box to the other bounding box is greater than d.
*/
bool IsFartherThan( double d, const ON_BoundingBox& other ) const;
// Description:
// Get point in a bounding box that is closest to a line
// segment.
// Parameters:
// line - [in] line segment
// box_point - [out] point in box that is closest to line
// segment point at t0.
// t0 - [out] parameter of point on line that is closest to
// the box.
// t1 - [out] parameter of point on line that is closest to
// the box.
// Returns:
// 3 success - line segments intersects box in a segment
// from line(t0) to line(t1) (t0 < t1)
// 2 success - line segments intersects box in a single point
// at line(t0) (t0==t1)
// 1 success - line segment does not intersect box. Closest
// point on the line is at line(t0) (t0==t1)
// 0 failure - box is invalid.
// Remarks:
// The box is treated as a solid box. If the intersection
// of the line segment, then 3 is returned.
int GetClosestPoint(
const ON_Line&, // line
ON_3dPoint&, // box_point
double*, // t0
double* // t1
) const;
//////////
// Get points on bounding boxes that are closest to each other.
// If the boxes intersect, then the point at the centroid of the
// intersection is returned for both points.
bool GetClosestPoint(
const ON_BoundingBox&, // "other" bounding box
ON_3dPoint&, // point on "this" box that is closest to "other" box
ON_3dPoint& // point on "other" box that is closest to "this" box
) const;
//////////
// Point on the box that is farthest from the test_point.
ON_3dPoint FarPoint(
const ON_3dPoint& // test_point
) const;
//////////
// Get points on bounding boxes that are farthest from each other.
bool GetFarPoint(
const ON_BoundingBox&, // "other" bounding box
ON_3dPoint&, // point on "this" box that is farthest from "other" box
ON_3dPoint& // point on "other" box that is farthest from "this" box
) const;
/*
Description:
Intersect this with other_bbox and save intersection in this.
Parameters:
other_bbox - [in]
Returns:
True if this-intesect-other_bbox is a non-empty valid bounding box
and this is set. False if the intersection is empty, in which case
"this" is set to an invalid bounding box.
Remarks:
If "this" or other_bbox is invalid, they are treated as
the empty set, and false is returned.
*/
bool Intersection(
const ON_BoundingBox& other_bbox
);
/*
Description:
Set "this" to the intersection of bbox_A and bbox_B.
Parameters:
bbox_A - [in]
bbox_B - [in]
Returns:
True if the "this" is a non-empty valid bounding box.
False if the intersection is empty, in which case
"this" is set to an invalid bounding box.
Remarks:
If bbox_A or bbox_B is invalid, they are treated as
the empty set, and false is returned.
*/
bool Intersection( // this = intersection of two args
const ON_BoundingBox& bbox_A,
const ON_BoundingBox& bbox_B
);
bool Intersection( //Returns true when intersect is non-empty.
const ON_Line&, //Infinite Line segment to intersect with
double* =nullptr , // t0 parameter of first intersection point
double* =nullptr // t1 parameter of last intersection point (t0<=t1)
) const;
/*
Description:
Test a box to see if it is contained in this box.
Parameters:
other - [in] box to test
bProperSubSet - [in] if true, then the test is for a proper inclusion.
Returns:
If bProperSubSet is false, then the result is true when
this->m_min[i] <= other.m_min[i] and other.m_max[i] <= this->m_max[i].
for i=0,1 and 2.
If bProperSubSet is true, then the result is true when
the above condition is true and at least one of the inequalities is strict.
*/
bool Includes(
const ON_BoundingBox& other,
bool bProperSubSet = false
) const;
double Volume() const;
double Area() const;
// Union() returns true if union is not empty.
// Invalid boxes are treated as the empty set.
bool Union( // this = this union arg
const ON_BoundingBox&
);
bool Union( // this = union of two args
const ON_BoundingBox&,
const ON_BoundingBox&
);
/*
Description:
Test to see if "this" and other_bbox are disjoint (do not intersect).
Parameters:
other_bbox - [in]
Returns:
True if "this" and other_bbox are disjoint.
Remarks:
If "this" or other_bbox is invalid, then true is returned.
*/
bool IsDisjoint(
const ON_BoundingBox& other_bbox
) const;
/*
Description:
Test to see if "this" and line are disjoint (do not intersect or line is included).
Parameters:
line - [in]
infinite - [in] if false or not provided, then the line is considered bounded by start and end points.
Returns:
True if "this" and line are disjoint.
*/
bool IsDisjoint(const ON_Line& line) const;
bool IsDisjoint(const ON_Line& line, bool infinite) const;
bool SwapCoordinates( int, int );
/*
Description:
Expand the box by adding delta to m_max and subtracting
it from m_min. So, when delta is positive and the interval is
increasing this function expands the box on each side.
Returns:
true if the result is Valid.
*/
bool Expand(ON_3dVector delta);
ON_3dPoint m_min;
ON_3dPoint m_max;
};
/*
Returns:
True if lhs and rhs are identical.
*/
ON_DECL
bool operator==( const ON_BoundingBox& lhs, const ON_BoundingBox& rhs );
/*
Returns:
True if lhs and rhs are not equal.
*/
ON_DECL
bool operator!=( const ON_BoundingBox& lhs, const ON_BoundingBox& rhs );
class ON_CLASS ON_BoundingBoxAndHash
{
public:
ON_BoundingBoxAndHash() = default;
~ON_BoundingBoxAndHash() = default;
ON_BoundingBoxAndHash(const ON_BoundingBoxAndHash&) = default;
ON_BoundingBoxAndHash& operator=(const ON_BoundingBoxAndHash&) = default;
public:
// This hash depends on the context and is a hash
// of the information used to calculte the bounding box.
// It is not the hash of the box values
void Set(
const ON_BoundingBox& bbox,
const ON_SHA1_Hash& hash
);
const ON_BoundingBox& BoundingBox() const;
const ON_SHA1_Hash& Hash() const;
/*
Returns:
True if bounding box IsSet() is true and hash is not EmptyContentHash.
*/
bool IsSet() const;
bool Write(
class ON_BinaryArchive& archive
) const;
bool Read(
class ON_BinaryArchive& archive
);
private:
ON_BoundingBox m_bbox = ON_BoundingBox::UnsetBoundingBox;
ON_SHA1_Hash m_hash = ON_SHA1_Hash::EmptyContentHash;
};
/*
A class that caches 8 bounding box - hash pairs and keeps the most frequently
used bounding boxes.
*/
class ON_CLASS ON_BoundingBoxCache
{
public:
ON_BoundingBoxCache() = default;
~ON_BoundingBoxCache() = default;
ON_BoundingBoxCache(const ON_BoundingBoxCache&) = default;
ON_BoundingBoxCache& operator=(const ON_BoundingBoxCache&) = default;
public:
/*
Description:
Add a bounding box that can be found from a hash value.
Parameters:
bbox - [in]
hash - [in]
A hash of the information needed to create this bounding box.
*/
void AddBoundingBox(
const ON_BoundingBox& bbox,
const ON_SHA1_Hash& hash
);
void AddBoundingBox(
const ON_BoundingBoxAndHash& bbox_and_hash
);
/*
Description:
Get a cached bounding box.
Parameters:
hash - [in]
bbox - [out]
If the hash identifies a bounding box in the cache, then
that bounding box is returned. Otherwise ON_BoundingBox::NanBoundingBox
is returned.
Returns:
true - cached bounding box returned
false - bounding box not in cache.
*/
bool GetBoundingBox(
const ON_SHA1_Hash& hash,
ON_BoundingBox& bbox
) const;
/*
Description:
Remove a bounding box that can be found from a hash value.
Parameters:
hash - [in]
Returns:
true - hash was in the cache and removed.
false - hash was not in the cache.
Remarks:
If the hash values you are using are correctly computed and include
all information that the bouding box depends on, then
you never need to remove bounding boxes. Unused ones will get
removed as new ones are added.
*/
bool RemoveBoundingBox(
const ON_SHA1_Hash& hash
);
/*
Description:
Removes all bounding boxes.
Remarks:
If the hash values you are using are correctly computed and include
all information that the bouding box depends on, then
you never need to remove bounding boxes. Unused ones will get
removed as new ones are added.
If the hash does not include all information required to compute
the bounding boxes, then call RemoveAllBoundingBoxes() when the
non-hashed information changes.
*/
void RemoveAllBoundingBoxes();
/*
Returns:
Number of cached boxes.
*/
unsigned int BoundingBoxCount() const;
bool Write(
class ON_BinaryArchive& archive
) const;
bool Read(
class ON_BinaryArchive& archive
);
private:
// number of boxes set in m_cache[]
unsigned int m_count = 0;
// capacity of m_cache[] - set when needed
unsigned int m_capacity = 0;
// Bounding box cache. Most recently used boxes are first.
mutable ON_BoundingBoxAndHash m_cache[8];
/*
Returns:
m_cache[] array index of box with the hash.
ON_UNSET_UINT_INDEX if hash is not present in m_cache[] array.
*/
unsigned int Internal_CacheIndex(const ON_SHA1_Hash& hash) const;
};
#if defined(ON_DLL_TEMPLATE)
ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray<ON_BoundingBox>;
ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray<ON_BoundingBoxAndHash>;
#endif
/*
Description:
Get a tight bounding box that contains the points.
Parameters:
dim - [in] (>=1)
is_rat - [in] true if points are rational
count - [in] number of points
stride - [in] stride between points
point_list - [in]
bbox - [in/out]
bGrowBox - [in] (default = false)
If the input bbox is valid and bGrowBox is true,
then the output bbox is the union of the input
bbox and the bounding box of the point list.
xform - [in] (default = nullptr)
If not null, the bounding box of the transformed
points is calculated. The points are not modified.
Returns:
True if the output bbox is valid.
*/
ON_DECL
bool ON_GetPointListBoundingBox(
int dim,
bool is_rat,
int count,
int stride,
const double* point_list,
ON_BoundingBox& bbox,
int bGrowBox = false,
const ON_Xform* xform = 0
);
ON_DECL
bool ON_GetPointListBoundingBox(
int dim,
bool is_rat,
int count,
int stride,
const float* point_list,
ON_BoundingBox& bbox,
int bGrowBox = false,
const ON_Xform* xform = 0
);
ON_DECL
bool ON_GetPointListBoundingBox(
int dim,
bool is_rat,
int count,
int stride,
const double* point_list,
double* boxmin, // min[dim]
double* boxmax, // max[dim]
int bGrowBox
);
ON_DECL
ON_BoundingBox ON_PointListBoundingBox(
int dim,
bool is_rat,
int count,
int stride,
const double* point_list
);
ON_DECL
bool ON_GetPointListBoundingBox(
int dim,
bool is_rat,
int count,
int stride,
const float* point_list,
float* boxmin, // min[dim]
float* boxmax, // max[dim]
int bGrowBox
);
ON_DECL
ON_BoundingBox ON_PointListBoundingBox( // low level workhorse function
int dim,
bool is_rat,
int count,
int stride,
const float* point_list
);
ON_DECL
bool ON_GetPointGridBoundingBox(
int dim,
bool is_rat,
int point_count0, int point_count1,
int point_stride0, int point_stride1,
const double* point_grid,
double* boxmin, // min[dim]
double* boxmax, // max[dim]
int bGrowBox
);
ON_DECL
ON_BoundingBox ON_PointGridBoundingBox(
int dim,
bool is_rat,
int point_count0, int point_count1,
int point_stride0, int point_stride1,
const double* point_grid
);
ON_DECL
double ON_BoundingBoxTolerance(
int dim,
const double* bboxmin,
const double* bboxmax
);
/*
Description:
Determine if an object is too large or too far
from the origin for single precision coordinates
to be useful.
Parameters:
bbox - [in]
Bounding box of an object with single precision
coordinates. An ON_Mesh is an example of an
object with single precision coordinates.
xform - [out]
If this function returns false and xform is not
null, then the identity transform is returned.
If this function returns true and xform is not
null, then the transform moves the region
contained in bbox to a location where single
precision coordinates will have enough
information for the object to be useful.
Returns:
true:
The region contained in bbox is too large
or too far from the origin for single
precision coordinates to be useful.
false:
A single precision object contained in bbox
will be satisfactory for common calculations.
*/
ON_DECL
bool ON_BeyondSinglePrecision( const ON_BoundingBox& bbox, ON_Xform* xform );
ON_DECL
bool ON_WorldBBoxIsInTightBBox(
const ON_BoundingBox& tight_bbox,
const ON_BoundingBox& world_bbox,
const ON_Xform* xform
);
#endif