mirror of
https://github.com/mcneel/opennurbs.git
synced 2026-03-22 02:20:35 +08:00
Sync changes from upstream repository
Co-authored-by: Alain <alain@mcneel.com> Co-authored-by: Andrew Le Bihan <andy@mcneel.com> Co-authored-by: Bozo <bozo@mcneel.com> Co-authored-by: chuck <chuck@mcneel.com> Co-authored-by: Dale Fugier <dale@mcneel.com> Co-authored-by: Giulio Piacentino <giulio@mcneel.com> Co-authored-by: John Croudy <croudyj@gmail.com> Co-authored-by: Mikko Oksanen <mikko@mcneel.com> Co-authored-by: Pierre Cuvilliers <pierre@mcneel.com> Co-authored-by: Steve Baer <steve@mcneel.com>
This commit is contained in:
@@ -1,266 +1,266 @@
|
||||
#include "opennurbs.h"
|
||||
|
||||
#if !defined(ON_COMPILING_OPENNURBS)
|
||||
// This check is included in all opennurbs source .c and .cpp files to insure
|
||||
// ON_COMPILING_OPENNURBS is defined when opennurbs source is compiled.
|
||||
// When opennurbs source is being compiled, ON_COMPILING_OPENNURBS is defined
|
||||
// and the opennurbs .h files alter what is declared and how it is declared.
|
||||
#error ON_COMPILING_OPENNURBS must be defined when compiling opennurbs
|
||||
#endif
|
||||
|
||||
ON_Box::ON_Box()
|
||||
{}
|
||||
|
||||
ON_Box::ON_Box( const ON_BoundingBox& bbox )
|
||||
{
|
||||
Create(bbox);
|
||||
}
|
||||
|
||||
ON_Box::~ON_Box()
|
||||
{}
|
||||
|
||||
void ON_Box::Destroy()
|
||||
{
|
||||
plane = ON_xy_plane;
|
||||
dx = ON_Interval::EmptyInterval;
|
||||
dy = ON_Interval::EmptyInterval;
|
||||
dz = ON_Interval::EmptyInterval;
|
||||
}
|
||||
|
||||
bool ON_Box::IsValid() const
|
||||
{
|
||||
return ( dx.IsIncreasing()
|
||||
&& dy.IsIncreasing()
|
||||
&& dz.IsIncreasing()
|
||||
&& plane.IsValid()
|
||||
);
|
||||
}
|
||||
|
||||
bool ON_Box::Create( const ON_BoundingBox& bbox )
|
||||
{
|
||||
plane = ON_xy_plane;
|
||||
dx.Set(bbox.m_min.x,bbox.m_max.x);
|
||||
dy.Set(bbox.m_min.y,bbox.m_max.y);
|
||||
dz.Set(bbox.m_min.z,bbox.m_max.z);
|
||||
return (dx.IsValid() && dy.IsValid() && dz.IsValid());
|
||||
}
|
||||
|
||||
int ON_Box::IsDegenerate( double tolerance ) const
|
||||
{
|
||||
int rc = 0;
|
||||
// 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
|
||||
if ( !dx.IsIncreasing() || !dy.IsIncreasing() || !dz.IsIncreasing() )
|
||||
{
|
||||
rc = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
const ON_3dVector diag(dx.Length(),dy.Length(),dz.Length());
|
||||
if ( !ON_IsValid(tolerance) || tolerance < 0.0 )
|
||||
{
|
||||
// compute scale invarient tolerance
|
||||
tolerance = diag.MaximumCoordinate()*ON_SQRT_EPSILON;
|
||||
}
|
||||
if ( diag.x <= tolerance )
|
||||
rc++;
|
||||
if ( diag.y <= tolerance )
|
||||
rc++;
|
||||
if ( diag.z <= tolerance )
|
||||
rc++;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
ON_3dPoint ON_Box::Center() const
|
||||
{
|
||||
return plane.PointAt(dx.Mid(),dy.Mid(),dz.Mid());
|
||||
}
|
||||
|
||||
bool ON_Box::GetCorners( ON_3dPoint* corners ) const
|
||||
{
|
||||
int i,j,k,n=0;
|
||||
double r,s,t;
|
||||
for( i= 0; i < 2; i++ )
|
||||
{
|
||||
r = dx.m_t[i];
|
||||
for ( j = 0; j < 2; j++ )
|
||||
{
|
||||
s = dy.m_t[j];
|
||||
for ( k = 0; k < 2; k++ )
|
||||
{
|
||||
t = dz.m_t[k];
|
||||
corners[n++] = plane.PointAt(r,s,t);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ON_Box::GetCorners( ON_SimpleArray<ON_3dPoint>& corners ) const
|
||||
{
|
||||
corners.Empty();
|
||||
corners.Reserve(8);
|
||||
bool rc = GetCorners(corners.Array());
|
||||
if (rc)
|
||||
corners.SetCount(8);
|
||||
return rc;
|
||||
}
|
||||
|
||||
ON_BoundingBox ON_Box::BoundingBox() const
|
||||
{
|
||||
ON_BoundingBox bbox;
|
||||
ON_3dPoint corners[8];
|
||||
if ( GetCorners(corners) )
|
||||
bbox.Set(3,0,8,3,&corners[0].x,false);
|
||||
return bbox;
|
||||
}
|
||||
|
||||
ON_3dPoint ON_Box::PointAt(
|
||||
double r,
|
||||
double s,
|
||||
double t
|
||||
) const
|
||||
{
|
||||
// Do not validate - it is too slow.
|
||||
return plane.PointAt(r,s,t);
|
||||
}
|
||||
|
||||
// returns point on cylinder that is closest to given point
|
||||
bool ON_Box::ClosestPointTo( ON_3dPoint point, double* r, double* s, double* t ) const
|
||||
{
|
||||
// Do not validate box - it is too slow.
|
||||
const ON_3dVector v = point - plane.origin;
|
||||
|
||||
*r = v*plane.xaxis;
|
||||
if ( *r < dx.m_t[0] )
|
||||
*r = dx.m_t[0];
|
||||
else if ( *r > dx.m_t[1] )
|
||||
*r = dx.m_t[1];
|
||||
|
||||
*s = v*plane.yaxis;
|
||||
if ( *s < dy.m_t[0] )
|
||||
*s = dy.m_t[0];
|
||||
else if ( *s > dy.m_t[1] )
|
||||
*s = dy.m_t[1];
|
||||
|
||||
*t = v*plane.zaxis;
|
||||
if ( *t < dz.m_t[0] )
|
||||
*t = dz.m_t[0];
|
||||
else if ( *t > dz.m_t[1] )
|
||||
*t = dz.m_t[1];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ON_3dPoint ON_Box::ClosestPointTo( ON_3dPoint point ) const
|
||||
{
|
||||
// Do not validate - it is too slow.
|
||||
double r,s,t;
|
||||
ClosestPointTo(point,&r,&s,&t);
|
||||
return PointAt(r,s,t);
|
||||
}
|
||||
|
||||
// rotate box about its center
|
||||
bool ON_Box::Rotate(
|
||||
double sin_angle,
|
||||
double cos_angle,
|
||||
const ON_3dVector& axis // axis of rotation
|
||||
)
|
||||
{
|
||||
return Rotate(sin_angle, cos_angle, axis, Center() );
|
||||
}
|
||||
|
||||
bool ON_Box::Rotate(
|
||||
double angle, // angle in radians
|
||||
const ON_3dVector& axis // axis of rotation
|
||||
)
|
||||
{
|
||||
return Rotate(sin(angle), cos(angle), axis, plane.origin );
|
||||
}
|
||||
|
||||
// rotate box about a point and axis
|
||||
bool ON_Box::Rotate(
|
||||
double sin_angle,
|
||||
double cos_angle,
|
||||
const ON_3dVector& axis, // axis of rotation
|
||||
const ON_3dPoint& point // center of rotation
|
||||
)
|
||||
{
|
||||
return plane.Rotate( sin_angle, cos_angle, axis, point );
|
||||
}
|
||||
|
||||
bool ON_Box::Rotate(
|
||||
double angle, // angle in radians
|
||||
const ON_3dVector& axis, // axis of rotation
|
||||
const ON_3dPoint& point // center of rotation
|
||||
)
|
||||
{
|
||||
return Rotate(sin(angle),cos(angle),axis,point);
|
||||
}
|
||||
|
||||
bool ON_Box::Translate(
|
||||
const ON_3dVector& delta
|
||||
)
|
||||
{
|
||||
return plane.Translate(delta);
|
||||
}
|
||||
|
||||
|
||||
bool ON_Box::Transform( const ON_Xform& xform )
|
||||
{
|
||||
ON_3dPoint corners[8];
|
||||
bool rc = GetCorners(corners);
|
||||
if ( rc )
|
||||
{
|
||||
ON_Plane xplane(plane);
|
||||
rc = xplane.Transform(xform);
|
||||
if ( rc )
|
||||
{
|
||||
int i;
|
||||
for ( i = 0; i < 8; i++ )
|
||||
{
|
||||
corners[i] = xform*corners[i];
|
||||
}
|
||||
double x0,x1,x,y0,y1,y,z0,z1,z;
|
||||
ON_3dVector v = corners[7] - plane.origin;
|
||||
x0 = x1 = v*plane.xaxis;
|
||||
y0 = y1 = v*plane.yaxis;
|
||||
z0 = z1 = v*plane.zaxis;
|
||||
for ( i = 0; i < 7; i++ )
|
||||
{
|
||||
v = corners[i] - plane.origin;
|
||||
x = v*plane.xaxis;
|
||||
if ( x < x0 ) x0 = x; else if (x > x1 ) x1 = x;
|
||||
y = v*plane.yaxis;
|
||||
if ( y < y0 ) y0 = y; else if (y > y1 ) y1 = y;
|
||||
z = v*plane.zaxis;
|
||||
if ( z < z0 ) z0 = z; else if (z > z1 ) z1 = z;
|
||||
}
|
||||
double tol = ON_SQRT_EPSILON;
|
||||
if ( fabs(dx.ParameterAt(x0)) > tol || fabs(dx.ParameterAt(x1)-1.0) > tol )
|
||||
dx.Set(x0,x1);
|
||||
if ( fabs(dy.ParameterAt(y0)) > tol || fabs(dy.ParameterAt(y1)-1.0) > tol )
|
||||
dy.Set(y0,y1);
|
||||
if ( fabs(dz.ParameterAt(z0)) > tol || fabs(dz.ParameterAt(z1)-1.0) > tol )
|
||||
dz.Set(z0,z1);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
double ON_Box::Volume() const
|
||||
{
|
||||
return dx.Length()*dy.Length()*dz.Length();
|
||||
}
|
||||
|
||||
double ON_Box::Area() const
|
||||
{
|
||||
double a = dx.Length();
|
||||
double b = dy.Length();
|
||||
double c = dz.Length();
|
||||
return 2.0*(a*b + b*c + c*a);
|
||||
}
|
||||
#include "opennurbs.h"
|
||||
|
||||
#if !defined(ON_COMPILING_OPENNURBS)
|
||||
// This check is included in all opennurbs source .c and .cpp files to insure
|
||||
// ON_COMPILING_OPENNURBS is defined when opennurbs source is compiled.
|
||||
// When opennurbs source is being compiled, ON_COMPILING_OPENNURBS is defined
|
||||
// and the opennurbs .h files alter what is declared and how it is declared.
|
||||
#error ON_COMPILING_OPENNURBS must be defined when compiling opennurbs
|
||||
#endif
|
||||
|
||||
ON_Box::ON_Box()
|
||||
{}
|
||||
|
||||
ON_Box::ON_Box( const ON_BoundingBox& bbox )
|
||||
{
|
||||
Create(bbox);
|
||||
}
|
||||
|
||||
ON_Box::~ON_Box()
|
||||
{}
|
||||
|
||||
void ON_Box::Destroy()
|
||||
{
|
||||
plane = ON_xy_plane;
|
||||
dx = ON_Interval::EmptyInterval;
|
||||
dy = ON_Interval::EmptyInterval;
|
||||
dz = ON_Interval::EmptyInterval;
|
||||
}
|
||||
|
||||
bool ON_Box::IsValid() const
|
||||
{
|
||||
return ( dx.IsIncreasing()
|
||||
&& dy.IsIncreasing()
|
||||
&& dz.IsIncreasing()
|
||||
&& plane.IsValid()
|
||||
);
|
||||
}
|
||||
|
||||
bool ON_Box::Create( const ON_BoundingBox& bbox )
|
||||
{
|
||||
plane = ON_xy_plane;
|
||||
dx.Set(bbox.m_min.x,bbox.m_max.x);
|
||||
dy.Set(bbox.m_min.y,bbox.m_max.y);
|
||||
dz.Set(bbox.m_min.z,bbox.m_max.z);
|
||||
return (dx.IsValid() && dy.IsValid() && dz.IsValid());
|
||||
}
|
||||
|
||||
int ON_Box::IsDegenerate( double tolerance ) const
|
||||
{
|
||||
int rc = 0;
|
||||
// 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
|
||||
if ( !dx.IsIncreasing() || !dy.IsIncreasing() || !dz.IsIncreasing() )
|
||||
{
|
||||
rc = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
const ON_3dVector diag(dx.Length(),dy.Length(),dz.Length());
|
||||
if ( !ON_IsValid(tolerance) || tolerance < 0.0 )
|
||||
{
|
||||
// compute scale invarient tolerance
|
||||
tolerance = diag.MaximumCoordinate()*ON_SQRT_EPSILON;
|
||||
}
|
||||
if ( diag.x <= tolerance )
|
||||
rc++;
|
||||
if ( diag.y <= tolerance )
|
||||
rc++;
|
||||
if ( diag.z <= tolerance )
|
||||
rc++;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
ON_3dPoint ON_Box::Center() const
|
||||
{
|
||||
return plane.PointAt(dx.Mid(),dy.Mid(),dz.Mid());
|
||||
}
|
||||
|
||||
bool ON_Box::GetCorners( ON_3dPoint* corners ) const
|
||||
{
|
||||
int i,j,k,n=0;
|
||||
double r,s,t;
|
||||
for( i= 0; i < 2; i++ )
|
||||
{
|
||||
r = dx.m_t[i];
|
||||
for ( j = 0; j < 2; j++ )
|
||||
{
|
||||
s = dy.m_t[j];
|
||||
for ( k = 0; k < 2; k++ )
|
||||
{
|
||||
t = dz.m_t[k];
|
||||
corners[n++] = plane.PointAt(r,s,t);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ON_Box::GetCorners( ON_SimpleArray<ON_3dPoint>& corners ) const
|
||||
{
|
||||
corners.Empty();
|
||||
corners.Reserve(8);
|
||||
bool rc = GetCorners(corners.Array());
|
||||
if (rc)
|
||||
corners.SetCount(8);
|
||||
return rc;
|
||||
}
|
||||
|
||||
ON_BoundingBox ON_Box::BoundingBox() const
|
||||
{
|
||||
ON_BoundingBox bbox;
|
||||
ON_3dPoint corners[8];
|
||||
if ( GetCorners(corners) )
|
||||
bbox.Set(3,0,8,3,&corners[0].x,false);
|
||||
return bbox;
|
||||
}
|
||||
|
||||
ON_3dPoint ON_Box::PointAt(
|
||||
double r,
|
||||
double s,
|
||||
double t
|
||||
) const
|
||||
{
|
||||
// Do not validate - it is too slow.
|
||||
return plane.PointAt(r,s,t);
|
||||
}
|
||||
|
||||
// returns point on cylinder that is closest to given point
|
||||
bool ON_Box::ClosestPointTo( ON_3dPoint point, double* r, double* s, double* t ) const
|
||||
{
|
||||
// Do not validate box - it is too slow.
|
||||
const ON_3dVector v = point - plane.origin;
|
||||
|
||||
*r = v*plane.xaxis;
|
||||
if ( *r < dx.m_t[0] )
|
||||
*r = dx.m_t[0];
|
||||
else if ( *r > dx.m_t[1] )
|
||||
*r = dx.m_t[1];
|
||||
|
||||
*s = v*plane.yaxis;
|
||||
if ( *s < dy.m_t[0] )
|
||||
*s = dy.m_t[0];
|
||||
else if ( *s > dy.m_t[1] )
|
||||
*s = dy.m_t[1];
|
||||
|
||||
*t = v*plane.zaxis;
|
||||
if ( *t < dz.m_t[0] )
|
||||
*t = dz.m_t[0];
|
||||
else if ( *t > dz.m_t[1] )
|
||||
*t = dz.m_t[1];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ON_3dPoint ON_Box::ClosestPointTo( ON_3dPoint point ) const
|
||||
{
|
||||
// Do not validate - it is too slow.
|
||||
double r,s,t;
|
||||
ClosestPointTo(point,&r,&s,&t);
|
||||
return PointAt(r,s,t);
|
||||
}
|
||||
|
||||
// rotate box about its center
|
||||
bool ON_Box::Rotate(
|
||||
double sin_angle,
|
||||
double cos_angle,
|
||||
const ON_3dVector& axis // axis of rotation
|
||||
)
|
||||
{
|
||||
return Rotate(sin_angle, cos_angle, axis, Center() );
|
||||
}
|
||||
|
||||
bool ON_Box::Rotate(
|
||||
double angle, // angle in radians
|
||||
const ON_3dVector& axis // axis of rotation
|
||||
)
|
||||
{
|
||||
return Rotate(sin(angle), cos(angle), axis, plane.origin );
|
||||
}
|
||||
|
||||
// rotate box about a point and axis
|
||||
bool ON_Box::Rotate(
|
||||
double sin_angle,
|
||||
double cos_angle,
|
||||
const ON_3dVector& axis, // axis of rotation
|
||||
const ON_3dPoint& point // center of rotation
|
||||
)
|
||||
{
|
||||
return plane.Rotate( sin_angle, cos_angle, axis, point );
|
||||
}
|
||||
|
||||
bool ON_Box::Rotate(
|
||||
double angle, // angle in radians
|
||||
const ON_3dVector& axis, // axis of rotation
|
||||
const ON_3dPoint& point // center of rotation
|
||||
)
|
||||
{
|
||||
return Rotate(sin(angle),cos(angle),axis,point);
|
||||
}
|
||||
|
||||
bool ON_Box::Translate(
|
||||
const ON_3dVector& delta
|
||||
)
|
||||
{
|
||||
return plane.Translate(delta);
|
||||
}
|
||||
|
||||
|
||||
bool ON_Box::Transform( const ON_Xform& xform )
|
||||
{
|
||||
ON_3dPoint corners[8];
|
||||
bool rc = GetCorners(corners);
|
||||
if ( rc )
|
||||
{
|
||||
ON_Plane xplane(plane);
|
||||
rc = xplane.Transform(xform);
|
||||
if ( rc )
|
||||
{
|
||||
int i;
|
||||
for ( i = 0; i < 8; i++ )
|
||||
{
|
||||
corners[i] = xform*corners[i];
|
||||
}
|
||||
double x0,x1,x,y0,y1,y,z0,z1,z;
|
||||
ON_3dVector v = corners[7] - plane.origin;
|
||||
x0 = x1 = v*plane.xaxis;
|
||||
y0 = y1 = v*plane.yaxis;
|
||||
z0 = z1 = v*plane.zaxis;
|
||||
for ( i = 0; i < 7; i++ )
|
||||
{
|
||||
v = corners[i] - plane.origin;
|
||||
x = v*plane.xaxis;
|
||||
if ( x < x0 ) x0 = x; else if (x > x1 ) x1 = x;
|
||||
y = v*plane.yaxis;
|
||||
if ( y < y0 ) y0 = y; else if (y > y1 ) y1 = y;
|
||||
z = v*plane.zaxis;
|
||||
if ( z < z0 ) z0 = z; else if (z > z1 ) z1 = z;
|
||||
}
|
||||
double tol = ON_SQRT_EPSILON;
|
||||
if ( fabs(dx.ParameterAt(x0)) > tol || fabs(dx.ParameterAt(x1)-1.0) > tol )
|
||||
dx.Set(x0,x1);
|
||||
if ( fabs(dy.ParameterAt(y0)) > tol || fabs(dy.ParameterAt(y1)-1.0) > tol )
|
||||
dy.Set(y0,y1);
|
||||
if ( fabs(dz.ParameterAt(z0)) > tol || fabs(dz.ParameterAt(z1)-1.0) > tol )
|
||||
dz.Set(z0,z1);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
double ON_Box::Volume() const
|
||||
{
|
||||
return dx.Length()*dy.Length()*dz.Length();
|
||||
}
|
||||
|
||||
double ON_Box::Area() const
|
||||
{
|
||||
double a = dx.Length();
|
||||
double b = dy.Length();
|
||||
double c = dz.Length();
|
||||
return 2.0*(a*b + b*c + c*a);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user