Files
opennurbs/opennurbs_point.cpp
Will Pearson 5f462fed0d Update source to v6.8.18240.20051
Previous source was actually for 6.1...
2018-09-15 11:26:15 -07:00

9266 lines
199 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>.
//
////////////////////////////////////////////////////////////////
*/
#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
bool ON_IsValid(double x)
{
return ON_IS_VALID(x);
}
int ON_CompareDouble(
double a,
double b
)
{
if (a < b)
return -1;
if (a > b)
return 1;
if (a == b)
return 0;
// below this point, a and/or b is a nan
if (a == a)
return -1; // b is a nan
if (b == b)
return 1; // ab is a nan
return 0; // both a and b are nans
}
int ON_CompareFloat(
float a,
float b
)
{
if (a < b)
return -1;
if (a > b)
return 1;
if (a == b)
return 0;
// below this point, a and/or b is a nan
if (a == a)
return -1; // b is a nan
if (b == b)
return 1; // ab is a nan
return 0; // both a and b are nans
}
static int Internal_DoubleArrayCompare(
size_t count,
const double* a,
const double* b
)
{
const double* e = a + count;
int rc = ON_CompareDouble(*a++, *b++);
while( 0 == rc && a < e)
rc = ON_CompareDouble(*a++, *b++);
return rc;
}
static int Internal_FloatArrayCompare(
size_t count,
const float* a,
const float* b
)
{
const float* e = a + count;
int rc = ON_CompareFloat(*a++, *b++);
while( 0 == rc && a < e)
rc = ON_CompareFloat(*a++, *b++);
return rc;
}
int ON_CompareDoubleArray(
size_t count,
const double* a,
const double* b
)
{
if (count <= 0)
return 0;
if (a == b)
return 0;
if (nullptr == a)
return 1;
if (nullptr == b)
return -1;
return Internal_DoubleArrayCompare(count, a, b);
}
static bool Internal_IsUnsetFloat(
size_t count,
const float* a
)
{
const float * e = a + count;
while (a < e)
{
float x = *a++;
if (ON_UNSET_FLOAT == x || ON_UNSET_POSITIVE_FLOAT == x)
return true;
}
return false;
}
bool ON_2fPoint::IsUnset() const
{
return Internal_IsUnsetFloat(2, &x);
}
bool ON_3fPoint::IsUnset() const
{
return Internal_IsUnsetFloat(3, &x);
}
bool ON_4fPoint::IsUnset() const
{
return Internal_IsUnsetFloat(4, &x);
}
bool ON_2fVector::IsUnset() const
{
return Internal_IsUnsetFloat(2, &x);
}
bool ON_3fVector::IsUnset() const
{
return Internal_IsUnsetFloat(3, &x);
}
static bool Internal_IsUnsetDouble(
size_t count,
const double* a
)
{
const double * e = a + count;
while (a < e)
{
double x = *a++;
if (ON_UNSET_VALUE == x || ON_UNSET_POSITIVE_VALUE == x)
return true;
}
return false;
}
bool ON_2dPoint::IsUnset() const
{
return Internal_IsUnsetDouble(2, &x);
}
bool ON_3dPoint::IsUnset() const
{
return Internal_IsUnsetDouble(3, &x);
}
bool ON_4dPoint::IsUnset() const
{
return Internal_IsUnsetDouble(4, &x);
}
bool ON_2dVector::IsUnset() const
{
return Internal_IsUnsetDouble(2, &x);
}
bool ON_3dVector::IsUnset() const
{
return Internal_IsUnsetDouble(3, &x);
}
int ON_2dVector::Compare(
const ON_2dVector& lhs,
const ON_2dVector& rhs
)
{
return Internal_DoubleArrayCompare(2, &lhs.x, &rhs.x);
}
int ON_3dVector::Compare(
const ON_3dVector& lhs,
const ON_3dVector& rhs
)
{
return Internal_DoubleArrayCompare(3, &lhs.x, &rhs.x);
}
int ON_2dPoint::Compare(
const ON_2dPoint& lhs,
const ON_2dPoint& rhs
)
{
return Internal_DoubleArrayCompare(2, &lhs.x, &rhs.x);
}
int ON_3dPoint::Compare(
const ON_3dPoint& lhs,
const ON_3dPoint& rhs
)
{
return Internal_DoubleArrayCompare(3, &lhs.x, &rhs.x);
}
int ON_4dPoint::ProjectiveCompare(
const ON_4dPoint& lhs,
const ON_4dPoint& rhs
)
{
if (lhs.w == rhs.w)
{
// neither lhs.w nor rhs.w is a nan
return Internal_DoubleArrayCompare(3, &lhs.x, &rhs.x);
}
if (0.0 != lhs.w && 0.0 != rhs.w)
{
// neither lhs.w nor rhs.w is a nan
return ON_3dPoint::Compare(ON_3dPoint(lhs), ON_3dPoint(lhs));
}
if (0.0 != lhs.w && 0.0 == rhs.w)
{
// neither lhs.w nor rhs.w is a nan
return -1;
}
if (0.0 == lhs.w && 0.0 != rhs.w)
{
// neither lhs.w nor rhs.w is a nan
return 1;
}
if (lhs.w == lhs.w)
{
// rhs.w is a nan
return -1;
}
if (rhs.w == rhs.w)
{
// lhs.w is a nan
return 1;
}
// lhs.w and rhs.w are both nans
return Internal_DoubleArrayCompare(3, &lhs.x, &rhs.x);
}
int ON_4dPoint::DictionaryCompare(
const ON_4dPoint& lhs,
const ON_4dPoint& rhs
)
{
return Internal_DoubleArrayCompare(4, &lhs.x, &rhs.x);
}
static double Internal_4dEuclideanCoordinate(double x, double w)
{
return
((ON_IS_UNSET_DOUBLE(x) || ON_IS_UNSET_DOUBLE(w)) && x==x && w==w)
? ON_UNSET_VALUE
: (x / w);
}
double ON_4dPoint::EuclideanX() const
{
return Internal_4dEuclideanCoordinate(x,w);
}
double ON_4dPoint::EuclideanY() const
{
return Internal_4dEuclideanCoordinate(y,w);
}
double ON_4dPoint::EuclideanZ() const
{
return Internal_4dEuclideanCoordinate(z,w);
}
static float Internal_4fEuclideanCoordinate(float x, float w)
{
return
((ON_IS_UNSET_FLOAT(x) || ON_IS_UNSET_FLOAT(w)) && x == x && w==w)
? ON_UNSET_FLOAT
: (x / w);
}
float ON_4fPoint::EuclideanX() const
{
return Internal_4fEuclideanCoordinate(x,w);
}
float ON_4fPoint::EuclideanY() const
{
return Internal_4fEuclideanCoordinate(y,w);
}
float ON_4fPoint::EuclideanZ() const
{
return Internal_4fEuclideanCoordinate(z,w);
}
int ON_2fVector::Compare(
const ON_2fVector& lhs,
const ON_2fVector& rhs
)
{
return Internal_FloatArrayCompare(2, &lhs.x, &rhs.x);
}
int ON_3fVector::Compare(
const ON_3fVector& lhs,
const ON_3fVector& rhs
)
{
return Internal_FloatArrayCompare(3, &lhs.x, &rhs.x);
}
int ON_2fPoint::Compare(
const ON_2fPoint& lhs,
const ON_2fPoint& rhs
)
{
return Internal_FloatArrayCompare(2, &lhs.x, &rhs.x);
}
int ON_3fPoint::Compare(
const ON_3fPoint& lhs,
const ON_3fPoint& rhs
)
{
return Internal_FloatArrayCompare(3, &lhs.x, &rhs.x);
}
int ON_4fPoint::DictionaryCompare(
const ON_4fPoint& lhs,
const ON_4fPoint& rhs
)
{
return Internal_FloatArrayCompare(4, &lhs.x, &rhs.x);
}
int ON_4fPoint::ProjectiveCompare(
const ON_4fPoint& lhs,
const ON_4fPoint& rhs
)
{
return ON_4dPoint::ProjectiveCompare(ON_4dPoint(lhs), ON_4dPoint(rhs));
}
bool ON_IsValidFloat(float x)
{
return ON_IS_VALID_FLOAT(x);
}
ON_Interval::ON_Interval()
{
m_t[0] = m_t[1] = ON_UNSET_VALUE;
}
ON_Interval::ON_Interval(double t0, double t1)
{
Set(t0,t1);
}
bool ON_Interval::operator!=(const ON_Interval& rhs) const
{
// Intentionally returns false if any double is a nan.
if (m_t[0] != rhs.m_t[0])
{
return (m_t[1] == m_t[1] && rhs.m_t[1] == rhs.m_t[1]);
}
return (m_t[0] == m_t[0] && m_t[1] != rhs.m_t[1]);
}
bool ON_Interval::operator==(const ON_Interval& rhs) const
{
// Intentionally returns false if any double is a nan.
return (m_t[0] == rhs.m_t[0] && m_t[1] == rhs.m_t[1]);
}
double&
ON_Interval::operator[](int i)
{
return m_t[(i<=0)?0:1];
}
double
ON_Interval::operator[](int i) const
{
return m_t[(i<=0)?0:1];
}
double&
ON_Interval::operator[](unsigned int i)
{
return m_t[(i<=0)?0:1];
}
double
ON_Interval::operator[](unsigned int i) const
{
return m_t[(i<=0)?0:1];
}
double
ON_Interval::Min() const
{
if (m_t[0] <= m_t[1])
return m_t[0];
if (m_t[1] <= m_t[0])
return m_t[1];
return ON_DBL_QNAN;
}
void ON_Interval::Destroy()
{
*this = ON_Interval::EmptyInterval;
}
void ON_Interval::Set(double t0,double t1)
{
m_t[0] = t0;
m_t[1] = t1;
}
double ON_Interval::ParameterAt(double x) const
{
return (ON_IS_VALID(x) ? ((1.0-x)*m_t[0] + x*m_t[1]) : ON_UNSET_VALUE);
}
ON_Interval ON_Interval::ParameterAt(ON_Interval x) const
{
return ON_Interval( ParameterAt(x[0]), ParameterAt(x[1]) );
}
double ON_Interval::NormalizedParameterAt( // returns x so that min*(1.0-x) + max*x = input
double t
) const
{
if (!ON_IS_VALID(t))
return ON_UNSET_VALUE; // added 29 Sep 2006
double x = m_t[0];
if ( m_t[0] != m_t[1] ) {
x = ( t == m_t[1]) ? 1.0 : (t - m_t[0])/(m_t[1] - m_t[0]);
}
return x;
}
ON_Interval ON_Interval::NormalizedParameterAt( // returns x so that min*(1.0-x) + max*x = input
ON_Interval t
) const
{
return ON_Interval( NormalizedParameterAt(t[0]) ,
NormalizedParameterAt(t[1]) );
}
double
ON_Interval::Max() const
{
if (m_t[0] >= m_t[1])
return m_t[0];
if (m_t[1] >= m_t[0])
return m_t[1];
return ON_DBL_QNAN;
}
double
ON_Interval::Mid() const
{
return 0.5*(m_t[0]+m_t[1]);
}
double
ON_Interval::Length() const
{
return ( ON_IS_VALID(m_t[0]) && ON_IS_VALID(m_t[1]) ) ? m_t[1]-m_t[0] : 0.0;
}
bool
ON_Interval::IsIncreasing() const
{
return ( m_t[0] < m_t[1] && ON_IS_VALID(m_t[0]) && ON_IS_VALID(m_t[1]) ) ? true : false;
}
bool
ON_Interval::IsDecreasing() const
{
return ( m_t[0] > m_t[1] && ON_IS_VALID(m_t[0]) && ON_IS_VALID(m_t[1]) ) ? true : false;
}
bool
ON_Interval::IsInterval() const
{
return ( m_t[0] != m_t[1] && ON_IS_VALID(m_t[0]) && ON_IS_VALID(m_t[1]) ) ? true : false;
}
bool
ON_Interval::IsSingleton() const
{
return ( m_t[0] == m_t[1] && ON_IS_VALID(m_t[1]) ) ? true : false;
}
bool
ON_Interval::IsEmptyInterval() const
{
return ( m_t[0] == ON_UNSET_VALUE && m_t[1] == ON_UNSET_VALUE ) ? true : false;
}
bool
ON_Interval::IsEmptySet() const
{
return ( m_t[0] == ON_UNSET_VALUE && m_t[1] == ON_UNSET_VALUE ) ? true : false;
}
bool
ON_Interval::IsValid() const
{
// 05/29/2007 TimH. Changed 0 to 1.
return ( ON_IS_VALID(m_t[0]) && ON_IS_VALID(m_t[1]) );
}
bool
ON_Interval::MakeIncreasing() // returns true if resulting interval IsIncreasing()
{
if( IsDecreasing()){
Swap();
return true;
}
return IsIncreasing();
}
int ON_Interval::Compare(const ON_Interval& lhs, const ON_Interval& rhs)
{
return Internal_DoubleArrayCompare(2, lhs.m_t, rhs.m_t);
}
bool
ON_Interval::Includes( double t, bool bTestOpenInterval) const
{
bool rc = false;
if ( ON_IS_VALID(t) && ON_IS_VALID(m_t[0]) && ON_IS_VALID(m_t[1]) )
{
int i = (m_t[0] <= m_t[1]) ? 0 : 1;
if ( bTestOpenInterval )
{
rc = ( m_t[i] < t && t < m_t[1-i] ) ? true : false;
}
else
{
rc = ( m_t[i] <= t && t <= m_t[1-i] ) ? true : false;
}
}
return rc;
}
bool
ON_Interval::Includes( const ON_Interval& other, bool bProperSubSet ) const
{
bool rc = ( Includes( other.m_t[0] ) && Includes( other.m_t[1] ) ) ? true : false;
if ( rc && bProperSubSet )
{
if ( !Includes( other.m_t[0], true ) && !Includes( other.m_t[1], true ) )
rc = false;
}
return rc;
}
bool
ON_Interval::IntervalsOverlap(const ON_Interval& A, const ON_Interval& B)
{
ON_Interval C;
C.Intersection(A, B);
return C.IsEmptyInterval() ? false : true;
}
void
ON_Interval::Reverse()
{
if ( !IsEmptyInterval() ) {
const double x = -m_t[0];
m_t[0] = -m_t[1];
m_t[1] = x;
}
}
void
ON_Interval::Swap()
{
const double x = m_t[0];
m_t[0] = m_t[1];
m_t[1] = x;
}
//////////
// If the intersection is not empty, then
// intersection = [max(this.Min(),arg.Min()), min(this.Max(),arg.Max())]
// Intersection() returns true if the intersection is not empty.
// The interval [ON_UNSET_VALUE,ON_UNSET_VALUE] is considered to be
// the empty set interval. The result of any intersection involving an
// empty set interval or disjoint intervals is the empty set interval.
bool ON_Interval::Intersection( // this = this intersect arg
const ON_Interval& other
)
{
bool rc = false;
if (IsEmptyInterval() && other.IsEmptyInterval())
{
*this = ON_Interval::EmptyInterval;
}
else
{
double a, b, mn, mx;
a = Min();
b = other.Min();
mn = (a>=b) ? a : b;
a = Max();
b = other.Max();
mx = (a<=b) ? a : b;
if ( mn <= mx )
{
Set(mn,mx);
rc = true;
}
else
{
*this = ON_Interval::EmptyInterval;
}
}
return rc;
}
//////////
// If the intersection is not empty, then
// intersection = [max(argA.Min(),argB.Min()), min(argA.Max(),argB.Max())]
// Intersection() returns true if the intersection is not empty.
// The interval [ON_UNSET_VALUE,ON_UNSET_VALUE] is considered to be
// the empty set interval. The result of any intersection involving an
// empty set interval or disjoint intervals is the empty set interval.
bool ON_Interval::Intersection( // this = intersection of two args
const ON_Interval& ain,
const ON_Interval& bin
)
{
bool rc = false;
if ( ain.IsEmptyInterval() && bin.IsEmptyInterval() )
{
*this = ON_Interval::EmptyInterval;
}
else
{
double a, b, mn, mx;
a = ain.Min();
b = bin.Min();
mn = (a >= b) ? a : b;
a = ain.Max();
b = bin.Max();
mx = (a <= b) ? a : b;
if (mn <= mx)
{
Set(mn, mx);
rc = true;
}
else
{
*this = ON_Interval::EmptyInterval;
}
}
return rc;
}
//////////
// The union of an empty set and an increasing interval is the increasing
// interval. The union of two empty sets is empty. The union of an empty
// set an a non-empty interval is the non-empty interval.
// The union of two non-empty intervals is
// union = [min(this.Min(),arg.Min()), max(this.Max(),arg.Max()),]
// Union() returns true if the union is not empty.
bool ON_Interval::Union( // this = this union arg
const ON_Interval& other
)
{
bool rc = false;
if ( other.IsEmptyInterval() )
{
// this may be increasing, decreasing, or empty
Set( Min(), Max() );
rc = !IsEmptyInterval();
}
else if ( IsEmptyInterval() )
{
// other may be increasing or decreasing
Set( other.Min(), other.Max() );
rc = true;
}
else {
double a, b, mn, mx;
a = Min();
b = other.Min();
mn = (a<=b) ? a : b;
a = Max();
b = other.Max();
mx = (a>=b) ? a : b;
if ( mn <= mx ) {
Set(mn,mx);
rc = true;
}
else
{
*this = ON_Interval::EmptyInterval;
}
}
return rc;
}
bool ON_Interval::Union(
int count,
const double* t
)
{
bool rc = false;
double a, mn, mx;
if ( 0 != t )
{
while ( count > 0 && !ON_IsValid(*t) )
{
count--;
t++;
}
}
if ( count <= 0 || 0 == t )
{
// this may be increasing, decreasing, or empty
if ( !IsEmptyInterval() )
{
mn = Min();
mx = Max();
if ( mn <= mx && ON_IsValid(mn) && ON_IsValid(mx) )
{
Set( mn, mx );
rc = true;
}
}
}
else
{
if ( IsEmptyInterval() )
{
a = *t++;
Set( a, a );
count--;
rc = true;
}
mn = Min();
mx = Max();
while( count > 0 )
{
count--;
a = *t++;
if ( ON_IsValid(a) )
{
if ( a < mn )
mn = a;
else if ( a > mx )
mx = a;
}
}
if ( mn <= mx && ON_IsValid(mn) && ON_IsValid(mx) )
{
Set(mn,mx);
rc = true;
}
else
{
*this = ON_Interval::EmptyInterval;
}
}
return rc;
}
bool ON_Interval::Union(
double t
)
{
return Union(1,&t);
}
//////////
// The union of an empty set and an increasing interval is the increasing
// interval. The union of two empty sets is empty. The union of an empty
// set an a non-empty interval is the non-empty interval.
// The union of two non-empty intervals is
// union = [min(argA.Min(),argB.Min()), max(argA.Max(),argB.Max()),]
// Union() returns true if the union is not empty.
bool ON_Interval::Union( // this = union of two args
const ON_Interval& ain,
const ON_Interval& bin
)
{
bool rc = false;
if ( bin.IsEmptyInterval() )
{
// ain may be increasing, decreasing, or empty
Set( ain.Min(), ain.Max() );
rc = !IsEmptyInterval();
}
else if ( ain.IsEmptyInterval() )
{
// bin may be increasing or decreasing
Set( bin.Min(), bin.Max() );
rc = true;
}
else {
double a, b, mn, mx;
a = ain.Min();
b = bin.Min();
mn = (a<=b) ? a : b;
a = ain.Max();
b = bin.Max();
mx = (a>=b) ? a : b;
if ( mn <= mx ) {
Set(mn,mx);
rc = true;
}
else
{
*this = ON_Interval::EmptyInterval;
}
}
return rc;
}
bool ON_3dVector::Decompose( // Computes a, b, c such that this vector = a*X + b*Y + c*Z
//
// If X,Y,Z is known to be an orthonormal frame,
// then a = V*X, b = V*Y, c = V*Z will compute
// the same result more quickly.
const ON_3dVector& X,
const ON_3dVector& Y,
const ON_3dVector& Z,
double* a,
double* b,
double* c
) const
{
int rank;
double pivot_ratio = 0.0;
double row0[3], row1[3], row2[3];
row0[0] = X*X; row0[1] = X*Y; row0[2] = X*Z;
row1[0] = row0[1]; row1[1] = Y*Y; row1[2] = Y*Z;
row2[0] = row0[2]; row2[1] = row1[2]; row2[2] = Z*Z;
rank = ON_Solve3x3( row0, row1, row2,
(*this)*X, (*this)*Y, (*this)*Z,
a, b, c, &pivot_ratio );
return (rank == 3) ? true : false;
}
int ON_3dVector::IsParallelTo(
// returns 1: this and other vectors are and parallel
// -1: this and other vectors are anti-parallel
// 0: this and other vectors are not parallel
// or at least one of the vectors is zero
const ON_3dVector& v,
double angle_tolerance // (default=ON_DEFAULT_ANGLE_TOLERANCE) radians
) const
{
int rc = 0;
const double ll = Length()*v.Length();
if ( ll > 0.0 ) {
const double cos_angle = (x*v.x + y*v.y + z*v.z)/ll;
const double cos_tol = cos(angle_tolerance);
if ( cos_angle >= cos_tol )
rc = 1;
else if ( cos_angle <= -cos_tol )
rc = -1;
}
return rc;
}
bool ON_3fVector::IsPerpendicularTo(
// returns true: this and other vectors are perpendicular
// false: this and other vectors are not perpendicular
// or at least one of the vectors is zero
const ON_3fVector& v,
double angle_tolerance // (default=ON_DEFAULT_ANGLE_TOLERANCE) radians
) const
{
ON_3dVector V(*this);
return V.IsPerpendicularTo(ON_3dVector(v),angle_tolerance);
}
bool ON_3dVector::IsPerpendicularTo(
// returns true: this and other vectors are perpendicular
// false: this and other vectors are not perpendicular
// or at least one of the vectors is zero
const ON_3dVector& v,
double angle_tolerance // (default=ON_DEFAULT_ANGLE_TOLERANCE) radians
) const
{
bool rc = false;
const double ll = Length()*v.Length();
if ( ll > 0.0 ) {
if ( fabs((x*v.x + y*v.y + z*v.z)/ll) <= sin(angle_tolerance) )
rc = true;
}
return rc;
}
bool ON_3fVector::PerpendicularTo( const ON_3fVector& v )
{
ON_3dVector V(*this);
return V.IsPerpendicularTo(ON_3dVector(v));
}
bool ON_3dVector::PerpendicularTo( const ON_3dVector& v )
{
//bool rc = false;
int i, j, k;
double a, b;
k = 2;
if ( fabs(v.y) > fabs(v.x) ) {
if ( fabs(v.z) > fabs(v.y) ) {
// |v.z| > |v.y| > |v.x|
i = 2;
j = 1;
k = 0;
a = v.z;
b = -v.y;
}
else if ( fabs(v.z) >= fabs(v.x) ){
// |v.y| >= |v.z| >= |v.x|
i = 1;
j = 2;
k = 0;
a = v.y;
b = -v.z;
}
else {
// |v.y| > |v.x| > |v.z|
i = 1;
j = 0;
k = 2;
a = v.y;
b = -v.x;
}
}
else if ( fabs(v.z) > fabs(v.x) ) {
// |v.z| > |v.x| >= |v.y|
i = 2;
j = 0;
k = 1;
a = v.z;
b = -v.x;
}
else if ( fabs(v.z) > fabs(v.y) ) {
// |v.x| >= |v.z| > |v.y|
i = 0;
j = 2;
k = 1;
a = v.x;
b = -v.z;
}
else {
// |v.x| >= |v.y| >= |v.z|
i = 0;
j = 1;
k = 2;
a = v.x;
b = -v.y;
}
double* this_v = &x;
this_v[i] = b;
this_v[j] = a;
this_v[k] = 0.0;
return (a != 0.0) ? true : false;
}
bool
ON_3dVector::PerpendicularTo(
const ON_3dPoint& P0, const ON_3dPoint& P1, const ON_3dPoint& P2
)
{
// Find a the unit normal to a triangle defined by 3 points
*this = ON_3dVector::ZeroVector;
ON_3dVector V0 = P2 - P1;
ON_3dVector V1 = P0 - P2;
ON_3dVector V2 = P1 - P0;
ON_3dVector N0 = ON_CrossProduct( V1, V2 );
if ( !N0.Unitize() )
return false;
ON_3dVector N1 = ON_CrossProduct( V2, V0 );
if ( !N1.Unitize() )
return false;
ON_3dVector N2 = ON_CrossProduct( V0, V1 );
if ( !N2.Unitize() )
return false;
const double s0 = 1.0/V0.Length();
const double s1 = 1.0/V1.Length();
const double s2 = 1.0/V2.Length();
// choose normal with smallest total error
const double e0 = s0*fabs(ON_DotProduct(N0,V0)) + s1*fabs(ON_DotProduct(N0,V1)) + s2*fabs(ON_DotProduct(N0,V2));
const double e1 = s0*fabs(ON_DotProduct(N1,V0)) + s1*fabs(ON_DotProduct(N1,V1)) + s2*fabs(ON_DotProduct(N1,V2));
const double e2 = s0*fabs(ON_DotProduct(N2,V0)) + s1*fabs(ON_DotProduct(N2,V1)) + s2*fabs(ON_DotProduct(N2,V2));
if ( e0 <= e1 ) {
if ( e0 <= e2 ) {
*this = N0;
}
else {
*this = N2;
}
}
else if (e1 <= e2) {
*this = N1;
}
else {
*this = N2;
}
return true;
}
void ON_2dPoint::Transform( const ON_Xform& xform )
{
double xx,yy,ww;
ww = xform.m_xform[3][0]*x + xform.m_xform[3][1]*y + xform.m_xform[3][3];
if ( ww != 0.0 )
ww = 1.0/ww;
xx = ww*(xform.m_xform[0][0]*x + xform.m_xform[0][1]*y + xform.m_xform[0][3]);
yy = ww*(xform.m_xform[1][0]*x + xform.m_xform[1][1]*y + xform.m_xform[1][3]);
x = xx;
y = yy;
}
void ON_3dPoint::Transform( const ON_Xform& xform )
{
double xx,yy,zz,ww;
ww = xform.m_xform[3][0]*x + xform.m_xform[3][1]*y + xform.m_xform[3][2]*z + xform.m_xform[3][3];
if ( ww != 0.0 )
ww = 1.0/ww;
xx = ww*(xform.m_xform[0][0]*x + xform.m_xform[0][1]*y + xform.m_xform[0][2]*z + xform.m_xform[0][3]);
yy = ww*(xform.m_xform[1][0]*x + xform.m_xform[1][1]*y + xform.m_xform[1][2]*z + xform.m_xform[1][3]);
zz = ww*(xform.m_xform[2][0]*x + xform.m_xform[2][1]*y + xform.m_xform[2][2]*z + xform.m_xform[2][3]);
x = xx;
y = yy;
z = zz;
}
void ON_4dPoint::Transform( const ON_Xform& xform )
{
double xx,yy,zz,ww;
xx = xform.m_xform[0][0]*x + xform.m_xform[0][1]*y + xform.m_xform[0][2]*z + xform.m_xform[0][3]*w;
yy = xform.m_xform[1][0]*x + xform.m_xform[1][1]*y + xform.m_xform[1][2]*z + xform.m_xform[1][3]*w;
zz = xform.m_xform[2][0]*x + xform.m_xform[2][1]*y + xform.m_xform[2][2]*z + xform.m_xform[2][3]*w;
ww = xform.m_xform[3][0]*x + xform.m_xform[3][1]*y + xform.m_xform[3][2]*z + xform.m_xform[3][3]*w;
x = xx;
y = yy;
z = zz;
w = ww;
}
void ON_2fPoint::Transform( const ON_Xform& xform )
{
double xx,yy,ww;
ww = xform.m_xform[3][0]*x + xform.m_xform[3][1]*y + xform.m_xform[3][3];
if ( ww != 0.0 )
ww = 1.0/ww;
xx = ww*(xform.m_xform[0][0]*x + xform.m_xform[0][1]*y + xform.m_xform[0][3]);
yy = ww*(xform.m_xform[1][0]*x + xform.m_xform[1][1]*y + xform.m_xform[1][3]);
x = (float)xx;
y = (float)yy;
}
void ON_2fPoint::Rotate(
double angle, // angle in radians
const ON_2fPoint& center // center of rotation
)
{
Rotate( sin(angle), cos(angle), center );
}
void ON_2fPoint::Rotate(
double sin_angle, // sin(angle)
double cos_angle, // cos(angle)
const ON_2fPoint& center // center of rotation
)
{
ON_Xform rot;
rot.Rotation( sin_angle, cos_angle, ON_3dVector::ZAxis, ON_3dPoint(center) );
Transform(rot);
}
void ON_3fPoint::Rotate(
double angle, // angle in radians
const ON_3fVector& axis, // axis of rotation
const ON_3fPoint& center // center of rotation
)
{
Rotate( sin(angle), cos(angle), axis, center );
}
void ON_3fPoint::Rotate(
double sin_angle, // sin(angle)
double cos_angle, // cos(angle)
const ON_3fVector& axis, // axis of rotation
const ON_3fPoint& center // center of rotation
)
{
ON_Xform rot;
rot.Rotation( sin_angle, cos_angle, ON_3dVector(axis), ON_3dPoint(center) );
Transform(rot);
}
void ON_3fPoint::Transform( const ON_Xform& xform )
{
const double ww = xform.m_xform[3][0]*x + xform.m_xform[3][1]*y + xform.m_xform[3][2]*z + xform.m_xform[3][3];
if (0.0 == ww)
{
ON_ERROR("divide by zero.");
*this = ON_3fPoint::NanPoint;
}
else
{
const double xx = (xform.m_xform[0][0] * x + xform.m_xform[0][1] * y + xform.m_xform[0][2] * z + xform.m_xform[0][3]) / ww;
const double yy = (xform.m_xform[1][0] * x + xform.m_xform[1][1] * y + xform.m_xform[1][2] * z + xform.m_xform[1][3]) / ww;
const double zz = (xform.m_xform[2][0] * x + xform.m_xform[2][1] * y + xform.m_xform[2][2] * z + xform.m_xform[2][3]) / ww;
x = (float)xx;
y = (float)yy;
z = (float)zz;
}
}
void ON_4fPoint::Transform( const ON_Xform& xform )
{
const double xx = xform.m_xform[0][0]*x + xform.m_xform[0][1]*y + xform.m_xform[0][2]*z + xform.m_xform[0][3]*w;
const double yy = xform.m_xform[1][0]*x + xform.m_xform[1][1]*y + xform.m_xform[1][2]*z + xform.m_xform[1][3]*w;
const double zz = xform.m_xform[2][0]*x + xform.m_xform[2][1]*y + xform.m_xform[2][2]*z + xform.m_xform[2][3]*w;
const double ww = xform.m_xform[3][0]*x + xform.m_xform[3][1]*y + xform.m_xform[3][2]*z + xform.m_xform[3][3]*w;
x = (float)xx;
y = (float)yy;
z = (float)zz;
w = (float)ww;
}
double ON_3fPoint::Fuzz(
double absolute_tolerance // (default = ON_ZERO_TOLERANCE)
) const
{
double t = MaximumCoordinate()* ON_RELATIVE_TOLERANCE;
return(t > absolute_tolerance) ? t : absolute_tolerance;
}
bool ON_4dPoint::Normalize()
{
bool rc = false;
const int i = MaximumCoordinateIndex();
double f[4];
f[0] = fabs(x);
f[1] = fabs(y);
f[2] = fabs(z);
f[3] = fabs(w);
const double c = f[i];
if ( c > 0.0 ) {
double len = 1.0/c;
f[0] *= len;
f[1] *= len;
f[2] *= len;
f[3] *= len;
f[i] = 1.0;
// GBA 7/1/04. Fixed typo
const double s = 1.0/( c*sqrt(f[0]*f[0] + f[1]*f[1] + f[2]*f[2] + f[3]*f[3]));
x *= s;
y *= s;
z *= s;
w *= s;
rc = true;
}
return rc;
}
bool ON_4fPoint::Normalize()
{
bool rc = false;
const int i = MaximumCoordinateIndex();
double f[4];
f[0] = fabs(x);
f[1] = fabs(y);
f[2] = fabs(z);
f[3] = fabs(w);
const double c = f[i];
if ( c > 0.0 ) {
double len = 1.0/c;
f[0] *= len;
f[1] *= len;
f[2] *= len;
f[3] *= len;
f[i] = 1.0;
// GBA 7/1/04. Fixed typo
const double s = 1.0/(c*sqrt(f[0]*f[0] + f[1]*f[1] + f[2]*f[2] + f[3]*f[3]));
x = (float)(s*x);
y = (float)(s*y);
z = (float)(s*z);
w = (float)(s*w);
rc = true;
}
return rc;
}
bool ON_2fVector::Decompose( // Computes a, b such that this vector = a*X + b*Y
//
// If X,Y is known to be an orthonormal frame,
// then a = V*X, b = V*Y will compute
// the same result more quickly.
const ON_2fVector& X,
const ON_2fVector& Y,
double* a,
double* b
) const
{
ON_2dVector V(*this);
return V.Decompose(ON_2dVector(X),ON_2dVector(Y),a,b);
}
bool ON_2dVector::Decompose( // Computes a, b such that this vector = a*X + b*Y
//
// If X,Y is known to be an orthonormal frame,
// then a = V*X, b = V*Y will compute
// the same result more quickly.
const ON_2dVector& X,
const ON_2dVector& Y,
double* a,
double* b
) const
{
int rank;
double pivot_ratio = 0.0;
double XoY = X*Y;
rank = ON_Solve2x2( X*X, XoY, Y*Y, XoY,
(*this)*X, (*this)*Y,
a, b, &pivot_ratio );
return (rank == 2) ? true : false;
}
int ON_2fVector::IsParallelTo(
// returns 1: this and other vectors are and parallel
// -1: this and other vectors are anti-parallel
// 0: this and other vectors are not parallel
// or at least one of the vectors is zero
const ON_2fVector& v,
double angle_tolerance // (default=ON_DEFAULT_ANGLE_TOLERANCE) radians
) const
{
ON_2dVector V(*this);
return V.IsParallelTo(ON_2dVector(v),angle_tolerance);
}
int ON_2dVector::IsParallelTo(
// returns 1: this and other vectors are and parallel
// -1: this and other vectors are anti-parallel
// 0: this and other vectors are not parallel
// or at least one of the vectors is zero
const ON_2dVector& v,
double angle_tolerance // (default=ON_DEFAULT_ANGLE_TOLERANCE) radians
) const
{
int rc = 0;
const double ll = Length()*v.Length();
if ( ll > 0.0 ) {
const double cos_angle = (x*v.x + y*v.y)/ll;
const double cos_tol = cos(angle_tolerance);
if ( cos_angle >= cos_tol )
rc = 1;
else if ( cos_angle <= -cos_tol )
rc = -1;
}
return rc;
}
bool ON_2fVector::IsPerpendicularTo(
// returns true: this and other vectors are perpendicular
// false: this and other vectors are not perpendicular
// or at least one of the vectors is zero
const ON_2fVector& v,
double angle_tolerance // (default=ON_DEFAULT_ANGLE_TOLERANCE) radians
) const
{
ON_2dVector V(*this);
return V.IsPerpendicularTo(ON_2dVector(v),angle_tolerance);
}
bool ON_2dVector::IsPerpendicularTo(
// returns true: this and other vectors are perpendicular
// false: this and other vectors are not perpendicular
// or at least one of the vectors is zero
const ON_2dVector& v,
double angle_tolerance // (default=ON_DEFAULT_ANGLE_TOLERANCE) radians
) const
{
bool rc = false;
const double ll = Length()*v.Length();
if ( ll > 0.0 ) {
if ( fabs((x*v.x + y*v.y)/ll) <= sin(angle_tolerance) )
rc = true;
}
return rc;
}
void ON_2dVector::Transform( const ON_Xform& xform )
{
double xx,yy;
xx = xform.m_xform[0][0]*x + xform.m_xform[0][1]*y;
yy = xform.m_xform[1][0]*x + xform.m_xform[1][1]*y;
x = xx;
y = yy;
}
void ON_3fVector::Transform( const ON_Xform& xform )
{
const double dx = x;
const double dy = y;
const double dz = z;
double xx = xform.m_xform[0][0]*dx + xform.m_xform[0][1]*dy + xform.m_xform[0][2]*dz;
double yy = xform.m_xform[1][0]*dx + xform.m_xform[1][1]*dy + xform.m_xform[1][2]*dz;
double zz = xform.m_xform[2][0]*dx + xform.m_xform[2][1]*dy + xform.m_xform[2][2]*dz;
x = (float)xx;
y = (float)yy;
z = (float)zz;
}
void ON_3dVector::Transform( const ON_Xform& xform )
{
double xx,yy,zz;
xx = xform.m_xform[0][0]*x + xform.m_xform[0][1]*y + xform.m_xform[0][2]*z;
yy = xform.m_xform[1][0]*x + xform.m_xform[1][1]*y + xform.m_xform[1][2]*z;
zz = xform.m_xform[2][0]*x + xform.m_xform[2][1]*y + xform.m_xform[2][2]*z;
x = xx;
y = yy;
z = zz;
}
void ON_3dPoint::Rotate(
double angle, // angle in radians
const ON_3dVector& axis, // axis of rotation
const ON_3dPoint& center // center of rotation
)
{
Rotate( sin(angle), cos(angle), axis, center );
}
void ON_3dPoint::Rotate(
double sin_angle, // sin(angle)
double cos_angle, // cos(angle)
const ON_3dVector& axis, // axis of rotation
const ON_3dPoint& center // center of rotation
)
{
ON_Xform rot;
rot.Rotation( sin_angle, cos_angle, axis, center );
Transform(rot);
}
void ON_2dPoint::Rotate(
double angle, // angle in radians
const ON_2dPoint& center // center of rotation
)
{
Rotate( sin(angle), cos(angle), center );
}
void ON_2dPoint::Rotate(
double sin_angle, // sin(angle)
double cos_angle, // cos(angle)
const ON_2dPoint& center // center of rotation
)
{
ON_Xform rot;
rot.Rotation( sin_angle, cos_angle, ON_3dVector::ZAxis, ON_3dPoint(center) );
Transform(rot);
}
void ON_2dVector::Rotate(
double angle // angle in radians
)
{
Rotate( sin(angle), cos(angle) );
}
void ON_2dVector::Rotate(
double sin_angle, // sin(angle)
double cos_angle // cos(angle)
)
{
ON_Xform rot;
rot.Rotation( sin_angle, cos_angle, ON_3dVector::ZAxis, ON_3dPoint::Origin );
Transform(rot);
}
bool ON_IsOrthogonalFrame( const ON_2dVector& X, const ON_2dVector& Y )
{
// returns true if X, Y, Z is an orthogonal frame
double lx = X.Length();
double ly = Y.Length();
if ( lx <= ON_SQRT_EPSILON )
return false;
if ( ly <= ON_SQRT_EPSILON )
return false;
lx = 1.0/lx;
ly = 1.0/ly;
double x = ON_DotProduct( X, Y )*lx*ly;
if ( fabs(x) > ON_SQRT_EPSILON )
return false;
return true;
}
bool ON_IsOrthonormalFrame( const ON_2dVector& X, const ON_2dVector& Y )
{
// returns true if X, Y, Z is an orthonormal frame
if ( !ON_IsOrthogonalFrame( X, Y ) )
return false;
double x = X.Length();
if ( fabs(x-1.0) > ON_SQRT_EPSILON )
return false;
x = Y.Length();
if ( fabs(x-1.0) > ON_SQRT_EPSILON )
return false;
return true;
}
bool ON_IsRightHandFrame( const ON_2dVector& X, const ON_2dVector& Y )
{
// returns true if X, Y, Z is an orthonormal right hand frame
if ( !ON_IsOrthonormalFrame(X,Y) )
return false;
double x = ON_DotProduct( ON_CrossProduct( X, Y ), ON_3dVector::ZAxis );
if ( x <= ON_SQRT_EPSILON )
return false;
return true;
}
void ON_3fVector::Rotate(
double angle, // angle in radians
const ON_3fVector& axis // axis of rotation
)
{
Rotate( sin(angle), cos(angle), axis );
}
void ON_3fVector::Rotate(
double sin_angle, // sin(angle)
double cos_angle, // cos(angle)
const ON_3fVector& axis // axis of rotation
)
{
//bool rc = false;
ON_Xform rot;
rot.Rotation( sin_angle, cos_angle, ON_3dVector(axis), ON_3dPoint::Origin );
Transform(rot);
}
void ON_3dVector::Rotate(
double angle, // angle in radians
const ON_3dVector& axis // axis of rotation
)
{
Rotate( sin(angle), cos(angle), axis );
}
void ON_3dVector::Rotate(
double sin_angle, // sin(angle)
double cos_angle, // cos(angle)
const ON_3dVector& axis // axis of rotation
)
{
//bool rc = false;
ON_Xform rot;
rot.Rotation( sin_angle, cos_angle, axis, ON_3dPoint::Origin );
Transform(rot);
}
bool ON_IsOrthogonalFrame( const ON_3dVector& X, const ON_3dVector& Y, const ON_3dVector& Z )
{
// returns true if X, Y, Z is an orthogonal frame
if (! X.IsValid() || !Y.IsValid() || !Z.IsValid() )
return false;
double lx = X.Length();
double ly = Y.Length();
double lz = Z.Length();
if ( lx <= ON_SQRT_EPSILON )
return false;
if ( ly <= ON_SQRT_EPSILON )
return false;
if ( lz <= ON_SQRT_EPSILON )
return false;
lx = 1.0/lx;
ly = 1.0/ly;
lz = 1.0/lz;
double xy = (X.x*Y.x + X.y*Y.y + X.z*Y.z)*lx*ly;
double yz = (Y.x*Z.x + Y.y*Z.y + Y.z*Z.z)*ly*lz;
double zx = (Z.x*X.x + Z.y*X.y + Z.z*X.z)*lz*lx;
if ( fabs(xy) > ON_SQRT_EPSILON
|| fabs(yz) > ON_SQRT_EPSILON
|| fabs(zx) > ON_SQRT_EPSILON
)
{
double t = 0.0000152587890625;
if ( fabs(xy) >= t || fabs(yz) >= t || fabs(zx) >= t )
return false;
// do a more careful (and time consuming check)
// This fixes RR 22219 and 22276
ON_3dVector V;
V = (lx*ly)*ON_CrossProduct(X,Y);
t = fabs((V.x*Z.x + V.y*Z.y + V.z*Z.z)*lz);
if ( fabs(t-1.0) > ON_SQRT_EPSILON )
return false;
V = (ly*lz)*ON_CrossProduct(Y,Z);
t = fabs((V.x*X.x + V.y*X.y + V.z*X.z)*lx);
if ( fabs(t-1.0) > ON_SQRT_EPSILON )
return false;
V = (lz*lx)*ON_CrossProduct(Z,X);
t = fabs((V.x*Y.x + V.y*Y.y + V.z*Y.z)*ly);
if ( fabs(t-1.0) > ON_SQRT_EPSILON )
return false;
}
return true;
}
bool ON_IsOrthonormalFrame( const ON_3dVector& X, const ON_3dVector& Y, const ON_3dVector& Z )
{
// returns true if X, Y, Z is an orthonormal frame
if ( !ON_IsOrthogonalFrame( X, Y, Z ) )
return false;
double x = X.Length();
if ( fabs(x-1.0) > ON_SQRT_EPSILON )
return false;
x = Y.Length();
if ( fabs(x-1.0) > ON_SQRT_EPSILON )
return false;
x = Z.Length();
if ( fabs(x-1.0) > ON_SQRT_EPSILON )
return false;
return true;
}
bool ON_IsRightHandFrame( const ON_3dVector& X, const ON_3dVector& Y, const ON_3dVector& Z )
{
// returns true if X, Y, Z is an orthonormal right hand frame
if ( !ON_IsOrthonormalFrame(X,Y,Z) )
return false;
double x = ON_DotProduct( ON_CrossProduct( X, Y ), Z );
if ( x <= ON_SQRT_EPSILON )
return false;
return true;
}
ON_2dPoint ON_2dPoint::operator*( const ON_Xform& xform ) const
{
const double px = x; // optimizer should put px,py in registers
const double py = y;
double hx[2], w;
const double* m = &xform.m_xform[0][0];
hx[0] = m[0]*px + m[4]*py + m[12];
hx[1] = m[1]*px + m[5]*py + m[13];
w = m[3]*px + m[7]*py + m[15];
w = (w != 0.0) ? 1.0/w : 1.0;
return ON_2dPoint( w*hx[0], w*hx[1] );
}
ON_3dPoint ON_3dPoint::operator*( const ON_Xform& xform ) const
{
const double px = x; // optimizer should put px,py,pz in registers
const double py = y;
const double pz = z;
double hx[3], w;
const double* m = &xform.m_xform[0][0];
hx[0] = m[0]*px + m[4]*py + m[ 8]*pz + m[12];
hx[1] = m[1]*px + m[5]*py + m[ 9]*pz + m[13];
hx[2] = m[2]*px + m[6]*py + m[10]*pz + m[14];
w = m[3]*px + m[7]*py + m[11]*pz + m[15];
w = (w != 0.0) ? 1.0/w : 1.0;
return ON_3dPoint( w*hx[0], w*hx[1], w*hx[2] );
}
double ON_3dPoint::Fuzz(
double absolute_tolerance // (default = ON_ZERO_TOLERANCE)
) const
{
double t = MaximumCoordinate()* ON_RELATIVE_TOLERANCE;
return(t > absolute_tolerance) ? t : absolute_tolerance;
}
ON_4dPoint ON_4dPoint::operator*( const ON_Xform& xform ) const
{
const double px = x; // optimizer should put x,y,z,w in registers
const double py = y;
const double pz = z;
const double pw = w;
double hx[4];
const double* m = &xform.m_xform[0][0];
hx[0] = m[0]*px + m[4]*py + m[ 8]*pz + m[12]*pw;
hx[1] = m[1]*px + m[5]*py + m[ 9]*pz + m[13]*pw;
hx[2] = m[2]*px + m[6]*py + m[10]*pz + m[14]*pw;
hx[3] = m[3]*px + m[7]*py + m[11]*pz + m[15]*pw;
return ON_4dPoint( hx[0],hx[1],hx[2],hx[3] );
}
ON_2dVector ON_2dVector::operator*( const ON_Xform& xform ) const
{
const double vx = x; // optimizer should put vx,vy in registers
const double vy = y;
double hx[2];
const double* m = &xform.m_xform[0][0];
hx[0] = m[0]*vx + m[4]*vy;
hx[1] = m[1]*vx + m[5]*vy;
return ON_2dVector( hx[0],hx[1] );
}
ON_3dVector ON_3dVector::operator*( const ON_Xform& xform ) const
{
const double vx = x; // optimizer should put vx,vy,vz in registers
const double vy = y;
const double vz = z;
double hx[3];
const double* m = &xform.m_xform[0][0];
hx[0] = m[0]*vx + m[4]*vy + m[ 8]*vz;
hx[1] = m[1]*vx + m[5]*vy + m[ 9]*vz;
hx[2] = m[2]*vx + m[6]*vy + m[10]*vz;
return ON_3dVector( hx[0],hx[1],hx[2] );
}
double ON_3fVector::Fuzz(
double absolute_tolerance // (default = ON_ZERO_TOLERANCE)
) const
{
double t = MaximumCoordinate()* ON_RELATIVE_TOLERANCE;
return(t > absolute_tolerance) ? t : absolute_tolerance;
}
double ON_3dVector::Fuzz(
double absolute_tolerance // (default = ON_ZERO_TOLERANCE)
) const
{
double t = MaximumCoordinate()* ON_RELATIVE_TOLERANCE;
return(t > absolute_tolerance) ? t : absolute_tolerance;
}
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
//
// ON_2fPoint
//
ON_2fPoint::ON_2fPoint( const double* p )
{
if (p) {
x = (float)p[0]; y = (float)p[1];
}
else {
x = y = 0.0;
}
}
ON_2fPoint::ON_2fPoint( const float* p )
{
if (p) {
x = p[0]; y = p[1];
}
else {
x = y = 0.0;
}
}
ON_2fPoint::ON_2fPoint(float xx,float yy)
{x=xx;y=yy;}
ON_2fPoint::ON_2fPoint(const ON_3fPoint& p)
{x=p.x;y=p.y;}
ON_2fPoint::ON_2fPoint(const ON_4fPoint& h)
{
const float w = (h.w != 1.0f && h.w != 0.0f) ? 1.0f/h.w : 1.0f;
x = w*h.x;
y = w*h.y;
}
ON_2fPoint::ON_2fPoint(const ON_2fVector& v)
{x=v.x;y=v.y;}
ON_2fPoint::ON_2fPoint(const ON_3fVector& v)
{x=v.x;y=v.y;}
ON_2fPoint::ON_2fPoint(const ON_2dPoint& p)
{x=(float)p.x;y=(float)p.y;}
ON_2fPoint::ON_2fPoint(const ON_3dPoint& p)
{x=(float)p.x;y=(float)p.y;}
ON_2fPoint::ON_2fPoint(const ON_4dPoint& h)
{
const double w = (h.w != 1.0 && h.w != 0.0) ? 1.0/h.w : 1.0;
x = (float)(w*h.x);
y = (float)(w*h.y);
}
ON_2fPoint::ON_2fPoint(const ON_2dVector& v)
{x=(float)v.x;y=(float)v.y;}
ON_2fPoint::ON_2fPoint(const ON_3dVector& v)
{x=(float)v.x;y=(float)v.y;}
ON_2fPoint::operator float*()
{
return &x;
}
ON_2fPoint::operator const float*() const
{
return &x;
}
ON_2fPoint& ON_2fPoint::operator=(const double* p)
{
if ( p ) {
x = (float)p[0];
y = (float)p[1];
}
else {
x = y = 0.0;
}
return *this;
}
ON_2fPoint& ON_2fPoint::operator=(const float* p)
{
if ( p ) {
x = p[0];
y = p[1];
}
else {
x = y = 0.0;
}
return *this;
}
ON_2fPoint& ON_2fPoint::operator=(const ON_3fPoint& p)
{
x = p.x;
y = p.y;
return *this;
}
ON_2fPoint& ON_2fPoint::operator=(const ON_4fPoint& h)
{
const float w = (h.w != 1.0f && h.w != 0.0f) ? 1.0f/h.w : 1.0f;
x = w*h.x;
y = w*h.y;
return *this;
}
ON_2fPoint& ON_2fPoint::operator=(const ON_2fVector& v)
{
x = v.x;
y = v.y;
return *this;
}
ON_2fPoint& ON_2fPoint::operator=(const ON_3fVector& v)
{
x = v.x;
y = v.y;
return *this;
}
ON_2fPoint& ON_2fPoint::operator=(const ON_2dPoint& p)
{
x = (float)p.x;
y = (float)p.y;
return *this;
}
ON_2fPoint& ON_2fPoint::operator=(const ON_3dPoint& p)
{
x = (float)p.x;
y = (float)p.y;
return *this;
}
ON_2fPoint& ON_2fPoint::operator=(const ON_4dPoint& h)
{
const double w = (h.w != 1.0 && h.w != 0.0) ? 1.0/h.w : 1.0;
x = (float)(w*h.x);
y = (float)(w*h.y);
return *this;
}
ON_2fPoint& ON_2fPoint::operator=(const ON_2dVector& v)
{
x = (float)v.x;
y = (float)v.y;
return *this;
}
ON_2fPoint& ON_2fPoint::operator=(const ON_3dVector& v)
{
x = (float)v.x;
y = (float)v.y;
return *this;
}
ON_2fPoint& ON_2fPoint::operator*=(float d)
{
x *= d;
y *= d;
return *this;
}
ON_2fPoint& ON_2fPoint::operator/=(float d)
{
const float one_over_d = 1.0f/d;
x *= one_over_d;
y *= one_over_d;
return *this;
}
ON_2fPoint& ON_2fPoint::operator+=(const ON_2fVector& v)
{
x += v.x;
y += v.y;
return *this;
}
ON_2fPoint& ON_2fPoint::operator-=(const ON_2fVector& v)
{
x -= v.x;
y -= v.y;
return *this;
}
ON_2fPoint ON_2fPoint::operator*( int d ) const
{
return ON_2fPoint(x*d,y*d);
}
ON_2fPoint ON_2fPoint::operator*( float d ) const
{
return ON_2fPoint(x*d,y*d);
}
ON_2dPoint ON_2fPoint::operator*( double d ) const
{
return ON_2dPoint(x*d,y*d);
}
ON_2fPoint ON_2fPoint::operator/( int i ) const
{
const float one_over_d = 1.0f/((float)i);
return ON_2fPoint(x*one_over_d,y*one_over_d);
}
ON_2fPoint ON_2fPoint::operator/( float d ) const
{
const float one_over_d = 1.0f/d;
return ON_2fPoint(x*one_over_d,y*one_over_d);
}
ON_2dPoint ON_2fPoint::operator/( double d ) const
{
const double one_over_d = 1.0/d;
return ON_2dPoint(x*one_over_d,y*one_over_d);
}
ON_2fPoint ON_2fPoint::operator+( const ON_2fPoint& p ) const
{
return ON_2fPoint(x+p.x,y+p.y);
}
ON_2fPoint ON_2fPoint::operator+( const ON_2fVector& v ) const
{
return ON_2fPoint(x+v.x,y+v.y);
}
ON_2fVector ON_2fPoint::operator-( const ON_2fPoint& p ) const
{
return ON_2fVector(x-p.x,y-p.y);
}
ON_2fPoint ON_2fPoint::operator-( const ON_2fVector& v ) const
{
return ON_2fPoint(x-v.x,y-v.y);
}
ON_3fPoint ON_2fPoint::operator+( const ON_3fPoint& p ) const
{
return ON_3fPoint(x+p.x,y+p.y,p.z);
}
ON_3fPoint ON_2fPoint::operator+( const ON_3fVector& v ) const
{
return ON_3fPoint(x+v.x,y+v.y,v.z);
}
ON_3fVector ON_2fPoint::operator-( const ON_3fPoint& p ) const
{
return ON_3fVector(x-p.x,y-p.y,-p.y);
}
ON_3fPoint ON_2fPoint::operator-( const ON_3fVector& v ) const
{
return ON_3fPoint(x-v.x,y-v.y,-v.z);
}
ON_2dPoint ON_2fPoint::operator+( const ON_2dPoint& p ) const
{
return ON_2dPoint(x+p.x,y+p.y);
}
ON_2dPoint ON_2fPoint::operator+( const ON_2dVector& v ) const
{
return ON_2dPoint(x+v.x,y+v.y);
}
ON_2dVector ON_2fPoint::operator-( const ON_2dPoint& p ) const
{
return ON_2dVector(x-p.x,y-p.y);
}
ON_2dPoint ON_2fPoint::operator-( const ON_2dVector& v ) const
{
return ON_2dPoint(x-v.x,y-v.y);
}
ON_3dPoint ON_2fPoint::operator+( const ON_3dPoint& p ) const
{
return ON_3dPoint(x+p.x,y+p.y,p.z);
}
ON_3dPoint ON_2fPoint::operator+( const ON_3dVector& v ) const
{
return ON_3dPoint(x+v.x,y+v.y,v.z);
}
ON_3dVector ON_2fPoint::operator-( const ON_3dPoint& p ) const
{
return ON_3dVector(x-p.x,y-p.y,-p.y);
}
ON_3dPoint ON_2fPoint::operator-( const ON_3dVector& v ) const
{
return ON_3dPoint(x-v.x,y-v.y,-v.z);
}
float ON_2fPoint::operator*(const ON_2fPoint& h) const
{
return x*h.x + y*h.y;
}
float ON_2fPoint::operator*(const ON_2fVector& h) const
{
return x*h.x + y*h.y;
}
bool ON_2fPoint::operator==( const ON_2fPoint& p ) const
{
return (x==p.x&&y==p.y)?true:false;
}
static bool Internal_NotEqualDoubleArray(size_t count, const double* lhs, const double* rhs)
{
bool rc = false;
const double* e = lhs + count;
while (lhs < e)
{
const double x = *lhs++;
const double y = *rhs++;
if (x != y)
{
// neither x nor y is a nan
rc = true;
continue;
}
if (!(x == x))
return false; // nan
if (!(y == y))
return false; // nan
}
return rc;
}
static bool Internal_NotEqualFloatArray(size_t count, const float* lhs, const float* rhs)
{
bool rc = false;
const float* e = lhs + count;
while (lhs < e)
{
const float x = *lhs++;
const float y = *rhs++;
if (x != y)
{
// neither x nor y is a nan
rc = true;
continue;
}
if (!(x == x))
return false; // nan
if (!(y == y))
return false; // nan
}
return rc;
}
bool ON_4fPoint::operator!=(const ON_4fPoint& rhs) const
{
return Internal_NotEqualFloatArray(4, &x, &rhs.x);
}
bool ON_4fPoint::operator==(const ON_4fPoint& rhs) const
{
return (x == rhs.x && y == rhs.y && z == rhs.z && w == rhs.w);
}
bool ON_2fPoint::operator!=( const ON_2fPoint& p ) const
{
return Internal_NotEqualFloatArray(2, &x, &p.x);
}
bool ON_2fPoint::operator<=( const ON_2fPoint& p ) const
{
// dictionary order
return ( (x<p.x) ? true : ((x==p.x&&y<=p.y)?true:false) );
}
bool ON_2fPoint::operator>=( const ON_2fPoint& p ) const
{
// dictionary order
return ( (x>p.x) ? true : ((x==p.x&&y>=p.y)?true:false) );
}
bool ON_2fPoint::operator<( const ON_2fPoint& p ) const
{
// dictionary order
return ( (x<p.x) ? true : ((x==p.x&&y<p.y)?true:false) );
}
bool ON_2fPoint::operator>( const ON_2fPoint& p ) const
{
// dictionary order
return ( (x>p.x) ? true : ((x==p.x&&y>p.y)?true:false) );
}
float ON_2fPoint::operator[](int i) const
{
return (i<=0) ? x : y;
}
float& ON_2fPoint::operator[](int i)
{
float* pd = (i<=0)? &x : &y;
return *pd;
}
float ON_2fPoint::operator[](unsigned int i) const
{
return (i<=0) ? x : y;
}
float& ON_2fPoint::operator[](unsigned int i)
{
float* pd = (i<=0)? &x : &y;
return *pd;
}
double ON_2fPoint::DistanceTo( const ON_2fPoint& p ) const
{
return ON_Length2d(p.x-x,p.y-y);
}
int ON_2fPoint::MaximumCoordinateIndex() const
{
return (fabs(y)>fabs(x)) ? 1 : 0;
}
double ON_2fPoint::MaximumCoordinate() const
{
double c = fabs(x); if (fabs(y)>c) c=fabs(y);
return c;
}
void ON_2fPoint::Zero()
{
x = y = 0.0;
}
bool ON_2fPoint::IsZero() const
{
return (x==0.0f && y==0.0f);
}
bool ON_2fPoint::IsNotZero() const
{
// the && (x == x && y == y) insures no coordinate is a Nan.
return (x != 0.0f || y != 0.0f) && (x == x && y == y);
}
ON_2fPoint operator*(int d, const ON_2fPoint& p)
{
return ON_2fPoint(d*p.x,d*p.y);
}
ON_2fPoint operator*(float d, const ON_2fPoint& p)
{
return ON_2fPoint(d*p.x,d*p.y);
}
ON_2dPoint operator*(double d, const ON_2fPoint& p)
{
return ON_2dPoint(d*p.x,d*p.y);
}
////////////////////////////////////////////////////////////////
//
// ON_3fPoint
//
ON_3fPoint::ON_3fPoint( const double* p )
{
if (p) {
x = (float)p[0]; y = (float)p[1]; z = (float)p[2];
}
else {
x = y = z = 0.0;
}
}
ON_3fPoint::ON_3fPoint( const float* p )
{
if (p) {
x = p[0]; y = p[1]; z = p[2];
}
else {
x = y = z = 0.0;
}
}
ON_3fPoint::ON_3fPoint(float xx,float yy,float zz)
{x=xx;y=yy;z=zz;}
ON_3fPoint::ON_3fPoint(const ON_2fPoint& p)
{x=p.x;y=p.y;z=0.0;}
ON_3fPoint::ON_3fPoint(const ON_4fPoint& p)
{
const double w = (p.w != 1.0f && p.w != 0.0f) ? 1.0/((double)p.w) : 1.0;
x = (float)(w*p.x);
y = (float)(w*p.y);
z = (float)(w*p.z);
}
ON_3fPoint::ON_3fPoint(const ON_2fVector& v)
{x=v.x;y=v.y;z=0.0f;}
ON_3fPoint::ON_3fPoint(const ON_3fVector& v)
{x=v.x;y=v.y;z=v.z;}
ON_3fPoint::ON_3fPoint(const ON_2dPoint& p)
{x=(float)p.x;y=(float)p.y;z=0.0;}
ON_3fPoint::ON_3fPoint(const ON_3dPoint& p)
{x=(float)p.x;y=(float)p.y;z=(float)p.z;}
ON_3fPoint::ON_3fPoint(const ON_4dPoint& p)
{
const double w = (p.w != 1.0 && p.w != 0.0) ? 1.0/p.w : 1.0;
x = (float)(w*p.x);
y = (float)(w*p.y);
z = (float)(w*p.z);
}
ON_3fPoint::ON_3fPoint(const ON_2dVector& v)
{x=(float)v.x;y=(float)v.y;z=0.0f;}
ON_3fPoint::ON_3fPoint(const ON_3dVector& v)
{x=(float)v.x;y=(float)v.y;z=(float)v.z;}
ON_3fPoint::operator float*()
{
return &x;
}
ON_3fPoint::operator const float*() const
{
return &x;
}
ON_3fPoint& ON_3fPoint::operator=(const double* p)
{
if ( p ) {
x = (float)p[0];
y = (float)p[1];
z = (float)p[2];
}
else {
x = y = z = 0.0;
}
return *this;
}
ON_3fPoint& ON_3fPoint::operator=(const float* p)
{
if ( p ) {
x = p[0];
y = p[1];
z = p[2];
}
else {
x = y = z = 0.0;
}
return *this;
}
ON_3fPoint& ON_3fPoint::operator=(const ON_2fPoint& p)
{
x = p.x;
y = p.y;
z = 0.0;
return *this;
}
ON_3fPoint& ON_3fPoint::operator=(const ON_4fPoint& p)
{
const float w = (p.w != 1.0f && p.w != 0.0f) ? 1.0f/p.w : 1.0f;
x = w*p.x;
y = w*p.y;
z = w*p.z;
return *this;
}
ON_3fPoint& ON_3fPoint::operator=(const ON_2fVector& v)
{
x = v.x;
y = v.y;
z = 0.0f;
return *this;
}
ON_3fPoint& ON_3fPoint::operator=(const ON_3fVector& v)
{
x = v.x;
y = v.y;
z = v.z;
return *this;
}
ON_3fPoint& ON_3fPoint::operator=(const ON_2dPoint& p)
{
x = (float)p.x;
y = (float)p.y;
z = 0.0f;
return *this;
}
ON_3fPoint& ON_3fPoint::operator=(const ON_3dPoint& p)
{
x = (float)p.x;
y = (float)p.y;
z = (float)p.z;
return *this;
}
ON_3fPoint& ON_3fPoint::operator=(const ON_4dPoint& p)
{
const double w = (p.w != 1.0 && p.w != 0.0) ? 1.0/p.w : 1.0;
x = (float)(w*p.x);
y = (float)(w*p.y);
z = (float)(w*p.z);
return *this;
}
ON_3fPoint& ON_3fPoint::operator=(const ON_2dVector& v)
{
x = (float)v.x;
y = (float)v.y;
z = 0.0f;
return *this;
}
ON_3fPoint& ON_3fPoint::operator=(const ON_3dVector& v)
{
x = (float)v.x;
y = (float)v.y;
z = (float)v.z;
return *this;
}
ON_3fPoint& ON_3fPoint::operator*=(float d)
{
x *= d;
y *= d;
z *= d;
return *this;
}
ON_3fPoint& ON_3fPoint::operator/=(float d)
{
const float one_over_d = 1.0f/d;
x *= one_over_d;
y *= one_over_d;
z *= one_over_d;
return *this;
}
ON_3fPoint& ON_3fPoint::operator+=(const ON_3fVector& v)
{
x += v.x;
y += v.y;
z += v.z;
return *this;
}
ON_3fPoint& ON_3fPoint::operator-=(const ON_3fVector& v)
{
x -= v.x;
y -= v.y;
z -= v.z;
return *this;
}
ON_3fPoint ON_3fPoint::operator*( int d ) const
{
return ON_3fPoint(x*d,y*d,z*d);
}
ON_3fPoint ON_3fPoint::operator*( float d ) const
{
return ON_3fPoint(x*d,y*d,z*d);
}
ON_3dPoint ON_3fPoint::operator*( double d ) const
{
return ON_3dPoint(x*d,y*d,z*d);
}
ON_3fPoint ON_3fPoint::operator/( int d ) const
{
const float one_over_d = 1.0f/((float)d);
return ON_3fPoint(x*one_over_d,y*one_over_d,z*one_over_d);
}
ON_3fPoint ON_3fPoint::operator/( float d ) const
{
const float one_over_d = 1.0f/d;
return ON_3fPoint(x*one_over_d,y*one_over_d,z*one_over_d);
}
ON_3dPoint ON_3fPoint::operator/( double d ) const
{
const double one_over_d = 1.0/d;
return ON_3dPoint(x*one_over_d,y*one_over_d,z*one_over_d);
}
ON_3fPoint ON_3fPoint::operator+( const ON_3fPoint& p ) const
{
return ON_3fPoint(x+p.x,y+p.y,z+p.z);
}
ON_3fPoint ON_3fPoint::operator+( const ON_3fVector& v ) const
{
return ON_3fPoint(x+v.x,y+v.y,z+v.z);
}
ON_3fVector ON_3fPoint::operator-( const ON_3fPoint& p ) const
{
return ON_3fVector(x-p.x,y-p.y,z-p.z);
}
ON_3fPoint ON_3fPoint::operator-( const ON_3fVector& v ) const
{
return ON_3fPoint(x-v.x,y-v.y,z-v.z);
}
ON_3fPoint ON_3fPoint::operator+( const ON_2fPoint& p ) const
{
return ON_3fPoint(x+p.x,y+p.y,z);
}
ON_3fPoint ON_3fPoint::operator+( const ON_2fVector& v ) const
{
return ON_3fPoint(x+v.x,y+v.y,z);
}
ON_3fVector ON_3fPoint::operator-( const ON_2fPoint& p ) const
{
return ON_3fVector(x-p.x,y-p.y,z);
}
ON_3fPoint ON_3fPoint::operator-( const ON_2fVector& v ) const
{
return ON_3fPoint(x-v.x,y-v.y,z);
}
ON_3dPoint ON_3fPoint::operator+( const ON_3dPoint& p ) const
{
return ON_3dPoint(x+p.x,y+p.y,z+p.z);
}
ON_3dPoint ON_3fPoint::operator+( const ON_3dVector& v ) const
{
return ON_3dPoint(x+v.x,y+v.y,z+v.z);
}
ON_3dVector ON_3fPoint::operator-( const ON_3dPoint& p ) const
{
return ON_3dVector(x-p.x,y-p.y,z-p.z);
}
ON_3dPoint ON_3fPoint::operator-( const ON_3dVector& v ) const
{
return ON_3dPoint(x-v.x,y-v.y,z-v.z);
}
ON_3dPoint ON_3fPoint::operator+( const ON_2dPoint& p ) const
{
return ON_3dPoint(x+p.x,y+p.y,z);
}
ON_3dPoint ON_3fPoint::operator+( const ON_2dVector& v ) const
{
return ON_3dPoint(x+v.x,y+v.y,z);
}
ON_3dVector ON_3fPoint::operator-( const ON_2dPoint& p ) const
{
return ON_3dVector(x-p.x,y-p.y,z);
}
ON_3dPoint ON_3fPoint::operator-( const ON_2dVector& v ) const
{
return ON_3dPoint(x-v.x,y-v.y,z);
}
float ON_3fPoint::operator*(const ON_3fPoint& h) const
{
return x*h.x + y*h.y + z*h.z;
}
float ON_3fPoint::operator*(const ON_3fVector& h) const
{
return x*h.x + y*h.y + z*h.z;
}
bool ON_3fPoint::operator==( const ON_3fPoint& p ) const
{
return (x==p.x&&y==p.y&&z==p.z)?true:false;
}
bool ON_3fPoint::operator!=( const ON_3fPoint& p ) const
{
return Internal_NotEqualFloatArray(3, &x, &p.x);
}
bool ON_3fPoint::operator<=( const ON_3fPoint& p ) const
{
// dictionary order
return ((x<p.x)?true:((x==p.x)?((y<p.y)?true:(y==p.y&&z<=p.z)?true:false):false));
}
bool ON_3fPoint::operator>=( const ON_3fPoint& p ) const
{
// dictionary order
return ((x>p.x)?true:((x==p.x)?((y>p.y)?true:(y==p.y&&z>=p.z)?true:false):false));
}
bool ON_3fPoint::operator<( const ON_3fPoint& p ) const
{
// dictionary order
return ((x<p.x)?true:((x==p.x)?((y<p.y)?true:(y==p.y&&z<p.z)?true:false):false));
}
bool ON_3fPoint::operator>( const ON_3fPoint& p ) const
{
// dictionary order
return ((x>p.x)?true:((x==p.x)?((y>p.y)?true:(y==p.y&&z>p.z)?true:false):false));
}
float ON_3fPoint::operator[](int i) const
{
return ( (i<=0)?x:((i>=2)?z:y) );
}
float& ON_3fPoint::operator[](int i)
{
float* pd = (i<=0)? &x : ( (i>=2) ? &z : &y);
return *pd;
}
float ON_3fPoint::operator[](unsigned int i) const
{
return ( (i<=0)?x:((i>=2)?z:y) );
}
float& ON_3fPoint::operator[](unsigned int i)
{
float* pd = (i<=0)? &x : ( (i>=2) ? &z : &y);
return *pd;
}
double ON_3fPoint::DistanceTo( const ON_3fPoint& p ) const
{
return ON_Length3d(p.x-x,p.y-y,p.z-z);
}
int ON_3fPoint::MaximumCoordinateIndex() const
{
return (fabs(y)>fabs(x)) ? ((fabs(z)>fabs(y))?2:1) : ((fabs(z)>fabs(x))?2:0);
}
double ON_3fPoint::MaximumCoordinate() const
{
double c = fabs(x); if (fabs(y)>c) c=fabs(y); if (fabs(z)>c) c=fabs(z);
return c;
}
void ON_3fPoint::Zero()
{
x = y = z = 0.0;
}
bool ON_3fPoint::IsZero() const
{
return (x==0.0f && y==0.0f && z==0.0f);
}
bool ON_3fPoint::IsNotZero() const
{
// the && (x == x && y == y) insures no coordinate is a Nan.
return (x != 0.0f || y != 0.0f || z != 0.0f) && (x == x && y == y && z == z);
}
ON_3fPoint operator*(int d, const ON_3fPoint& p)
{
return ON_3fPoint(d*p.x,d*p.y,d*p.z);
}
ON_3fPoint operator*(float d, const ON_3fPoint& p)
{
return ON_3fPoint(d*p.x,d*p.y,d*p.z);
}
ON_3dPoint operator*(double d, const ON_3fPoint& p)
{
return ON_3dPoint(d*p.x,d*p.y,d*p.z);
}
////////////////////////////////////////////////////////////////
//
// ON_4fPoint
//
ON_4fPoint::ON_4fPoint( const double* p )
{
if (p) {
x = (float)p[0]; y = (float)p[1]; z = (float)p[2]; w = (float)p[3];
}
else {
x = y = z = 0.0; w = 1.0;
}
}
ON_4fPoint::ON_4fPoint( const float* p )
{
if (p) {
x = p[0]; y = p[1]; z = p[2]; w = p[3];
}
else {
x = y = z = 0.0; w = 1.0;
}
}
ON_4fPoint::ON_4fPoint(float xx,float yy,float zz,float ww)
{x=xx;y=yy;z=zz;w=ww;}
ON_4fPoint::ON_4fPoint(const ON_2fPoint& p)
{x=p.x;y=p.y;z=0.0;w=1.0;}
ON_4fPoint::ON_4fPoint(const ON_3fPoint& p)
{
x=p.x;y=p.y;z=p.z;w=1.0;
}
ON_4fPoint::ON_4fPoint(const ON_2fVector& v)
{x=v.x;y=v.y;z=w=0.0;}
ON_4fPoint::ON_4fPoint(const ON_3fVector& v)
{x=v.x;y=v.y;z=v.z;w=0.0;}
ON_4fPoint::ON_4fPoint(const ON_2dPoint& p)
{x=(float)p.x;y=(float)p.y;z=0.0f;w=1.0f;}
ON_4fPoint::ON_4fPoint(const ON_3dPoint& p)
{
x=(float)p.x;y=(float)p.y;z=(float)p.z;w=1.0f;
}
ON_4fPoint::ON_4fPoint(const ON_4dPoint& p)
{
x=(float)p.x;y=(float)p.y;z=(float)p.z;w=(float)p.w;
}
ON_4fPoint::ON_4fPoint(const ON_2dVector& v)
{x=(float)v.x;y=(float)v.y;z=w=0.0f;}
ON_4fPoint::ON_4fPoint(const ON_3dVector& v)
{x=(float)v.x;y=(float)v.y;z=(float)v.z;w=0.0f;}
ON_4fPoint::operator float*()
{
return &x;
}
ON_4fPoint::operator const float*() const
{
return &x;
}
ON_4fPoint& ON_4fPoint::operator=(const double* p)
{
if ( p ) {
x = (float)p[0];
y = (float)p[1];
z = (float)p[2];
w = (float)p[3];
}
else {
x = y = z = 0.0; w = 1.0;
}
return *this;
}
ON_4fPoint& ON_4fPoint::operator=(const float* p)
{
if ( p ) {
x = p[0];
y = p[1];
z = p[2];
w = p[3];
}
else {
x = y = z = 0.0; w = 1.0;
}
return *this;
}
ON_4fPoint& ON_4fPoint::operator=(const ON_2fPoint& p)
{
x = p.x;
y = p.y;
z = 0.0;
w = 1.0;
return *this;
}
ON_4fPoint& ON_4fPoint::operator=(const ON_3fPoint& p)
{
x = p.x;
y = p.y;
z = p.z;
w = 1.0;
return *this;
}
ON_4fPoint& ON_4fPoint::operator=(const ON_2fVector& v)
{
x = v.x;
y = v.y;
z = 0.0;
w = 0.0;
return *this;
}
ON_4fPoint& ON_4fPoint::operator=(const ON_3fVector& v)
{
x = v.x;
y = v.y;
z = v.z;
w = 0.0;
return *this;
}
ON_4fPoint& ON_4fPoint::operator=(const ON_2dPoint& p)
{
x = (float)p.x;
y = (float)p.y;
z = 0.0;
w = 1.0;
return *this;
}
ON_4fPoint& ON_4fPoint::operator=(const ON_3dPoint& p)
{
x = (float)p.x;
y = (float)p.y;
z = (float)p.z;
w = 1.0;
return *this;
}
ON_4fPoint& ON_4fPoint::operator=(const ON_4dPoint& p)
{
x = (float)p.x;
y = (float)p.y;
z = (float)p.z;
w = (float)p.w;
return *this;
}
ON_4fPoint& ON_4fPoint::operator=(const ON_2dVector& v)
{
x = (float)v.x;
y = (float)v.y;
z = 0.0;
w = 0.0;
return *this;
}
ON_4fPoint& ON_4fPoint::operator=(const ON_3dVector& v)
{
x = (float)v.x;
y = (float)v.y;
z = (float)v.z;
w = 0.0;
return *this;
}
ON_4fPoint& ON_4fPoint::operator*=(float d)
{
x *= d;
y *= d;
z *= d;
w *= d;
return *this;
}
ON_4fPoint& ON_4fPoint::operator/=(float d)
{
const float one_over_d = 1.0f/d;
x *= one_over_d;
y *= one_over_d;
z *= one_over_d;
w *= one_over_d;
return *this;
}
ON_4fPoint& ON_4fPoint::operator+=(const ON_4fPoint& p)
{
// sum w = sqrt(w1*w2)
if ( p.w == w ) {
x += p.x;
y += p.y;
z += p.z;
}
else if (p.w == 0.0 ) {
x += p.x;
y += p.y;
z += p.z;
}
else if ( w == 0.0 ) {
x += p.x;
y += p.y;
z += p.z;
w = p.w;
}
else {
const double sw1 = (w>0.0) ? sqrt(w) : -sqrt(-w);
const double sw2 = (p.w>0.0) ? sqrt(p.w) : -sqrt(-p.w);
const double s1 = sw2/sw1;
const double s2 = sw1/sw2;
x = (float)(x*s1 + p.x*s2);
y = (float)(y*s1 + p.y*s2);
z = (float)(z*s1 + p.z*s2);
w = (float)(sw1*sw2);
}
return *this;
}
ON_4fPoint& ON_4fPoint::operator-=(const ON_4fPoint& p)
{
// difference w = sqrt(w1*w2)
if ( p.w == w ) {
x -= p.x;
y -= p.y;
z -= p.z;
}
else if (p.w == 0.0 ) {
x -= p.x;
y -= p.y;
z -= p.z;
}
else if ( w == 0.0 ) {
x -= p.x;
y -= p.y;
z -= p.z;
w = p.w;
}
else {
const double sw1 = (w>0.0) ? sqrt(w) : -sqrt(-w);
const double sw2 = (p.w>0.0) ? sqrt(p.w) : -sqrt(-p.w);
const double s1 = sw2/sw1;
const double s2 = sw1/sw2;
x = (float)(x*s1 - p.x*s2);
y = (float)(y*s1 - p.y*s2);
z = (float)(z*s1 - p.z*s2);
w = (float)(sw1*sw2);
}
return *this;
}
ON_4fPoint ON_4fPoint::operator+( const ON_4fPoint& p ) const
{
ON_4fPoint q(x,y,z,w);
q+=p;
return q;
}
ON_4fPoint ON_4fPoint::operator-( const ON_4fPoint& p ) const
{
ON_4fPoint q(x,y,z,w);
q-=p;
return q;
}
ON_4fPoint ON_4fPoint::operator*( float d ) const
{
return ON_4fPoint(x*d,y*d,z*d,w*d);
}
ON_4fPoint ON_4fPoint::operator/( float d ) const
{
const float one_over_d = 1.0f/d;
return ON_4fPoint(x*one_over_d,y*one_over_d,z*one_over_d,w*one_over_d);
}
float ON_4fPoint::operator[](int i) const
{
return ((i<=0)?x:((i>=3)?w:((i==1)?y:z)));
}
float& ON_4fPoint::operator[](int i)
{
float* pd = (i<=0) ? &x : ( (i>=3) ? &w : (i==1)?&y:&z);
return *pd;
}
float ON_4fPoint::operator[](unsigned int i) const
{
return ((i<=0)?x:((i>=3)?w:((i==1)?y:z)));
}
float& ON_4fPoint::operator[](unsigned int i)
{
float* pd = (i<=0) ? &x : ( (i>=3) ? &w : (i==1)?&y:&z);
return *pd;
}
int ON_4fPoint::MaximumCoordinateIndex() const
{
const float* a = &x;
int i = ( fabs(y) > fabs(x) ) ? 1 : 0;
if (fabs(z) > fabs(a[i])) i = 2; if (fabs(w) > fabs(a[i])) i = 3;
return i;
}
double ON_4fPoint::MaximumCoordinate() const
{
double c = fabs(x); if (fabs(y)>c) c=fabs(y); if (fabs(z)>c) c=fabs(z); if (fabs(w)>c) c=fabs(w);
return c;
}
ON_4fPoint operator*( float d, const ON_4fPoint& p )
{
return ON_4fPoint( d*p.x, d*p.y, d*p.z, d*p.w );
}
ON_4dPoint operator*( double d, const ON_4fPoint& p )
{
return ON_4dPoint( d*p.x, d*p.y, d*p.z, d*p.w );
}
////////////////////////////////////////////////////////////////
//
// ON_2fVector
//
// static
const ON_2fVector& ON_2fVector::UnitVector(int index)
{
static ON_2fVector o(0.0,0.0);
static ON_2fVector x(1.0,0.0);
static ON_2fVector y(0.0,1.0);
switch(index)
{
case 0:
return x;
case 1:
return y;
}
return o;
}
ON_2fVector::ON_2fVector( const double* v )
{
if (v) {
x = (float)v[0]; y = (float)v[1];
}
else {
x = y = 0.0;
}
}
ON_2fVector::ON_2fVector( const float* v )
{
if (v) {
x = v[0]; y = v[1];
}
else {
x = y = 0.0;
}
}
ON_2fVector::ON_2fVector(float xx,float yy)
{x=xx;y=yy;}
ON_2fVector::ON_2fVector(const ON_3fVector& v)
{x=v.x;y=v.y;}
ON_2fVector::ON_2fVector(const ON_2fPoint& p)
{x=p.x;y=p.y;}
ON_2fVector::ON_2fVector(const ON_3fPoint& p)
{x=p.x;y=p.y;}
ON_2fVector::ON_2fVector(const ON_2dVector& v)
{x=(float)v.x;y=(float)v.y;}
ON_2fVector::ON_2fVector(const ON_3dVector& v)
{x=(float)v.x;y=(float)v.y;}
ON_2fVector::ON_2fVector(const ON_2dPoint& p)
{x=(float)p.x;y=(float)p.y;}
ON_2fVector::ON_2fVector(const ON_3dPoint& p)
{x=(float)p.x;y=(float)p.y;}
ON_2fVector::operator float*()
{
return &x;
}
ON_2fVector::operator const float*() const
{
return &x;
}
ON_2fVector& ON_2fVector::operator=(const double* v)
{
if ( v ) {
x = (float)v[0];
y = (float)v[1];
}
else {
x = y = 0.0;
}
return *this;
}
ON_2fVector& ON_2fVector::operator=(const float* v)
{
if ( v ) {
x = v[0];
y = v[1];
}
else {
x = y = 0.0;
}
return *this;
}
ON_2fVector& ON_2fVector::operator=(const ON_3fVector& v)
{
x = v.x;
y = v.y;
return *this;
}
ON_2fVector& ON_2fVector::operator=(const ON_2fPoint& p)
{
x = p.x;
y = p.y;
return *this;
}
ON_2fVector& ON_2fVector::operator=(const ON_3fPoint& p)
{
x = p.x;
y = p.y;
return *this;
}
ON_2fVector& ON_2fVector::operator=(const ON_2dVector& v)
{
x = (float)v.x;
y = (float)v.y;
return *this;
}
ON_2fVector& ON_2fVector::operator=(const ON_3dVector& v)
{
x = (float)v.x;
y = (float)v.y;
return *this;
}
ON_2fVector& ON_2fVector::operator=(const ON_2dPoint& p)
{
x = (float)p.x;
y = (float)p.y;
return *this;
}
ON_2fVector& ON_2fVector::operator=(const ON_3dPoint& p)
{
x = (float)p.x;
y = (float)p.y;
return *this;
}
ON_2fVector ON_2fVector::operator-() const
{
return ON_2fVector(-x,-y);
}
ON_2fVector& ON_2fVector::operator*=(float d)
{
x *= d;
y *= d;
return *this;
}
ON_2fVector& ON_2fVector::operator/=(float d)
{
const float one_over_d = 1.0f/d;
x *= one_over_d;
y *= one_over_d;
return *this;
}
ON_2fVector& ON_2fVector::operator+=(const ON_2fVector& v)
{
x += v.x;
y += v.y;
return *this;
}
ON_2fVector& ON_2fVector::operator-=(const ON_2fVector& v)
{
x -= v.x;
y -= v.y;
return *this;
}
ON_2fVector ON_2fVector::operator*( int d ) const
{
return ON_2fVector(x*d,y*d);
}
ON_2fVector ON_2fVector::operator*( float d ) const
{
return ON_2fVector(x*d,y*d);
}
ON_2dVector ON_2fVector::operator*( double d ) const
{
return ON_2dVector(x*d,y*d);
}
float ON_2fVector::operator*( const ON_2fVector& v ) const
{
return (x*v.x + y*v.y);
}
float ON_2fVector::operator*( const ON_2fPoint& v ) const
{
return (x*v.x + y*v.y);
}
double ON_2fVector::operator*( const ON_2dVector& v ) const
{
return (x*v.x + y*v.y);
}
ON_2fVector ON_2fVector::operator/( int d ) const
{
const float one_over_d = 1.0f/((float)d);
return ON_2fVector(x*one_over_d,y*one_over_d);
}
ON_2fVector ON_2fVector::operator/( float d ) const
{
const float one_over_d = 1.0f/d;
return ON_2fVector(x*one_over_d,y*one_over_d);
}
ON_2dVector ON_2fVector::operator/( double d ) const
{
const double one_over_d = 1.0/d;
return ON_2dVector(x*one_over_d,y*one_over_d);
}
ON_2fVector ON_2fVector::operator+( const ON_2fVector& v ) const
{
return ON_2fVector(x+v.x,y+v.y);
}
ON_2fPoint ON_2fVector::operator+( const ON_2fPoint& p ) const
{
return ON_2fPoint(x+p.x,y+p.y);
}
ON_2fVector ON_2fVector::operator-( const ON_2fVector& v ) const
{
return ON_2fVector(x-v.x,y-v.y);
}
ON_2fPoint ON_2fVector::operator-( const ON_2fPoint& v ) const
{
return ON_2fPoint(x-v.x,y-v.y);
}
ON_3fVector ON_2fVector::operator+( const ON_3fVector& v ) const
{
return ON_3fVector(x+v.x,y+v.y,v.z);
}
ON_3fPoint ON_2fVector::operator+( const ON_3fPoint& p ) const
{
return ON_3fPoint(x+p.x,y+p.y,p.z);
}
ON_3fVector ON_2fVector::operator-( const ON_3fVector& v ) const
{
return ON_3fVector(x-v.x,y-v.y,-v.z);
}
ON_3fPoint ON_2fVector::operator-( const ON_3fPoint& v ) const
{
return ON_3fPoint(x-v.x,y-v.y,-v.z);
}
////
ON_2dVector ON_2fVector::operator+( const ON_2dVector& v ) const
{
return ON_2dVector(x+v.x,y+v.y);
}
ON_2dPoint ON_2fVector::operator+( const ON_2dPoint& p ) const
{
return ON_2dPoint(x+p.x,y+p.y);
}
ON_2dVector ON_2fVector::operator-( const ON_2dVector& v ) const
{
return ON_2dVector(x-v.x,y-v.y);
}
ON_2dPoint ON_2fVector::operator-( const ON_2dPoint& v ) const
{
return ON_2dPoint(x-v.x,y-v.y);
}
ON_3dVector ON_2fVector::operator+( const ON_3dVector& v ) const
{
return ON_3dVector(x+v.x,y+v.y,v.z);
}
ON_3dPoint ON_2fVector::operator+( const ON_3dPoint& p ) const
{
return ON_3dPoint(x+p.x,y+p.y,p.z);
}
ON_3dVector ON_2fVector::operator-( const ON_3dVector& v ) const
{
return ON_3dVector(x-v.x,y-v.y,-v.z);
}
ON_3dPoint ON_2fVector::operator-( const ON_3dPoint& v ) const
{
return ON_3dPoint(x-v.x,y-v.y,-v.z);
}
bool ON_2fVector::operator==( const ON_2fVector& v ) const
{
return (x==v.x&&y==v.y)?true:false;
}
bool ON_2fVector::operator!=( const ON_2fVector& v ) const
{
return Internal_NotEqualFloatArray(2, &x, &v.x);
}
bool ON_2fVector::operator<=( const ON_2fVector& v ) const
{
// dictionary order
return ((x<v.x)?true:((x==v.x&&y<=v.y)?true:false));
}
bool ON_2fVector::operator>=( const ON_2fVector& v ) const
{
// dictionary order
return ((x>v.x)?true:((x==v.x&&y>=v.y)?true:false));
}
bool ON_2fVector::operator<( const ON_2fVector& v ) const
{
// dictionary order
return ((x<v.x)?true:((x==v.x&&y<v.y)?true:false));
}
bool ON_2fVector::operator>( const ON_2fVector& v ) const
{
// dictionary order
return ((x>v.x)?true:((x==v.x&&y>v.y)?true:false));
}
float ON_2fVector::operator[](int i) const
{
return ((i<=0)?x:y);
}
float& ON_2fVector::operator[](int i)
{
float* pd = (i<=0)? &x : &y;
return *pd;
}
float ON_2fVector::operator[](unsigned int i) const
{
return ((i<=0)?x:y);
}
float& ON_2fVector::operator[](unsigned int i)
{
float* pd = (i<=0)? &x : &y;
return *pd;
}
int ON_2fVector::MaximumCoordinateIndex() const
{
return ( (fabs(y)>fabs(x)) ? 1 : 0 );
}
double ON_2fVector::MaximumCoordinate() const
{
double c = fabs(x); if (fabs(y)>c) c=fabs(y);
return c;
}
double ON_2fVector::LengthSquared() const
{
return (x*x + y*y);
}
double ON_2fVector::Length() const
{
return ON_Length2d((double)x,(double)y);
}
void ON_2fVector::Reverse()
{
x = -x;
y = -y;
}
bool ON_2fVector::Unitize()
{
bool rc = false;
// Since x,y are floats, d will not be denormalized and the
// ON_DBL_MIN tests in ON_2dVector::Unitize() are not needed.
double d = Length();
if ( d > 0.0 )
{
double dx = (double)x;
double dy = (double)y;
x = (float)(dx/d);
y = (float)(dy/d);
rc = true;
}
return rc;
}
ON_2fVector ON_2fVector::UnitVector() const
{
ON_2fVector u(*this);
u.Unitize();
return u;
}
bool ON_2fVector::IsUnitVector() const
{
return (x != ON_UNSET_FLOAT && y != ON_UNSET_FLOAT && fabs(Length() - 1.0) <= 1.0e-5);
}
bool ON_3fVector::IsUnitVector() const
{
return (x != ON_UNSET_FLOAT && y != ON_UNSET_FLOAT && z != ON_UNSET_FLOAT && fabs(Length() - 1.0) <= 1.0e-5);
}
bool ON_2fVector::IsTiny( double tiny_tol ) const
{
return (fabs(x) <= tiny_tol && fabs(y) <= tiny_tol );
}
void ON_2fVector::Zero()
{
x = y = 0.0;
}
bool ON_2fVector::IsZero() const
{
return (x==0.0f && y==0.0f);
}
bool ON_2fVector::IsNotZero() const
{
// the && (x == x && y == y) insures no coordinate is a Nan.
return (x != 0.0f || y != 0.0f) && (x == x && y == y);
}
// set this vector to be perpendicular to another vector
bool ON_2fVector::PerpendicularTo( // Result is not unitized.
// returns false if input vector is zero
const ON_2fVector& v
)
{
y = v.x;
x = -v.y;
return (x!= 0.0f || y!= 0.0f) ? true : false;
}
// set this vector to be perpendicular to a line defined by 2 points
bool ON_2fVector::PerpendicularTo(
const ON_2fPoint& p,
const ON_2fPoint& q
)
{
return PerpendicularTo(q-p);
}
ON_2fVector operator*(int d, const ON_2fVector& v)
{
return ON_2fVector(d*v.x,d*v.y);
}
ON_2fVector operator*(float d, const ON_2fVector& v)
{
return ON_2fVector(d*v.x,d*v.y);
}
ON_2dVector operator*(double d, const ON_2fVector& v)
{
return ON_2dVector(d*v.x,d*v.y);
}
float ON_DotProduct( const ON_2fVector& a , const ON_2fVector& b )
{
// inner (dot) product between 3d vectors
return (a.x*b.x + a.y*b.y );
}
ON_3fVector ON_CrossProduct( const ON_2fVector& a , const ON_2fVector& b )
{
return ON_3fVector(0.0, 0.0, a.x*b.y - b.x*a.y );
}
////////////////////////////////////////////////////////////////
//
// ON_3fVector
//
// static
const ON_3fVector& ON_3fVector::UnitVector(int index)
{
static ON_3fVector o(0.0,0.0,0.0);
static ON_3fVector x(1.0,0.0,0.0);
static ON_3fVector y(0.0,1.0,0.0);
static ON_3fVector z(0.0,0.0,1.0);
switch(index)
{
case 0:
return x;
case 1:
return y;
case 2:
return z;
}
return o;
}
ON_3fVector::ON_3fVector( const double* v )
{
if (v) {
x = (float)v[0]; y = (float)v[1]; z = (float)v[2];
}
else {
x = y = z = 0.0;
}
}
ON_3fVector::ON_3fVector( const float* v )
{
if (v) {
x = v[0]; y = v[1]; z = v[2];
}
else {
x = y = z = 0.0;
}
}
ON_3fVector::ON_3fVector(float xx,float yy,float zz)
{x=xx;y=yy;z=zz;}
ON_3fVector::ON_3fVector(const ON_2fVector& v)
{x=v.x;y=v.y;z=0.0f;}
ON_3fVector::ON_3fVector(const ON_2fPoint& p)
{x=p.x;y=p.y;z=0.0f;}
ON_3fVector::ON_3fVector(const ON_3fPoint& p)
{x=p.x;y=p.y;z=p.z;}
ON_3fVector::ON_3fVector(const ON_2dVector& v)
{x=(float)v.x;y=(float)v.y;z=(float)0.0f;}
ON_3fVector::ON_3fVector(const ON_3dVector& v)
{x=(float)v.x;y=(float)v.y;z=(float)v.z;}
ON_3fVector::ON_3fVector(const ON_2dPoint& p)
{x=(float)p.x;y=(float)p.y;z=(float)0.0f;}
ON_3fVector::ON_3fVector(const ON_3dPoint& p)
{x=(float)p.x;y=(float)p.y;z=(float)p.z;}
ON_3fVector::operator float*()
{
return &x;
}
ON_3fVector::operator const float*() const
{
return &x;
}
ON_3fVector& ON_3fVector::operator=(const double* v)
{
if ( v ) {
x = (float)v[0];
y = (float)v[1];
z = (float)v[2];
}
else {
x = y = z = 0.0;
}
return *this;
}
ON_3fVector& ON_3fVector::operator=(const float* v)
{
if ( v ) {
x = v[0];
y = v[1];
z = v[2];
}
else {
x = y = z = 0.0;
}
return *this;
}
ON_3fVector& ON_3fVector::operator=(const ON_2fVector& v)
{
x = v.x;
y = v.y;
z = 0.0;
return *this;
}
ON_3fVector& ON_3fVector::operator=(const ON_2fPoint& p)
{
x = p.x;
y = p.y;
z = 0.0f;
return *this;
}
ON_3fVector& ON_3fVector::operator=(const ON_3fPoint& p)
{
x = p.x;
y = p.y;
z = p.z;
return *this;
}
ON_3fVector& ON_3fVector::operator=(const ON_2dVector& v)
{
x = (float)v.x;
y = (float)v.y;
z = 0.0f;
return *this;
}
ON_3fVector& ON_3fVector::operator=(const ON_3dVector& v)
{
x = (float)v.x;
y = (float)v.y;
z = (float)v.z;
return *this;
}
ON_3fVector& ON_3fVector::operator=(const ON_2dPoint& p)
{
x = (float)p.x;
y = (float)p.y;
z = 0.0f;
return *this;
}
ON_3fVector& ON_3fVector::operator=(const ON_3dPoint& p)
{
x = (float)p.x;
y = (float)p.y;
z = (float)p.z;
return *this;
}
ON_3fVector ON_3fVector::operator-() const
{
return ON_3fVector(-x,-y,-z);
}
ON_3fVector& ON_3fVector::operator*=(float d)
{
x *= d;
y *= d;
z *= d;
return *this;
}
ON_3fVector& ON_3fVector::operator/=(float d)
{
const float one_over_d = 1.0f/d;
x *= one_over_d;
y *= one_over_d;
z *= one_over_d;
return *this;
}
ON_3fVector& ON_3fVector::operator+=(const ON_3fVector& v)
{
x += v.x;
y += v.y;
z += v.z;
return *this;
}
ON_3fVector& ON_3fVector::operator-=(const ON_3fVector& v)
{
x -= v.x;
y -= v.y;
z -= v.z;
return *this;
}
ON_3fVector ON_3fVector::operator*( int d ) const
{
return ON_3fVector(x*d,y*d,z*d);
}
ON_3fVector ON_3fVector::operator*( float d ) const
{
return ON_3fVector(x*d,y*d,z*d);
}
ON_3dVector ON_3fVector::operator*( double d ) const
{
return ON_3dVector(x*d,y*d,z*d);
}
float ON_3fVector::operator*( const ON_3fVector& v ) const
{
return (x*v.x + y*v.y + z*v.z);
}
float ON_3fVector::operator*( const ON_3fPoint& v ) const
{
return (x*v.x + y*v.y + z*v.z);
}
double ON_3fVector::operator*( const ON_3dVector& v ) const
{
return (x*v.x + y*v.y + z*v.z);
}
ON_3fVector ON_3fVector::operator/( int d ) const
{
const float one_over_d = 1.0f/((int)d);
return ON_3fVector(x*one_over_d,y*one_over_d,z*one_over_d);
}
ON_3fVector ON_3fVector::operator/( float d ) const
{
const float one_over_d = 1.0f/d;
return ON_3fVector(x*one_over_d,y*one_over_d,z*one_over_d);
}
ON_3dVector ON_3fVector::operator/( double d ) const
{
const double one_over_d = 1.0/d;
return ON_3dVector(x*one_over_d,y*one_over_d,z*one_over_d);
}
ON_3fVector ON_3fVector::operator+( const ON_3fVector& v ) const
{
return ON_3fVector(x+v.x,y+v.y,z+v.z);
}
ON_3fPoint ON_3fVector::operator+( const ON_3fPoint& p ) const
{
return ON_3fPoint(x+p.x,y+p.y,z+p.z);
}
ON_3fVector ON_3fVector::operator-( const ON_3fVector& v ) const
{
return ON_3fVector(x-v.x,y-v.y,z-v.z);
}
ON_3fPoint ON_3fVector::operator-( const ON_3fPoint& v ) const
{
return ON_3fPoint(x-v.x,y-v.y,z-v.z);
}
ON_3fVector ON_3fVector::operator+( const ON_2fVector& v ) const
{
return ON_3fVector(x+v.x,y+v.y,z);
}
ON_3fPoint ON_3fVector::operator+( const ON_2fPoint& p ) const
{
return ON_3fPoint(x+p.x,y+p.y,z);
}
ON_3fVector ON_3fVector::operator-( const ON_2fVector& v ) const
{
return ON_3fVector(x-v.x,y-v.y,z);
}
ON_3fPoint ON_3fVector::operator-( const ON_2fPoint& v ) const
{
return ON_3fPoint(x-v.x,y-v.y,z);
}
/////
ON_3dVector ON_3fVector::operator+( const ON_3dVector& v ) const
{
return ON_3dVector(x+v.x,y+v.y,z+v.z);
}
ON_3dPoint ON_3fVector::operator+( const ON_3dPoint& p ) const
{
return ON_3dPoint(x+p.x,y+p.y,z+p.z);
}
ON_3dVector ON_3fVector::operator-( const ON_3dVector& v ) const
{
return ON_3dVector(x-v.x,y-v.y,z-v.z);
}
ON_3dPoint ON_3fVector::operator-( const ON_3dPoint& v ) const
{
return ON_3dPoint(x-v.x,y-v.y,z-v.z);
}
ON_3dVector ON_3fVector::operator+( const ON_2dVector& v ) const
{
return ON_3dVector(x+v.x,y+v.y,z);
}
ON_3dPoint ON_3fVector::operator+( const ON_2dPoint& p ) const
{
return ON_3dPoint(x+p.x,y+p.y,z);
}
ON_3dVector ON_3fVector::operator-( const ON_2dVector& v ) const
{
return ON_3dVector(x-v.x,y-v.y,z);
}
ON_3dPoint ON_3fVector::operator-( const ON_2dPoint& v ) const
{
return ON_3dPoint(x-v.x,y-v.y,z);
}
bool ON_3fVector::operator==( const ON_3fVector& v ) const
{
return (x==v.x&&y==v.y&&z==v.z)?true:false;
}
bool ON_3fVector::operator!=( const ON_3fVector& v ) const
{
return Internal_NotEqualFloatArray(3, &x, &v.x);
}
bool ON_3fVector::operator<=( const ON_3fVector& v ) const
{
// dictionary order
return ((x<v.x)?true:((x==v.x)?((y<v.y)?true:(y==v.y&&z<=v.z)?true:false):false));
}
bool ON_3fVector::operator>=( const ON_3fVector& v ) const
{
// dictionary order
return ((x>v.x)?true:((x==v.x)?((y>v.y)?true:(y==v.y&&z>=v.z)?true:false):false));
}
bool ON_3fVector::operator<( const ON_3fVector& v ) const
{
// dictionary order
return ((x<v.x)?true:((x==v.x)?((y<v.y)?true:(y==v.y&&z<v.z)?true:false):false));
}
bool ON_3fVector::operator>( const ON_3fVector& v ) const
{
// dictionary order
return ((x>v.x)?true:((x==v.x)?((y>v.y)?true:(y==v.y&&z>v.z)?true:false):false));
}
float ON_3fVector::operator[](int i) const
{
return ( (i<=0)?x:((i>=2)?z:y) );
}
float& ON_3fVector::operator[](int i)
{
float* pd = (i<=0)? &x : ( (i>=2) ? &z : &y);
return *pd;
}
float ON_3fVector::operator[](unsigned int i) const
{
return ( (i<=0)?x:((i>=2)?z:y) );
}
float& ON_3fVector::operator[](unsigned int i)
{
float* pd = (i<=0)? &x : ( (i>=2) ? &z : &y);
return *pd;
}
int ON_3fVector::MaximumCoordinateIndex() const
{
return (fabs(y)>fabs(x)) ? ((fabs(z)>fabs(y))?2:1) : ((fabs(z)>fabs(x))?2:0);
}
double ON_3fVector::MaximumCoordinate() const
{
double c = fabs(x); if (fabs(y)>c) c=fabs(y); if (fabs(z)>c) c=fabs(z);
return c;
}
double ON_3fVector::LengthSquared() const
{
return (x*x + y*y + z*z);
}
double ON_3fVector::Length() const
{
return ON_Length3d((double)x,(double)y,(double)z);
}
void ON_3fVector::Reverse()
{
x = -x;
y = -y;
z = -z;
}
bool ON_3fVector::Unitize()
{
bool rc = false;
// Since x,y,z are floats, d will not be denormalized and the
// ON_DBL_MIN tests in ON_2dVector::Unitize() are not needed.
double d = Length();
if ( d > 0.0 )
{
double dx = x;
double dy = y;
double dz = z;
x = (float)(dx/d);
y = (float)(dy/d);
z = (float)(dz/d);
rc = true;
}
return rc;
}
ON_3fVector ON_3fVector::UnitVector() const
{
ON_3fVector u(*this);
u.Unitize();
return u;
}
bool ON_3fVector::IsTiny( double tiny_tol ) const
{
return (fabs(x) <= tiny_tol && fabs(y) <= tiny_tol && fabs(z) <= tiny_tol );
}
void ON_3fVector::Zero()
{
x = y = z = 0.0;
}
bool ON_3fVector::IsZero() const
{
return (x==0.0f && y==0.0f && z==0.0f);
}
bool ON_3fVector::IsNotZero() const
{
// the && (x == x && y == y && z == z) insures no coordinate is a Nan.
return (x != 0.0f || y != 0.0f || z != 0.0f) && (x == x && y == y && z == z);
}
ON_3fVector operator*(int d, const ON_3fVector& v)
{
return ON_3fVector(d*v.x,d*v.y,d*v.z);
}
ON_3fVector operator*(float d, const ON_3fVector& v)
{
return ON_3fVector(d*v.x,d*v.y,d*v.z);
}
ON_3dVector operator*(double d, const ON_3fVector& v)
{
return ON_3dVector(d*v.x,d*v.y,d*v.z);
}
float ON_DotProduct( const ON_3fVector& a , const ON_3fVector& b )
{
// inner (dot) product between 3d vectors
return (a.x*b.x + a.y*b.y + a.z*b.z);
}
ON_3fVector ON_CrossProduct( const ON_3fVector& a , const ON_3fVector& b )
{
return ON_3fVector(a.y*b.z - b.y*a.z, a.z*b.x - b.z*a.x, a.x*b.y - b.x*a.y );
}
ON_3fVector ON_CrossProduct( const float* a, const float* b )
{
return ON_3fVector(a[1]*b[2] - b[1]*a[2], a[2]*b[0] - b[2]*a[0], a[0]*b[1] - b[0]*a[1] );
}
float ON_TripleProduct( const ON_3fVector& a, const ON_3fVector& b, const ON_3fVector& c )
{
// = a o (b x c )
return (a.x*(b.y*c.z - b.z*c.y) + a.y*(b.z*c.x - b.x*c.z) + a.z*(b.x*c.y - b.y*c.x));
}
float ON_TripleProduct( const float* a, const float* b, const float* c )
{
// = a o (b x c )
return (a[0]*(b[1]*c[2] - b[2]*c[1]) + a[1]*(b[2]*c[0] - b[0]*c[2]) + a[2]*(b[0]*c[1] - b[1]*c[0]));
}
////////////////////////////////////////////////////////////////
//
// ON_2dPoint
//
ON_2dPoint::ON_2dPoint( const float* p )
{
if (p) {
x = (double)p[0]; y = (double)p[1];
}
else {
x = y = 0.0;
}
}
ON_2dPoint::ON_2dPoint( const double* p )
{
if (p) {
x = p[0]; y = p[1];
}
else {
x = y = 0.0;
}
}
ON_2dPoint::ON_2dPoint(double xx,double yy)
{x=xx;y=yy;}
ON_2dPoint::ON_2dPoint(const ON_3dPoint& p)
{x=p.x;y=p.y;}
ON_2dPoint::ON_2dPoint(const ON_4dPoint& h)
{
x=h.x;y=h.y;
const double w = (h.w != 1.0 && h.w != 0.0) ? 1.0/h.w : 1.0;
x *= w;
y *= w;
}
ON_2dPoint::ON_2dPoint(const ON_2dVector& v)
{x=v.x;y=v.y;}
ON_2dPoint::ON_2dPoint(const ON_3dVector& v)
{x=v.x;y=v.y;}
ON_2dPoint::ON_2dPoint(const ON_2fPoint& p)
{x=p.x;y=p.y;}
ON_2dPoint::ON_2dPoint(const ON_3fPoint& p)
{x=p.x;y=p.y;}
ON_2dPoint::ON_2dPoint(const ON_4fPoint& h)
{
const double w = (h.w != 1.0f && h.w != 0.0f) ? 1.0/((double)h.w) : 1.0;
x *= w*h.x;
y *= w*h.y;
}
ON_2dPoint::ON_2dPoint(const ON_2fVector& v)
{x=v.x;y=v.y;}
ON_2dPoint::ON_2dPoint(const ON_3fVector& v)
{x=v.x;y=v.y;}
ON_2dPoint::operator double*()
{
return &x;
}
ON_2dPoint::operator const double*() const
{
return &x;
}
ON_2dPoint& ON_2dPoint::operator=(const float* p)
{
if ( p ) {
x = (double)p[0];
y = (double)p[1];
}
else {
x = y = 0.0;
}
return *this;
}
ON_2dPoint& ON_2dPoint::operator=(const double* p)
{
if ( p ) {
x = p[0];
y = p[1];
}
else {
x = y = 0.0;
}
return *this;
}
ON_2dPoint& ON_2dPoint::operator=(const ON_3dPoint& p)
{
x = p.x;
y = p.y;
return *this;
}
ON_2dPoint& ON_2dPoint::operator=(const ON_4dPoint& h)
{
const double w = (h.w != 1.0 && h.w != 0.0) ? 1.0/h.w : 1.0;
x = w*h.x;
y = w*h.y;
return *this;
}
ON_2dPoint& ON_2dPoint::operator=(const ON_2dVector& v)
{
x = v.x;
y = v.y;
return *this;
}
ON_2dPoint& ON_2dPoint::operator=(const ON_3dVector& v)
{
x = v.x;
y = v.y;
return *this;
}
ON_2dPoint& ON_2dPoint::operator=(const ON_2fPoint& p)
{
x = p.x;
y = p.y;
return *this;
}
ON_2dPoint& ON_2dPoint::operator=(const ON_3fPoint& p)
{
x = p.x;
y = p.y;
return *this;
}
ON_2dPoint& ON_2dPoint::operator=(const ON_4fPoint& h)
{
const double w = (h.w != 1.0f && h.w != 0.0f) ? 1.0/((double)h.w) : 1.0;
x = w*h.x;
y = w*h.y;
return *this;
}
ON_2dPoint& ON_2dPoint::operator=(const ON_2fVector& v)
{
x = v.x;
y = v.y;
return *this;
}
ON_2dPoint& ON_2dPoint::operator=(const ON_3fVector& v)
{
x = v.x;
y = v.y;
y = v.z;
return *this;
}
ON_2dPoint& ON_2dPoint::operator*=(double d)
{
x *= d;
y *= d;
return *this;
}
ON_2dPoint& ON_2dPoint::operator/=(double d)
{
const double one_over_d = 1.0/d;
x *= one_over_d;
y *= one_over_d;
return *this;
}
ON_2dPoint& ON_2dPoint::operator+=(const ON_2dVector& v)
{
x += v.x;
y += v.y;
return *this;
}
ON_2dPoint& ON_2dPoint::operator-=(const ON_2dVector& v)
{
x -= v.x;
y -= v.y;
return *this;
}
ON_2dPoint ON_2dPoint::operator*( int i ) const
{
double d = i;
return ON_2dPoint(x*d,y*d);
}
ON_2dPoint ON_2dPoint::operator*( float f ) const
{
double d = f;
return ON_2dPoint(x*d,y*d);
}
ON_2dPoint ON_2dPoint::operator*( double d ) const
{
return ON_2dPoint(x*d,y*d);
}
ON_2dPoint ON_2dPoint::operator/( int i ) const
{
const double one_over_d = 1.0/((double)i);
return ON_2dPoint(x*one_over_d,y*one_over_d);
}
ON_2dPoint ON_2dPoint::operator/( float f ) const
{
const double one_over_d = 1.0/((double)f);
return ON_2dPoint(x*one_over_d,y*one_over_d);
}
ON_2dPoint ON_2dPoint::operator/( double d ) const
{
const double one_over_d = 1.0/d;
return ON_2dPoint(x*one_over_d,y*one_over_d);
}
ON_2dPoint ON_2dPoint::operator+( const ON_2dPoint& p ) const
{
return ON_2dPoint(x+p.x,y+p.y);
}
ON_2dPoint ON_2dPoint::operator+( const ON_2dVector& v ) const
{
return ON_2dPoint(x+v.x,y+v.y);
}
ON_2dVector ON_2dPoint::operator-( const ON_2dPoint& p ) const
{
return ON_2dVector(x-p.x,y-p.y);
}
ON_2dPoint ON_2dPoint::operator-( const ON_2dVector& v ) const
{
return ON_2dPoint(x-v.x,y-v.y);
}
ON_3dPoint ON_2dPoint::operator+( const ON_3dPoint& p ) const
{
return ON_3dPoint(x+p.x,y+p.y,p.z);
}
ON_3dPoint ON_2dPoint::operator+( const ON_3dVector& v ) const
{
return ON_3dPoint(x+v.x,y+v.y,v.z);
}
ON_3dVector ON_2dPoint::operator-( const ON_3dPoint& p ) const
{
return ON_3dVector(x-p.x,y-p.y,-p.z);
}
ON_3dPoint ON_2dPoint::operator-( const ON_3dVector& v ) const
{
return ON_3dPoint(x-v.x,y-v.y,-v.z);
}
///////////////////////////////////////////////////
ON_2dPoint ON_2dPoint::operator+( const ON_2fPoint& p ) const
{
return ON_2dPoint(x+p.x,y+p.y);
}
ON_2dPoint ON_2dPoint::operator+( const ON_2fVector& v ) const
{
return ON_2dPoint(x+v.x,y+v.y);
}
ON_2dVector ON_2dPoint::operator-( const ON_2fPoint& p ) const
{
return ON_2dVector(x-p.x,y-p.y);
}
ON_2dPoint ON_2dPoint::operator-( const ON_2fVector& v ) const
{
return ON_2dPoint(x-v.x,y-v.y);
}
ON_3dPoint ON_2dPoint::operator+( const ON_3fPoint& p ) const
{
return ON_3dPoint(x+p.x,y+p.y,p.z);
}
ON_3dPoint ON_2dPoint::operator+( const ON_3fVector& v ) const
{
return ON_3dPoint(x+v.x,y+v.y,v.z);
}
ON_3dVector ON_2dPoint::operator-( const ON_3fPoint& p ) const
{
return ON_3dVector(x-p.x,y-p.y,-p.z);
}
ON_3dPoint ON_2dPoint::operator-( const ON_3fVector& v ) const
{
return ON_3dPoint(x-v.x,y-v.y,-v.z);
}
double ON_2dPoint::operator*(const ON_2dPoint& h) const
{
return x*h.x + y*h.y;
}
double ON_2dPoint::operator*(const ON_2dVector& h) const
{
return x*h.x + y*h.y;
}
bool ON_2dPoint::operator==( const ON_2dPoint& p ) const
{
return (x==p.x&&y==p.y)?true:false;
}
bool ON_2dPoint::operator!=( const ON_2dPoint& p ) const
{
return Internal_NotEqualDoubleArray(2, &x, &p.x);
}
bool ON_2dPoint::operator<=( const ON_2dPoint& p ) const
{
// dictionary order
return ( (x<p.x) ? true : ((x==p.x&&y<=p.y)?true:false) );
}
bool ON_2dPoint::operator>=( const ON_2dPoint& p ) const
{
// dictionary order
return ( (x>p.x) ? true : ((x==p.x&&y>=p.y)?true:false) );
}
bool ON_2dPoint::operator<( const ON_2dPoint& p ) const
{
// dictionary order
return ( (x<p.x) ? true : ((x==p.x&&y<p.y)?true:false) );
}
bool ON_2dPoint::operator>( const ON_2dPoint& p ) const
{
// dictionary order
return ( (x>p.x) ? true : ((x==p.x&&y>p.y)?true:false) );
}
double ON_2dPoint::operator[](int i) const
{
return (i<=0) ? x : y;
}
double& ON_2dPoint::operator[](int i)
{
double* pd = (i<=0)? &x : &y;
return *pd;
}
double ON_2dPoint::operator[](unsigned int i) const
{
return (i<=0) ? x : y;
}
double& ON_2dPoint::operator[](unsigned int i)
{
double* pd = (i<=0)? &x : &y;
return *pd;
}
double ON_2dPoint::DistanceTo( const ON_2dPoint& p ) const
{
return ON_Length2d(p.x-x,p.y-y);
}
int ON_2dPoint::MaximumCoordinateIndex() const
{
return (fabs(y)>fabs(x)) ? 1 : 0;
}
double ON_2dPoint::MaximumCoordinate() const
{
double c = fabs(x); if (fabs(y)>c) c=fabs(y);
return c;
}
int ON_2dPoint::MinimumCoordinateIndex() const
{
return (fabs(y)<fabs(x)) ? 1 : 0;
}
double ON_2dPoint::MinimumCoordinate() const
{
double c = fabs(x); if (fabs(y)<c) c=fabs(y);
return c;
}
void ON_2dPoint::Zero()
{
x = y = 0.0;
}
bool ON_2dPoint::IsZero() const
{
return (x==0.0 && y==0.0);
}
bool ON_2dPoint::IsNotZero() const
{
// the && (x == x && y == y) insures no coordinate is a Nan.
return (x != 0.0 || y != 0.0) && (x == x && y == y);
}
ON_2dPoint operator*(int i, const ON_2dPoint& p)
{
double d = i;
return ON_2dPoint(d*p.x,d*p.y);
}
ON_2dPoint operator*(float f, const ON_2dPoint& p)
{
double d = f;
return ON_2dPoint(d*p.x,d*p.y);
}
ON_2dPoint operator*(double d, const ON_2dPoint& p)
{
return ON_2dPoint(d*p.x,d*p.y);
}
////////////////////////////////////////////////////////////////
//
// ON_3dPoint
//
ON_3dPoint::ON_3dPoint( const float* p )
{
if (p) {
x = (double)p[0]; y = (double)p[1]; z = (double)p[2];
}
else {
x = y = z = 0.0;
}
}
ON_3dPoint::ON_3dPoint(const ON_2fPoint& p)
{x=(double)p.x;y=(double)p.y;z=0.0;}
ON_3dPoint::ON_3dPoint(const ON_3fPoint& p)
{x=(double)p.x;y=(double)p.y;z=(double)p.z;}
ON_3dPoint::ON_3dPoint(const ON_4fPoint& p)
{
const double w = (p.w != 1.0f && p.w != 0.0f) ? 1.0/((double)p.w) : 1.0;
x = w*((double)p.x);
y = w*((double)p.y);
z = w*((double)p.z);
}
ON_3dPoint::ON_3dPoint(const ON_2fVector& p)
{x=(double)p.x;y=(double)p.y;z=0.0;}
ON_3dPoint::ON_3dPoint(const ON_3fVector& p)
{x=(double)p.x;y=(double)p.y;z=(double)p.z;}
ON_3dPoint::ON_3dPoint( const double* p )
{
if (p) {
x = p[0]; y = p[1]; z = p[2];
}
else {
x = y = z = 0.0;
}
}
ON_3dPoint::ON_3dPoint(double xx,double yy,double zz)
{x=xx;y=yy;z=zz;}
ON_3dPoint::ON_3dPoint(const ON_2dPoint& p)
{x=p.x;y=p.y;z=0.0;}
ON_3dPoint::ON_3dPoint(const ON_4dPoint& p)
{
x=p.x;y=p.y;z=p.z;
const double w = (p.w != 1.0 && p.w != 0.0) ? 1.0/p.w : 1.0;
x *= w;
y *= w;
z *= w;
}
ON_3dPoint::ON_3dPoint(const ON_2dVector& v)
{x=v.x;y=v.y;z=0.0;}
ON_3dPoint::ON_3dPoint(const ON_3dVector& v)
{x=v.x;y=v.y;z=v.z;}
ON_3dPoint::operator double*()
{
return &x;
}
ON_3dPoint::operator const double*() const
{
return &x;
}
ON_3dPoint& ON_3dPoint::operator=(const float* p)
{
if ( p ) {
x = (double)p[0];
y = (double)p[1];
z = (double)p[2];
}
else {
x = y = z = 0.0;
}
return *this;
}
ON_3dPoint& ON_3dPoint::operator=(const double* p)
{
if ( p ) {
x = p[0];
y = p[1];
z = p[2];
}
else {
x = y = z = 0.0;
}
return *this;
}
ON_3dPoint& ON_3dPoint::operator=(const ON_2dPoint& p)
{
x = p.x;
y = p.y;
z = 0.0;
return *this;
}
ON_3dPoint& ON_3dPoint::operator=(const ON_4dPoint& p)
{
const double w = (p.w != 1.0 && p.w != 0.0) ? 1.0/p.w : 1.0;
x = w*p.x;
y = w*p.y;
z = w*p.z;
return *this;
}
ON_3dPoint& ON_3dPoint::operator=(const ON_2dVector& v)
{
x = v.x;
y = v.y;
z = 0.0;
return *this;
}
ON_3dPoint& ON_3dPoint::operator=(const ON_3dVector& v)
{
x = v.x;
y = v.y;
z = v.z;
return *this;
}
ON_3dPoint& ON_3dPoint::operator=(const ON_2fPoint& p)
{
x = (double)p.x;
y = (double)p.y;
z = (double)0.0;
return *this;
}
ON_3dPoint& ON_3dPoint::operator=(const ON_3fPoint& p)
{
x = (double)p.x;
y = (double)p.y;
z = (double)p.z;
return *this;
}
ON_3dPoint& ON_3dPoint::operator=(const ON_4fPoint& p)
{
const double w = (p.w != 1.0f && p.w != 0.0f) ? 1.0/((double)p.w) : 1.0;
x = w*((double)p.x);
y = w*((double)p.y);
z = w*((double)p.z);
return *this;
}
ON_3dPoint& ON_3dPoint::operator=(const ON_2fVector& v)
{
x = v.x;
y = v.y;
z = 0.0;
return *this;
}
ON_3dPoint& ON_3dPoint::operator=(const ON_3fVector& v)
{
x = v.x;
y = v.y;
z = v.z;
return *this;
}
ON_3dPoint& ON_3dPoint::operator*=(double d)
{
x *= d;
y *= d;
z *= d;
return *this;
}
ON_3dPoint& ON_3dPoint::operator/=(double d)
{
const double one_over_d = 1.0/d;
x *= one_over_d;
y *= one_over_d;
z *= one_over_d;
return *this;
}
ON_3dPoint& ON_3dPoint::operator+=(const ON_3dVector& v)
{
x += v.x;
y += v.y;
z += v.z;
return *this;
}
ON_3dPoint& ON_3dPoint::operator-=(const ON_3dVector& v)
{
x -= v.x;
y -= v.y;
z -= v.z;
return *this;
}
ON_3dPoint ON_3dPoint::operator*( int i ) const
{
double d = i;
return ON_3dPoint(x*d,y*d,z*d);
}
ON_3dPoint ON_3dPoint::operator*( float f ) const
{
double d = f;
return ON_3dPoint(x*d,y*d,z*d);
}
ON_3dPoint ON_3dPoint::operator*( double d ) const
{
return ON_3dPoint(x*d,y*d,z*d);
}
ON_3dPoint ON_3dPoint::operator/( int i ) const
{
const double one_over_d = 1.0/((double)i);
return ON_3dPoint(x*one_over_d,y*one_over_d,z*one_over_d);
}
ON_3dPoint ON_3dPoint::operator/( float f ) const
{
const double one_over_d = 1.0/((double)f);
return ON_3dPoint(x*one_over_d,y*one_over_d,z*one_over_d);
}
ON_3dPoint ON_3dPoint::operator/( double d ) const
{
const double one_over_d = 1.0/d;
return ON_3dPoint(x*one_over_d,y*one_over_d,z*one_over_d);
}
ON_3dPoint ON_3dPoint::operator+( const ON_3dPoint& p ) const
{
return ON_3dPoint(x+p.x,y+p.y,z+p.z);
}
ON_3dPoint ON_3dPoint::operator+( const ON_3dVector& v ) const
{
return ON_3dPoint(x+v.x,y+v.y,z+v.z);
}
ON_3dVector ON_3dPoint::operator-( const ON_3dPoint& p ) const
{
return ON_3dVector(x-p.x,y-p.y,z-p.z);
}
ON_3dPoint ON_3dPoint::operator-( const ON_3dVector& v ) const
{
return ON_3dPoint(x-v.x,y-v.y,z-v.z);
}
ON_3dPoint ON_3dPoint::operator+( const ON_2dPoint& p ) const
{
return ON_3dPoint(x+p.x,y+p.y,z);
}
ON_3dPoint ON_3dPoint::operator+( const ON_2dVector& v ) const
{
return ON_3dPoint(x+v.x,y+v.y,z);
}
ON_3dVector ON_3dPoint::operator-( const ON_2dPoint& p ) const
{
return ON_3dVector(x-p.x,y-p.y,z);
}
ON_3dPoint ON_3dPoint::operator-( const ON_2dVector& v ) const
{
return ON_3dPoint(x-v.x,y-v.y,z);
}
ON_3dPoint ON_3dPoint::operator+( const ON_3fPoint& p ) const
{
return ON_3dPoint(x+p.x,y+p.y,z+p.z);
}
ON_3dPoint ON_3dPoint::operator+( const ON_3fVector& v ) const
{
return ON_3dPoint(x+v.x,y+v.y,z+v.z);
}
ON_3dVector ON_3dPoint::operator-( const ON_3fPoint& p ) const
{
return ON_3dVector(x-p.x,y-p.y,z-p.z);
}
ON_3dPoint ON_3dPoint::operator-( const ON_3fVector& v ) const
{
return ON_3dPoint(x-v.x,y-v.y,z-v.z);
}
ON_3dPoint ON_3dPoint::operator+( const ON_2fPoint& p ) const
{
return ON_3dPoint(x+p.x,y+p.y,z);
}
ON_3dPoint ON_3dPoint::operator+( const ON_2fVector& v ) const
{
return ON_3dPoint(x+v.x,y+v.y,z);
}
ON_3dVector ON_3dPoint::operator-( const ON_2fPoint& p ) const
{
return ON_3dVector(x-p.x,y-p.y,z);
}
ON_3dPoint ON_3dPoint::operator-( const ON_2fVector& v ) const
{
return ON_3dPoint(x-v.x,y-v.y,z);
}
double ON_3dPoint::operator*(const ON_3dPoint& h) const
{
return x*h.x + y*h.y + z*h.z;
}
double ON_3dPoint::operator*(const ON_3dVector& h) const
{
return x*h.x + y*h.y + z*h.z;
}
bool operator==(const ON_3dPoint& a, const ON_3dPoint& b)
{
// Properly handles nans.
return (a.x==b.x && a.y==b.y && a.z==b.z);
}
bool operator!=(const ON_3dPoint& a, const ON_3dPoint& b)
{
// Properly handles nans.
return (a.x!=b.x || a.y!=b.y || a.z!=b.z);
}
bool ON_3dPoint::operator<=( const ON_3dPoint& p ) const
{
// dictionary order
return ((x<p.x)?true:((x==p.x)?((y<p.y)?true:(y==p.y&&z<=p.z)?true:false):false));
}
bool ON_3dPoint::operator>=( const ON_3dPoint& p ) const
{
// dictionary order
return ((x>p.x)?true:((x==p.x)?((y>p.y)?true:(y==p.y&&z>=p.z)?true:false):false));
}
bool ON_3dPoint::operator<( const ON_3dPoint& p ) const
{
// dictionary order
return ((x<p.x)?true:((x==p.x)?((y<p.y)?true:(y==p.y&&z<p.z)?true:false):false));
}
bool ON_3dPoint::operator>( const ON_3dPoint& p ) const
{
// dictionary order
return ((x>p.x)?true:((x==p.x)?((y>p.y)?true:(y==p.y&&z>p.z)?true:false):false));
}
double ON_3dPoint::operator[](int i) const
{
return ( (i<=0)?x:((i>=2)?z:y) );
}
double& ON_3dPoint::operator[](int i)
{
double* pd = (i<=0)? &x : ( (i>=2) ? &z : &y);
return *pd;
}
double ON_3dPoint::operator[](unsigned int i) const
{
return ( (i<=0)?x:((i>=2)?z:y) );
}
double& ON_3dPoint::operator[](unsigned int i)
{
double* pd = (i<=0)? &x : ( (i>=2) ? &z : &y);
return *pd;
}
double ON_3dPoint::DistanceTo( const ON_3dPoint& p ) const
{
return ON_Length3d(p.x-x,p.y-y,p.z-z);
}
int ON_3dPoint::MaximumCoordinateIndex() const
{
return (fabs(y)>fabs(x)) ? ((fabs(z)>fabs(y))?2:1) : ((fabs(z)>fabs(x))?2:0);
}
double ON_3dPoint::MaximumCoordinate() const
{
double c = fabs(x); if (fabs(y)>c) c=fabs(y); if (fabs(z)>c) c=fabs(z);
return c;
}
int ON_3dPoint::MinimumCoordinateIndex() const
{
return (fabs(y)<fabs(x)) ? ((fabs(z)<fabs(y))?2:1) : ((fabs(z)<fabs(x))?2:0);
}
double ON_3dPoint::MinimumCoordinate() const
{
double c = fabs(x); if (fabs(y)<c) c=fabs(y); if (fabs(z)<c) c=fabs(z);
return c;
}
void ON_3dPoint::Zero()
{
x = y = z = 0.0;
}
bool ON_3dPoint::IsZero() const
{
return x == 0.0 && y == 0.0 && z == 0.0;
}
bool ON_3dPoint::IsNotZero() const
{
// the && (x == x && y == y && z == z) insures no coordinate is a Nan.
return (x != 0.0 || y != 0.0 || z != 0.0) && (x == x && y == y && z == z);
}
ON_3dPoint operator*(int i, const ON_3dPoint& p)
{
double d = i;
return ON_3dPoint(d*p.x,d*p.y,d*p.z);
}
ON_3dPoint operator*(float f, const ON_3dPoint& p)
{
double d = f;
return ON_3dPoint(d*p.x,d*p.y,d*p.z);
}
ON_3dPoint operator*(double d, const ON_3dPoint& p)
{
return ON_3dPoint(d*p.x,d*p.y,d*p.z);
}
////////////////////////////////////////////////////////////////
//
// ON_4dPoint
//
bool ON_4dPoint::operator!=(const ON_4dPoint& rhs) const
{
return Internal_NotEqualDoubleArray(4, &x, &rhs.x);
}
bool ON_4dPoint::operator==(const ON_4dPoint& rhs) const
{
return (x == rhs.x && y == rhs.y && z == rhs.z && w == rhs.w);
}
double ON_4dPoint::InnerProduct(
const ON_4dPoint& lhs,
const ON_4dPoint& rhs
)
{
return (lhs.x*rhs.x + lhs.y*rhs.y + lhs.z*rhs.z + lhs.w*rhs.w);
}
ON_4dPoint::ON_4dPoint( const float* p )
{
if (p) {
x = (double)p[0]; y = (double)p[1]; z = (double)p[2]; w = (double)p[3];
}
else {
x = y = z = 0.0; w = 1.0;
}
}
ON_4dPoint::ON_4dPoint( const double* p )
{
if (p) {
x = p[0]; y = p[1]; z = p[2]; w = p[3];
}
else {
x = y = z = 0.0; w = 1.0;
}
}
ON_4dPoint::ON_4dPoint(double xx,double yy,double zz,double ww)
{x=xx;y=yy;z=zz;w=ww;}
ON_4dPoint::ON_4dPoint(const ON_2dPoint& p)
{x=p.x;y=p.y;z=0.0;w=1.0;}
ON_4dPoint::ON_4dPoint(const ON_3dPoint& p)
{
x=p.x;y=p.y;z=p.z;w=1.0;
}
ON_4dPoint::ON_4dPoint(const ON_2dVector& v)
{x=v.x;y=v.y;z=w=0.0;}
ON_4dPoint::ON_4dPoint(const ON_3dVector& v)
{x=v.x;y=v.y;z=v.z;w=0.0;}
ON_4dPoint::ON_4dPoint(const ON_2fPoint& p)
{x=p.x;y=p.y;z=0.0;w=1.0;}
ON_4dPoint::ON_4dPoint(const ON_3fPoint& p)
{
x=p.x;y=p.y;z=p.z;w=1.0;
}
ON_4dPoint::ON_4dPoint(const ON_4fPoint& p)
{
x=p.x;y=p.y;z=p.z;w=p.w;
}
ON_4dPoint::ON_4dPoint(const ON_2fVector& v)
{x=v.x;y=v.y;z=w=0.0;}
ON_4dPoint::ON_4dPoint(const ON_3fVector& v)
{x=v.x;y=v.y;z=v.z;w=0.0;}
ON_4dPoint::operator double*()
{
return &x;
}
ON_4dPoint::operator const double*() const
{
return &x;
}
ON_4dPoint& ON_4dPoint::operator=(const float* p)
{
if ( p ) {
x = (double)p[0];
y = (double)p[1];
z = (double)p[2];
w = (double)p[3];
}
else {
x = y = z = 0.0; w = 1.0;
}
return *this;
}
ON_4dPoint& ON_4dPoint::operator=(const double* p)
{
if ( p ) {
x = p[0];
y = p[1];
z = p[2];
w = p[3];
}
else {
x = y = z = 0.0; w = 1.0;
}
return *this;
}
ON_4dPoint& ON_4dPoint::operator=(const ON_2dPoint& p)
{
x = p.x;
y = p.y;
z = 0.0;
w = 1.0;
return *this;
}
ON_4dPoint& ON_4dPoint::operator=(const ON_3dPoint& p)
{
x = p.x;
y = p.y;
z = p.z;
w = 1.0;
return *this;
}
ON_4dPoint& ON_4dPoint::operator=(const ON_2dVector& v)
{
x = v.x;
y = v.y;
z = 0.0;
w = 0.0;
return *this;
}
ON_4dPoint& ON_4dPoint::operator=(const ON_3dVector& v)
{
x = v.x;
y = v.y;
z = v.z;
w = 0.0;
return *this;
}
ON_4dPoint& ON_4dPoint::operator=(const ON_2fPoint& p)
{
x = (double)p.x;
y = (double)p.y;
z = 0.0;
w = 1.0;
return *this;
}
ON_4dPoint& ON_4dPoint::operator=(const ON_3fPoint& p)
{
x = (double)p.x;
y = (double)p.y;
z = (double)p.z;
w = 1.0;
return *this;
}
ON_4dPoint& ON_4dPoint::operator=(const ON_4fPoint& p)
{
x = (double)p.x;
y = (double)p.y;
z = (double)p.z;
w = (double)p.w;
return *this;
}
ON_4dPoint& ON_4dPoint::operator=(const ON_2fVector& v)
{
x = (double)v.x;
y = (double)v.y;
z = 0.0;
w = 0.0;
return *this;
}
ON_4dPoint& ON_4dPoint::operator=(const ON_3fVector& v)
{
x = (double)v.x;
y = (double)v.y;
z = (double)v.z;
w = 0.0;
return *this;
}
ON_4dPoint& ON_4dPoint::operator*=(double d)
{
x *= d;
y *= d;
z *= d;
w *= d;
return *this;
}
ON_4dPoint& ON_4dPoint::operator/=(double d)
{
const double one_over_d = 1.0/d;
x *= one_over_d;
y *= one_over_d;
z *= one_over_d;
w *= one_over_d;
return *this;
}
ON_4dPoint& ON_4dPoint::operator+=(const ON_4dPoint& p)
{
// sum w = sqrt(w1*w2)
if ( p.w == w ) {
x += p.x;
y += p.y;
z += p.z;
}
else if (p.w == 0.0 ) {
x += p.x;
y += p.y;
z += p.z;
}
else if ( w == 0.0 ) {
x += p.x;
y += p.y;
z += p.z;
w = p.w;
}
else {
const double sw1 = (w>0.0) ? sqrt(w) : -sqrt(-w);
const double sw2 = (p.w>0.0) ? sqrt(p.w) : -sqrt(-p.w);
const double s1 = sw2/sw1;
const double s2 = sw1/sw2;
x = x*s1 + p.x*s2;
y = y*s1 + p.y*s2;
z = z*s1 + p.z*s2;
w = sw1*sw2;
}
return *this;
}
ON_4dPoint& ON_4dPoint::operator-=(const ON_4dPoint& p)
{
// difference w = sqrt(w1*w2)
if ( p.w == w ) {
x -= p.x;
y -= p.y;
z -= p.z;
}
else if (p.w == 0.0 ) {
x -= p.x;
y -= p.y;
z -= p.z;
}
else if ( w == 0.0 ) {
x -= p.x;
y -= p.y;
z -= p.z;
w = p.w;
}
else {
const double sw1 = (w>0.0) ? sqrt(w) : -sqrt(-w);
const double sw2 = (p.w>0.0) ? sqrt(p.w) : -sqrt(-p.w);
const double s1 = sw2/sw1;
const double s2 = sw1/sw2;
x = x*s1 - p.x*s2;
y = y*s1 - p.y*s2;
z = z*s1 - p.z*s2;
w = sw1*sw2;
}
return *this;
}
ON_4dPoint ON_4dPoint::operator+( const ON_4dPoint& p ) const
{
ON_4dPoint q(x,y,z,w);
q+=p;
return q;
}
ON_4dPoint ON_4dPoint::operator-( const ON_4dPoint& p ) const
{
ON_4dPoint q(x,y,z,w);
q-=p;
return q;
}
ON_4dPoint ON_4dPoint::operator*( double d ) const
{
return ON_4dPoint(x*d,y*d,z*d,w*d);
}
ON_4dPoint ON_4dPoint::operator/( double d ) const
{
const double one_over_d = 1.0/d;
return ON_4dPoint(x*one_over_d,y*one_over_d,z*one_over_d,w*one_over_d);
}
double ON_4dPoint::operator[](int i) const
{
return ((i<=0)?x:((i>=3)?w:((i==1)?y:z)));
}
double& ON_4dPoint::operator[](int i)
{
double* pd = (i<=0) ? &x : ( (i>=3) ? &w : (i==1)?&y:&z);
return *pd;
}
double ON_4dPoint::operator[](unsigned int i) const
{
return ((i<=0)?x:((i>=3)?w:((i==1)?y:z)));
}
double& ON_4dPoint::operator[](unsigned int i)
{
double* pd = (i<=0) ? &x : ( (i>=3) ? &w : (i==1)?&y:&z);
return *pd;
}
int ON_4dPoint::MaximumCoordinateIndex() const
{
const double* a = &x;
int i = ( fabs(y) > fabs(x) ) ? 1 : 0;
if (fabs(z) > fabs(a[i])) i = 2; if (fabs(w) > fabs(a[i])) i = 3;
return i;
}
double ON_4dPoint::MaximumCoordinate() const
{
double c = fabs(x); if (fabs(y)>c) c=fabs(y); if (fabs(z)>c) c=fabs(z); if (fabs(w)>c) c=fabs(w);
return c;
}
int ON_4dPoint::MinimumCoordinateIndex() const
{
const double* a = &x;
int i = ( fabs(y) < fabs(x) ) ? 1 : 0;
if (fabs(z) < fabs(a[i])) i = 2; if (fabs(w) < fabs(a[i])) i = 3;
return i;
}
double ON_4dPoint::MinimumCoordinate() const
{
double c = fabs(x); if (fabs(y)<c) c=fabs(y); if (fabs(z)<c) c=fabs(z); if (fabs(w)<c) c=fabs(w);
return c;
}
ON_4dPoint operator*( double d, const ON_4dPoint& p )
{
return ON_4dPoint( d*p.x, d*p.y, d*p.z, d*p.w );
}
////////////////////////////////////////////////////////////////
//
// ON_2dVector
//
// static
const ON_2dVector& ON_2dVector::UnitVector(int index)
{
static ON_2dVector o(0.0,0.0);
static ON_2dVector x(1.0,0.0);
static ON_2dVector y(0.0,1.0);
switch(index)
{
case 0:
return x;
case 1:
return y;
}
return o;
}
ON_2dVector::ON_2dVector( const float* v )
{
if (v) {
x = (double)v[0]; y = (double)v[1];
}
else {
x = y = 0.0;
}
}
ON_2dVector::ON_2dVector( const double* v )
{
if (v) {
x = v[0]; y = v[1];
}
else {
x = y = 0.0;
}
}
ON_2dVector::ON_2dVector(double xx,double yy)
{x=xx;y=yy;}
ON_2dVector::ON_2dVector(const ON_3dVector& v)
{x=v.x;y=v.y;}
ON_2dVector::ON_2dVector(const ON_2dPoint& p)
{x=p.x;y=p.y;}
ON_2dVector::ON_2dVector(const ON_3dPoint& p)
{x=p.x;y=p.y;}
ON_2dVector::ON_2dVector(const ON_2fVector& v)
{x=v.x;y=v.y;}
ON_2dVector::ON_2dVector(const ON_3fVector& v)
{x=v.x;y=v.y;}
ON_2dVector::ON_2dVector(const ON_2fPoint& p)
{x=p.x;y=p.y;}
ON_2dVector::ON_2dVector(const ON_3fPoint& p)
{x=p.x;y=p.y;}
ON_2dVector::operator double*()
{
return &x;
}
ON_2dVector::operator const double*() const
{
return &x;
}
ON_2dVector& ON_2dVector::operator=(const float* v)
{
if ( v ) {
x = (double)v[0];
y = (double)v[1];
}
else {
x = y = 0.0;
}
return *this;
}
ON_2dVector& ON_2dVector::operator=(const double* v)
{
if ( v ) {
x = v[0];
y = v[1];
}
else {
x = y = 0.0;
}
return *this;
}
ON_2dVector& ON_2dVector::operator=(const ON_3dVector& v)
{
x = v.x;
y = v.y;
return *this;
}
ON_2dVector& ON_2dVector::operator=(const ON_2dPoint& p)
{
x = p.x;
y = p.y;
return *this;
}
ON_2dVector& ON_2dVector::operator=(const ON_3dPoint& p)
{
x = p.x;
y = p.y;
return *this;
}
ON_2dVector& ON_2dVector::operator=(const ON_2fVector& v)
{
x = v.x;
y = v.y;
return *this;
}
ON_2dVector& ON_2dVector::operator=(const ON_3fVector& v)
{
x = v.x;
y = v.y;
return *this;
}
ON_2dVector& ON_2dVector::operator=(const ON_2fPoint& p)
{
x = p.x;
y = p.y;
return *this;
}
ON_2dVector& ON_2dVector::operator=(const ON_3fPoint& p)
{
x = p.x;
y = p.y;
return *this;
}
ON_2dVector ON_2dVector::operator-() const
{
return ON_2dVector(-x,-y);
}
ON_2dVector& ON_2dVector::operator*=(double d)
{
x *= d;
y *= d;
return *this;
}
ON_2dVector& ON_2dVector::operator/=(double d)
{
const double one_over_d = 1.0/d;
x *= one_over_d;
y *= one_over_d;
return *this;
}
ON_2dVector& ON_2dVector::operator+=(const ON_2dVector& v)
{
x += v.x;
y += v.y;
return *this;
}
ON_2dVector& ON_2dVector::operator-=(const ON_2dVector& v)
{
x -= v.x;
y -= v.y;
return *this;
}
ON_2dVector ON_2dVector::operator*( int i ) const
{
double d = i;
return ON_2dVector(x*d,y*d);
}
ON_2dVector ON_2dVector::operator*( float f ) const
{
double d = f;
return ON_2dVector(x*d,y*d);
}
ON_2dVector ON_2dVector::operator*( double d ) const
{
return ON_2dVector(x*d,y*d);
}
double ON_2dVector::operator*( const ON_2dVector& v ) const
{
return (x*v.x + y*v.y);
}
double ON_2dVector::operator*( const ON_2dPoint& v ) const
{
return (x*v.x + y*v.y);
}
double ON_2dVector::operator*( const ON_2fVector& v ) const
{
return (x*v.x + y*v.y);
}
ON_2dVector ON_2dVector::operator/( int i ) const
{
const double one_over_d = 1.0/((double)i);
return ON_2dVector(x*one_over_d,y*one_over_d);
}
ON_2dVector ON_2dVector::operator/( float f ) const
{
const double one_over_d = 1.0/((double)f);
return ON_2dVector(x*one_over_d,y*one_over_d);
}
ON_2dVector ON_2dVector::operator/( double d ) const
{
const double one_over_d = 1.0/d;
return ON_2dVector(x*one_over_d,y*one_over_d);
}
ON_2dVector ON_2dVector::operator+( const ON_2dVector& v ) const
{
return ON_2dVector(x+v.x,y+v.y);
}
ON_2dPoint ON_2dVector::operator+( const ON_2dPoint& p ) const
{
return ON_2dPoint(x+p.x,y+p.y);
}
ON_2dVector ON_2dVector::operator-( const ON_2dVector& v ) const
{
return ON_2dVector(x-v.x,y-v.y);
}
ON_2dPoint ON_2dVector::operator-( const ON_2dPoint& v ) const
{
return ON_2dPoint(x-v.x,y-v.y);
}
ON_3dVector ON_2dVector::operator+( const ON_3dVector& v ) const
{
return ON_3dVector(x+v.x,y+v.y,v.z);
}
ON_3dPoint ON_2dVector::operator+( const ON_3dPoint& p ) const
{
return ON_3dPoint(x+p.x,y+p.y,p.z);
}
ON_3dVector ON_2dVector::operator-( const ON_3dVector& v ) const
{
return ON_3dVector(x-v.x,y-v.y,-v.z);
}
ON_3dPoint ON_2dVector::operator-( const ON_3dPoint& v ) const
{
return ON_3dPoint(x-v.x,y-v.y,-v.z);
}
ON_2dVector ON_2dVector::operator+( const ON_2fVector& v ) const
{
return ON_2dVector(x+v.x,y+v.y);
}
ON_2dPoint ON_2dVector::operator+( const ON_2fPoint& p ) const
{
return ON_2dPoint(x+p.x,y+p.y);
}
ON_2dVector ON_2dVector::operator-( const ON_2fVector& v ) const
{
return ON_2dVector(x-v.x,y-v.y);
}
ON_2dPoint ON_2dVector::operator-( const ON_2fPoint& v ) const
{
return ON_2dPoint(x-v.x,y-v.y);
}
ON_3dVector ON_2dVector::operator+( const ON_3fVector& v ) const
{
return ON_3dVector(x+v.x,y+v.y,v.z);
}
ON_3dPoint ON_2dVector::operator+( const ON_3fPoint& p ) const
{
return ON_3dPoint(x+p.x,y+p.y,p.z);
}
ON_3dVector ON_2dVector::operator-( const ON_3fVector& v ) const
{
return ON_3dVector(x-v.x,y-v.y,-v.z);
}
ON_3dPoint ON_2dVector::operator-( const ON_3fPoint& v ) const
{
return ON_3dPoint(x-v.x,y-v.y,-v.z);
}
bool ON_2dVector::operator==( const ON_2dVector& v ) const
{
return (x==v.x&&y==v.y)?true:false;
}
bool ON_2dVector::operator!=( const ON_2dVector& v ) const
{
return Internal_NotEqualDoubleArray(2, &x, &v.x);
}
bool ON_2dVector::operator<=( const ON_2dVector& v ) const
{
// dictionary order
return ((x<v.x)?true:((x==v.x&&y<=v.y)?true:false));
}
bool ON_2dVector::operator>=( const ON_2dVector& v ) const
{
// dictionary order
return ((x>v.x)?true:((x==v.x&&y>=v.y)?true:false));
}
bool ON_2dVector::operator<( const ON_2dVector& v ) const
{
// dictionary order
return ((x<v.x)?true:((x==v.x&&y<v.y)?true:false));
}
bool ON_2dVector::operator>( const ON_2dVector& v ) const
{
// dictionary order
return ((x>v.x)?true:((x==v.x&&y>v.y)?true:false));
}
double ON_2dVector::operator[](int i) const
{
return ((i<=0)?x:y);
}
double& ON_2dVector::operator[](int i)
{
double* pd = (i<=0)? &x : &y;
return *pd;
}
double ON_2dVector::operator[](unsigned int i) const
{
return ((i<=0)?x:y);
}
double& ON_2dVector::operator[](unsigned int i)
{
double* pd = (i<=0)? &x : &y;
return *pd;
}
int ON_2dVector::MaximumCoordinateIndex() const
{
return ( (fabs(y)>fabs(x)) ? 1 : 0 );
}
double ON_2dVector::MaximumCoordinate() const
{
double c = fabs(x); if (fabs(y)>c) c=fabs(y);
return c;
}
int ON_2dVector::MinimumCoordinateIndex() const
{
return (fabs(y)<fabs(x)) ? 1: 0;
}
double ON_2dVector::MinimumCoordinate() const
{
double c = fabs(x); if (fabs(y)<c) c=fabs(y);
return c;
}
double ON_2dVector::LengthSquared() const
{
return (x*x + y*y);
}
double ON_Length2d( double x, double y )
{
double len;
x = fabs(x);
y = fabs(y);
if ( y > x ) {
len = x; x = y; y = len;
}
// 15 September 2003 Dale Lear
// For small denormalized doubles (positive but smaller
// than DBL_MIN), some compilers/FPUs set 1.0/fx to +INF.
// Without the ON_DBL_MIN test we end up with
// microscopic vectors that have infinte length!
//
// This code is absolutely necessary. It is a critical
// part of the bug fix for RR 11217.
if ( x > ON_DBL_MIN )
{
y /= x;
len = x*sqrt(1.0 + y*y);
}
else if ( x > 0.0 && ON_IS_FINITE(x) )
len = x;
else
len = 0.0;
return len;
}
double ON_2dVector::Length() const
{
return ON_Length2d(x,y);
}
double ON_2dVector::WedgeProduct(const ON_2dVector& B) const{
return x*B.y - y*B.x;
}
void ON_2dVector::Reverse()
{
x = -x;
y = -y;
}
bool ON_2dVector::Unitize()
{
// 15 September 2003 Dale Lear
// Added the ON_IS_FINITE and ON_DBL_MIN test. See ON_2dVector::Length()
// for details.
double d = Length();
if ( ON_IS_FINITE(d) )
{
if ( d > ON_DBL_MIN )
{
x /= d;
y /= d;
return true;
}
if ( d > 0.0 )
{
// This code is rarely used and can be slow.
// It multiplies by 2^1023 in an attempt to
// normalize the coordinates.
// If the renormalization works, then we're
// ok. If the renormalization fails, we
// return false.
ON_2dVector tmp;
tmp.x = x*8.9884656743115795386465259539451e+307;
tmp.y = y*8.9884656743115795386465259539451e+307;
d = tmp.Length();
if ( ON_IS_FINITE(d) && d > ON_DBL_MIN )
{
x = tmp.x/d;
y = tmp.y/d;
return true;
}
}
}
x = 0.0;
y = 0.0;
return false;
}
ON_2dVector ON_2dVector::UnitVector() const
{
ON_2dVector u(*this);
u.Unitize();
return u;
}
bool ON_2dVector::IsTiny( double tiny_tol ) const
{
return (fabs(x) <= tiny_tol && fabs(y) <= tiny_tol );
}
void ON_2dVector::Zero()
{
x = y = 0.0;
}
bool ON_2dVector::IsZero() const
{
return (x==0.0 && y==0.0);
}
bool ON_2dVector::IsNotZero() const
{
// the && (x == x && y == y) insures no coordinate is a Nan.
return (x != 0.0 || y != 0.0) && (x == x && y == y);
}
bool ON_2dVector::IsUnitVector() const
{
return (x != ON_UNSET_VALUE && y != ON_UNSET_VALUE && fabs(Length() - 1.0) <= ON_SQRT_EPSILON);
}
// set this vector to be perpendicular to another vector
bool ON_2dVector::PerpendicularTo( // Result is not unitized.
// returns false if input vector is zero
const ON_2dVector& v
)
{
y = v.x;
x = -v.y;
return (x!= 0.0 || y!= 0.0) ? true : false;
}
// set this vector to be perpendicular to a line defined by 2 points
bool ON_2dVector::PerpendicularTo(
const ON_2dPoint& p,
const ON_2dPoint& q
)
{
return PerpendicularTo(q-p);
}
ON_2dVector operator*(int i, const ON_2dVector& v)
{
double d = i;
return ON_2dVector(d*v.x,d*v.y);
}
ON_2dVector operator*(float f, const ON_2dVector& v)
{
double d = f;
return ON_2dVector(d*v.x,d*v.y);
}
ON_2dVector operator*(double d, const ON_2dVector& v)
{
return ON_2dVector(d*v.x,d*v.y);
}
double ON_DotProduct( const ON_2dVector& a , const ON_2dVector& b )
{
// inner (dot) product between 3d vectors
return (a.x*b.x + a.y*b.y );
}
double ON_WedgeProduct( const ON_2dVector& a , const ON_2dVector& b )
{
// exterior (wedge) product between 2d vectors
return (a.x*b.y - a.y*b.x );
}
ON_3dVector ON_CrossProduct( const ON_2dVector& a , const ON_2dVector& b )
{
return ON_3dVector(0.0, 0.0, a.x*b.y - b.x*a.y );
}
////////////////////////////////////////////////////////////////
//
// ON_3dVector
//
// static
const ON_3dVector& ON_3dVector::UnitVector(int index)
{
static ON_3dVector o(0.0,0.0,0.0);
static ON_3dVector x(1.0,0.0,0.0);
static ON_3dVector y(0.0,1.0,0.0);
static ON_3dVector z(0.0,0.0,1.0);
switch(index)
{
case 0:
return x;
case 1:
return y;
case 2:
return z;
}
return o;
}
ON_3dVector::ON_3dVector( const float* v )
{
if (v) {
x = (double)v[0]; y = (double)v[1]; z = (double)v[2];
}
else {
x = y = z = 0.0;
}
}
ON_3dVector::ON_3dVector( const double* v )
{
if (v) {
x = v[0]; y = v[1]; z = v[2];
}
else {
x = y = z = 0.0;
}
}
ON_3dVector::ON_3dVector(double xx,double yy,double zz)
{x=xx;y=yy;z=zz;}
ON_3dVector::ON_3dVector(const ON_2dVector& v)
{x=v.x;y=v.y;z=0.0;}
ON_3dVector::ON_3dVector(const ON_2dPoint& p)
{x=p.x;y=p.y;z=0.0;}
ON_3dVector::ON_3dVector(const ON_3dPoint& p)
{x=p.x;y=p.y;z=p.z;}
ON_3dVector::ON_3dVector(const ON_2fVector& v)
{x=v.x;y=v.y;z=0.0;}
ON_3dVector::ON_3dVector(const ON_3fVector& v)
{x=v.x;y=v.y;z=v.z;}
ON_3dVector::ON_3dVector(const ON_2fPoint& p)
{x=p.x;y=p.y;z=0.0;}
ON_3dVector::ON_3dVector(const ON_3fPoint& p)
{x=p.x;y=p.y;z=p.z;}
ON_3dVector::operator double*()
{
return &x;
}
ON_3dVector::operator const double*() const
{
return &x;
}
ON_3dVector& ON_3dVector::operator=(const float* v)
{
if ( v ) {
x = (double)v[0];
y = (double)v[1];
z = (double)v[2];
}
else {
x = y = z = 0.0;
}
return *this;
}
ON_3dVector& ON_3dVector::operator=(const double* v)
{
if ( v ) {
x = v[0];
y = v[1];
z = v[2];
}
else {
x = y = z = 0.0;
}
return *this;
}
ON_3dVector& ON_3dVector::operator=(const ON_2dVector& v)
{
x = v.x;
y = v.y;
z = 0.0;
return *this;
}
ON_3dVector& ON_3dVector::operator=(const ON_2dPoint& p)
{
x = p.x;
y = p.y;
z = 0.0;
return *this;
}
ON_3dVector& ON_3dVector::operator=(const ON_3dPoint& p)
{
x = p.x;
y = p.y;
z = p.z;
return *this;
}
ON_3dVector& ON_3dVector::operator=(const ON_2fVector& v)
{
x = v.x;
y = v.y;
z = 0.0;
return *this;
}
ON_3dVector& ON_3dVector::operator=(const ON_3fVector& v)
{
x = v.x;
y = v.y;
z = v.z;
return *this;
}
ON_3dVector& ON_3dVector::operator=(const ON_2fPoint& p)
{
x = p.x;
y = p.y;
z = 0.0;
return *this;
}
ON_3dVector& ON_3dVector::operator=(const ON_3fPoint& p)
{
x = p.x;
y = p.y;
z = p.z;
return *this;
}
ON_3dVector ON_3dVector::operator-() const
{
return ON_3dVector(-x,-y,-z);
}
ON_3dVector& ON_3dVector::operator*=(double d)
{
x *= d;
y *= d;
z *= d;
return *this;
}
ON_3dVector& ON_3dVector::operator/=(double d)
{
const double one_over_d = 1.0/d;
x *= one_over_d;
y *= one_over_d;
z *= one_over_d;
return *this;
}
ON_3dVector& ON_3dVector::operator+=(const ON_3dVector& v)
{
x += v.x;
y += v.y;
z += v.z;
return *this;
}
ON_3dVector& ON_3dVector::operator-=(const ON_3dVector& v)
{
x -= v.x;
y -= v.y;
z -= v.z;
return *this;
}
ON_3dVector ON_3dVector::operator*( int i ) const
{
double d = i;
return ON_3dVector(x*d,y*d,z*d);
}
ON_3dVector ON_3dVector::operator*( float f ) const
{
double d = f;
return ON_3dVector(x*d,y*d,z*d);
}
ON_3dVector ON_3dVector::operator*( double d ) const
{
return ON_3dVector(x*d,y*d,z*d);
}
double ON_3dVector::operator*( const ON_3dVector& v ) const
{
return (x*v.x + y*v.y + z*v.z);
}
double ON_3dVector::operator*( const ON_3dPoint& v ) const
{
return (x*v.x + y*v.y + z*v.z);
}
double ON_3dVector::operator*( const ON_3fVector& v ) const
{
return (x*v.x + y*v.y + z*v.z);
}
ON_3dVector ON_3dVector::operator/( int i ) const
{
const double one_over_d = 1.0/((double)i);
return ON_3dVector(x*one_over_d,y*one_over_d,z*one_over_d);
}
ON_3dVector ON_3dVector::operator/( float f ) const
{
const double one_over_d = 1.0/((double)f);
return ON_3dVector(x*one_over_d,y*one_over_d,z*one_over_d);
}
ON_3dVector ON_3dVector::operator/( double d ) const
{
const double one_over_d = 1.0/d;
return ON_3dVector(x*one_over_d,y*one_over_d,z*one_over_d);
}
ON_3dVector ON_3dVector::operator+( const ON_3dVector& v ) const
{
return ON_3dVector(x+v.x,y+v.y,z+v.z);
}
ON_3dPoint ON_3dVector::operator+( const ON_3dPoint& p ) const
{
return ON_3dPoint(x+p.x,y+p.y,z+p.z);
}
ON_3dVector ON_3dVector::operator-( const ON_3dVector& v ) const
{
return ON_3dVector(x-v.x,y-v.y,z-v.z);
}
ON_3dPoint ON_3dVector::operator-( const ON_3dPoint& v ) const
{
return ON_3dPoint(x-v.x,y-v.y,z-v.z);
}
ON_3dVector ON_3dVector::operator+( const ON_2dVector& v ) const
{
return ON_3dVector(x+v.x,y+v.y,z);
}
ON_3dPoint ON_3dVector::operator+( const ON_2dPoint& p ) const
{
return ON_3dPoint(x+p.x,y+p.y,z);
}
ON_3dVector ON_3dVector::operator-( const ON_2dVector& v ) const
{
return ON_3dVector(x-v.x,y-v.y,z);
}
ON_3dPoint ON_3dVector::operator-( const ON_2dPoint& v ) const
{
return ON_3dPoint(x-v.x,y-v.y,z);
}
ON_3dVector ON_3dVector::operator+( const ON_3fVector& v ) const
{
return ON_3dVector(x+v.x,y+v.y,z+v.z);
}
ON_3dPoint ON_3dVector::operator+( const ON_3fPoint& p ) const
{
return ON_3dPoint(x+p.x,y+p.y,z+p.z);
}
ON_3dVector ON_3dVector::operator-( const ON_3fVector& v ) const
{
return ON_3dVector(x-v.x,y-v.y,z-v.z);
}
ON_3dPoint ON_3dVector::operator-( const ON_3fPoint& v ) const
{
return ON_3dPoint(x-v.x,y-v.y,z-v.z);
}
ON_3dVector ON_3dVector::operator+( const ON_2fVector& v ) const
{
return ON_3dVector(x+v.x,y+v.y,z);
}
ON_3dPoint ON_3dVector::operator+( const ON_2fPoint& p ) const
{
return ON_3dPoint(x+p.x,y+p.y,z);
}
ON_3dVector ON_3dVector::operator-( const ON_2fVector& v ) const
{
return ON_3dVector(x-v.x,y-v.y,z);
}
ON_3dPoint ON_3dVector::operator-( const ON_2fPoint& v ) const
{
return ON_3dPoint(x-v.x,y-v.y,z);
}
bool ON_3dPoint::operator==( const ON_3dPoint& v ) const
{
return (x==v.x&&y==v.y&&z==v.z)?true:false;
}
bool ON_3dPoint::operator!=( const ON_3dPoint& v ) const
{
return Internal_NotEqualDoubleArray(3, &x, &v.x);
}
bool ON_3dVector::operator==( const ON_3dVector& v ) const
{
return (x==v.x&&y==v.y&&z==v.z)?true:false;
}
bool ON_3dVector::operator!=( const ON_3dVector& v ) const
{
return Internal_NotEqualDoubleArray(3, &x, &v.x);
}
bool ON_3dVector::operator<=( const ON_3dVector& v ) const
{
// dictionary order
return ((x<v.x)?true:((x==v.x)?((y<v.y)?true:(y==v.y&&z<=v.z)?true:false):false));
}
bool ON_3dVector::operator>=( const ON_3dVector& v ) const
{
// dictionary order
return ((x>v.x)?true:((x==v.x)?((y>v.y)?true:(y==v.y&&z>=v.z)?true:false):false));
}
bool ON_3dVector::operator<( const ON_3dVector& v ) const
{
// dictionary order
return ((x<v.x)?true:((x==v.x)?((y<v.y)?true:(y==v.y&&z<v.z)?true:false):false));
}
bool ON_3dVector::operator>( const ON_3dVector& v ) const
{
// dictionary order
return ((x>v.x)?true:((x==v.x)?((y>v.y)?true:(y==v.y&&z>v.z)?true:false):false));
}
double ON_3dVector::operator[](int i) const
{
return ( (i<=0)?x:((i>=2)?z:y) );
}
double& ON_3dVector::operator[](int i)
{
double* pd = (i<=0)? &x : ( (i>=2) ? &z : &y);
return *pd;
}
double ON_3dVector::operator[](unsigned int i) const
{
return ( (i<=0)?x:((i>=2)?z:y) );
}
double& ON_3dVector::operator[](unsigned int i)
{
double* pd = (i<=0)? &x : ( (i>=2) ? &z : &y);
return *pd;
}
int ON_3dVector::MaximumCoordinateIndex() const
{
return (fabs(y)>fabs(x)) ? ((fabs(z)>fabs(y))?2:1) : ((fabs(z)>fabs(x))?2:0);
}
double ON_3dVector::MaximumCoordinate() const
{
double c = fabs(x); if (fabs(y)>c) c=fabs(y); if (fabs(z)>c) c=fabs(z);
return c;
}
int ON_3dVector::MinimumCoordinateIndex() const
{
return (fabs(y)<fabs(x)) ? ((fabs(z)<fabs(y))?2:1) : ((fabs(z)<fabs(x))?2:0);
}
double ON_3dVector::MinimumCoordinate() const
{
double c = fabs(x); if (fabs(y)<c) c=fabs(y); if (fabs(z)<c) c=fabs(z);
return c;
}
double ON_3dVector::LengthSquared() const
{
return (x*x + y*y + z*z);
}
double ON_Length3d(double x, double y, double z)
{
double len;
x = fabs(x);
y = fabs(y);
z = fabs(z);
if ( y >= x && y >= z ) {
len = x; x = y; y = len;
}
else if ( z >= x && z >= y ) {
len = x; x = z; z = len;
}
// 15 September 2003 Dale Lear
// For small denormalized doubles (positive but smaller
// than DBL_MIN), some compilers/FPUs set 1.0/x to +INF.
// Without the ON_DBL_MIN test we end up with
// microscopic vectors that have infinte length!
//
// This code is absolutely necessary. It is a critical
// part of the bug fix for RR 11217.
if ( x > ON_DBL_MIN )
{
y /= x;
z /= x;
len = x*sqrt(1.0 + y*y + z*z);
}
else if ( x > 0.0 && ON_IS_FINITE(x) )
len = x;
else
len = 0.0;
return len;
}
double ON_3dVector::Length() const
{
return ON_Length3d(x,y,z);
}
void ON_3dVector::Reverse()
{
x = -x;
y = -y;
z = -z;
}
bool ON_3dVector::Unitize()
{
// 15 September 2003 Dale Lear
// Added the ON_IS_FINITE and ON_DBL_MIN test. See ON_3dVector::Length()
// for details.
double d = Length();
if ( ON_IS_FINITE(d) )
{
if ( d > ON_DBL_MIN )
{
x /= d;
y /= d;
z /= d;
return true;
}
if ( d > 0.0 )
{
// This code is rarely used and can be slow.
// It multiplies by 2^1023 in an attempt to
// normalize the coordinates.
// If the renormalization works, then we're
// ok. If the renormalization fails, we
// return false.
ON_3dVector tmp;
tmp.x = x*8.9884656743115795386465259539451e+307;
tmp.y = y*8.9884656743115795386465259539451e+307;
tmp.z = z*8.9884656743115795386465259539451e+307;
d = tmp.Length();
if ( ON_IS_FINITE(d) && d > ON_DBL_MIN )
{
x = tmp.x/d;
y = tmp.y/d;
z = tmp.z/d;
return true;
}
}
}
x = 0.0;
y = 0.0;
z = 0.0;
return false;
}
ON_3dVector ON_3dVector::UnitVector() const
{
ON_3dVector u(*this);
u.Unitize();
return u;
}
double ON_3dVector::LengthAndUnitize()
{
double d;
double len = Length();
if ( len > ON_DBL_MIN )
{
d = 1.0/len;
x *= d;
y *= d;
z *= d;
}
else if ( len > 0.0 && ON_IS_FINITE(len) )
{
// This code is rarely used and can be slow.
// It multiplies by 2^1023 in an attempt to
// normalize the coordinates.
// If the renormalization works, then we're
// ok. If the renormalization fails, we
// return false.
ON_3dVector tmp;
tmp.x = x*8.9884656743115795386465259539451e+307;
tmp.y = y*8.9884656743115795386465259539451e+307;
tmp.z = z*8.9884656743115795386465259539451e+307;
d = tmp.Length();
if ( d > ON_DBL_MIN )
{
d = 1.0/d;
x = tmp.x*d;
y = tmp.y*d;
z = tmp.z*d;
}
else
{
len = 0.0;
x = 0.0;
y = 0.0;
z = 0.0;
}
}
else
{
len = 0.0;
x = 0.0;
y = 0.0;
z = 0.0;
}
return len;
}
bool ON_3dVector::IsTiny( double tiny_tol ) const
{
return (fabs(x) <= tiny_tol && fabs(y) <= tiny_tol && fabs(z) <= tiny_tol );
}
void ON_3dVector::Zero()
{
x = y = z = 0.0;
}
bool ON_3dVector::IsZero() const
{
return (x==0.0 && y==0.0 && z==0.0);
}
bool ON_3dVector::IsNotZero() const
{
// the && (x == x && y == y && z == z) insures no coordinate is a Nan.
return (x != 0.0 || y != 0.0 || z != 0.0) && (x == x && y == y && z == z);
}
bool ON_3dVector::IsUnitVector() const
{
return (x != ON_UNSET_VALUE && y != ON_UNSET_VALUE && z != ON_UNSET_VALUE && fabs(Length() - 1.0) <= ON_SQRT_EPSILON);
}
ON_3dVector operator*(int i, const ON_3dVector& v)
{
double d = i;
return ON_3dVector(d*v.x,d*v.y,d*v.z);
}
ON_3dVector operator*(float f, const ON_3dVector& v)
{
double d = f;
return ON_3dVector(d*v.x,d*v.y,d*v.z);
}
ON_3dVector operator*(double d, const ON_3dVector& v)
{
return ON_3dVector(d*v.x,d*v.y,d*v.z);
}
double ON_DotProduct( const ON_3dVector& a , const ON_3dVector& b )
{
// inner (dot) product between 3d vectors
return (a.x*b.x + a.y*b.y + a.z*b.z);
}
ON_3dVector ON_CrossProduct( const ON_3dVector& a , const ON_3dVector& b )
{
return ON_3dVector(a.y*b.z - b.y*a.z, a.z*b.x - b.z*a.x, a.x*b.y - b.x*a.y );
}
ON_3dVector ON_CrossProduct( const double* a, const double* b )
{
return ON_3dVector(a[1]*b[2] - b[1]*a[2], a[2]*b[0] - b[2]*a[0], a[0]*b[1] - b[0]*a[1] );
}
double ON_TripleProduct( const ON_3dVector& a, const ON_3dVector& b, const ON_3dVector& c )
{
// = a o (b x c )
return (a.x*(b.y*c.z - b.z*c.y) + a.y*(b.z*c.x - b.x*c.z) + a.z*(b.x*c.y - b.y*c.x));
}
double ON_TripleProduct( const double* a, const double* b, const double* c )
{
// = a o (b x c )
return (a[0]*(b[1]*c[2] - b[2]*c[1]) + a[1]*(b[2]*c[0] - b[0]*c[2]) + a[2]*(b[0]*c[1] - b[1]*c[0]));
}
bool ON_2dVector::IsValid() const
{
return ( ON_IS_VALID(x) && ON_IS_VALID(y) ) ? true : false;
}
bool ON_3dVector::IsValid() const
{
return ( ON_IS_VALID(x) && ON_IS_VALID(y) && ON_IS_VALID(z) ) ? true : false;
}
bool ON_2dPoint::IsValid() const
{
return (ON_IS_VALID(x) && ON_IS_VALID(y)) ? true : false;
}
bool ON_3dPoint::IsValid() const
{
return (ON_IS_VALID(x) && ON_IS_VALID(y) && ON_IS_VALID(z) ) ? true : false;
}
bool ON_4dPoint::IsValid() const
{
return (ON_IS_VALID(x) && ON_IS_VALID(y) && ON_IS_VALID(z) && ON_IS_VALID(w)) ? true : false;
}
bool ON_2fVector::IsValid() const
{
return ( ON_IS_VALID_FLOAT(x) && ON_IS_VALID_FLOAT(y) ) ? true : false;
}
bool ON_3fVector::IsValid() const
{
return ( ON_IS_VALID_FLOAT(x) && ON_IS_VALID_FLOAT(y) && ON_IS_VALID_FLOAT(z) ) ? true : false;
}
bool ON_2fPoint::IsValid() const
{
return (ON_IS_VALID_FLOAT(x) && ON_IS_VALID_FLOAT(y)) ? true : false;
}
bool ON_3fPoint::IsValid() const
{
return (ON_IS_VALID_FLOAT(x) && ON_IS_VALID_FLOAT(y) && ON_IS_VALID_FLOAT(z) ) ? true : false;
}
bool ON_4fPoint::IsValid() const
{
return (ON_IS_VALID_FLOAT(x) && ON_IS_VALID_FLOAT(y) && ON_IS_VALID_FLOAT(z) && ON_IS_VALID_FLOAT(w)) ? true : false;
}
void ON_2dPoint::Set(double xx, double yy)
{
x = xx; y = yy;
}
void ON_3dPoint::Set(double xx, double yy, double zz)
{
x = xx; y = yy; z = zz;
}
void ON_4dPoint::Set(double xx, double yy, double zz, double ww)
{
x = xx; y = yy; z = zz; w = ww;
}
void ON_2dVector::Set(double xx, double yy)
{
x = xx; y = yy;
}
void ON_3dVector::Set(double xx, double yy, double zz)
{
x = xx; y = yy; z = zz;
}
void ON_2fPoint::Set(float xx, float yy)
{
x = xx; y = yy;
}
void ON_3fPoint::Set(float xx, float yy, float zz)
{
x = xx; y = yy; z = zz;
}
void ON_4fPoint::Set(float xx, float yy, float zz, float ww)
{
x = xx; y = yy; z = zz; w = ww;
}
void ON_2fVector::Set(float xx, float yy)
{
x = xx; y = yy;
}
void ON_3fVector::Set(float xx, float yy, float zz)
{
x = xx; y = yy; z = zz;
}
bool ON_PlaneEquation::Create( ON_3dPoint P, ON_3dVector N )
{
bool rc = false;
if ( P.IsValid() && N.IsValid() )
{
x = N.x;
y = N.y;
z = N.z;
ON_3dVector* v = (ON_3dVector*)&x;
rc = (fabs(1.0 - v->Length()) > ON_ZERO_TOLERANCE) ? v->Unitize() : true;
d = -(x*P.x + y*P.y + z*P.z);
}
return rc;
}
ON_PlaneEquation::ON_PlaneEquation()
: x(0.0)
, y(0.0)
, z(0.0)
, d(0.0)
{}
ON_PlaneEquation::ON_PlaneEquation(double xx, double yy, double zz, double dd)
: x(xx)
, y(yy)
, z(zz)
, d(dd)
{}
void ON_PlaneEquation::Set(ON_PlaneEquation& plane_equation, double x, double y, double z, double d)
{
plane_equation.x = x;
plane_equation.y = y;
plane_equation.z = z;
plane_equation.d = d;
}
double ON_PlaneEquation::MaximumCoefficient() const
{
double m = fabs(x);
if (fabs(y) > m)
m = fabs(y);
if (fabs(z) > m)
m = fabs(z);
if (fabs(d) > m)
m = fabs(d);
return m;
}
double& ON_PlaneEquation::operator[](int i)
{
switch (i)
{
case 0:
return x;
break;
case 1:
return y;
break;
case 2:
return z;
break;
case 3:
return d;
break;
}
ON_ERROR("Invalid coefficient index.");
// send caller something that can be dereferenced without crashing.
double* invalid_coefficient = (double*)onmalloc_forever(sizeof(*invalid_coefficient));
*invalid_coefficient = ON_DBL_QNAN;
return *invalid_coefficient;
}
double& ON_PlaneEquation::operator[](unsigned int i)
{
switch (i)
{
case 0:
return x;
break;
case 1:
return y;
break;
case 2:
return z;
break;
case 3:
return d;
break;
}
ON_ERROR("Invalid coefficient index.");
// send caller something that can be dereferenced without crashing.
double* invalid_coefficient = (double*)onmalloc_forever(sizeof(*invalid_coefficient));
*invalid_coefficient = ON_DBL_QNAN;
return *invalid_coefficient;
}
double ON_PlaneEquation::operator[](int i) const
{
switch (i)
{
case 0:
return x;
break;
case 1:
return y;
break;
case 2:
return z;
break;
case 3:
return d;
break;
}
ON_ERROR("Invalid coefficient index.");
return ON_UNSET_VALUE;
}
double ON_PlaneEquation::operator[](unsigned int i) const
{
switch (i)
{
case 0:
return x;
break;
case 1:
return y;
break;
case 2:
return z;
break;
case 3:
return d;
break;
}
ON_ERROR("Invalid coefficient index.");
return ON_UNSET_VALUE;
}
ON_PlaneEquation ON_PlaneEquation::NegatedPlaneEquation() const
{
// do not negate ON_UNSET_VALUE or NaN
return ON_PlaneEquation(ON_IS_VALID(x) ? -x : x, ON_IS_VALID(y) ? -y : y, ON_IS_VALID(z) ? -z : z, ON_IS_VALID(d) ? -d : d);
}
ON_PlaneEquation ON_PlaneEquation::UnitizedPlaneEquation() const
{
if (IsSet())
{
// 15 September 2003 Dale Lear
// Added the ON_IS_FINITE and ON_DBL_MIN test. See ON_3dVector::Length()
// for details.
double dd = DirectionLength();
if (ON_IS_FINITE(dd))
{
if (dd > ON_DBL_MIN)
{
return ON_PlaneEquation(x / dd, y / dd, z / dd, d / dd);
}
if (dd > 0.0)
{
// This code is rarely used and can be slow.
// It multiplies by 2^1023 in an attempt to
// normalize the coordinates.
// If the renormalization works, then we're
// ok. If the renormalization fails, we
// return false.
ON_PlaneEquation tmp(
x*8.9884656743115795386465259539451e+307,
y*8.9884656743115795386465259539451e+307,
z*8.9884656743115795386465259539451e+307,
d*8.9884656743115795386465259539451e+307
);
dd = tmp.DirectionLength();
if (ON_IS_FINITE(dd) && dd > ON_DBL_MIN)
{
return ON_PlaneEquation(tmp.x / dd, tmp.y / dd, tmp.z / dd, tmp.d / dd);
}
}
}
}
else if ( d == ON_UNSET_VALUE )
{
ON_3dVector v = Direction();
if (v.IsValid() && v.Unitize())
{
return ON_PlaneEquation(v.x, v.y, v.z, ON_UNSET_VALUE);
}
}
return ON_PlaneEquation::ZeroPlaneEquation;
}
bool ON_PlaneEquation::IsValid() const
{
return ( ON_IS_VALID(x) && ON_IS_VALID(y) && ON_IS_VALID(z) && ON_IS_VALID(d) );
}
bool ON_PlaneEquation::IsSet() const
{
return ( ON_IS_VALID(x) && ON_IS_VALID(y) && ON_IS_VALID(z) && ON_IS_VALID(d)
&& (0.0 != x || 0.0 != y || 0.0 != z)
);
}
ON_3dVector ON_PlaneEquation::Direction() const
{
return ON_3dVector(x, y, z);
}
double ON_PlaneEquation::DirectionLength() const
{
return ((const ON_3dVector*)&x)->Length();
}
ON_3dVector ON_PlaneEquation::UnitNormal() const
{
ON_3dVector normal(x, y, z);
if (false == normal.IsUnitVector() && false == normal.Unitize())
normal = ON_3dVector::ZeroVector;
return normal;
}
int ON_PlaneEquation::IsParallelTo(const ON_PlaneEquation& other, double angle_tolerance /*= ON_DEFAULT_ANGLE_TOLERANCE*/) const
{
return ON_3dVector(x, y, z).IsParallelTo(ON_3dVector(other.x, other.y, other.z), angle_tolerance);
}
double ON_PlaneEquation::ZeroTolerance() const
{
double zero_tolerance = 0.0;
ON_3dVector N(x,y,z);
if ( N.Unitize() && ON_IS_VALID(d) )
{
const ON_3dPoint P( -d*N.x, -d*N.y, -d*N.z );
zero_tolerance = fabs(ValueAt(P));
ON_3dVector X;
X.PerpendicularTo(N);
X.Unitize();
double t = fabs(ValueAt(P+X));
if ( t > zero_tolerance )
zero_tolerance = t;
t = fabs(ValueAt(P-X));
if ( t > zero_tolerance )
zero_tolerance = t;
t = fabs(ValueAt(P+d*X));
if ( t > zero_tolerance )
zero_tolerance = t;
t = fabs(ValueAt(P-d*X));
if ( t > zero_tolerance )
zero_tolerance = t;
ON_3dVector Y = ON_CrossProduct(N,X);
Y.Unitize();
t = fabs(ValueAt(P+Y));
if ( t > zero_tolerance )
zero_tolerance = t;
t = fabs(ValueAt(P-Y));
if ( t > zero_tolerance )
zero_tolerance = t;
t = fabs(ValueAt(P+d*Y));
if ( t > zero_tolerance )
zero_tolerance = t;
t = fabs(ValueAt(P-d*Y));
if ( t > zero_tolerance )
zero_tolerance = t;
}
return zero_tolerance;
}
bool ON_PlaneEquation::Transform( const ON_Xform& xform )
{
bool rc = IsValid();
if ( rc )
{
// Apply the inverse transpose to the equation parameters
ON_Xform T(xform);
rc = T.Invert();
if ( rc )
{
const double xx=x;
const double yy=y;
const double zz=z;
const double dd=d;
x = T.m_xform[0][0]*xx + T.m_xform[1][0]*yy + T.m_xform[2][0]*zz + T.m_xform[3][0]*dd;
y = T.m_xform[0][1]*xx + T.m_xform[1][1]*yy + T.m_xform[2][1]*zz + T.m_xform[3][1]*dd;
z = T.m_xform[0][2]*xx + T.m_xform[1][2]*yy + T.m_xform[2][2]*zz + T.m_xform[3][2]*dd;
d = T.m_xform[0][3]*xx + T.m_xform[1][3]*yy + T.m_xform[2][3]*zz + T.m_xform[3][3]*dd;
}
}
return rc;
}
double ON_PlaneEquation::ValueAt(ON_3dPoint P) const
{
return (x*P.x + y*P.y + z*P.z + d);
}
double ON_PlaneEquation::ValueAt(ON_4dPoint P) const
{
return (x*P.x + y*P.y + z*P.z + d*P.w);
}
double ON_PlaneEquation::ValueAt(ON_3dVector P) const
{
return (x*P.x + y*P.y + z*P.z + d);
}
double ON_PlaneEquation::ValueAt(double xx, double yy, double zz) const
{
return (x*xx + y*yy + z*zz + d);
}
double* ON_PlaneEquation::ValueAt(
int Pcount,
const ON_3fPoint* P,
double* value,
double value_range[2]
) const
{
if ( Pcount <= 0 || 0 == P )
return 0;
int i;
double s;
const double* e = &x;
if ( 0 == value )
value = (double*)onmalloc(Pcount * sizeof(*value) );
if ( 0 == value )
return 0;
if ( 0 != value_range )
{
value[0] = s = e[0]*((double)P[0].x) + e[1]*((double)P[0].y) + e[2]*((double)P[0].z) + e[3];
value_range[0] = s;
value_range[1] = s;
for ( i = 1; i < Pcount; i++ )
{
value[i] = s = e[0]*((double)P[i].x) + e[1]*((double)P[i].y) + e[2]*((double)P[i].z) + e[3];
if ( s < value_range[0] )
value_range[0] = s;
else if ( s > value_range[1] )
value_range[1] = s;
}
}
else
{
for ( i = 0; i < Pcount; i++ )
{
value[i] = e[0]*((double)P[i].x) + e[1]*((double)P[i].y) + e[2]*((double)P[i].z) + e[3];
}
}
return value;
}
double* ON_PlaneEquation::ValueAt(
int Pcount,
const ON_3dPoint* P,
double* value,
double value_range[2]
) const
{
if ( Pcount <= 0 || 0 == P )
return 0;
int i;
double s;
const double* e = &x;
if ( 0 == value )
value = (double*)onmalloc(Pcount * sizeof(*value) );
if ( 0 == value )
return 0;
if ( 0 != value_range )
{
value[0] = s = e[0]*(P[0].x) + e[1]*(P[0].y) + e[2]*(P[0].z) + e[3];
value_range[0] = s;
value_range[1] = s;
for ( i = 1; i < Pcount; i++ )
{
value[i] = s = e[0]*(P[i].x) + e[1]*(P[i].y) + e[2]*(P[i].z) + e[3];
if ( s < value_range[0] )
value_range[0] = s;
else if ( s > value_range[1] )
value_range[1] = s;
}
}
else
{
for ( i = 0; i < Pcount; i++ )
{
value[i] = e[0]*(P[i].x) + e[1]*(P[i].y) + e[2]*(P[i].z) + e[3];
}
}
return value;
}
ON_Interval ON_PlaneEquation::ValueRange(
size_t point_list_count,
const ON_3dPoint* point_list
) const
{
ON_3dPointListRef vertex_list;
vertex_list.SetFromDoubleArray(point_list_count,3,(const double*)point_list);
return ValueRange(vertex_list);
}
ON_Interval ON_PlaneEquation::ValueRange(
const ON_SimpleArray< ON_3dPoint >& point_list
) const
{
return ValueRange(point_list.UnsignedCount(),point_list.Array());
}
ON_Interval ON_PlaneEquation::ValueRange(
size_t point_list_count,
const ON_3fPoint* point_list
) const
{
ON_3dPointListRef vertex_list;
vertex_list.SetFromFloatArray(point_list_count,3,(const float*)point_list);
return ValueRange(vertex_list);
}
ON_Interval ON_PlaneEquation::ValueRange(
const ON_SimpleArray< ON_3fPoint >& point_list
) const
{
return ValueRange(point_list.UnsignedCount(),point_list.Array());
}
ON_Interval ON_PlaneEquation::ValueRange(
const class ON_3dPointListRef& point_list
) const
{
return ValueRange(point_list.PointCount(),0,point_list);
}
ON_Interval ON_PlaneEquation::ValueRange(
size_t point_index_count,
const unsigned int* point_index_list,
const class ON_3dPointListRef& point_list
) const
{
size_t point_index_stride = 1;
return ValueRange(
point_index_count,
point_index_stride,
point_index_list,
point_list
);
}
ON_Interval ON_PlaneEquation::ValueRange(
size_t point_index_count,
size_t point_index_stride,
const unsigned int* point_index_list,
const class ON_3dPointListRef& point_list
) const
{
ON_Interval value_interval(ON_Interval::EmptyInterval);
for(;;)
{
if ( false == IsValid() )
break; // invalid plane equation;
double h;
const unsigned int vertex_count = point_list.PointCount();
if ( 0 == vertex_count )
break;
const unsigned int point_count = (point_index_count > 0 && point_index_count < (size_t)ON_UNSET_UINT_INDEX)
? ((unsigned int)point_index_count)
: 0;
if ( 0 == point_count )
break;
if ( 0 != point_index_list )
{
const unsigned int point_stride = (point_index_stride > 0 && point_index_stride < (size_t)ON_UNSET_UINT_INDEX)
? ((unsigned int)point_index_stride)
: 0;
if ( 0 == point_stride )
break;
for ( unsigned int i = 0; i < point_count*point_stride; i += point_stride )
{
unsigned int j = point_index_list[i];
if ( j >= vertex_count )
continue;
h = ValueAt(point_list[j]);
if ( ON_IsValid(h) )
{
value_interval.Set(h,h);
for (i++; i < point_count*point_stride; i+= point_stride )
{
unsigned int j_local = point_index_list[i];
if ( j_local >= vertex_count )
continue;
h = ValueAt(point_list[j_local]);
if ( ON_IsValid(h) )
{
if ( h < value_interval.m_t[0] )
value_interval.m_t[0] = h;
else if ( h > value_interval.m_t[1] )
value_interval.m_t[1] = h;
}
}
break;
}
}
}
else if ( point_count <= vertex_count )
{
for ( unsigned int i = 0; i < point_count; i++ )
{
h = ValueAt(point_list[i]);
if ( ON_IsValid(h) )
{
value_interval.Set(h,h);
for (i++; i < point_count; i++ )
{
h = ValueAt(point_list[i]);
if ( ON_IsValid(h) )
{
if ( h < value_interval.m_t[0] )
value_interval.m_t[0] = h;
else if ( h > value_interval.m_t[1] )
value_interval.m_t[1] = h;
}
}
break;
}
}
}
break;
}
return value_interval;
}
ON_3dPoint ON_PlaneEquation::ClosestPointTo( ON_3dPoint P ) const
{
const double t = -(x*P.x + y*P.y + z*P.z + d)/(x*x+y*y+z*z);
return ON_3dPoint( P.x + t*x, P.y + t*y, P.z + t*z);
}
double ON_PlaneEquation::MinimumValueAt(const ON_BoundingBox& bbox) const
{
double xx, yy, zz, s;
s = x*bbox.m_min.x;
if ( s < (xx = x*bbox.m_max.x) ) xx = s;
s = y*bbox.m_min.y;
if ( s < (yy = y*bbox.m_max.y) ) yy = s;
s = z*bbox.m_min.z;
if ( s < (zz = z*bbox.m_max.z) ) zz = s;
return (xx + yy + zz + d);
}
double ON_PlaneEquation::MaximumValueAt(const ON_BoundingBox& bbox) const
{
double xx, yy, zz, s;
s = x*bbox.m_min.x;
if ( s > (xx = x*bbox.m_max.x) ) xx = s;
s = y*bbox.m_min.y;
if ( s > (yy = y*bbox.m_max.y) ) yy = s;
s = z*bbox.m_min.z;
if ( s > (zz = z*bbox.m_max.z) ) zz = s;
return (xx + yy + zz + d);
}
double ON_PlaneEquation::MaximumAbsoluteValueAt(
bool bRational,
int point_count,
int point_stride,
const double* points,
double stop_value
) const
{
double value, max_value, w;
if ( point_count < 1
|| point_stride < (bRational?4:3)
|| 0 == points
)
{
return ON_UNSET_VALUE;
}
if ( ON_IsValid(stop_value) )
{
if ( bRational )
{
w = points[3];
w = (0.0 != w) ? 1.0/w : 1.0;
max_value = fabs(x*w*points[0]+y*w*points[1]+z*w*points[2]+points[3]);
if ( max_value > stop_value )
return max_value;
for(point_count--; point_count--; /*empty iterator*/ )
{
points += point_stride;
w = points[3];
w = (0.0 != w) ? 1.0/w : 1.0;
value = fabs(x*w*points[0]+y*w*points[1]+z*w*points[2]+points[3]);
if ( value > max_value )
{
if ( (max_value = value) > stop_value )
return max_value;
}
}
}
else
{
max_value = fabs(x*points[0]+y*points[1]+z*points[2]+d);
if ( max_value > stop_value )
return max_value;
for(point_count--; point_count--; /*empty iterator*/ )
{
points += point_stride;
value = fabs(x*points[0]+y*points[1]+z*points[2]+d);
if ( value > max_value )
{
if ( (max_value = value) > stop_value )
return max_value;
}
}
}
}
else
{
if ( bRational )
{
w = points[3];
w = (0.0 != w) ? 1.0/w : 1.0;
max_value = fabs(x*w*points[0]+y*w*points[1]+z*w*points[2]+points[3]);
for(point_count--; point_count--; /*empty iterator*/ )
{
points += point_stride;
w = points[3];
w = (0.0 != w) ? 1.0/w : 1.0;
value = fabs(x*w*points[0]+y*w*points[1]+z*w*points[2]+points[3]);
if ( value > max_value )
max_value = value;
}
}
else
{
max_value = fabs(x*points[0]+y*points[1]+z*points[2]+d);
for(point_count--; point_count--; /*empty iterator*/ )
{
points += point_stride;
value = fabs(x*points[0]+y*points[1]+z*points[2]+d);
if ( value > max_value )
max_value = value;
}
}
}
return max_value;
}
double ON_PlaneEquation::MaximumValueAt(
bool bRational,
int point_count,
int point_stride,
const double* points,
double stop_value
) const
{
double value, max_value, w;
if ( point_count < 1
|| point_stride < (bRational?4:3)
|| 0 == points
)
{
return ON_UNSET_VALUE;
}
if ( ON_IsValid(stop_value) )
{
if ( bRational )
{
w = points[3];
w = (0.0 != w) ? 1.0/w : 1.0;
max_value = x*w*points[0]+y*w*points[1]+z*w*points[2]+points[3];
if ( max_value > stop_value )
return max_value;
for(point_count--; point_count--; /*empty iterator*/ )
{
points += point_stride;
w = points[3];
w = (0.0 != w) ? 1.0/w : 1.0;
value = x*w*points[0]+y*w*points[1]+z*w*points[2]+points[3];
if ( value > max_value )
{
if ( (max_value = value) > stop_value )
return max_value;
}
}
}
else
{
max_value = x*points[0]+y*points[1]+z*points[2]+d;
if ( max_value > stop_value )
return max_value;
for(point_count--; point_count--; /*empty iterator*/ )
{
points += point_stride;
value = x*points[0]+y*points[1]+z*points[2]+d;
if ( value > max_value )
{
if ( (max_value = value) > stop_value )
return max_value;
}
}
}
}
else
{
if ( bRational )
{
w = points[3];
w = (0.0 != w) ? 1.0/w : 1.0;
max_value = x*w*points[0]+y*w*points[1]+z*w*points[2]+points[3];
for(point_count--; point_count--; /*empty iterator*/ )
{
points += point_stride;
w = points[3];
w = (0.0 != w) ? 1.0/w : 1.0;
value = x*w*points[0]+y*w*points[1]+z*w*points[2]+points[3];
if ( value > max_value )
max_value = value;
}
}
else
{
max_value = x*points[0]+y*points[1]+z*points[2]+d;
for(point_count--; point_count--; /*empty iterator*/ )
{
points += point_stride;
value = x*points[0]+y*points[1]+z*points[2]+d;
if ( value > max_value )
max_value = value;
}
}
}
return max_value;
}
double ON_PlaneEquation::MinimumValueAt(
bool bRational,
int point_count,
int point_stride,
const double* points,
double stop_value
) const
{
double value, min_value, w;
if ( point_count < 1
|| point_stride < (bRational?4:3)
|| 0 == points
)
{
return ON_UNSET_VALUE;
}
if ( ON_IsValid(stop_value) )
{
if ( bRational )
{
w = points[3];
w = (0.0 != w) ? 1.0/w : 1.0;
min_value = x*w*points[0]+y*w*points[1]+z*w*points[2]+points[3];
if ( min_value < stop_value )
return min_value;
for(point_count--; point_count--; /*empty iterator*/ )
{
points += point_stride;
w = points[3];
w = (0.0 != w) ? 1.0/w : 1.0;
value = x*w*points[0]+y*w*points[1]+z*w*points[2]+points[3];
if ( value < min_value )
{
if ( (min_value = value) < stop_value )
return min_value;
}
}
}
else
{
min_value = x*points[0]+y*points[1]+z*points[2]+d;
if ( min_value < stop_value )
return min_value;
for(point_count--; point_count--; /*empty iterator*/ )
{
points += point_stride;
value = x*points[0]+y*points[1]+z*points[2]+d;
if ( value < min_value )
{
if ( (min_value = value) < stop_value )
return min_value;
}
}
}
}
else
{
if ( bRational )
{
w = points[3];
w = (0.0 != w) ? 1.0/w : 1.0;
min_value = x*w*points[0]+y*w*points[1]+z*w*points[2]+points[3];
for(point_count--; point_count--; /*empty iterator*/ )
{
points += point_stride;
w = points[3];
w = (0.0 != w) ? 1.0/w : 1.0;
value = x*w*points[0]+y*w*points[1]+z*w*points[2]+points[3];
if ( value < min_value )
min_value = value;
}
}
else
{
min_value = x*points[0]+y*points[1]+z*points[2]+d;
for(point_count--; point_count--; /*empty iterator*/ )
{
points += point_stride;
value = x*points[0]+y*points[1]+z*points[2]+d;
if ( value < min_value )
min_value = value;
}
}
}
return min_value;
}
bool ON_PlaneEquation::IsNearerThan(
const ON_BezierCurve& bezcrv,
double s0,
double s1,
int sample_count,
double endpoint_tolerance,
double interior_tolerance,
double* smin,
double* smax
) const
{
int i, n;
double smn, smx, vmn, vmx, s, v, w;
ON_3dPoint P;
P.z = 0.0; // for 2d curves
sample_count--;
s = 0.5*(s0+s1);
bezcrv.Evaluate(s,0,3,&P.x);
vmn = vmx = x*P.x + y*P.y + z*P.z + d;
smn = smx = s;
if ( vmn > interior_tolerance )
{
if ( smin )
*smin = s;
if ( smax )
*smax = s;
return false;
}
if ( endpoint_tolerance >= 0.0 )
{
bezcrv.Evaluate(s0,0,3,&P.x);
v = x*P.x + y*P.y + z*P.z + d;
if (v > endpoint_tolerance )
{
if ( smin )
*smin = smn;
if ( smax )
*smax = s0;
return false;
}
if ( v < vmn ) { vmn = v; smn = s0; } else if (v > vmx) { vmx = v; smx = s0; }
bezcrv.Evaluate(s1,0,3,&P.x);
v = x*P.x + y*P.y + z*P.z + d;
if (v > endpoint_tolerance )
{
if ( smin )
*smin = smn;
if ( smax )
*smax = s1;
return false;
}
if ( v < vmn ) { vmn = v; smn = s1; } else if (v > vmx) { vmx = v; smx = s1; }
}
w = 0.5;
for ( n = 4; sample_count > 0; n *= 2 )
{
w *= 0.5;
for ( i = 1; i < n; i+= 2 ) // do not test sample_count here
{
s = w*i;
s = (1.0-s)*s0 + s*s1;
bezcrv.Evaluate(s,0,3,&P.x);
v = x*P.x + y*P.y + z*P.z + d;
if ( v < vmn )
{
vmn = v;
smn = s;
}
else if (v > vmx)
{
vmx = v;
smx = s;
if ( vmx > interior_tolerance )
{
if ( smin )
*smin = smn;
if ( smax )
*smax = s;
return false;
}
}
sample_count--;
}
}
if ( smin )
*smin = smn;
if ( smax )
*smax = smx;
return true;
}
bool ON_PlaneEquation::operator==( const ON_PlaneEquation& eq ) const
{
return (x==eq.x && y==eq.y && z==eq.z && d==eq.d)?true:false;
}
bool ON_PlaneEquation::operator!=( const ON_PlaneEquation& eq ) const
{
return (x!=eq.x || y!=eq.y || z!=eq.z || d!=eq.d)?true:false;
}
int ON_Get3dConvexHull(
const ON_SimpleArray<ON_3dPoint>& points,
ON_SimpleArray<ON_PlaneEquation>& hull
)
{
// This is a slow and stupid way to get the convex hull.
// It works for small point sets. If you need something
// that is efficient, look elsewhere.
const int point_count = points.Count();
if ( point_count < 3 )
return 0;
const int count0 = hull.Count();
hull.Reserve(count0+4);
int i,j,k,n;
ON_3dPoint A,B,C;
ON_PlaneEquation e;
double d0,d1,h0,h1,d;
bool bGoodSide;
for ( i = 0; i < point_count; i++ )
{
A = points[i];
for ( j = i+1; j < point_count; j++ )
{
B = points[j];
for (k = j+1; k < point_count; k++ )
{
C = points[k];
ON_3dVector* v = (ON_3dVector*)&e.x;
v->operator=(ON_CrossProduct(B-A,C-A));
if ( !v->Unitize() )
continue;
e.d = -(A.x*e.x + A.y*e.y + A.z*e.z);
d0 = d1 = e.ValueAt(A);
d = e.ValueAt(B); if ( d < d0 ) d0 = d; else if (d > d1) d1 = d;
d = e.ValueAt(C); if ( d < d0 ) d0 = d; else if (d > d1) d1 = d;
if ( d0 > -ON_ZERO_TOLERANCE )
d0 = -ON_ZERO_TOLERANCE;
if ( d1 < ON_ZERO_TOLERANCE )
d1 = ON_ZERO_TOLERANCE;
h0 = 0.0; h1 = 0.0;
bGoodSide = true;
for ( n = 0; n < point_count && bGoodSide; n++ )
{
d = e.ValueAt(points[n]);
if ( d < h0 )
{
h0 = d;
bGoodSide = (d0 <= h0 || h1 <= d1);
}
else if ( d > h1 )
{
h1 = d;
bGoodSide = (d0 <= h0 || h1 <= d1);
}
}
if ( bGoodSide )
{
if ( h1 <= d1 )
{
// all points are "below" the plane
if ( d0 <= h0 )
{
// all points are also "above" the plane,
hull.SetCount(count0);
ON_PlaneEquation& e0 = hull.AppendNew();
e0.x = -e.x;
e0.y = -e.y;
e0.z = -e.z;
e0.d = -(e.d-h0);
}
ON_PlaneEquation& e1 = hull.AppendNew();
e1.x = e.x;
e1.y = e.y;
e1.z = e.z;
e1.d = (e.d-h1);
if ( d0 <= h0 )
{
// points are (nearly) planar
return 2;
}
}
else if ( d0 <= h0 )
{
// all points are "above" the plane
ON_PlaneEquation& e0 = hull.AppendNew();
e0.x = -e.x;
e0.y = -e.y;
e0.z = -e.z;
e0.d = -(e.d-h0);
}
}
}
}
}
if ( hull.Count() < count0 + 4 )
hull.SetCount(count0);
return hull.Count() - count0;
}
bool ON_IsDegenrateConicHelper(double A, double B, double C, double D, double E)
{
//
// The conic is degenerate (lines and/or points) if the
//
// A B/2 D/2
// B/2 C E/2
// D/2 E/2 F
//
// has rank < 3
// (F = 0 in our case here.)
// zero_tol was tuned by
// 1) testing sets of equaly spaced collinear
// points with coordinate sizes ranging from 0.001 to 1.0e4 and
// segment lengths from 0.001 to 1000.0.
// 2) testing ellipses with axes lengths ranging from 0.001 to 1000
// where the major/minor ration <= 2000 and the centers had coordinates
// from 0.001 to 1.0e4.
// Do not change zero_tol without extensive testing.
const double zero_tol = 1.0e-9;
double x, y;
double M[3][3];
int i0, i1, i2;
// scale matrix coefficients so largest is 1 to
// make checking for a zero pivot easier.
x = fabs(A);
if ( x < (y=fabs(B)) ) x = y;
if ( x < (y=fabs(C)) ) x = y;
if ( x < (y=fabs(D)) ) x = y;
if ( x < (y=fabs(E)) ) x = y;
if ( x <= 1.0e-12 )
return true; // rank 0
x = 1.0/x;
// set up matrix
M[0][0] = x*A;
M[1][1] = x*C;
x *= 0.5;
M[0][1] = M[1][0] = x*B;
M[0][2] = M[2][0] = x*D;
M[1][2] = M[2][1] = x*E;
M[2][2] = 0.0;
// since M is symmetric, just use partial pivoting
// get first pivot ic column M[][0]
i0 = 0;
x = fabs(M[0][0]);
if ( x < (y=fabs(M[1][0])) ) {x=y;i0=1;}
if ( x < (y=fabs(M[2][0])) ) {x=y;i0=2;}
if ( x <= zero_tol )
return true; // rank 0
// first pivot row reduction
x = 1.0/M[i0][0];
M[i0][1] *= x;
M[i0][2] *= x;
i1 = (i0+1)%3;
if ( 0.0 != (y = -M[i1][0]) )
{
M[i1][1] += y*M[i0][1];
M[i1][2] += y*M[i0][2];
}
i2 = (i0+2)%3;
if ( 0.0 != (y = -M[i2][0]) )
{
M[i2][1] += y*M[i0][1];
M[i2][2] += y*M[i0][2];
}
// get second pivot in column M[][1]
if ( fabs(M[i1][1]) < fabs(M[i2][1]) )
{
i1 = i2;
i2 = (i0+1)%3;
}
if ( fabs(M[i1][1]) <= zero_tol )
return true; // rank 1
// second pivot row reduction
x = 1.0/M[i1][1];
M[i1][2] *= x;
if ( 0.0 != (y = -M[i2][1]) )
M[i2][2] += y*M[i1][2];
// test third and final pivot
if ( fabs(M[i2][2]) <= zero_tol )
return true; // rank 2
return false;
}
bool ON_GetConicEquationThrough6Points(
int stride,
const double* points2d,
double conic[6],
double* max_pivot,
double* min_pivot,
double* zero_pivot
)
{
// Sets conic[] to the coefficents = (A,B,C,D,E,F),
// such that A*x*x + B*x*y + C*y*y + D*x + E*y + F = 0
// for each of the 6 input points.
// This code is long and ugly. The reason for unrolling the
// obvious loops is to make it as efficient as possible.
// Rhino calls this function in time critical situations.
//
ON_2dPoint pts[6], bboxmin, bboxmax;
double scale, x, y, M[5][5], N[5][5], max_piv, min_piv;
const double* p;
int i, j, k;
if ( 0 == conic )
return false;
memset(conic,0,6*sizeof(conic[0]));
if ( max_pivot )
*max_pivot = 0.0;
if ( min_pivot )
*min_pivot = 0.0;
if ( zero_pivot )
*zero_pivot = 0.0;
// copy input points into pts[6] and calculate bounding box
bboxmin.x = bboxmax.x = pts[0].x = points2d[0];
bboxmin.y = bboxmax.y = pts[0].y = points2d[1];
if ( !pts[0].IsValid() )
return false;
for ( i = 1; i < 6; i++ )
{
points2d += stride;
pts[i].x = points2d[0];
pts[i].y = points2d[1];
if ( !pts[i].IsValid() )
return false;
if ( pts[i].x < bboxmin.x ) bboxmin.x = pts[i].x;
else if ( pts[i].x > bboxmax.x ) bboxmax.x = pts[i].x;
if ( pts[i].y < bboxmin.y ) bboxmin.y = pts[i].y;
else if ( pts[i].y > bboxmax.y ) bboxmax.y = pts[i].y;
}
// translate and scale pts[] so pts[5] is at the origin and
// (pts[0],...pts[4]) have and have a "diameter" near 1.
// This keeps the starting coefficients in M[][] less than 5
// with the largest generally near one.
x = bboxmax.x-bboxmin.x;
y = bboxmax.y-bboxmin.y;
if ( x >= y )
{
if ( x > 0.0 )
{
y /= x;
scale = x*sqrt(1.0 + y*y);
}
else
return false;
}
else
{
x /= y;
scale = y*sqrt(1.0 + x*x);
}
if ( scale > 0.0 )
scale = 1.0/scale;
else
return false;
for ( i = 0; i < 5; i++ )
{
x = scale*(pts[i].x - pts[5].x);
y = scale*(pts[i].y - pts[5].y);
M[i][0] = x*x;
M[i][1] = x*y;
M[i][2] = y*y;
M[i][3] = x;
M[i][4] = y;
}
memset( N,0,sizeof(N) );
N[0][0] = N[1][1] = N[2][2] = N[3][3] = N[4][4] = 1.0;
// The conic (A,B,C,D,E) is the kernel of M.
//////////////////////////////////////////////////////////
//
// find first pivot
//
j = 0;
p = &M[0][0];
x = fabs(*p);
for ( i = 1; i < 25; i++ )
{
if ( x < (y = fabs(*(++p))) )
{
x = y;
j = i;
}
}
max_piv = min_piv = x;
if ( 0.0 == x )
return false; // all input points are equal
i = j/5;
j %= 5;
if ( 0 != i )
{
// swap rows M[0][] and M[i][]
// Do not modify N because row ops act on the left of M.
for ( k = 0; k < 5; k++ )
{
y = M[0][k]; M[0][k] = M[i][k]; M[i][k] = y;
}
}
if ( 0 != j )
{
// Swap columns M[][0] and M[][j]
// Also swap N[][] columns because column swap
// matrix acts on the right of M.
for ( k = 0; k < 5; k++ )
{
y = M[k][0]; M[k][0] = M[k][j]; M[k][j] = y;
y = N[k][0]; N[k][0] = N[k][j]; N[k][j] = y;
}
}
// scale row M[0][] so that M[0][0] = 1.
// Do not modify N because row ops act on the left of M.
x = 1.0/M[0][0];
M[0][0] = 1.0;
M[0][1] *= x; M[0][2] *= x; M[0][3] *= x; M[0][4] *= x;
// kill column M[1,2,3,4][0]
for ( i = 1; i < 5; i++)
{
if ( 0.0 != (y = -M[i][0]) )
{
// use row op M[i][] += y*M[0][]
// Do not modify N because row ops act on the left of M.
M[i][0] = 0.0; // set to zero so search for pivot is faster
M[i][1] += y*M[0][1]; M[i][2] += y*M[0][2]; M[i][3] += y*M[0][3]; M[i][4] += y*M[0][4];
}
}
//////////////////////////////////////////////////////////
//
// find second pivot
//
j = 6;
p = &M[1][1];
x = fabs(*p);
for ( i = 7; i < 25; i++ )
{
if ( x < (y = fabs(*(++p))) )
{
x = y;
j = i;
}
}
if ( x > max_piv ) max_piv = x; else if ( x < min_piv ) min_piv = x;
if ( 0.0 == x )
{
if ( 0 != max_pivot )
*max_pivot = max_piv;
return false; // two distinct points in input point list.
}
i = j/5; // should always be >= 1
j %= 5; // should always be >= 1
if ( i > 1 )
{
// swap rows M[1][] and M[i][]
// Do not modify N because row ops act on the left of M.
for ( k = 1; k < 5; k++ )
{
y = M[1][k]; M[1][k] = M[i][k]; M[i][k] = y;
}
}
if ( j > 1 )
{
// Swap columns M[][1] and M[][j]
// Also swap N[][] columns because column swap
// matrix acts on the right of M.
for ( k = 0; k < 5; k++ )
{
y = M[k][1]; M[k][1] = M[k][j]; M[k][j] = y;
y = N[k][1]; N[k][1] = N[k][j]; N[k][j] = y;
}
}
// scale row M[1][] so that M[1][1] = 1.
// Do not modify N because row ops act on the left of M.
x = 1.0/M[1][1];
M[1][1] = 1.0;
M[1][2] *= x; M[1][3] *= x; M[1][4] *= x;
// kill column M[2,3,4][1]
for ( i = 2; i < 5; i++)
{
if ( 0.0 != (y = -M[i][1]) )
{
// use row op M[i][] += y*M[0][]
// Do not modify N because row ops act on the left of M.
M[i][1] = 0.0; // set to zero so search for pivot is faster
M[i][2] += y*M[1][2]; M[i][3] += y*M[1][3]; M[i][4] += y*M[1][4];
}
}
//////////////////////////////////////////////////////////
//
// find third pivot
//
j = 12;
p = &M[2][2];
x = fabs(*p);
for ( i = 13; i < 25; i++ )
{
if ( x < (y = fabs(*(++p))) )
{
x = y;
j = i;
}
}
if ( x > max_piv ) max_piv = x; else if ( x < min_piv ) min_piv = x;
if ( 0.0 == x )
{
if ( 0 != max_pivot )
*max_pivot = max_piv;
return false; // three distinct points in input point list.
}
i = j/5; // should always be >= 2
j %= 5; // should always be >= 2
if ( i > 2 )
{
// swap rows M[2][] and M[i][]
// Do not modify N because row ops act on the left of M.
for ( k = 2; k < 5; k++ )
{
y = M[2][k]; M[2][k] = M[i][k]; M[i][k] = y;
}
}
if ( j > 2 )
{
// Swap columns M[][2] and M[][j]
// Also swap N[][] columns because column swap
// matrix acts on the right of M.
for ( k = 0; k < 5; k++ )
{
y = M[k][2]; M[k][2] = M[k][j]; M[k][j] = y;
y = N[k][2]; N[k][2] = N[k][j]; N[k][j] = y;
}
}
// scale row M[2][] so that M[2][2] = 1.
// Do not modify N because row ops act on the left of M.
x = 1.0/M[2][2];
M[2][2] = 1.0; M[2][3] *= x; M[2][4] *= x;
// kill column M[3,4][2]
for ( i = 3; i < 5; i++)
{
if ( 0.0 != (y = -M[i][2]) )
{
// use row op M[i][] += y*M[0][]
// Do not modify N because row ops act on the left of M.
M[i][2] = 0.0; // set to zero so search for pivot is faster
M[i][3] += y*M[2][3]; M[i][4] += y*M[2][4];
}
}
//////////////////////////////////////////////////////////
//
// find fourth pivot
//
i = j = 3;
x = fabs(M[3][3]);
if ( x < (y = fabs(M[3][4])) )
{
x = y; j = 4;
}
if ( x < (y = fabs(M[4][3])) )
{
x = y; i = 4; j = 3;
}
if ( x < (y = fabs(M[4][4])) )
{
x = y; i = j = 4;
}
if ( x > max_piv ) max_piv = x; else if ( x < min_piv ) min_piv = x;
if ( 0.0 == x )
{
if ( 0 != max_pivot )
*max_pivot = max_piv;
return false; // four distinct points in the input point list.
}
if ( i > 3 )
{
// swap rows M[3][] and M[i][]
// Do not modify N[][] because row ops act on the left of M.
y = M[3][3]; M[3][3] = M[4][3]; M[4][3] = y;
y = M[3][4]; M[3][4] = M[i][4]; M[4][4] = y;
}
if ( j > 3 )
{
// Swap columns M[][3] and M[][j]
// Also swap N[][] columns because column swap
// matrix acts on the right of M.
for ( k = 0; k < 5; k++ )
{
y = M[k][3]; M[k][3] = M[k][4]; M[k][4] = y;
y = N[k][3]; N[k][3] = N[k][4]; N[k][4] = y;
}
}
// scale row M[3][] so that M[3][3] = 1.
// Do not modify N because row ops act on the left of M.
x = 1.0/M[3][3];
M[3][3] = 1.0;
M[3][4] *= x;
// kill column M[4][3]
if ( 0.0 != M[4][3] )
{
// use row op M[i][] += y*M[3][]
// Do not modify N because row ops act on the left of M.
M[4][4] -= M[4][3]*M[3][4];
M[4][3] = 0.0; // set to zero so search for pivot is faster
}
// By construction, M[][] is singular and M[4][4] should be nearly zero.
// It should be upper triangluar with diagonal 1,1,1,1,0-ish
if ( max_pivot )
*max_pivot = max_piv;
if ( min_pivot )
*min_pivot = max_piv;
if ( zero_pivot )
*zero_pivot = fabs(M[4][4]);
// Use column operations to make M[][] the identity.
// The operations must also be applied to N[][] in order to
// calculate the kernel of the original M[][].
for ( i = 0; i < 4; i++ )
{
for (j = i+1; j < 5; j++ )
{
if ( 0.0 != (y = -M[i][j]) )
{
// waste of time // M[i][j] = 0.0;
for ( k = 0; k < 5; k++ )
{
//M[k][j] += y*M[k][i];
N[k][j] += y*N[k][i];
}
}
}
}
// At this point, M[][] should be reduced to a diagonal matrix with
// 1,1,1,1,0 on the diagonal. The vector (A,B,C,D,E) = N*Transpose(0,0,0,0,1)
// will be in the kernel of the original M[][]. The conic through the
// six points( scale*(pts[0]-pts[5]),...,scale*(pts[4]-pts[5]),(0,0) )
// is Ax^2 + Bxy + Cy^2 + Dx + Ey = 0.
// We need to apply the inverse of the scale and then translate by
// (pts[5].x,pts[5].y) to get the equation of the conic through the
// input point list.
double A = N[0][4];
double B = N[1][4];
double C = N[2][4];
double D = N[3][4];
double E = N[4][4];
// F = 0
// check for collinear point set
if ( ON_IsDegenrateConicHelper(A,B,C,D,E) )
{
// points lie on one or two lines
return false;
}
// points are not collinear
// undo the scale we applied when we calculated M[][]
x = scale*scale;
A *= x;
B *= x;
C *= x;
D *= scale;
E *= scale;
// undo the translation of pts[5] to (0,0) we applied when we calculated M[][]
x = -pts[5].x;
y = -pts[5].y;
double F = A*x*x + B*x*y + C*y*y + D*x + E*y;
D += 2.0*A*x + B*y;
E += 2.0*C*y + B*x;
if ( (fabs(A) >= fabs(C)) ? (A<0.0):(C<0.0) )
{
// Make the largest A/C coefficent positive.
A = -A; B = -B; C = -C; D = -D; E = -E; F = -F;
}
conic[0] = A; conic[1] = B; conic[2] = C;
conic[3] = D; conic[4] = E; conic[5] = F;
//
j = 0;
x = fabs(conic[0]);
for ( i = 0; i < 6; i++ )
{
if ( x < (y = fabs(conic[i])) )
{
x = y;
j = i;
}
}
if ( !(conic[j] != 0.0) )
return false;
y = 1.0/conic[j];
conic[0] *= y; conic[1] *= y; conic[2] *= y;
conic[3] *= y; conic[4] *= y; conic[5] *= y;
conic[j] = 1.0;
return true;
}
bool ON_IsConicEquationAnEllipse(
const double conic[6],
ON_2dPoint& center,
ON_2dVector& major_axis,
ON_2dVector& minor_axis,
double* major_radius,
double* minor_radius
)
{
double A, C, D, E, F, x0, y0;
double X[2], Y[2], P[2];
if ( !ON_IsValid(conic[0])
|| !ON_IsValid(conic[1])
|| !ON_IsValid(conic[2])
|| !ON_IsValid(conic[3])
|| !ON_IsValid(conic[4])
|| !ON_IsValid(conic[5])
)
{
return false;
}
if ( fabs(conic[1]) > 1.0e-14*fabs(conic[0]+fabs(conic[2])) )
{
// "B" is non zero - remove "rotation" from conic equation
const double alpha = 0.5*atan2(conic[1],conic[0]-conic[2]);
const double s = sin(alpha);
const double c = cos(alpha);
X[0] = c; X[1] = s;
Y[0] = -s; Y[1] = c;
A = conic[0]*c*c + conic[1]*c*s + conic[2]*s*s;
// B = conic[1]*(c*c-s*s) + 2.0*(conic[2]-conic[0])*s*c; // (B = 0)
C = conic[0]*s*s - conic[1]*c*s + conic[2]*c*c;
D = conic[3]*c + conic[4]*s;
E = conic[4]*c - conic[3]*s;
// F = conic[5]; // F not changed by rotation
}
else
{
A = conic[0];
// B = conic[1];
C = conic[2];
D = conic[3];
E = conic[4];
// F = conic[5];
X[0] = 1.0; X[1] = 0.0;
Y[0] = 0.0; Y[1] = 1.0;
}
F = conic[5];
// the if (!(...)) insures we exit if A or C is a NaN
if ( !((A > 0.0 && C > 0.0) || (A < 0.0 && C < 0.0)) )
return false; // conic is not an ellipse
// set P = center
x0 = -0.5*D/A;
y0 = -0.5*E/C;
P[0] = x0*X[0] + y0*Y[0];
P[1] = x0*X[1] + y0*Y[1];
// set A and C to elipse axes lengths
F = conic[5] -(A*x0*x0 + C*y0*y0);
if ( !(0.0 != F) )
return false; // F is 0.0 or a NaN
// We know A and C have the same sign and F has the opposite sign.
A = sqrt(-F/A);
C = sqrt(-F/C);
if ( A == C )
{
// circle
major_axis.x = 1.0;
major_axis.y = 0.0;
minor_axis.x = 0.0;
minor_axis.y = 1.0;
*major_radius = A;
*minor_radius = C;
}
else if ( A > C )
{
// X = major axis, Y = minor axis
major_axis.x = X[0];
major_axis.y = X[1];
minor_axis.x = Y[0];
minor_axis.y = Y[1];
*major_radius = A;
*minor_radius = C;
}
else if ( C > A )
{
// Y = major axis, -X = minor axis
major_axis.x = Y[0];
major_axis.y = Y[1];
minor_axis.x = -X[0];
minor_axis.y = -X[1];
*major_radius = C;
*minor_radius = A;
}
else
{
// A or C is a NaN
return false;
}
center.x = P[0];
center.y = P[1];
return true;
}
bool ON_GetEllipseConicEquation(
double a, double b,
double x0, double y0,
double alpha,
double conic[6]
)
{
if ( 0 == conic )
return false;
if ( !(a > 0.0 && b > 0.0 && ON_IsValid(x0) && ON_IsValid(y0) && ON_IsValid(alpha)) )
{
return false;
}
int k;
double e, y;
double a2 = a*a;
double b2 = b*b;
double A0 = 1.0/a2; // A*x*x
double B0 = 0.0; // B*x*y
double C0 = 1.0/b2; // C*y*y
double D0 = 0.0; // D*x
double E0 = 0.0; // E*y
double F0 = -1.0; // F
// rotate
const double ca = cos(-alpha);
const double sa = sin(-alpha);
const double A = A0*ca*ca + B0*ca*sa + C0*sa*sa;
const double B = B0*(ca*ca - sa*sa) + 2.0*(C0-A0)*sa*ca;
const double C = C0*ca*ca - B0*sa*ca + A0*sa*sa;
const double D = D0*ca + E0*sa;
const double E = E0*ca - D0*sa;
const double F = F0;
if ( !((A > 0.0 && C > 0.0) || (A < 0.0 && C < 0.0)) )
{
return false;
}
// translate center to (x0,y0)
conic[0] = A;
conic[1] = B;
conic[2] = C;
conic[3] = D - 2.0*A*x0 - B*y0;
conic[4] = E - 2.0*C*y0 - B*x0;
conic[5] = F + A*x0*x0 + B*x0*y0 + C*y0*y0 - D*x0 - E*y0;
k = 0;
e = fabs(conic[0]);
if ( e < (y=fabs(conic[1])) ) {e=y;k=1;}
if ( e < (y=fabs(conic[2])) ) {e=y;k=2;}
if ( e < (y=fabs(conic[3])) ) {e=y;k=3;}
if ( e < (y=fabs(conic[4])) ) {e=y;k=4;}
if ( e < (y=fabs(conic[5])) ) {e=y;k=5;}
e = 1.0/conic[k];
conic[0] *= e; conic[1] *= e; conic[2] *= e;
conic[3] *= e; conic[4] *= e; conic[5] *= e;
conic[k] = 1.0;
if ( conic[0] < 0.0 )
{
conic[0] = -conic[0]; conic[1] = -conic[1]; conic[2] = -conic[2];
conic[3] = -conic[3]; conic[4] = -conic[4]; conic[5] = -conic[5];
}
return true;
}
ON_3dPointListRef::ON_3dPointListRef(
const class ON_Mesh* mesh
)
{
*this = ON_3dPointListRef::FromMesh(mesh);
}
ON_3dPointListRef::ON_3dPointListRef(
const class ON_SimpleArray<ON_3dPoint>& point_array
)
{
*this = ON_3dPointListRef::FromPointArray(point_array);
}
ON_3dPointListRef::ON_3dPointListRef(
const class ON_SimpleArray<ON_3fPoint>& point_array
)
{
*this = ON_3dPointListRef::FromPointArray(point_array);
}
const ON_3dPointListRef ON_3dPointListRef::EmptyPointList;
unsigned int ON_3dPointListRef::SetFromDoubleArray(
size_t point_count,
size_t point_stride,
const double* point_array
)
{
*this = ON_3dPointListRef::EmptyPointList;
if ( point_count > 0
&& point_count < (size_t)ON_UNSET_UINT_INDEX
&& point_stride >= 3
&& point_stride < (size_t)ON_UNSET_UINT_INDEX
&& 0 != point_array
)
{
m_point_count = (unsigned int)point_count;
m_point_stride = (unsigned int)point_stride;
m_dP = point_array;
}
return m_point_count;
}
unsigned int ON_3dPointListRef::SetFromFloatArray(
size_t point_count,
size_t point_stride,
const float* point_array
)
{
*this = ON_3dPointListRef::EmptyPointList;
if ( point_count > 0
&& point_count < (size_t)ON_UNSET_UINT_INDEX
&& point_stride >= 3
&& point_stride < (size_t)ON_UNSET_UINT_INDEX
&& 0 != point_array
)
{
m_point_count = (unsigned int)point_count;
m_point_stride = (unsigned int)point_stride;
m_fP = point_array;
}
return m_point_count;
}
unsigned int ON_3dPointListRef::SetFromMesh(
const class ON_Mesh* mesh
)
{
if ( 0 != mesh )
{
const unsigned int vertex_count = mesh->VertexUnsignedCount();
if ( vertex_count > 0 )
{
return (mesh->HasDoublePrecisionVertices())
? SetFromDoubleArray(vertex_count,3,(const double*)(mesh->m_dV.Array()))
: SetFromFloatArray(vertex_count,3,(const float*)(mesh->m_V.Array()));
}
}
*this = ON_3dPointListRef::EmptyPointList;
return m_point_count;
}
ON_3dPointListRef ON_3dPointListRef::FromDoubleArray(
size_t point_count,
size_t point_stride,
const double* point_array
)
{
ON_3dPointListRef p;
p.SetFromDoubleArray(point_count,point_stride,point_array);
return p;
}
ON_3dPointListRef ON_3dPointListRef::FromFloatArray(
size_t point_count,
size_t point_stride,
const float* point_array
)
{
ON_3dPointListRef p;
p.SetFromFloatArray(point_count,point_stride,point_array);
return p;
}
ON_3dPointListRef ON_3dPointListRef::FromPointArray(
const class ON_SimpleArray<ON_3dPoint>& point_array
)
{
ON_3dPointListRef p;
p.SetFromDoubleArray(point_array.UnsignedCount(),3,(const double*)point_array.Array());
return p;
}
ON_3dPointListRef ON_3dPointListRef::FromPointArray(
const class ON_SimpleArray<ON_3fPoint>& point_array
)
{
ON_3dPointListRef p;
p.SetFromFloatArray(point_array.UnsignedCount(),3,(const float*)point_array.Array());
return p;
}
ON_3dPointListRef ON_3dPointListRef::FromMesh(
const class ON_Mesh* mesh
)
{
ON_3dPointListRef p;
p.SetFromMesh(mesh);
return p;
}
unsigned int ON_3dPointListRef::Precision() const
{
if ( 0 != m_dP )
return 2;
if ( 0 != m_fP )
return 1;
return 0;
}
ON_SimpleArray<ON_3dPoint> ON_3dPointListRef::To3dPointArray() const
{
ON_SimpleArray<ON_3dPoint> a;
unsigned int i = m_point_count;
if ( i > 0 )
{
a.Reserve(i);
a.SetCount(i);
double* dst = (double*)a.Array();
if ( m_dP )
{
const double* src = m_dP;
while(i--)
{
*dst++ = src[0];
*dst++ = src[1];
*dst++ = src[2];
src += m_point_stride;
}
}
else if ( m_fP )
{
const float* src = m_fP;
while(i--)
{
*dst++ = src[0];
*dst++ = src[1];
*dst++ = src[2];
src += m_point_stride;
}
}
}
// Note:
// ON_SimpleArray<ON_3dPoint> has rvalue copy constructor
// and operator=, so this return does not create a copy.
return a;
}
ON_SimpleArray<ON_3fPoint> ON_3dPointListRef::To3fPointArray() const
{
ON_SimpleArray<ON_3fPoint> a;
unsigned int i = m_point_count;
if ( i > 0 )
{
a.Reserve(i);
a.SetCount(i);
float* dst = (float*)a.Array();
if ( m_dP )
{
const double* src = m_dP;
while(i--)
{
*dst++ = (float)src[0];
*dst++ = (float)src[1];
*dst++ = (float)src[2];
src += m_point_stride;
}
}
else if ( m_fP )
{
const float* src = m_fP;
while(i--)
{
*dst++ = src[0];
*dst++ = src[1];
*dst++ = src[2];
src += m_point_stride;
}
}
}
// Note:
// ON_SimpleArray<ON_3fPoint> has rvalue copy constructor
// and operator=, so this return does not create a copy.
return a;
}
/*
Returns:
true if the points are double precision
*/
bool ON_3dPointListRef::DoublePrecision() const
{
return (0 != m_dP);
}
/*
Returns:
true if the points are single precision
*/
bool ON_3dPointListRef::SinglePrecision() const
{
return (0 != m_dP);
}
unsigned int ON_3dPointListRef::GetMeshFacePoints(
const class ON_MeshFace* mesh_face,
ON_3dPoint face_points[4]
) const
{
return (0 != mesh_face)
? GetPoints(4U,(const unsigned int*)(mesh_face->vi),face_points)
: 0;
}
unsigned int ON_3dPointListRef::GetMeshNgonPoints(
const class ON_MeshNgon* mesh_ngon,
size_t ngon_points_capacity,
class ON_3dPoint* ngon_points
) const
{
return ( 0 != mesh_ngon && ((size_t)mesh_ngon->m_Vcount) <= ngon_points_capacity)
? GetPoints(mesh_ngon->m_Vcount, mesh_ngon->m_vi, ngon_points)
: 0;
}
unsigned int ON_3dPointListRef::GetMeshNgonPoints(
const class ON_MeshNgon* mesh_ngon,
ON_SimpleArray<ON_3dPoint>& ngon_points
) const
{
if ( mesh_ngon && mesh_ngon->m_Vcount > 0 && 0 != mesh_ngon->m_vi )
{
ngon_points.Reserve(mesh_ngon->m_Vcount);
ngon_points.SetCount(mesh_ngon->m_Vcount);
return GetPoints(mesh_ngon->m_Vcount, mesh_ngon->m_vi, ngon_points.Array());
}
ngon_points.SetCount(0);
return 0;
}
unsigned int ON_3dPointListRef::GetQuadPoints(
const int quad_point_indices[4],
class ON_3dPoint quad_points[4]
) const
{
return GetPoints(4,quad_point_indices,quad_points);
}
unsigned int ON_3dPointListRef::GetQuadPoints(
const unsigned int quad_point_indices[4],
class ON_3dPoint quad_points[4]
) const
{
return GetPoints(4,quad_point_indices,quad_points);
}
unsigned int ON_3dPointListRef::GetTrianglePoints(
const int triangle_point_indices[3],
class ON_3dPoint triangle_points[3]
) const
{
return GetPoints(3,triangle_point_indices,triangle_points);
}
unsigned int ON_3dPointListRef::GetTrianglePoints(
const unsigned int triangle_point_indices[3],
class ON_3dPoint triangle_points[3]
) const
{
return GetPoints(3,triangle_point_indices,triangle_points);
}
unsigned int ON_3dPointListRef::GetPoints(
int point_index_count,
const int* point_index_list,
class ON_3dPoint* points
) const
{
return GetPoints((unsigned int)point_index_count,(const unsigned int*)point_index_list,points);
}
unsigned int ON_3dPointListRef::GetPoints(
unsigned int point_index_count,
const unsigned int* point_index_list,
class ON_3dPoint* points
) const
{
unsigned int rc = 0;
if ( 0 == point_index_list
|| 0 == points
|| 0 == point_index_count
|| point_index_count >= m_point_count
)
{
return rc;
}
double* dst = &points[0].x;
if ( m_dP )
{
rc = point_index_count;
while(point_index_count--)
{
unsigned int i = *point_index_list++;
if ( i < m_point_count )
{
const double* src = m_dP + i*m_point_stride;
*dst++ = *src++;
*dst++ = *src++;
*dst++ = *src;
}
else
{
*dst++ = ON_UNSET_VALUE;
*dst++ = ON_UNSET_VALUE;
*dst++ = ON_UNSET_VALUE;
}
}
return rc;
}
if ( m_fP )
{
rc = point_index_count;
while(point_index_count--)
{
unsigned int i = *point_index_list++;
if ( i < m_point_count )
{
const float* src = m_fP + i*m_point_stride;
*dst++ = *src++;
*dst++ = *src++;
*dst++ = *src;
}
else
{
*dst++ = ON_UNSET_VALUE;
*dst++ = ON_UNSET_VALUE;
*dst++ = ON_UNSET_VALUE;
}
}
return rc;
}
return rc;
}
unsigned int ON_3dPointListRef::GetPoints(
const ON_SimpleArray<int>& point_index_list,
ON_SimpleArray<ON_3dPoint>& points
) const
{
points.Reserve(point_index_list.UnsignedCount());
points.SetCount(point_index_list.UnsignedCount());
unsigned int rc = GetPoints( point_index_list.UnsignedCount(),
(const unsigned int*)point_index_list.Array(),
points.Array()
);
if ( rc < points.UnsignedCount() )
points.SetCount(rc);
return rc;
}
unsigned int ON_3dPointListRef::GetPoints(
int point_index_count,
const int* point_index_list,
ON_SimpleArray<ON_3dPoint>& points
) const
{
unsigned int rc = (point_index_count > 0)
? GetPoints((unsigned int)point_index_count,(const unsigned int*)point_index_list,points)
: 0;
if (rc < points.UnsignedCount())
points.SetCount(rc);
return rc;
}
unsigned int ON_3dPointListRef::GetPoints(
unsigned int point_index_count,
const unsigned int* point_index_list,
ON_SimpleArray<ON_3dPoint>& points
) const
{
unsigned int rc = 0;
if ( point_index_count > 0 && 0 != point_index_list )
{
points.Reserve(point_index_count);
points.SetCount(point_index_count);
rc = GetPoints(point_index_count,point_index_list,points.Array());
}
if (rc < points.UnsignedCount())
points.SetCount(rc);
return rc;
}
static ON__UINT32 Internal_DoubleArrayDataCRC(
ON__UINT32 current_remainder,
size_t count,
const double* a
)
{
double x;
char* byte_swap
= (ON::endian::big_endian == ON::Endian())
? ((char*)&x)
: nullptr;
char c;
if (nullptr != a && count > 0)
{
const double* a1 = a + count;
while (a < a1)
{
x = *a++;
if (0.0 == x)
x = 0.0; // change -0.0 into +0.0
else if (false == (x == x))
x = ON_DBL_QNAN; // change any nan into ON_DBL_QNAN.
if (nullptr != byte_swap)
{
c = byte_swap[0]; byte_swap[0] = byte_swap[7]; byte_swap[7] = c;
c = byte_swap[1]; byte_swap[1] = byte_swap[6]; byte_swap[6] = c;
c = byte_swap[2]; byte_swap[2] = byte_swap[5]; byte_swap[5] = c;
c = byte_swap[3]; byte_swap[3] = byte_swap[4]; byte_swap[4] = c;
}
current_remainder = ON_CRC32(current_remainder, sizeof(x), (const void*)&x);
}
}
return current_remainder;
}
ON__UINT32 ON_2dPoint::DataCRC(ON__UINT32 current_remainder) const
{
return Internal_DoubleArrayDataCRC(current_remainder, 2, &x);
}
ON__UINT32 ON_3dPoint::DataCRC(ON__UINT32 current_remainder) const
{
return Internal_DoubleArrayDataCRC(current_remainder, 3, &x);
}
ON__UINT32 ON_4dPoint::DataCRC(ON__UINT32 current_remainder) const
{
return Internal_DoubleArrayDataCRC(current_remainder, 4, &x);
}
ON__UINT32 ON_2dVector::DataCRC(ON__UINT32 current_remainder) const
{
return Internal_DoubleArrayDataCRC(current_remainder, 2, &x);
}
ON__UINT32 ON_3dVector::DataCRC(ON__UINT32 current_remainder) const
{
return Internal_DoubleArrayDataCRC(current_remainder, 3, &x);
}
ON__UINT32 ON_2fPoint::DataCRC(ON__UINT32 current_remainder) const
{
const ON_2dPoint p(*this);
return p.DataCRC(current_remainder);
}
ON__UINT32 ON_3fPoint::DataCRC(ON__UINT32 current_remainder) const
{
const ON_3dPoint p(*this);
return p.DataCRC(current_remainder);
}
ON__UINT32 ON_4fPoint::DataCRC(ON__UINT32 current_remainder) const
{
const ON_4dPoint p(*this);
return p.DataCRC(current_remainder);
}
ON__UINT32 ON_2fVector::DataCRC(ON__UINT32 current_remainder) const
{
const ON_2dVector v(*this);
return v.DataCRC(current_remainder);
}
ON__UINT32 ON_3fVector::DataCRC(ON__UINT32 current_remainder) const
{
const ON_3dVector v(*this);
return v.DataCRC(current_remainder);
}
// ON_2dSize
int ON_2dSize::Compare(
const ON_2dSize& lhs,
const ON_2dSize& rhs
)
{
if (lhs.cx < rhs.cx)
return -1;
if (lhs.cx > rhs.cx)
return 1;
if (lhs.cy < rhs.cy)
return -1;
if (lhs.cy > rhs.cy)
return 1;
return 0;
}
int ON_2dSize::ComparePointer(
const ON_2dSize* lhs,
const ON_2dSize* rhs
)
{
if (lhs == rhs)
return 0;
if (nullptr == lhs)
return -1;
if (nullptr == rhs)
return 1;
if (lhs->cx < rhs->cx)
return -1;
if (lhs->cx > rhs->cx)
return 1;
if (lhs->cy < rhs->cy)
return -1;
if (lhs->cy > rhs->cy)
return 1;
return 0;
}
ON_2dSize::ON_2dSize(double cxValue, double cyValue)
: cx(cxValue)
, cy(cyValue)
{}
bool ON_2dSize::IsSet() const
{
return (ON_UNSET_VALUE != cx && ON_UNSET_VALUE != cy);
}
bool ON_2dSize::IsZero() const
{
return (0 == cx && 0 == cy);
}
bool operator==(
const ON_2dSize& lhs,
const ON_2dSize& rhs
)
{
return (lhs.cx == rhs.cx && lhs.cy == rhs.cy);
}
bool operator!=(const ON_2dSize& lhs, const ON_2dSize& rhs)
{
return (lhs.cx != rhs.cx || lhs.cy != rhs.cy);
}
// ON_4dRect
ON_4dRect::ON_4dRect(double leftValue, double topValue, double rightValue, double bottomValue)
: left(leftValue)
, top(topValue)
, right(rightValue)
, bottom(bottomValue)
{}
ON_4dRect::ON_4dRect(const ON_2dPoint topLeft, const ON_2dPoint& bottomRight)
: left(topLeft.x)
, top(topLeft.y)
, right(bottomRight.x)
, bottom(bottomRight.y)
{}
ON_4dRect::ON_4dRect(const ON_2dPoint& point, const ON_2dSize& size)
{
left = point.x;
top = point.y;
right = left + size.cx;
bottom = top + size.cy;
}
bool ON_4dRect::IsSet() const
{
return (
ON_UNSET_VALUE != left
&& ON_UNSET_VALUE != top
&& ON_UNSET_VALUE != right
&& ON_UNSET_VALUE != bottom
);
}
double ON_4dRect::Width(void) const { return fabs(right - left); }
double ON_4dRect::Height(void) const { return fabs(bottom - top); }
const ON_2dSize ON_4dRect::Size(void) const { return ON_2dSize(Width(), Height()); }
const ON_2dPoint ON_4dRect::CenterPoint(void) const { return ON_2dPoint((left + right) / 2.0, (top + bottom) / 2.0); }
const ON_2dPoint ON_4dRect::TopLeft(void) const { return ON_2dPoint(left, top); }
const ON_2dPoint ON_4dRect::BottomRight(void) const { return ON_2dPoint(right, bottom); }
bool ON_4dRect::IntersectRect(const ON_4dRect * r1, const ON_4dRect * r2)
{
left = ON_Max(r1->left, r2->left);
top = ON_Max(r1->top, r2->top);
right = ON_Min(r1->right, r2->right);
bottom = ON_Min(r1->bottom, r2->bottom);
if (IsRectEmpty()) {
// degenerate rectangle
SetRectEmpty();
return false;
}
return true;
}
bool ON_4dRect::IntersectRect(const ON_4dRect & r1, const ON_4dRect & r2) { return IntersectRect(&r1, &r2); }
bool ON_4dRect::IsRectEmpty(void) const
{
return 0 == Width() || 0 == Height();
}
bool ON_4dRect::IsRectNull(void) const
{
return 0.0 == left &&
0.0 == top &&
0.0 == bottom &&
0.0 == right;
}
void ON_4dRect::SetRect(double l, double t, double r, double b) { left = l; top = t; right = r; bottom = b; }
bool ON_4dRect::PtInRect(const ON_2dPoint & pt) const
{
return pt.x >= left && pt.y >= top && pt.x < right && pt.y < bottom;
}
void ON_4dRect::OffsetRect(double x, double y)
{
left += x;
right += x;
top += y;
bottom += y;
}
void ON_4dRect::OffsetRect(const ON_2dVector& v)
{
left += v.x;
right += v.x;
top += v.y;
bottom += v.y;
}
void ON_4dRect::InflateRect(double x, double y)
{
left -= x;
top -= y;
right += x;
bottom += y;
}
void ON_4dRect::InflateRect(double l, double t, double r, double b)
{
left -= l;
top -= t;
right += r;
bottom += b;
}
void ON_4dRect::DeflateRect(double x, double y)
{
left += x;
top += y;
right -= x;
bottom -= y;
}
bool ON_4dRect::SubtractRect(const ON_4dRect* rect1, const ON_4dRect* rect2)
{
if (rect1 == nullptr)
return false;
*this = *rect1;
if (rect1->IsRectEmpty() || rect2 == nullptr || rect2->IsRectEmpty())
{
return true;
}
if (rect2->top <= rect1->top && rect2->bottom >= rect1->bottom)
{
if (left < rect2->right)
{
left = ON_Min(rect2->right, right);
}
if (right > rect2->left)
{
right = ON_Max(left, rect2->left);
}
}
if (rect2->left <= rect1->left && rect2->right >= rect1->right)
{
if (top < rect2->bottom)
{
top = ON_Min(rect2->bottom, bottom);
}
if (bottom > rect2->top)
{
bottom = ON_Max(top, rect2->top);
}
}
return true;
}
void ON_4dRect::NormalizeRect()
{
double nTemp;
if (left > right)
{
nTemp = left;
left = right;
right = nTemp;
}
if (top > bottom)
{
nTemp = top;
top = bottom;
bottom = nTemp;
}
}
bool ON_4dRect::IsZero() const
{
return (0.0 == left && 0.0 == top && 0.0 == right && 0.0 == bottom);
}
void ON_4dRect::SetZero() { *this = Zero; }
bool operator==(const ON_4dRect& lhs, const ON_4dRect& rhs)
{
return (lhs.left == rhs.left
&& lhs.top == rhs.top
&& lhs.right == rhs.right
&& lhs.bottom == rhs.bottom);
}
bool operator!=(const ON_4dRect& lhs, const ON_4dRect& rhs)
{
return (lhs.left != rhs.left
|| lhs.top != rhs.top
|| lhs.right != rhs.right
|| lhs.bottom != rhs.bottom);
}
ON_PeriodicDomain::ON_PeriodicDomain(const ON_Interval dom[2], const bool closed[2], double normband) :
m_dom{ dom[0], dom[1] },
m_closed{ closed[0],closed[1] },
m_normband(normband),
m_deck{ 0,0 }
{}
void ON_PeriodicDomain::Initialize(const ON_Interval dom[2], const bool closed[2], double normband)
{
m_dom[0] = dom[0];
m_dom[1] = dom[1];
m_closed[0] = closed[0];
m_closed[1] = closed[1];
m_normband = normband;
m_deck[0] = m_deck[1] = 0;
}
// Repeated application of LiftToCover maps a sequence in the domain covering space,
// Pin[i] to Out[i].
//
// * proj(Pin[i]) = proj(Out[i])
// * Out[0] = Pin[0]
// * Out[i+1] and Out[i] are in adjacnt bands
ON_2dPoint ON_PeriodicDomain::LiftToCover(ON_2dPoint Pin, bool stealth )
{
ON_2dPoint out = Pin;
ON_2dPoint nnext;
int deck_in[2] = { 0,0 };
// decompose Pin
// Pin = m_dom.ParameterAt( deck + nnext)
// where nnext[i] is in [0.0, 1.0)
for (int i = 0; i < 2; i++)
{
nnext[i] = m_dom[i].NormalizedParameterAt(out[i]);
if (m_closed[i])
{
deck_in[i] = int(floor(nnext[i]));
nnext[i] -= deck_in[i];
}
}
if (m_nprev == ON_2dPoint::UnsetPoint)
{
if( !stealth)
{
m_nprev = nnext;
m_deck[0] = deck_in[0];
m_deck[1] = deck_in[1];
}
return Pin;
}
int deck[2] = { m_deck[0], m_deck[1] };
for (int i = 0; i < 2; i++)
{
if (!m_closed[i])
continue;
if (m_nprev[i]<m_normband && nnext[i]>1.0 - m_normband)
deck[i] --;
else if (m_nprev[i] > 1.0 - m_normband && nnext[i] < m_normband)
deck[i]++;
}
for (int i = 0; i < 2; i++)
out[i] = m_dom[i].ParameterAt(deck[i] + nnext[i]);
if (!stealth)
{
m_deck[0] = deck[0];
m_deck[1] = deck[1];
m_nprev = nnext;
}
return out;
}
ON_2dPoint ON_PeriodicDomain::LiftInverse(ON_2dPoint p)
{
return ON_LiftInverse(p, m_dom, m_closed);
}
ON_SimpleArray<ON_2dPoint> ON_LiftToCover(
const ON_SimpleArray<ON_2dPoint>& in,
const ON_Interval dom[2], bool closed[2],
double normband)
{
ON_PeriodicDomain Cover(dom, closed, normband);
ON_SimpleArray<ON_2dPoint> out(in.Count());
for (int i = 0; i < in.Count(); i++)
out.Append(Cover.LiftToCover(in[i]));
return out;
}
ON_2dPoint ON_LiftInverse(ON_2dPoint P, ON_Interval dom[2], bool closed[2])
{
ON_2dPoint Q = P;
if (closed[0] || closed[1])
{
for (int di = 0; di < 2; di++)
{
if (closed[di])
Q[di] -= floor((Q[di] - dom[di][0]) / dom[di].Length())*dom[di].Length();
}
}
return Q;
}