opennurbs_point.cpp
Go to the documentation of this file.
00001 /* $NoKeywords: $ */
00002 /*
00003 //
00004 // Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved.
00005 // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
00006 // McNeel & Associates.
00007 //
00008 // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
00009 // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
00010 // MERCHANTABILITY ARE HEREBY DISCLAIMED.
00011 //                              
00012 // For complete openNURBS copyright information see <http://www.opennurbs.org>.
00013 //
00015 */
00016 
00017 #include "pcl/surface/3rdparty/opennurbs/opennurbs.h"
00018 
00019 bool ON_IsValid(double x)
00020 {
00021   return ON_IS_VALID(x);
00022 }
00023 
00024 bool ON_IsValidFloat(float x)
00025 {
00026   return ON_IS_VALID_FLOAT(x);
00027 }
00028 
00029 const ON_Interval ON_Interval::EmptyInterval(ON_UNSET_VALUE,ON_UNSET_VALUE);
00030 
00031 ON_Interval::ON_Interval()
00032 {
00033   m_t[0] = m_t[1] = ON_UNSET_VALUE; 
00034 }
00035 
00036 ON_Interval::ON_Interval(double t0, double t1)
00037 {
00038   Set(t0,t1);
00039 }
00040 
00041 ON_Interval::~ON_Interval()
00042 {}
00043 
00044 double&
00045 ON_Interval::operator[](int i)
00046 {
00047   return m_t[(i<=0)?0:1];
00048 }
00049 
00050 double
00051 ON_Interval::operator[](int i) const
00052 {
00053   return m_t[(i<=0)?0:1];
00054 }
00055 
00056 double
00057 ON_Interval::Min() const
00058 {
00059   return m_t[IsDecreasing()?1:0];
00060 }
00061 
00062 void ON_Interval::Destroy()
00063 {
00064   Set(ON_UNSET_VALUE,ON_UNSET_VALUE);
00065 }
00066 
00067 void ON_Interval::Set(double t0,double t1)
00068 {
00069   m_t[0] = t0;
00070   m_t[1] = t1;
00071 }
00072 
00073 double ON_Interval::ParameterAt(double x) const
00074 {
00075   return (ON_IS_VALID(x) ? ((1.0-x)*m_t[0] + x*m_t[1]) : ON_UNSET_VALUE);
00076 }
00077 
00078 ON_Interval ON_Interval::ParameterAt(ON_Interval x) const
00079 {
00080   return ON_Interval( ParameterAt(x[0]), ParameterAt(x[1]) );
00081 }
00082 
00083 double ON_Interval::NormalizedParameterAt( // returns x so that min*(1.0-x) + max*x = input
00084   double t
00085   ) const
00086 {
00087   if (!ON_IS_VALID(t))
00088     return ON_UNSET_VALUE; // added 29 Sep 2006
00089 
00090   double x = m_t[0];
00091   if ( m_t[0] != m_t[1] ) {
00092     x = ( t == m_t[1]) ? 1.0 : (t - m_t[0])/(m_t[1] - m_t[0]);
00093   }
00094   return x;
00095 }
00096 
00097 ON_Interval ON_Interval::NormalizedParameterAt( // returns x so that min*(1.0-x) + max*x = input
00098   ON_Interval t
00099   ) const
00100 {
00101         return  ON_Interval(    NormalizedParameterAt(t[0]) , 
00102                                                                                                 NormalizedParameterAt(t[1]) );
00103 }
00104 
00105 double
00106 ON_Interval::Max() const
00107 {
00108   return m_t[IsDecreasing()?0:1];
00109 }
00110 
00111 double
00112 ON_Interval::Mid() const
00113 {
00114   return 0.5*(m_t[0]+m_t[1]);
00115 }
00116 
00117 double
00118 ON_Interval::Length() const
00119 {
00120   return ( ON_IS_VALID(m_t[0]) && ON_IS_VALID(m_t[1]) ) ? m_t[1]-m_t[0] : 0.0;
00121 }
00122 
00123 bool
00124 ON_Interval::IsIncreasing() const
00125 {
00126   return ( m_t[0] < m_t[1] && ON_IS_VALID(m_t[0]) && ON_IS_VALID(m_t[1]) ) ? true : false;
00127 }
00128 
00129 bool
00130 ON_Interval::IsDecreasing() const
00131 {
00132   return ( m_t[0] > m_t[1] && ON_IS_VALID(m_t[0]) && ON_IS_VALID(m_t[1]) ) ? true : false;
00133 }
00134 
00135 bool
00136 ON_Interval::IsInterval() const
00137 {
00138   return ( m_t[0] != m_t[1] && ON_IS_VALID(m_t[0]) && ON_IS_VALID(m_t[1]) ) ? true : false;
00139 }
00140 
00141 
00142 bool
00143 ON_Interval::IsSingleton() const
00144 {
00145   return ( m_t[0] == m_t[1] && ON_IS_VALID(m_t[1]) ) ? true : false;
00146 }
00147 
00148 bool
00149 ON_Interval::IsEmptyInterval() const
00150 {
00151   return ( m_t[0] == ON_UNSET_VALUE && m_t[1] == ON_UNSET_VALUE ) ? true : false;
00152 }
00153 
00154 bool
00155 ON_Interval::IsEmptySet() const
00156 {
00157   return ( m_t[0] == ON_UNSET_VALUE && m_t[1] == ON_UNSET_VALUE ) ? true : false;
00158 }
00159 
00160 bool
00161 ON_Interval::IsValid() const
00162 {
00163   // 05/29/2007 TimH. Changed 0 to 1.
00164   return ( ON_IS_VALID(m_t[0]) && ON_IS_VALID(m_t[1]) );
00165 }
00166 
00167 bool 
00168 ON_Interval::MakeIncreasing()           // returns true if resulting interval IsIncreasing() 
00169 {
00170         if( IsDecreasing()){ 
00171                 Swap();
00172                 return true;
00173         }
00174         return IsIncreasing();
00175 }
00176 
00177 bool 
00178 ON_Interval::operator!=(const ON_Interval& other) const
00179 {
00180   return Compare(other) ? true : false;
00181 }
00182 
00183 bool 
00184 ON_Interval::operator==(const ON_Interval& other) const
00185 {
00186   return Compare(other) ? false : true;
00187 }
00188 
00189 
00190 int
00191 ON_Interval::Compare( const ON_Interval& other ) const
00192 {
00193   if ( m_t[0] < other.m_t[0] )
00194     return -1;
00195   if ( m_t[0] > other.m_t[0] )
00196     return 1;
00197   if ( m_t[1] < other.m_t[1] )
00198     return -1;
00199   if ( m_t[1] > other.m_t[1] )
00200     return 1;
00201   return 0;
00202 }
00203 
00204 bool
00205 ON_Interval::Includes( double t, bool bTestOpenInterval) const
00206 {
00207   bool rc = false;
00208   if ( ON_IS_VALID(t) && ON_IS_VALID(m_t[0]) && ON_IS_VALID(m_t[1]) )
00209   {
00210     int i = (m_t[0] <= m_t[1]) ? 0 : 1;
00211     if ( bTestOpenInterval )
00212     {
00213       rc = ( m_t[i] < t && t < m_t[1-i] ) ? true : false;
00214     }
00215     else
00216     {
00217       rc = ( m_t[i] <= t && t <= m_t[1-i] ) ? true : false;
00218     }
00219   }
00220   return rc;
00221 }
00222 
00223 bool
00224 ON_Interval::Includes( const ON_Interval& other, bool bProperSubSet ) const
00225 {
00226   bool rc = ( Includes( other.m_t[0] ) && Includes( other.m_t[1] ) ) ? true : false;
00227   if ( rc && bProperSubSet )
00228   {
00229     if ( !Includes( other.m_t[0], true ) && !Includes( other.m_t[1], true ) )
00230       rc = false;
00231   }
00232   return rc;
00233 }
00234 
00235 void
00236 ON_Interval::Reverse()
00237 {
00238   if ( !IsEmptySet() ) {
00239     const double x = -m_t[0];
00240     m_t[0] = -m_t[1];
00241     m_t[1] = x;
00242   }
00243 }
00244 
00245 void
00246 ON_Interval::Swap()
00247 {
00248   const double x = m_t[0];
00249   m_t[0] = m_t[1];
00250   m_t[1] = x;
00251 }
00252 
00254 // If the intersection is not empty, then 
00255 // intersection = [max(this.Min(),arg.Min()), min(this.Max(),arg.Max())]
00256 // Intersection() returns true if the intersection is not empty.
00257 // The interval [ON_UNSET_VALUE,ON_UNSET_VALUE] is considered to be
00258 // the empty set interval.  The result of any intersection involving an
00259 // empty set interval or disjoint intervals is the empty set interval.
00260 bool ON_Interval::Intersection( // this = this intersect arg
00261        const ON_Interval& other
00262        )
00263 {
00264   bool rc = false;
00265   if ( IsEmptySet() && other.IsEmptySet() )
00266     Destroy();
00267   else {
00268     double a, b, mn, mx;
00269     a = Min();
00270     b = other.Min();
00271     mn = (a>=b) ? a : b;
00272     a = Max();
00273     b = other.Max();
00274     mx = (a<=b) ? a : b;
00275     if ( mn <= mx ) {
00276       Set(mn,mx);
00277       rc = true;
00278     }
00279     else
00280       Destroy();
00281   }
00282   return rc;
00283 }
00284 
00286 // If the intersection is not empty, then 
00287 // intersection = [max(argA.Min(),argB.Min()), min(argA.Max(),argB.Max())]
00288 // Intersection() returns true if the intersection is not empty.
00289 // The interval [ON_UNSET_VALUE,ON_UNSET_VALUE] is considered to be
00290 // the empty set interval.  The result of any intersection involving an
00291 // empty set interval or disjoint intervals is the empty set interval.
00292 bool ON_Interval::Intersection( // this = intersection of two args
00293        const ON_Interval& ain, 
00294        const ON_Interval& bin
00295        )
00296 {
00297   bool rc = false;
00298   if ( ain.IsEmptySet() && bin.IsEmptySet() )
00299     Destroy();
00300   else {
00301     double a, b, mn, mx;
00302     a = ain.Min();
00303     b = bin.Min();
00304     mn = (a>=b) ? a : b;
00305     a = ain.Max();
00306     b = bin.Max();
00307     mx = (a<=b) ? a : b;
00308     if ( mn <= mx ) {
00309       Set(mn,mx);
00310       rc = true;
00311     }
00312     else
00313       Destroy();
00314   }
00315   return rc;
00316 }
00317 
00319   // The union of an empty set and an increasing interval is the increasing
00320   // interval.  The union of two empty sets is empty. The union of an empty
00321   // set an a non-empty interval is the non-empty interval.
00322   // The union of two non-empty intervals is
00323 // union = [min(this.Min(),arg.Min()), max(this.Max(),arg.Max()),]
00324 // Union() returns true if the union is not empty.
00325 bool ON_Interval::Union( // this = this union arg
00326        const ON_Interval& other
00327        )
00328 {
00329   bool rc = false;
00330   if ( other.IsEmptySet() ) {
00331     // this may be increasing, decreasing, or empty
00332     Set( Min(), Max() );
00333     rc = !IsEmptySet();
00334   }
00335   else if ( IsEmptySet() ) {
00336     // other may be increasing or decreasing
00337     Set( other.Min(), other.Max() );
00338     rc = true;
00339   }
00340   else {
00341     double a, b, mn, mx;
00342     a = Min();
00343     b = other.Min();
00344     mn = (a<=b) ? a : b;
00345     a = Max();
00346     b = other.Max();
00347     mx = (a>=b) ? a : b;
00348     if ( mn <= mx ) {
00349       Set(mn,mx);
00350       rc = true;
00351     }
00352     else
00353       Destroy();
00354   }
00355   return rc;
00356 }
00357 
00358 bool ON_Interval::Union(
00359   int count,
00360   const double* t
00361   )
00362 {
00363   bool rc = false;
00364   double a, mn, mx;
00365 
00366   if ( 0 != t )
00367   {
00368     while ( count > 0 && !ON_IsValid(*t) )
00369     {
00370       count--;
00371       t++;
00372     }
00373   }
00374 
00375   if ( count <= 0 || 0 == t )
00376   {
00377     // this may be increasing, decreasing, or empty
00378     if ( !IsEmptySet() )
00379     {
00380       mn = Min();
00381       mx = Max();
00382       if ( mn <= mx && ON_IsValid(mn) && ON_IsValid(mx) )
00383       {
00384         Set( mn, mx );
00385         rc = true;
00386       }
00387     }
00388   }
00389   else 
00390   {
00391     if ( IsEmptySet() ) 
00392     {
00393       a = *t++;
00394       Set( a, a );
00395       count--;
00396       rc = true;
00397     }
00398     mn = Min();
00399     mx = Max();
00400     while( count > 0 )
00401     {
00402       count--;
00403       a = *t++;
00404       if ( ON_IsValid(a) )
00405       {
00406         if ( a < mn )
00407           mn = a;
00408         else if ( a > mx )
00409           mx = a;
00410       }
00411     }
00412     if ( mn <= mx && ON_IsValid(mn) && ON_IsValid(mx) )
00413     {
00414       Set(mn,mx);
00415       rc = true;
00416     }
00417     else
00418       Destroy();
00419   }
00420   return rc;
00421 }
00422 
00423 bool ON_Interval::Union(
00424        double t
00425        )
00426 {
00427   return Union(1,&t);
00428 }
00429 
00431   // The union of an empty set and an increasing interval is the increasing
00432   // interval.  The union of two empty sets is empty. The union of an empty
00433   // set an a non-empty interval is the non-empty interval.
00434   // The union of two non-empty intervals is
00435 // union = [min(argA.Min(),argB.Min()), max(argA.Max(),argB.Max()),]
00436 // Union() returns true if the union is not empty.
00437 bool ON_Interval::Union( // this = union of two args
00438        const ON_Interval& ain, 
00439        const ON_Interval& bin
00440        )
00441 {
00442   bool rc = false;
00443   if ( bin.IsEmptySet() ) {
00444     // ain may be increasing, decreasing, or empty
00445     Set( ain.Min(), ain.Max() );
00446     rc = !IsEmptySet();
00447   }
00448   else if ( ain.IsEmptySet() ) {
00449     // bin may be increasing or decreasing
00450     Set( bin.Min(), bin.Max() );
00451     rc = true;
00452   }
00453   else {
00454     double a, b, mn, mx;
00455     a = ain.Min();
00456     b = bin.Min();
00457     mn = (a<=b) ? a : b;
00458     a = ain.Max();
00459     b = bin.Max();
00460     mx = (a>=b) ? a : b;
00461     if ( mn <= mx ) {
00462       Set(mn,mx);
00463       rc = true;
00464     }
00465     else
00466       Destroy();
00467   }
00468   return rc;
00469 }
00470 
00471 
00472 bool ON_3dVector::Decompose( // Computes a, b, c such that this vector = a*X + b*Y + c*Z
00473        //
00474        // If X,Y,Z is known to be an orthonormal frame,
00475        // then a = V*X, b = V*Y, c = V*Z will compute
00476        // the same result more quickly.
00477        const ON_3dVector& X,
00478        const ON_3dVector& Y,
00479        const ON_3dVector& Z,
00480        double* a,
00481        double* b,
00482        double* c
00483        ) const
00484 {
00485   int rank;
00486   double pivot_ratio = 0.0;
00487   double row0[3], row1[3], row2[3];
00488   row0[0] = X*X;   row0[1] = X*Y;   row0[2] = X*Z;
00489   row1[0] = row0[1]; row1[1] = Y*Y;   row1[2] = Y*Z;
00490   row2[0] = row0[2]; row2[1] = row1[2]; row2[2] = Z*Z;
00491   rank = ON_Solve3x3( row0, row1, row2, 
00492                     (*this)*X, (*this)*Y, (*this)*Z,
00493                     a, b, c, &pivot_ratio );
00494   return (rank == 3) ? true : false;
00495 }
00496 
00497 int ON_3dVector::IsParallelTo( 
00498       // returns  1: this and other vectors are and parallel
00499       //         -1: this and other vectors are anti-parallel
00500       //          0: this and other vectors are not parallel
00501       //             or at least one of the vectors is zero
00502       const ON_3dVector& v,
00503       double angle_tolerance // (default=ON_DEFAULT_ANGLE_TOLERANCE) radians
00504       ) const
00505 {
00506   int rc = 0;
00507   const double ll = Length()*v.Length();
00508   if ( ll > 0.0 ) {
00509     const double cos_angle = (x*v.x + y*v.y + z*v.z)/ll;
00510     const double cos_tol = cos(angle_tolerance);
00511     if ( cos_angle >= cos_tol )
00512       rc = 1;
00513     else if ( cos_angle <= -cos_tol )
00514       rc = -1;
00515   }
00516   return rc;
00517 }
00518 
00519 bool ON_3fVector::IsPerpendicularTo(
00520       // returns true:  this and other vectors are perpendicular
00521       //         false: this and other vectors are not perpendicular
00522       //                or at least one of the vectors is zero
00523       const ON_3fVector& v,
00524       double angle_tolerance // (default=ON_DEFAULT_ANGLE_TOLERANCE) radians
00525       ) const
00526 {
00527   ON_3dVector V(*this);
00528   return V.IsPerpendicularTo(ON_3dVector(v),angle_tolerance);
00529 }
00530 
00531 bool ON_3dVector::IsPerpendicularTo(
00532       // returns true:  this and other vectors are perpendicular
00533       //         false: this and other vectors are not perpendicular
00534       //                or at least one of the vectors is zero
00535       const ON_3dVector& v,
00536       double angle_tolerance // (default=ON_DEFAULT_ANGLE_TOLERANCE) radians
00537       ) const
00538 {
00539   bool rc = false;
00540   const double ll = Length()*v.Length();
00541   if ( ll > 0.0 ) {
00542     if ( fabs((x*v.x + y*v.y + z*v.z)/ll) <= sin(angle_tolerance) )
00543       rc = true;
00544   }
00545   return rc;
00546 }
00547 
00548 bool ON_3fVector::PerpendicularTo( const ON_3fVector& v )
00549 {
00550   ON_3dVector V(*this);
00551   return V.IsPerpendicularTo(ON_3dVector(v));
00552 }
00553 
00554 bool ON_3dVector::PerpendicularTo( const ON_3dVector& v )
00555 {
00556   //bool rc = false;
00557   int i, j, k; 
00558   double a, b;
00559   k = 2;
00560   if ( fabs(v.y) > fabs(v.x) ) {
00561     if ( fabs(v.z) > fabs(v.y) ) {
00562       // |v.z| > |v.y| > |v.x|
00563       i = 2;
00564       j = 1;
00565       k = 0;
00566       a = v.z;
00567       b = -v.y;
00568     }
00569     else if ( fabs(v.z) >= fabs(v.x) ){
00570       // |v.y| >= |v.z| >= |v.x|
00571       i = 1;
00572       j = 2;
00573       k = 0;
00574       a = v.y;
00575       b = -v.z;
00576     }
00577     else {
00578       // |v.y| > |v.x| > |v.z|
00579       i = 1;
00580       j = 0;
00581       k = 2;
00582       a = v.y;
00583       b = -v.x;
00584     }
00585   }
00586   else if ( fabs(v.z) > fabs(v.x) ) {
00587     // |v.z| > |v.x| >= |v.y|
00588     i = 2;
00589     j = 0;
00590     k = 1;
00591     a = v.z;
00592     b = -v.x;
00593   }
00594   else if ( fabs(v.z) > fabs(v.y) ) {
00595     // |v.x| >= |v.z| > |v.y|
00596     i = 0;
00597     j = 2;
00598     k = 1;
00599     a = v.x;
00600     b = -v.z;
00601   }
00602   else {
00603     // |v.x| >= |v.y| >= |v.z|
00604     i = 0;
00605     j = 1;
00606     k = 2;
00607     a = v.x;
00608     b = -v.y;
00609   }
00610   double* this_v = &x;
00611   this_v[i] = b;
00612   this_v[j] = a;
00613   this_v[k] = 0.0;
00614   return (a != 0.0) ? true : false;
00615 }
00616 
00617 bool
00618 ON_3dVector::PerpendicularTo( 
00619       const ON_3dPoint& P0, const ON_3dPoint& P1, const ON_3dPoint& P2
00620       )
00621 {
00622   // Find a the unit normal to a triangle defined by 3 points
00623   ON_3dVector V0, V1, V2, N0, N1, N2;
00624 
00625   Zero();
00626 
00627   V0 = P2 - P1;
00628   V1 = P0 - P2;
00629   V2 = P1 - P0;
00630 
00631   N0 = ON_CrossProduct( V1, V2 );
00632   if ( !N0.Unitize() )
00633     return false;
00634   N1 = ON_CrossProduct( V2, V0 );
00635   if ( !N1.Unitize() )
00636     return false;
00637   N2 = ON_CrossProduct( V0, V1 );
00638   if ( !N2.Unitize() )
00639     return false;
00640 
00641   const double s0 = 1.0/V0.Length();
00642   const double s1 = 1.0/V1.Length();
00643   const double s2 = 1.0/V2.Length();
00644 
00645   // choose normal with smallest total error
00646   const double e0 = s0*fabs(ON_DotProduct(N0,V0)) + s1*fabs(ON_DotProduct(N0,V1)) + s2*fabs(ON_DotProduct(N0,V2));
00647   const double e1 = s0*fabs(ON_DotProduct(N1,V0)) + s1*fabs(ON_DotProduct(N1,V1)) + s2*fabs(ON_DotProduct(N1,V2));
00648   const double e2 = s0*fabs(ON_DotProduct(N2,V0)) + s1*fabs(ON_DotProduct(N2,V1)) + s2*fabs(ON_DotProduct(N2,V2));
00649 
00650   if ( e0 <= e1 ) {
00651     if ( e0 <= e2 ) {
00652       *this = N0;
00653     }
00654     else {
00655       *this = N2;
00656     }
00657   }
00658   else if (e1 <= e2) {
00659     *this = N1;
00660   }
00661   else {
00662     *this = N2;
00663   }
00664   
00665   return true;
00666 }
00667 
00668 void ON_2dPoint::Transform( const ON_Xform& xform )
00669 {
00670   double xx,yy,ww;
00671   if ( xform.m_xform ) {
00672     ww = xform.m_xform[3][0]*x + xform.m_xform[3][1]*y + xform.m_xform[3][3];
00673     if ( ww != 0.0 )
00674       ww = 1.0/ww;
00675     xx = ww*(xform.m_xform[0][0]*x + xform.m_xform[0][1]*y + xform.m_xform[0][3]);
00676     yy = ww*(xform.m_xform[1][0]*x + xform.m_xform[1][1]*y + xform.m_xform[1][3]);
00677     x = xx;
00678     y = yy;
00679   }
00680 }
00681 
00682 void ON_3dPoint::Transform( const ON_Xform& xform )
00683 {
00684   double xx,yy,zz,ww;
00685   if ( xform.m_xform ) {
00686     ww = xform.m_xform[3][0]*x + xform.m_xform[3][1]*y + xform.m_xform[3][2]*z + xform.m_xform[3][3];
00687     if ( ww != 0.0 )
00688       ww = 1.0/ww;
00689     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]);
00690     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]);
00691     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]);
00692     x = xx;
00693     y = yy;
00694     z = zz;
00695   }
00696 }
00697 
00698 void ON_4dPoint::Transform( const ON_Xform& xform )
00699 {
00700   double xx,yy,zz,ww;
00701   if ( xform.m_xform ) {
00702     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;
00703     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;
00704     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;
00705     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;
00706     x = xx;
00707     y = yy;
00708     z = zz;
00709     w = ww;
00710   }
00711 }
00712 
00713 void ON_2fPoint::Transform( const ON_Xform& xform )
00714 {
00715   double xx,yy,ww;
00716   if ( xform.m_xform ) {
00717     ww = xform.m_xform[3][0]*x + xform.m_xform[3][1]*y + xform.m_xform[3][3];
00718     if ( ww != 0.0 )
00719       ww = 1.0/ww;
00720     xx = ww*(xform.m_xform[0][0]*x + xform.m_xform[0][1]*y + xform.m_xform[0][3]);
00721     yy = ww*(xform.m_xform[1][0]*x + xform.m_xform[1][1]*y + xform.m_xform[1][3]);
00722     x = (float)xx;
00723     y = (float)yy;
00724   }
00725 }
00726 
00727 void ON_2fPoint::Rotate( 
00728       double angle,               // angle in radians
00729       const ON_2fPoint& center  // center of rotation
00730       )
00731 {
00732   Rotate( sin(angle), cos(angle), center );
00733 }
00734 
00735 void ON_2fPoint::Rotate( 
00736       double sin_angle,           // sin(angle)
00737       double cos_angle,           // cos(angle)
00738       const ON_2fPoint& center  // center of rotation
00739       )
00740 {
00741   ON_Xform rot;
00742   rot.Rotation( sin_angle, cos_angle, ON_zaxis, ON_3dPoint(center) );
00743   Transform(rot);
00744 }
00745 
00746 void ON_3fPoint::Rotate( 
00747       double angle,               // angle in radians
00748       const ON_3fVector& axis,  // axis of rotation
00749       const ON_3fPoint& center  // center of rotation
00750       )
00751 {
00752   Rotate( sin(angle), cos(angle), axis, center );
00753 }
00754 
00755 void ON_3fPoint::Rotate( 
00756       double sin_angle,           // sin(angle)
00757       double cos_angle,           // cos(angle)
00758       const ON_3fVector& axis,  // axis of rotation
00759       const ON_3fPoint& center  // center of rotation
00760       )
00761 {
00762   ON_Xform rot;
00763   rot.Rotation( sin_angle, cos_angle, ON_3dVector(axis), ON_3dPoint(center) );
00764   Transform(rot);
00765 }
00766 
00767 void ON_3fPoint::Transform( const ON_Xform& xform )
00768 {
00769   double xx,yy,zz,ww;
00770   if ( xform.m_xform ) {
00771     ww = xform.m_xform[3][0]*x + xform.m_xform[3][1]*y + xform.m_xform[3][2]*z + xform.m_xform[3][3];
00772     if ( ww != 0.0 )
00773       ww = 1.0/ww;
00774     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]);
00775     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]);
00776     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]);
00777     x = (float)xx;
00778     y = (float)yy;
00779     z = (float)zz;
00780   }
00781 }
00782 
00783 void ON_4fPoint::Transform( const ON_Xform& xform )
00784 {
00785   double xx,yy,zz,ww;
00786   if ( xform.m_xform ) {
00787     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;
00788     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;
00789     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;
00790     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;
00791     x = (float)xx;
00792     y = (float)yy;
00793     z = (float)zz;
00794     w = (float)ww;
00795   }
00796 }
00797 
00798 double ON_3fPoint::Fuzz( 
00799           double absolute_tolerance // (default =  ON_ZERO_TOLERANCE) 
00800           ) const
00801 {
00802   double t = MaximumCoordinate()* ON_RELATIVE_TOLERANCE;
00803   return(t > absolute_tolerance) ? t : absolute_tolerance;
00804 }
00805 
00806 bool ON_4dPoint::Normalize()
00807 {
00808   bool rc = false;
00809   const int i = MaximumCoordinateIndex();
00810   double f[4];
00811   f[0] = fabs(x);
00812   f[1] = fabs(y);
00813   f[2] = fabs(z);
00814   f[3] = fabs(w);
00815   const double c = f[i];
00816   if ( c > 0.0 ) {
00817     double len = 1.0/c;
00818     f[0] *= len;
00819     f[1] *= len;
00820     f[2] *= len;
00821     f[3] *= len;
00822     f[i] = 1.0;
00823                 // GBA 7/1/04.  Fixed typo
00824     const double s = 1.0/( c*sqrt(f[0]*f[0] + f[1]*f[1] + f[2]*f[2] + f[3]*f[3]));
00825     x *= s;
00826     y *= s;
00827     z *= s;
00828     w *= s;
00829     rc = true;
00830   }
00831   return rc;
00832 }
00833 
00834 bool ON_4fPoint::Normalize()
00835 {
00836   bool rc = false;
00837   const int i = MaximumCoordinateIndex();
00838   double f[4];
00839   f[0] = fabs(x);
00840   f[1] = fabs(y);
00841   f[2] = fabs(z);
00842   f[3] = fabs(w);
00843   const double c = f[i];
00844   if ( c > 0.0 ) {
00845     double len = 1.0/c;
00846     f[0] *= len;
00847     f[1] *= len;
00848     f[2] *= len;
00849     f[3] *= len;
00850     f[i] = 1.0;
00851                 // GBA 7/1/04.  Fixed typo
00852     const double s = 1.0/(c*sqrt(f[0]*f[0] + f[1]*f[1] + f[2]*f[2] + f[3]*f[3]));
00853     x = (float)(s*x);
00854     y = (float)(s*y);
00855     z = (float)(s*z);
00856     w = (float)(s*w);
00857     rc = true;
00858   }
00859   return rc;
00860 }
00861 
00862 bool ON_2fVector::Decompose( // Computes a, b such that this vector = a*X + b*Y
00863        //
00864        // If X,Y is known to be an orthonormal frame,
00865        // then a = V*X, b = V*Y will compute
00866        // the same result more quickly.
00867        const ON_2fVector& X,
00868        const ON_2fVector& Y,
00869        double* a,
00870        double* b
00871        ) const
00872 {
00873   ON_2dVector V(*this);
00874   return V.Decompose(ON_2dVector(X),ON_2dVector(Y),a,b);
00875 }
00876 
00877 
00878 bool ON_2dVector::Decompose( // Computes a, b such that this vector = a*X + b*Y
00879        //
00880        // If X,Y is known to be an orthonormal frame,
00881        // then a = V*X, b = V*Y will compute
00882        // the same result more quickly.
00883        const ON_2dVector& X,
00884        const ON_2dVector& Y,
00885        double* a,
00886        double* b
00887        ) const
00888 {
00889   int rank;
00890   double pivot_ratio = 0.0;
00891   double XoY = X*Y;
00892   rank = ON_Solve2x2( X*X, XoY, Y*Y, XoY,
00893                     (*this)*X, (*this)*Y, 
00894                     a, b, &pivot_ratio );
00895   return (rank == 2) ? true : false;
00896 }
00897 
00898 
00899 int ON_2fVector::IsParallelTo( 
00900       // returns  1: this and other vectors are and parallel
00901       //         -1: this and other vectors are anti-parallel
00902       //          0: this and other vectors are not parallel
00903       //             or at least one of the vectors is zero
00904       const ON_2fVector& v,
00905       double angle_tolerance // (default=ON_DEFAULT_ANGLE_TOLERANCE) radians
00906       ) const
00907 {
00908   ON_2dVector V(*this);
00909   return V.IsParallelTo(ON_2dVector(v),angle_tolerance);
00910 }
00911 
00912 int ON_2dVector::IsParallelTo( 
00913       // returns  1: this and other vectors are and parallel
00914       //         -1: this and other vectors are anti-parallel
00915       //          0: this and other vectors are not parallel
00916       //             or at least one of the vectors is zero
00917       const ON_2dVector& v,
00918       double angle_tolerance // (default=ON_DEFAULT_ANGLE_TOLERANCE) radians
00919       ) const
00920 {
00921   int rc = 0;
00922   const double ll = Length()*v.Length();
00923   if ( ll > 0.0 ) {
00924     const double cos_angle = (x*v.x + y*v.y)/ll;
00925     const double cos_tol = cos(angle_tolerance);
00926     if ( cos_angle >= cos_tol )
00927       rc = 1;
00928     else if ( cos_angle <= -cos_tol )
00929       rc = -1;
00930   }
00931   return rc;
00932 }
00933 
00934 
00935 bool ON_2fVector::IsPerpendicularTo(
00936       // returns true:  this and other vectors are perpendicular
00937       //         false: this and other vectors are not perpendicular
00938       //                or at least one of the vectors is zero
00939       const ON_2fVector& v,
00940       double angle_tolerance // (default=ON_DEFAULT_ANGLE_TOLERANCE) radians
00941       ) const
00942 {
00943   ON_2dVector V(*this);
00944   return V.IsPerpendicularTo(ON_2dVector(v),angle_tolerance);
00945 }
00946 
00947 bool ON_2dVector::IsPerpendicularTo(
00948       // returns true:  this and other vectors are perpendicular
00949       //         false: this and other vectors are not perpendicular
00950       //                or at least one of the vectors is zero
00951       const ON_2dVector& v,
00952       double angle_tolerance // (default=ON_DEFAULT_ANGLE_TOLERANCE) radians
00953       ) const
00954 {
00955   bool rc = false;
00956   const double ll = Length()*v.Length();
00957   if ( ll > 0.0 ) {
00958     if ( fabs((x*v.x + y*v.y)/ll) <= sin(angle_tolerance) )
00959       rc = true;
00960   }
00961   return rc;
00962 }
00963 
00964 void ON_2dVector::Transform( const ON_Xform& xform )
00965 {
00966   double xx,yy;
00967   xx = xform.m_xform[0][0]*x + xform.m_xform[0][1]*y;
00968   yy = xform.m_xform[1][0]*x + xform.m_xform[1][1]*y;
00969   x = xx;
00970   y = yy;
00971 }
00972 
00973 void ON_3fVector::Transform( const ON_Xform& xform )
00974 {
00975   const double dx = x;
00976   const double dy = y;
00977   const double dz = z;
00978   double xx = xform.m_xform[0][0]*dx + xform.m_xform[0][1]*dy + xform.m_xform[0][2]*dz;
00979   double yy = xform.m_xform[1][0]*dx + xform.m_xform[1][1]*dy + xform.m_xform[1][2]*dz;
00980   double zz = xform.m_xform[2][0]*dx + xform.m_xform[2][1]*dy + xform.m_xform[2][2]*dz;
00981   x = (float)xx;
00982   y = (float)yy;
00983   z = (float)zz;
00984 }
00985 
00986 void ON_3dVector::Transform( const ON_Xform& xform )
00987 {
00988   double xx,yy,zz;
00989   xx = xform.m_xform[0][0]*x + xform.m_xform[0][1]*y + xform.m_xform[0][2]*z;
00990   yy = xform.m_xform[1][0]*x + xform.m_xform[1][1]*y + xform.m_xform[1][2]*z;
00991   zz = xform.m_xform[2][0]*x + xform.m_xform[2][1]*y + xform.m_xform[2][2]*z;
00992   x = xx;
00993   y = yy;
00994   z = zz;
00995 }
00996 
00997 void ON_3dPoint::Rotate( 
00998       double angle,               // angle in radians
00999       const ON_3dVector& axis,  // axis of rotation
01000       const ON_3dPoint& center  // center of rotation
01001       )
01002 {
01003   Rotate( sin(angle), cos(angle), axis, center );
01004 }
01005 
01006 void ON_3dPoint::Rotate( 
01007       double sin_angle,           // sin(angle)
01008       double cos_angle,           // cos(angle)
01009       const ON_3dVector& axis,  // axis of rotation
01010       const ON_3dPoint& center  // center of rotation
01011       )
01012 {
01013   ON_Xform rot;
01014   rot.Rotation( sin_angle, cos_angle, axis, center );
01015   Transform(rot);
01016 }
01017 
01018 void ON_2dPoint::Rotate( 
01019       double angle,               // angle in radians
01020       const ON_2dPoint& center  // center of rotation
01021       )
01022 {
01023   Rotate( sin(angle), cos(angle), center );
01024 }
01025 
01026 void ON_2dPoint::Rotate( 
01027       double sin_angle,           // sin(angle)
01028       double cos_angle,           // cos(angle)
01029       const ON_2dPoint& center  // center of rotation
01030       )
01031 {
01032   ON_Xform rot;
01033   rot.Rotation( sin_angle, cos_angle, ON_zaxis, center );
01034   Transform(rot);
01035 }
01036 
01037 void ON_2dVector::Rotate( 
01038       double angle // angle in radians
01039       )
01040 {
01041   Rotate( sin(angle), cos(angle) );
01042 }
01043 
01044 void ON_2dVector::Rotate( 
01045       double sin_angle, // sin(angle)
01046       double cos_angle  // cos(angle)
01047       )
01048 {
01049   ON_Xform rot;
01050   rot.Rotation( sin_angle, cos_angle, ON_zaxis, ON_origin );
01051   Transform(rot);
01052 }
01053 
01054 bool ON_IsOrthogonalFrame( const ON_2dVector& X,  const ON_2dVector& Y )
01055 {
01056   // returns true if X, Y, Z is an orthogonal frame
01057   double lx = X.Length();
01058   double ly = Y.Length();
01059   if ( lx <=  ON_SQRT_EPSILON )
01060     return false;
01061   if ( ly <=  ON_SQRT_EPSILON )
01062     return false;
01063   lx = 1.0/lx;
01064   ly = 1.0/ly;
01065   double x = ON_DotProduct( X, Y )*lx*ly;
01066   if ( fabs(x) >  ON_SQRT_EPSILON )
01067     return false;
01068   return true;
01069 }
01070 
01071 bool ON_IsOrthonormalFrame( const ON_2dVector& X,  const ON_2dVector& Y )
01072 {
01073   // returns true if X, Y, Z is an orthonormal frame
01074   if ( !ON_IsOrthogonalFrame( X, Y ) )
01075     return false;
01076   double x = X.Length();
01077   if ( fabs(x-1.0) >  ON_SQRT_EPSILON )
01078     return false;
01079   x = Y.Length();
01080   if ( fabs(x-1.0) >  ON_SQRT_EPSILON )
01081     return false;
01082 
01083   return true;
01084 }
01085 
01086 bool ON_IsRightHandFrame( const ON_2dVector& X,  const ON_2dVector& Y )
01087 {
01088   // returns true if X, Y, Z is an orthonormal right hand frame
01089   if ( !ON_IsOrthonormalFrame(X,Y) )
01090     return false;
01091   double x = ON_DotProduct( ON_CrossProduct( X, Y ), ON_zaxis );
01092   if ( x <=  ON_SQRT_EPSILON )
01093     return false;
01094   return true;
01095 }
01096 void ON_3fVector::Rotate( 
01097       double angle,              // angle in radians
01098       const ON_3fVector& axis   // axis of rotation
01099       )
01100 {
01101   Rotate( sin(angle), cos(angle), axis );
01102 }
01103 
01104 void ON_3fVector::Rotate( 
01105       double sin_angle,        // sin(angle)
01106       double cos_angle,        // cos(angle)
01107       const ON_3fVector& axis  // axis of rotation
01108       )
01109 {
01110   //bool rc = false;
01111   ON_Xform rot;
01112   rot.Rotation( sin_angle, cos_angle, ON_3dVector(axis), ON_origin );
01113   Transform(rot);
01114 }
01115 
01116 void ON_3dVector::Rotate( 
01117       double angle,              // angle in radians
01118       const ON_3dVector& axis   // axis of rotation
01119       )
01120 {
01121   Rotate( sin(angle), cos(angle), axis );
01122 }
01123 
01124 void ON_3dVector::Rotate( 
01125       double sin_angle,        // sin(angle)
01126       double cos_angle,        // cos(angle)
01127       const ON_3dVector& axis  // axis of rotation
01128       )
01129 {
01130   //bool rc = false;
01131   ON_Xform rot;
01132   rot.Rotation( sin_angle, cos_angle, axis, ON_origin );
01133   Transform(rot);
01134 }
01135 
01136 bool ON_IsOrthogonalFrame( const ON_3dVector& X,  const ON_3dVector& Y,  const ON_3dVector& Z )
01137 {
01138   // returns true if X, Y, Z is an orthogonal frame
01139   if (! X.IsValid() || !Y.IsValid() || !Z.IsValid() )
01140     return false;
01141 
01142   double lx = X.Length();
01143   double ly = Y.Length();
01144   double lz = Z.Length();
01145   if ( lx <=  ON_SQRT_EPSILON )
01146     return false;
01147   if ( ly <=  ON_SQRT_EPSILON )
01148     return false;
01149   if ( lz <=  ON_SQRT_EPSILON )
01150     return false;
01151   lx = 1.0/lx;
01152   ly = 1.0/ly;
01153   lz = 1.0/lz;
01154   double xy = (X.x*Y.x + X.y*Y.y + X.z*Y.z)*lx*ly;
01155   double yz = (Y.x*Z.x + Y.y*Z.y + Y.z*Z.z)*ly*lz;
01156   double zx = (Z.x*X.x + Z.y*X.y + Z.z*X.z)*lz*lx;
01157   if (    fabs(xy) > ON_SQRT_EPSILON 
01158        || fabs(yz) > ON_SQRT_EPSILON
01159        || fabs(zx) > ON_SQRT_EPSILON
01160      )
01161   {
01162     double t = 0.0000152587890625;
01163     if ( fabs(xy) >= t || fabs(yz)  >= t || fabs(zx) >= t )
01164       return false;
01165 
01166     // do a more careful (and time consuming check)
01167     // This fixes RR 22219 and 22276
01168     ON_3dVector V;
01169     V = (lx*ly)*ON_CrossProduct(X,Y);
01170     t = fabs((V.x*Z.x + V.y*Z.y + V.z*Z.z)*lz);
01171     if ( fabs(t-1.0) > ON_SQRT_EPSILON )
01172       return false;
01173 
01174     V = (ly*lz)*ON_CrossProduct(Y,Z);
01175     t = fabs((V.x*X.x + V.y*X.y + V.z*X.z)*lx);
01176     if ( fabs(t-1.0) > ON_SQRT_EPSILON )
01177       return false;
01178 
01179     V = (lz*lx)*ON_CrossProduct(Z,X);
01180     t = fabs((V.x*Y.x + V.y*Y.y + V.z*Y.z)*ly);
01181     if ( fabs(t-1.0) > ON_SQRT_EPSILON )
01182       return false;
01183   }
01184   return true;
01185 }
01186 
01187 bool ON_IsOrthonormalFrame( const ON_3dVector& X,  const ON_3dVector& Y,  const ON_3dVector& Z )
01188 {
01189   // returns true if X, Y, Z is an orthonormal frame
01190   if ( !ON_IsOrthogonalFrame( X, Y, Z ) )
01191     return false;
01192   double x = X.Length();
01193   if ( fabs(x-1.0) >  ON_SQRT_EPSILON )
01194     return false;
01195   x = Y.Length();
01196   if ( fabs(x-1.0) >  ON_SQRT_EPSILON )
01197     return false;
01198   x = Z.Length();
01199   if ( fabs(x-1.0) >  ON_SQRT_EPSILON )
01200     return false;
01201 
01202   return true;
01203 }
01204 
01205 bool ON_IsRightHandFrame( const ON_3dVector& X,  const ON_3dVector& Y,  const ON_3dVector& Z )
01206 {
01207   // returns true if X, Y, Z is an orthonormal right hand frame
01208   if ( !ON_IsOrthonormalFrame(X,Y,Z) )
01209     return false;
01210   double x = ON_DotProduct( ON_CrossProduct( X, Y ), Z );
01211   if ( x <=  ON_SQRT_EPSILON )
01212     return false;
01213   return true;
01214 }
01215 
01216 ON_2dPoint ON_2dPoint::operator*( const ON_Xform& xform ) const
01217 {
01218   const double px = x; // optimizer should put px,py in registers
01219   const double py = y;
01220   double hx[2], w;
01221   const double* m = &xform.m_xform[0][0];
01222   hx[0] = m[0]*px + m[4]*py + m[12];
01223   hx[1] = m[1]*px + m[5]*py + m[13];
01224   w     = m[3]*px + m[7]*py + m[15];
01225   w = (w != 0.0) ? 1.0/w : 1.0;
01226   return ON_2dPoint( w*hx[0], w*hx[1] );
01227 }
01228 
01229 ON_3dPoint ON_3dPoint::operator*( const ON_Xform& xform ) const
01230 {
01231   const double px = x; // optimizer should put px,py,pz in registers
01232   const double py = y;
01233   const double pz = z;
01234   double hx[3], w;
01235   const double* m = &xform.m_xform[0][0];
01236   hx[0] = m[0]*px + m[4]*py + m[ 8]*pz + m[12];
01237   hx[1] = m[1]*px + m[5]*py + m[ 9]*pz + m[13];
01238   hx[2] = m[2]*px + m[6]*py + m[10]*pz + m[14];
01239   w     = m[3]*px + m[7]*py + m[11]*pz + m[15];
01240   w = (w != 0.0) ? 1.0/w : 1.0;
01241   return ON_3dPoint( w*hx[0], w*hx[1], w*hx[2] );
01242 }
01243 
01244 double ON_3dPoint::Fuzz( 
01245           double absolute_tolerance // (default =  ON_ZERO_TOLERANCE) 
01246           ) const
01247 {
01248   double t = MaximumCoordinate()* ON_RELATIVE_TOLERANCE;
01249   return(t > absolute_tolerance) ? t : absolute_tolerance;
01250 }
01251 
01252 ON_4dPoint ON_4dPoint::operator*( const ON_Xform& xform ) const
01253 {
01254   const double px = x; // optimizer should put x,y,z,w in registers
01255   const double py = y;
01256   const double pz = z;
01257   const double pw = w;
01258   double hx[4];
01259   const double* m = &xform.m_xform[0][0];
01260   hx[0] = m[0]*px + m[4]*py + m[ 8]*pz + m[12]*pw;
01261   hx[1] = m[1]*px + m[5]*py + m[ 9]*pz + m[13]*pw;
01262   hx[2] = m[2]*px + m[6]*py + m[10]*pz + m[14]*pw;
01263   hx[3] = m[3]*px + m[7]*py + m[11]*pz + m[15]*pw;
01264 
01265   return ON_4dPoint( hx[0],hx[1],hx[2],hx[3] );
01266 }
01267 
01268 ON_2dVector ON_2dVector::operator*( const ON_Xform& xform ) const
01269 {
01270   const double vx = x; // optimizer should put vx,vy in registers
01271   const double vy = y;
01272   double hx[2];
01273   const double* m = &xform.m_xform[0][0];
01274   hx[0] = m[0]*vx + m[4]*vy;
01275   hx[1] = m[1]*vx + m[5]*vy;
01276   return ON_2dVector( hx[0],hx[1] );
01277 }
01278 
01279 ON_3dVector ON_3dVector::operator*( const ON_Xform& xform ) const
01280 {
01281   const double vx = x; // optimizer should put vx,vy,vz in registers
01282   const double vy = y;
01283   const double vz = z;
01284   double hx[3];
01285   const double* m = &xform.m_xform[0][0];
01286   hx[0] = m[0]*vx + m[4]*vy + m[ 8]*vz;
01287   hx[1] = m[1]*vx + m[5]*vy + m[ 9]*vz;
01288   hx[2] = m[2]*vx + m[6]*vy + m[10]*vz;
01289   return ON_3dVector( hx[0],hx[1],hx[2] );
01290 }
01291 
01292 double ON_3fVector::Fuzz(
01293           double absolute_tolerance // (default =  ON_ZERO_TOLERANCE) 
01294           ) const
01295 {
01296   double t = MaximumCoordinate()* ON_RELATIVE_TOLERANCE;
01297   return(t > absolute_tolerance) ? t : absolute_tolerance;
01298 }
01299 
01300 
01301 double ON_3dVector::Fuzz(
01302           double absolute_tolerance // (default =  ON_ZERO_TOLERANCE) 
01303           ) const
01304 {
01305   double t = MaximumCoordinate()* ON_RELATIVE_TOLERANCE;
01306   return(t > absolute_tolerance) ? t : absolute_tolerance;
01307 }
01308 
01309 const ON_2dPoint ON_2dPoint::Origin(0.0,0.0);
01310 const ON_2dPoint ON_2dPoint::UnsetPoint(ON_UNSET_VALUE,ON_UNSET_VALUE);
01311 
01312 const ON_3dPoint ON_3dPoint::Origin(0.0,0.0,0.0);
01313 const ON_3dPoint ON_3dPoint::UnsetPoint(ON_UNSET_VALUE,ON_UNSET_VALUE,ON_UNSET_VALUE);
01314 
01315 const ON_2dVector ON_2dVector::ZeroVector(0.0,0.0);
01316 const ON_2dVector ON_2dVector::XAxis(1.0,0.0);
01317 const ON_2dVector ON_2dVector::YAxis(0.0,1.0);
01318 const ON_2dVector ON_2dVector::UnsetVector(ON_UNSET_VALUE,ON_UNSET_VALUE);
01319 
01320 const ON_3dVector ON_3dVector::ZeroVector(0.0,0.0,0.0);
01321 const ON_3dVector ON_3dVector::XAxis(1.0,0.0,0.0);
01322 const ON_3dVector ON_3dVector::YAxis(0.0,1.0,0.0);
01323 const ON_3dVector ON_3dVector::ZAxis(0.0,0.0,1.0);
01324 const ON_3dVector ON_3dVector::UnsetVector(ON_UNSET_VALUE,ON_UNSET_VALUE,ON_UNSET_VALUE);
01325 
01326 const ON_2fPoint ON_2fPoint::Origin(0.0f,0.0f);
01327 const ON_3fPoint ON_3fPoint::Origin(0.0f,0.0f,0.0f);
01328 
01329 const ON_2fVector ON_2fVector::ZeroVector(0.0f,0.0f);
01330 const ON_2fVector ON_2fVector::XAxis(1.0f,0.0f);
01331 const ON_2fVector ON_2fVector::YAxis(0.0f,1.0f);
01332 
01333 const ON_3fVector ON_3fVector::ZeroVector(0.0f,0.0f,0.0f);
01334 const ON_3fVector ON_3fVector::XAxis(1.0f,0.0f,0.0f);
01335 const ON_3fVector ON_3fVector::YAxis(0.0f,1.0f,0.0f);
01336 const ON_3fVector ON_3fVector::ZAxis(0.0f,0.0f,1.0f);
01337 
01338 // OBSOLETE  - use ON_3dPoint::UnsetPoint
01339 const ON_3dPoint  ON_UNSET_POINT(ON_UNSET_VALUE, ON_UNSET_VALUE, ON_UNSET_VALUE);
01340 
01341 // OBSOLETE  - use ON_3dVector::UnsetVector
01342 const ON_3dVector ON_UNSET_VECTOR(ON_UNSET_VALUE, ON_UNSET_VALUE, ON_UNSET_VALUE);
01343 
01344 // OBSOLETE  - use ON_3dPoint::Origin
01345 const ON_3dPoint  ON_origin(0.0, 0.0,0.0);
01346 
01347 // OBSOLETE  - use ON_3dVector::XAxis
01348 const ON_3dVector ON_xaxis(1.0, 0.0, 0.0);
01349 
01350 // OBSOLETE  - use ON_3dVector::YAxis
01351 const ON_3dVector ON_yaxis(0.0, 1.0, 0.0);
01352 
01353 // OBSOLETE  - use ON_3dVector::ZAxis
01354 const ON_3dVector ON_zaxis(0.0, 0.0, 1.0);
01355 
01356 // OBSOLETE  - use ON_3fPoint::Origin
01357 const ON_3fPoint  ON_forigin(0.0f, 0.0f, 0.0f);
01358 
01359 // OBSOLETE  - use ON_3fVector::XAxis
01360 const ON_3fVector ON_fxaxis(1.0f, 0.0f, 0.0f);
01361 
01362 // OBSOLETE  - use ON_3fVector::YAxis
01363 const ON_3fVector ON_fyaxis(0.0f, 1.0f, 0.0f);
01364 
01365 // OBSOLETE  - use ON_3fVector::ZAxis
01366 const ON_3fVector ON_fzaxis(0.0f, 0.0f, 1.0f);
01367 
01368 
01372 
01374 //
01375 // ON_2fPoint
01376 //
01377 
01378 ON_2fPoint::ON_2fPoint()
01379 {}
01380 
01381 ON_2fPoint::ON_2fPoint( const double* p )
01382 {
01383   if (p) {
01384     x = (float)p[0]; y = (float)p[1];
01385   }
01386   else {
01387     x = y = 0.0;
01388   }
01389 }
01390 
01391 ON_2fPoint::ON_2fPoint( const float* p )
01392 {
01393   if (p) {
01394     x = p[0]; y = p[1];
01395   }
01396   else {
01397     x = y = 0.0;
01398   }
01399 }
01400 
01401 ON_2fPoint::ON_2fPoint(float xx,float yy)
01402 {x=xx;y=yy;}
01403 
01404 ON_2fPoint::ON_2fPoint(const ON_3fPoint& p)
01405 {x=p.x;y=p.y;}
01406 
01407 ON_2fPoint::ON_2fPoint(const ON_4fPoint& h)
01408 {
01409   const float w = (h.w != 1.0f && h.w != 0.0f) ? 1.0f/h.w : 1.0f;
01410   x = w*h.x;
01411   y = w*h.y;
01412 }
01413 
01414 ON_2fPoint::ON_2fPoint(const ON_2fVector& v)
01415 {x=v.x;y=v.y;}
01416 
01417 ON_2fPoint::ON_2fPoint(const ON_3fVector& v)
01418 {x=v.x;y=v.y;}
01419 
01420 ON_2fPoint::ON_2fPoint(const ON_2dPoint& p)
01421 {x=(float)p.x;y=(float)p.y;}
01422 
01423 ON_2fPoint::ON_2fPoint(const ON_3dPoint& p)
01424 {x=(float)p.x;y=(float)p.y;}
01425 
01426 ON_2fPoint::ON_2fPoint(const ON_4dPoint& h)
01427 {
01428   const double w = (h.w != 1.0 && h.w != 0.0) ? 1.0/h.w : 1.0;
01429   x = (float)(w*h.x);
01430   y = (float)(w*h.y);
01431 }
01432 
01433 ON_2fPoint::ON_2fPoint(const ON_2dVector& v)
01434 {x=(float)v.x;y=(float)v.y;}
01435 
01436 ON_2fPoint::ON_2fPoint(const ON_3dVector& v)
01437 {x=(float)v.x;y=(float)v.y;}
01438 
01439 
01440 ON_2fPoint::operator float*()
01441 {
01442   return &x;
01443 }
01444 
01445 ON_2fPoint::operator const float*() const
01446 {
01447   return &x;
01448 }
01449 
01450 ON_2fPoint& ON_2fPoint::operator=(const double* p)
01451 {
01452   if ( p ) {
01453     x = (float)p[0];
01454     y = (float)p[1];
01455   }
01456   else {
01457     x = y = 0.0;
01458   }
01459   return *this;
01460 }
01461 
01462 ON_2fPoint& ON_2fPoint::operator=(const float* p)
01463 {
01464   if ( p ) {
01465     x = p[0];
01466     y = p[1];
01467   }
01468   else {
01469     x = y = 0.0;
01470   }
01471   return *this;
01472 }
01473 
01474 ON_2fPoint& ON_2fPoint::operator=(const ON_3fPoint& p)
01475 {
01476   x = p.x;
01477   y = p.y;
01478   return *this;
01479 }
01480 
01481 ON_2fPoint& ON_2fPoint::operator=(const ON_4fPoint& h)
01482 {
01483   const float w = (h.w != 1.0f && h.w != 0.0f) ? 1.0f/h.w : 1.0f;
01484   x = w*h.x;
01485   y = w*h.y;
01486   return *this;
01487 }
01488 
01489 ON_2fPoint& ON_2fPoint::operator=(const ON_2fVector& v)
01490 {
01491   x = v.x;
01492   y = v.y;
01493   return *this;
01494 }
01495 
01496 ON_2fPoint& ON_2fPoint::operator=(const ON_3fVector& v)
01497 {
01498   x = v.x;
01499   y = v.y;
01500   return *this;
01501 }
01502 
01503 ON_2fPoint& ON_2fPoint::operator=(const ON_2dPoint& p)
01504 {
01505   x = (float)p.x;
01506   y = (float)p.y;
01507   return *this;
01508 }
01509 
01510 ON_2fPoint& ON_2fPoint::operator=(const ON_3dPoint& p)
01511 {
01512   x = (float)p.x;
01513   y = (float)p.y;
01514   return *this;
01515 }
01516 
01517 ON_2fPoint& ON_2fPoint::operator=(const ON_4dPoint& h)
01518 {
01519   const double w = (h.w != 1.0 && h.w != 0.0) ? 1.0/h.w : 1.0;
01520   x = (float)(w*h.x);
01521   y = (float)(w*h.y);
01522   return *this;
01523 }
01524 
01525 ON_2fPoint& ON_2fPoint::operator=(const ON_2dVector& v)
01526 {
01527   x = (float)v.x;
01528   y = (float)v.y;
01529   return *this;
01530 }
01531 
01532 ON_2fPoint& ON_2fPoint::operator=(const ON_3dVector& v)
01533 {
01534   x = (float)v.x;
01535   y = (float)v.y;
01536   return *this;
01537 }
01538 
01539 ON_2fPoint& ON_2fPoint::operator*=(float d)
01540 {
01541   x *= d;
01542   y *= d;
01543   return *this;
01544 }
01545 
01546 ON_2fPoint& ON_2fPoint::operator/=(float d)
01547 {
01548   const float one_over_d = 1.0f/d;
01549   x *= one_over_d;
01550   y *= one_over_d;
01551   return *this;
01552 }
01553 
01554 ON_2fPoint& ON_2fPoint::operator+=(const ON_2fPoint& p)
01555 {
01556   x += p.x;
01557   y += p.y;
01558   return *this;
01559 }
01560 
01561 ON_2fPoint& ON_2fPoint::operator+=(const ON_2fVector& v)
01562 {
01563   x += v.x;
01564   y += v.y;
01565   return *this;
01566 }
01567 
01568 ON_2fPoint& ON_2fPoint::operator+=(const ON_3fVector& v)
01569 {
01570   x += v.x;
01571   y += v.y;
01572   return *this;
01573 }
01574 
01575 ON_2fPoint& ON_2fPoint::operator-=(const ON_2fPoint& p)
01576 {
01577   x -= p.x;
01578   y -= p.y;
01579   return *this;
01580 }
01581 
01582 ON_2fPoint& ON_2fPoint::operator-=(const ON_2fVector& v)
01583 {
01584   x -= v.x;
01585   y -= v.y;
01586   return *this;
01587 }
01588 
01589 ON_2fPoint& ON_2fPoint::operator-=(const ON_3fVector& v)
01590 {
01591   x -= v.x;
01592   y -= v.y;
01593   return *this;
01594 }
01595 
01596 ON_2fPoint ON_2fPoint::operator*( int d ) const
01597 {
01598   return ON_2fPoint(x*d,y*d);
01599 }
01600 
01601 ON_2fPoint ON_2fPoint::operator*( float d ) const
01602 {
01603   return ON_2fPoint(x*d,y*d);
01604 }
01605 
01606 ON_2dPoint ON_2fPoint::operator*( double d ) const
01607 {
01608   return ON_2dPoint(x*d,y*d);
01609 }
01610 
01611 ON_2fPoint ON_2fPoint::operator/( int i ) const
01612 {
01613   const float one_over_d = 1.0f/((float)i);
01614   return ON_2fPoint(x*one_over_d,y*one_over_d);
01615 }
01616 
01617 ON_2fPoint ON_2fPoint::operator/( float d ) const
01618 {
01619   const float one_over_d = 1.0f/d;
01620   return ON_2fPoint(x*one_over_d,y*one_over_d);
01621 }
01622 
01623 ON_2dPoint ON_2fPoint::operator/( double d ) const
01624 {
01625   const double one_over_d = 1.0/d;
01626   return ON_2dPoint(x*one_over_d,y*one_over_d);
01627 }
01628 
01629 ON_2fPoint ON_2fPoint::operator+( const ON_2fPoint& p ) const
01630 {
01631   return ON_2fPoint(x+p.x,y+p.y);
01632 }
01633 
01634 ON_2fPoint ON_2fPoint::operator+( const ON_2fVector& v ) const
01635 {
01636   return ON_2fPoint(x+v.x,y+v.y);
01637 }
01638 
01639 ON_2fVector ON_2fPoint::operator-( const ON_2fPoint& p ) const
01640 {
01641   return ON_2fVector(x-p.x,y-p.y);
01642 }
01643 
01644 ON_2fPoint ON_2fPoint::operator-( const ON_2fVector& v ) const
01645 {
01646   return ON_2fPoint(x-v.x,y-v.y);
01647 }
01648 
01649 ON_3fPoint ON_2fPoint::operator+( const ON_3fPoint& p ) const
01650 {
01651   return ON_3fPoint(x+p.x,y+p.y,p.z);
01652 }
01653 
01654 ON_3fPoint ON_2fPoint::operator+( const ON_3fVector& v ) const
01655 {
01656   return ON_3fPoint(x+v.x,y+v.y,v.z);
01657 }
01658 
01659 ON_3fVector ON_2fPoint::operator-( const ON_3fPoint& p ) const
01660 {
01661   return ON_3fVector(x-p.x,y-p.y,-p.y);
01662 }
01663 
01664 ON_3fPoint ON_2fPoint::operator-( const ON_3fVector& v ) const
01665 {
01666   return ON_3fPoint(x-v.x,y-v.y,-v.z);
01667 }
01668 
01669 ON_2dPoint ON_2fPoint::operator+( const ON_2dPoint& p ) const
01670 {
01671   return ON_2dPoint(x+p.x,y+p.y);
01672 }
01673 
01674 ON_2dPoint ON_2fPoint::operator+( const ON_2dVector& v ) const
01675 {
01676   return ON_2dPoint(x+v.x,y+v.y);
01677 }
01678 
01679 ON_2dVector ON_2fPoint::operator-( const ON_2dPoint& p ) const
01680 {
01681   return ON_2dVector(x-p.x,y-p.y);
01682 }
01683 
01684 ON_2dPoint ON_2fPoint::operator-( const ON_2dVector& v ) const
01685 {
01686   return ON_2dPoint(x-v.x,y-v.y);
01687 }
01688 
01689 ON_3dPoint ON_2fPoint::operator+( const ON_3dPoint& p ) const
01690 {
01691   return ON_3dPoint(x+p.x,y+p.y,p.z);
01692 }
01693 
01694 ON_3dPoint ON_2fPoint::operator+( const ON_3dVector& v ) const
01695 {
01696   return ON_3dPoint(x+v.x,y+v.y,v.z);
01697 }
01698 
01699 ON_3dVector ON_2fPoint::operator-( const ON_3dPoint& p ) const
01700 {
01701   return ON_3dVector(x-p.x,y-p.y,-p.y);
01702 }
01703 
01704 ON_3dPoint ON_2fPoint::operator-( const ON_3dVector& v ) const
01705 {
01706   return ON_3dPoint(x-v.x,y-v.y,-v.z);
01707 }
01708 
01709 
01710 float ON_2fPoint::operator*(const ON_2fPoint& h) const
01711 {
01712   return x*h.x + y*h.y;
01713 }
01714 
01715 float ON_2fPoint::operator*(const ON_2fVector& h) const
01716 {
01717   return x*h.x + y*h.y;
01718 }
01719 
01720 float ON_2fPoint::operator*(const ON_4fPoint& h) const
01721 {
01722   return x*h.x + y*h.y + h.w;
01723 }
01724 
01725 bool ON_2fPoint::operator==( const ON_2fPoint& p ) const
01726 {
01727   return (x==p.x&&y==p.y)?true:false;
01728 }
01729 
01730 bool ON_2fPoint::operator!=( const ON_2fPoint& p ) const
01731 {
01732   return (x!=p.x||y!=p.y)?true:false;
01733 }
01734 
01735 bool ON_2fPoint::operator<=( const ON_2fPoint& p ) const
01736 {
01737   // dictionary order
01738   return ( (x<p.x) ? true : ((x==p.x&&y<=p.y)?true:false) );
01739 }
01740 
01741 bool ON_2fPoint::operator>=( const ON_2fPoint& p ) const
01742 {
01743   // dictionary order
01744   return ( (x>p.x) ? true : ((x==p.x&&y>=p.y)?true:false) );
01745 }
01746 
01747 bool ON_2fPoint::operator<( const ON_2fPoint& p ) const
01748 {
01749   // dictionary order
01750   return ( (x<p.x) ? true : ((x==p.x&&y<p.y)?true:false) );
01751 }
01752 
01753 bool ON_2fPoint::operator>( const ON_2fPoint& p ) const
01754 {
01755   // dictionary order
01756   return ( (x>p.x) ? true : ((x==p.x&&y>p.y)?true:false) );
01757 }
01758 
01759 float ON_2fPoint::operator[](int i) const
01760 {
01761   return (i<=0) ? x : y;
01762 }
01763 
01764 float& ON_2fPoint::operator[](int i)
01765 {
01766   float* pd = (i<=0)? &x : &y;
01767   return *pd;
01768 }
01769 
01770 float ON_2fPoint::operator[](unsigned int i) const
01771 {
01772   return (i<=0) ? x : y;
01773 }
01774 
01775 float& ON_2fPoint::operator[](unsigned int i)
01776 {
01777   float* pd = (i<=0)? &x : &y;
01778   return *pd;
01779 }
01780 
01781 double ON_2fPoint::DistanceTo( const ON_2fPoint& p ) const
01782 {
01783   return ON_Length2d(p.x-x,p.y-y);
01784 }
01785 
01786 int ON_2fPoint::MaximumCoordinateIndex() const
01787 {
01788   return (fabs(y)>fabs(x)) ? 1 : 0;
01789 }
01790 
01791 double ON_2fPoint::MaximumCoordinate() const
01792 {
01793   double c = fabs(x); if (fabs(y)>c) c=fabs(y);
01794   return c;
01795 }
01796 
01797 void ON_2fPoint::Zero()
01798 {
01799   x = y = 0.0;
01800 }
01801 
01802 ON_2fPoint operator*(int d, const ON_2fPoint& p)
01803 {
01804   return ON_2fPoint(d*p.x,d*p.y);
01805 }
01806 
01807 ON_2fPoint operator*(float d, const ON_2fPoint& p)
01808 {
01809   return ON_2fPoint(d*p.x,d*p.y);
01810 }
01811 
01812 ON_2dPoint operator*(double d, const ON_2fPoint& p)
01813 {
01814   return ON_2dPoint(d*p.x,d*p.y);
01815 }
01816 
01818 //
01819 // ON_3fPoint
01820 //
01821 
01822 ON_3fPoint::ON_3fPoint()
01823 {}
01824 
01825 ON_3fPoint::ON_3fPoint( const double* p )
01826 {
01827   if (p) {
01828     x = (float)p[0]; y = (float)p[1]; z = (float)p[2];
01829   }
01830   else {
01831     x = y = z = 0.0;
01832   }
01833 }
01834 
01835 ON_3fPoint::ON_3fPoint( const float* p )
01836 {
01837   if (p) {
01838     x = p[0]; y = p[1]; z = p[2];
01839   }
01840   else {
01841     x = y = z = 0.0;
01842   }
01843 }
01844 
01845 ON_3fPoint::ON_3fPoint(float xx,float yy,float zz)
01846 {x=xx;y=yy;z=zz;}
01847 
01848 ON_3fPoint::ON_3fPoint(const ON_2fPoint& p)
01849 {x=p.x;y=p.y;z=0.0;}
01850 
01851 ON_3fPoint::ON_3fPoint(const ON_4fPoint& p)
01852 {
01853   const double w = (p.w != 1.0f && p.w != 0.0f) ? 1.0/((double)p.w) : 1.0;
01854   x = (float)(w*p.x);
01855   y = (float)(w*p.y);
01856   z = (float)(w*p.z);
01857 }
01858 
01859 ON_3fPoint::ON_3fPoint(const ON_2fVector& v)
01860 {x=v.x;y=v.y;z=0.0f;}
01861 
01862 ON_3fPoint::ON_3fPoint(const ON_3fVector& v)
01863 {x=v.x;y=v.y;z=v.z;}
01864 
01865 ON_3fPoint::ON_3fPoint(const ON_2dPoint& p)
01866 {x=(float)p.x;y=(float)p.y;z=0.0;}
01867 
01868 ON_3fPoint::ON_3fPoint(const ON_3dPoint& p)
01869 {x=(float)p.x;y=(float)p.y;z=(float)p.z;}
01870 
01871 ON_3fPoint::ON_3fPoint(const ON_4dPoint& p)
01872 {
01873   const double w = (p.w != 1.0 && p.w != 0.0) ? 1.0/p.w : 1.0;
01874   x = (float)(w*p.x);
01875   y = (float)(w*p.y);
01876   z = (float)(w*p.z);
01877 }
01878 
01879 ON_3fPoint::ON_3fPoint(const ON_2dVector& v)
01880 {x=(float)v.x;y=(float)v.y;z=0.0f;}
01881 
01882 ON_3fPoint::ON_3fPoint(const ON_3dVector& v)
01883 {x=(float)v.x;y=(float)v.y;z=(float)v.z;}
01884 
01885 ON_3fPoint::operator float*()
01886 {
01887   return &x;
01888 }
01889 
01890 ON_3fPoint::operator const float*() const
01891 {
01892   return &x;
01893 }
01894 
01895 ON_3fPoint& ON_3fPoint::operator=(const double* p)
01896 {
01897   if ( p ) {
01898     x = (float)p[0];
01899     y = (float)p[1];
01900     z = (float)p[2];
01901   }
01902   else {
01903     x = y = z = 0.0;
01904   }
01905   return *this;
01906 }
01907 
01908 ON_3fPoint& ON_3fPoint::operator=(const float* p)
01909 {
01910   if ( p ) {
01911     x = p[0];
01912     y = p[1];
01913     z = p[2];
01914   }
01915   else {
01916     x = y = z = 0.0;
01917   }
01918   return *this;
01919 }
01920 
01921 ON_3fPoint& ON_3fPoint::operator=(const ON_2fPoint& p)
01922 {
01923   x = p.x;
01924   y = p.y;
01925   z = 0.0;
01926   return *this;
01927 }
01928 
01929 ON_3fPoint& ON_3fPoint::operator=(const ON_4fPoint& p)
01930 {
01931   const float w = (p.w != 1.0f && p.w != 0.0f) ? 1.0f/p.w : 1.0f;
01932   x = w*p.x;
01933   y = w*p.y;
01934   z = w*p.z;
01935   return *this;
01936 }
01937 
01938 ON_3fPoint& ON_3fPoint::operator=(const ON_2fVector& v)
01939 {
01940   x = v.x;
01941   y = v.y;
01942   z = 0.0f;
01943   return *this;
01944 }
01945 
01946 ON_3fPoint& ON_3fPoint::operator=(const ON_3fVector& v)
01947 {
01948   x = v.x;
01949   y = v.y;
01950   z = v.z;
01951   return *this;
01952 }
01953 
01954 ON_3fPoint& ON_3fPoint::operator=(const ON_2dPoint& p)
01955 {
01956   x = (float)p.x;
01957   y = (float)p.y;
01958   z = 0.0f;
01959   return *this;
01960 }
01961 
01962 ON_3fPoint& ON_3fPoint::operator=(const ON_3dPoint& p)
01963 {
01964   x = (float)p.x;
01965   y = (float)p.y;
01966   z = (float)p.z;
01967   return *this;
01968 }
01969 
01970 ON_3fPoint& ON_3fPoint::operator=(const ON_4dPoint& p)
01971 {
01972   const double w = (p.w != 1.0 && p.w != 0.0) ? 1.0/p.w : 1.0;
01973   x = (float)(w*p.x);
01974   y = (float)(w*p.y);
01975   z = (float)(w*p.z);
01976   return *this;
01977 }
01978 
01979 ON_3fPoint& ON_3fPoint::operator=(const ON_2dVector& v)
01980 {
01981   x = (float)v.x;
01982   y = (float)v.y;
01983   z = 0.0f;
01984   return *this;
01985 }
01986 
01987 ON_3fPoint& ON_3fPoint::operator=(const ON_3dVector& v)
01988 {
01989   x = (float)v.x;
01990   y = (float)v.y;
01991   z = (float)v.z;
01992   return *this;
01993 }
01994 
01995 ON_3fPoint& ON_3fPoint::operator*=(float d)
01996 {
01997   x *= d;
01998   y *= d;
01999   z *= d;
02000   return *this;
02001 }
02002 
02003 ON_3fPoint& ON_3fPoint::operator/=(float d)
02004 {
02005   const float one_over_d = 1.0f/d;
02006   x *= one_over_d;
02007   y *= one_over_d;
02008   z *= one_over_d;
02009   return *this;
02010 }
02011 
02012 ON_3fPoint& ON_3fPoint::operator+=(const ON_3fPoint& p)
02013 {
02014   x += p.x;
02015   y += p.y;
02016   z += p.z;
02017   return *this;
02018 }
02019 
02020 ON_3fPoint& ON_3fPoint::operator+=(const ON_3fVector& v)
02021 {
02022   x += v.x;
02023   y += v.y;
02024   z += v.z;
02025   return *this;
02026 }
02027 
02028 ON_3fPoint& ON_3fPoint::operator-=(const ON_3fPoint& p)
02029 {
02030   x -= p.x;
02031   y -= p.y;
02032   z -= p.z;
02033   return *this;
02034 }
02035 
02036 ON_3fPoint& ON_3fPoint::operator-=(const ON_3fVector& v)
02037 {
02038   x -= v.x;
02039   y -= v.y;
02040   z -= v.z;
02041   return *this;
02042 }
02043 
02044 ON_3fPoint ON_3fPoint::operator*( int d ) const
02045 {
02046   return ON_3fPoint(x*d,y*d,z*d);
02047 }
02048 
02049 ON_3fPoint ON_3fPoint::operator*( float d ) const
02050 {
02051   return ON_3fPoint(x*d,y*d,z*d);
02052 }
02053 
02054 ON_3dPoint ON_3fPoint::operator*( double d ) const
02055 {
02056   return ON_3dPoint(x*d,y*d,z*d);
02057 }
02058 
02059 ON_3fPoint ON_3fPoint::operator/( int d ) const
02060 {
02061   const float one_over_d = 1.0f/((float)d);
02062   return ON_3fPoint(x*one_over_d,y*one_over_d,z*one_over_d);
02063 }
02064 
02065 ON_3fPoint ON_3fPoint::operator/( float d ) const
02066 {
02067   const float one_over_d = 1.0f/d;
02068   return ON_3fPoint(x*one_over_d,y*one_over_d,z*one_over_d);
02069 }
02070 
02071 ON_3dPoint ON_3fPoint::operator/( double d ) const
02072 {
02073   const double one_over_d = 1.0/d;
02074   return ON_3dPoint(x*one_over_d,y*one_over_d,z*one_over_d);
02075 }
02076 
02077 ON_3fPoint ON_3fPoint::operator+( const ON_3fPoint& p ) const
02078 {
02079   return ON_3fPoint(x+p.x,y+p.y,z+p.z);
02080 }
02081 
02082 ON_3fPoint ON_3fPoint::operator+( const ON_3fVector& v ) const
02083 {
02084   return ON_3fPoint(x+v.x,y+v.y,z+v.z);
02085 }
02086 
02087 ON_3fVector ON_3fPoint::operator-( const ON_3fPoint& p ) const
02088 {
02089   return ON_3fVector(x-p.x,y-p.y,z-p.z);
02090 }
02091 
02092 ON_3fPoint ON_3fPoint::operator-( const ON_3fVector& v ) const
02093 {
02094   return ON_3fPoint(x-v.x,y-v.y,z-v.z);
02095 }
02096 
02097 
02098 ON_3fPoint ON_3fPoint::operator+( const ON_2fPoint& p ) const
02099 {
02100   return ON_3fPoint(x+p.x,y+p.y,z);
02101 }
02102 
02103 ON_3fPoint ON_3fPoint::operator+( const ON_2fVector& v ) const
02104 {
02105   return ON_3fPoint(x+v.x,y+v.y,z);
02106 }
02107 
02108 ON_3fVector ON_3fPoint::operator-( const ON_2fPoint& p ) const
02109 {
02110   return ON_3fVector(x-p.x,y-p.y,z);
02111 }
02112 
02113 ON_3fPoint ON_3fPoint::operator-( const ON_2fVector& v ) const
02114 {
02115   return ON_3fPoint(x-v.x,y-v.y,z);
02116 }
02117 
02118 ON_3dPoint ON_3fPoint::operator+( const ON_3dPoint& p ) const
02119 {
02120   return ON_3dPoint(x+p.x,y+p.y,z+p.z);
02121 }
02122 
02123 ON_3dPoint ON_3fPoint::operator+( const ON_3dVector& v ) const
02124 {
02125   return ON_3dPoint(x+v.x,y+v.y,z+v.z);
02126 }
02127 
02128 ON_3dVector ON_3fPoint::operator-( const ON_3dPoint& p ) const
02129 {
02130   return ON_3dVector(x-p.x,y-p.y,z-p.z);
02131 }
02132 
02133 ON_3dPoint ON_3fPoint::operator-( const ON_3dVector& v ) const
02134 {
02135   return ON_3dPoint(x-v.x,y-v.y,z-v.z);
02136 }
02137 
02138 
02139 ON_3dPoint ON_3fPoint::operator+( const ON_2dPoint& p ) const
02140 {
02141   return ON_3dPoint(x+p.x,y+p.y,z);
02142 }
02143 
02144 ON_3dPoint ON_3fPoint::operator+( const ON_2dVector& v ) const
02145 {
02146   return ON_3dPoint(x+v.x,y+v.y,z);
02147 }
02148 
02149 ON_3dVector ON_3fPoint::operator-( const ON_2dPoint& p ) const
02150 {
02151   return ON_3dVector(x-p.x,y-p.y,z);
02152 }
02153 
02154 ON_3dPoint ON_3fPoint::operator-( const ON_2dVector& v ) const
02155 {
02156   return ON_3dPoint(x-v.x,y-v.y,z);
02157 }
02158 
02159 
02160 float ON_3fPoint::operator*(const ON_3fPoint& h) const
02161 {
02162   return x*h.x + y*h.y + z*h.z;
02163 }
02164 
02165 float ON_3fPoint::operator*(const ON_3fVector& h) const
02166 {
02167   return x*h.x + y*h.y + z*h.z;
02168 }
02169 
02170 float ON_3fPoint::operator*(const ON_4fPoint& h) const
02171 {
02172   return x*h.x + y*h.y + z*h.z + h.w;
02173 }
02174 
02175 bool ON_3fPoint::operator==( const ON_3fPoint& p ) const
02176 {
02177   return (x==p.x&&y==p.y&&z==p.z)?true:false;
02178 }
02179 
02180 bool ON_3fPoint::operator!=( const ON_3fPoint& p ) const
02181 {
02182   return (x!=p.x||y!=p.y||z!=p.z)?true:false;
02183 }
02184 
02185 bool ON_3fPoint::operator<=( const ON_3fPoint& p ) const
02186 {
02187   // dictionary order
02188   return ((x<p.x)?true:((x==p.x)?((y<p.y)?true:(y==p.y&&z<=p.z)?true:false):false));
02189 }
02190 
02191 bool ON_3fPoint::operator>=( const ON_3fPoint& p ) const
02192 {
02193   // dictionary order
02194   return ((x>p.x)?true:((x==p.x)?((y>p.y)?true:(y==p.y&&z>=p.z)?true:false):false));
02195 }
02196 
02197 bool ON_3fPoint::operator<( const ON_3fPoint& p ) const
02198 {
02199   // dictionary order
02200   return ((x<p.x)?true:((x==p.x)?((y<p.y)?true:(y==p.y&&z<p.z)?true:false):false));
02201 }
02202 
02203 bool ON_3fPoint::operator>( const ON_3fPoint& p ) const
02204 {
02205   // dictionary order
02206   return ((x>p.x)?true:((x==p.x)?((y>p.y)?true:(y==p.y&&z>p.z)?true:false):false));
02207 }
02208 
02209 float ON_3fPoint::operator[](int i) const
02210 {
02211   return ( (i<=0)?x:((i>=2)?z:y) );
02212 }
02213 
02214 float& ON_3fPoint::operator[](int i)
02215 {
02216   float* pd = (i<=0)? &x : ( (i>=2) ?  &z : &y);
02217   return *pd;
02218 }
02219 
02220 float ON_3fPoint::operator[](unsigned int i) const
02221 {
02222   return ( (i<=0)?x:((i>=2)?z:y) );
02223 }
02224 
02225 float& ON_3fPoint::operator[](unsigned int i)
02226 {
02227   float* pd = (i<=0)? &x : ( (i>=2) ?  &z : &y);
02228   return *pd;
02229 }
02230 
02231 double ON_3fPoint::DistanceTo( const ON_3fPoint& p ) const
02232 {
02233   return ON_Length3d(p.x-x,p.y-y,p.z-z);
02234 }
02235 
02236 int ON_3fPoint::MaximumCoordinateIndex() const
02237 {
02238   return (fabs(y)>fabs(x)) ? ((fabs(z)>fabs(y))?2:1) : ((fabs(z)>fabs(x))?2:0);
02239 }
02240 
02241 double ON_3fPoint::MaximumCoordinate() const
02242 {
02243   double c = fabs(x); if (fabs(y)>c) c=fabs(y); if (fabs(z)>c) c=fabs(z);
02244   return c;
02245 }
02246 
02247 void ON_3fPoint::Zero()
02248 {
02249   x = y = z = 0.0;
02250 }
02251 
02252 ON_3fPoint operator*(int d, const ON_3fPoint& p)
02253 {
02254   return ON_3fPoint(d*p.x,d*p.y,d*p.z);
02255 }
02256 
02257 ON_3fPoint operator*(float d, const ON_3fPoint& p)
02258 {
02259   return ON_3fPoint(d*p.x,d*p.y,d*p.z);
02260 }
02261 
02262 ON_3dPoint operator*(double d, const ON_3fPoint& p)
02263 {
02264   return ON_3dPoint(d*p.x,d*p.y,d*p.z);
02265 }
02266 
02268 //
02269 // ON_4fPoint
02270 //
02271 
02272 ON_4fPoint::ON_4fPoint()
02273 {}
02274 
02275 ON_4fPoint::ON_4fPoint( const double* p )
02276 {
02277   if (p) {
02278     x = (float)p[0]; y = (float)p[1]; z = (float)p[2]; w = (float)p[3];
02279   }
02280   else {
02281     x = y = z = 0.0; w = 1.0;
02282   }
02283 }
02284 
02285 ON_4fPoint::ON_4fPoint( const float* p )
02286 {
02287   if (p) {
02288     x = p[0]; y = p[1]; z = p[2]; w = p[3];
02289   }
02290   else {
02291     x = y = z = 0.0; w = 1.0;
02292   }
02293 }
02294 
02295 ON_4fPoint::ON_4fPoint(float xx,float yy,float zz,float ww)
02296 {x=xx;y=yy;z=zz;w=ww;}
02297 
02298 ON_4fPoint::ON_4fPoint(const ON_2fPoint& p)
02299 {x=p.x;y=p.y;z=0.0;w=1.0;}
02300 
02301 ON_4fPoint::ON_4fPoint(const ON_3fPoint& p)
02302 {
02303   x=p.x;y=p.y;z=p.z;w=1.0;
02304 }
02305 
02306 ON_4fPoint::ON_4fPoint(const ON_2fVector& v)
02307 {x=v.x;y=v.y;z=w=0.0;}
02308 
02309 ON_4fPoint::ON_4fPoint(const ON_3fVector& v)
02310 {x=v.x;y=v.y;z=v.z;w=0.0;}
02311 
02312 ON_4fPoint::ON_4fPoint(const ON_2dPoint& p)
02313 {x=(float)p.x;y=(float)p.y;z=0.0f;w=1.0f;}
02314 
02315 ON_4fPoint::ON_4fPoint(const ON_3dPoint& p)
02316 {
02317   x=(float)p.x;y=(float)p.y;z=(float)p.z;w=1.0f;
02318 }
02319 
02320 ON_4fPoint::ON_4fPoint(const ON_4dPoint& p)
02321 {
02322   x=(float)p.x;y=(float)p.y;z=(float)p.z;w=(float)p.w;
02323 }
02324 
02325 ON_4fPoint::ON_4fPoint(const ON_2dVector& v)
02326 {x=(float)v.x;y=(float)v.y;z=w=0.0f;}
02327 
02328 ON_4fPoint::ON_4fPoint(const ON_3dVector& v)
02329 {x=(float)v.x;y=(float)v.y;z=(float)v.z;w=0.0f;}
02330 
02331 ON_4fPoint::operator float*()
02332 {
02333   return &x;
02334 }
02335 
02336 ON_4fPoint::operator const float*() const
02337 {
02338   return &x;
02339 }
02340 
02341 ON_4fPoint& ON_4fPoint::operator=(const double* p)
02342 {
02343   if ( p ) {
02344     x = (float)p[0];
02345     y = (float)p[1];
02346     z = (float)p[2];
02347     w = (float)p[3];
02348   }
02349   else {
02350     x = y = z = 0.0; w = 1.0;
02351   }
02352   return *this;
02353 }
02354 
02355 ON_4fPoint& ON_4fPoint::operator=(const float* p)
02356 {
02357   if ( p ) {
02358     x = p[0];
02359     y = p[1];
02360     z = p[2];
02361     w = p[3];
02362   }
02363   else {
02364     x = y = z = 0.0; w = 1.0;
02365   }
02366   return *this;
02367 }
02368 
02369 ON_4fPoint& ON_4fPoint::operator=(const ON_2fPoint& p)
02370 {
02371   x = p.x;
02372   y = p.y;
02373   z = 0.0;
02374   w = 1.0;
02375   return *this;
02376 }
02377 
02378 ON_4fPoint& ON_4fPoint::operator=(const ON_3fPoint& p)
02379 {
02380   x = p.x;
02381   y = p.y;
02382   z = p.z;
02383   w = 1.0;
02384   return *this;
02385 }
02386 
02387 ON_4fPoint& ON_4fPoint::operator=(const ON_2fVector& v)
02388 {
02389   x = v.x;
02390   y = v.y;
02391   z = 0.0;
02392   w = 0.0;
02393   return *this;
02394 }
02395 
02396 ON_4fPoint& ON_4fPoint::operator=(const ON_3fVector& v)
02397 {
02398   x = v.x;
02399   y = v.y;
02400   z = v.z;
02401   w = 0.0;
02402   return *this;
02403 }
02404 
02405 ON_4fPoint& ON_4fPoint::operator=(const ON_2dPoint& p)
02406 {
02407   x = (float)p.x;
02408   y = (float)p.y;
02409   z = 0.0;
02410   w = 1.0;
02411   return *this;
02412 }
02413 
02414 ON_4fPoint& ON_4fPoint::operator=(const ON_3dPoint& p)
02415 {
02416   x = (float)p.x;
02417   y = (float)p.y;
02418   z = (float)p.z;
02419   w = 1.0;
02420   return *this;
02421 }
02422 
02423 ON_4fPoint& ON_4fPoint::operator=(const ON_4dPoint& p)
02424 {
02425   x = (float)p.x;
02426   y = (float)p.y;
02427   z = (float)p.z;
02428   w = (float)p.w;
02429   return *this;
02430 }
02431 
02432 ON_4fPoint& ON_4fPoint::operator=(const ON_2dVector& v)
02433 {
02434   x = (float)v.x;
02435   y = (float)v.y;
02436   z = 0.0;
02437   w = 0.0;
02438   return *this;
02439 }
02440 
02441 ON_4fPoint& ON_4fPoint::operator=(const ON_3dVector& v)
02442 {
02443   x = (float)v.x;
02444   y = (float)v.y;
02445   z = (float)v.z;
02446   w = 0.0;
02447   return *this;
02448 }
02449 
02450 ON_4fPoint& ON_4fPoint::operator*=(float d)
02451 {
02452   x *= d;
02453   y *= d;
02454   z *= d;
02455   w *= d;
02456   return *this;
02457 }
02458 
02459 ON_4fPoint& ON_4fPoint::operator/=(float d)
02460 {
02461   const float one_over_d = 1.0f/d;
02462   x *= one_over_d;
02463   y *= one_over_d;
02464   z *= one_over_d;
02465   w *= one_over_d;
02466   return *this;
02467 }
02468 
02469 ON_4fPoint& ON_4fPoint::operator+=(const ON_4fPoint& p)
02470 {
02471   // sum w = sqrt(w1*w2)
02472   if ( p.w == w ) {
02473     x += p.x;
02474     y += p.y;
02475     z += p.z;
02476   }
02477   else if (p.w == 0.0 ) {
02478     x += p.x;
02479     y += p.y;
02480     z += p.z;
02481   }
02482   else if ( w == 0.0 ) {
02483     x += p.x;
02484     y += p.y;
02485     z += p.z;
02486     w = p.w;
02487   }
02488   else {
02489     const double sw1 = (w>0.0) ? sqrt(w) : -sqrt(-w);
02490     const double sw2 = (p.w>0.0) ? sqrt(p.w) : -sqrt(-p.w);
02491     const double s1 = sw2/sw1;
02492     const double s2 = sw1/sw2;
02493     x = (float)(x*s1 + p.x*s2);
02494     y = (float)(y*s1 + p.y*s2);
02495     z = (float)(z*s1 + p.z*s2);
02496     w = (float)(sw1*sw2);
02497   }
02498   return *this;
02499 }
02500 
02501 ON_4fPoint& ON_4fPoint::operator-=(const ON_4fPoint& p)
02502 {
02503   // difference w = sqrt(w1*w2)
02504   if ( p.w == w ) {
02505     x -= p.x;
02506     y -= p.y;
02507     z -= p.z;
02508   }
02509   else if (p.w == 0.0 ) {
02510     x -= p.x;
02511     y -= p.y;
02512     z -= p.z;
02513   }
02514   else if ( w == 0.0 ) {
02515     x -= p.x;
02516     y -= p.y;
02517     z -= p.z;
02518     w = p.w;
02519   }
02520   else {
02521     const double sw1 = (w>0.0) ? sqrt(w) : -sqrt(-w);
02522     const double sw2 = (p.w>0.0) ? sqrt(p.w) : -sqrt(-p.w);
02523     const double s1 = sw2/sw1;
02524     const double s2 = sw1/sw2;
02525     x = (float)(x*s1 - p.x*s2);
02526     y = (float)(y*s1 - p.y*s2);
02527     z = (float)(z*s1 - p.z*s2);
02528     w = (float)(sw1*sw2);
02529   }
02530   return *this;
02531 }
02532 
02533 ON_4fPoint ON_4fPoint::operator+( const ON_4fPoint& p ) const
02534 {
02535   ON_4fPoint q(x,y,z,w);
02536   q+=p;
02537   return q;
02538 }
02539 
02540 ON_4fPoint ON_4fPoint::operator-( const ON_4fPoint& p ) const
02541 {
02542   ON_4fPoint q(x,y,z,w);
02543   q-=p;
02544   return q;
02545 }
02546 
02547 
02548 ON_4fPoint ON_4fPoint::operator*( float d ) const
02549 {
02550   return ON_4fPoint(x*d,y*d,z*d,w*d);
02551 }
02552 
02553 ON_4fPoint ON_4fPoint::operator/( float d ) const
02554 {
02555   const float one_over_d = 1.0f/d;
02556   return ON_4fPoint(x*one_over_d,y*one_over_d,z*one_over_d,w*one_over_d);
02557 }
02558 
02559 float ON_4fPoint::operator*(const ON_4fPoint& h) const
02560 {
02561   return x*h.x + y*h.y + z*h.z + w*h.w;
02562 }
02563 
02564 bool ON_4fPoint::operator==( ON_4fPoint p ) const
02565 {
02566   ON_4fPoint a = *this; a.Normalize(); p.Normalize();
02567   if ( fabs(a.x-p.x) >  ON_SQRT_EPSILON ) return false;
02568   if ( fabs(a.y-p.y) >  ON_SQRT_EPSILON ) return false;
02569   if ( fabs(a.z-p.z) >  ON_SQRT_EPSILON ) return false;
02570   if ( fabs(a.w-p.w) >  ON_SQRT_EPSILON ) return false;
02571   return true;
02572 }
02573 
02574 bool ON_4fPoint::operator!=( const ON_4fPoint& p ) const
02575 {
02576   return (*this == p)?false:true;
02577 }
02578 
02579 float ON_4fPoint::operator[](int i) const
02580 {
02581   return ((i<=0)?x:((i>=3)?w:((i==1)?y:z)));
02582 }
02583 
02584 float& ON_4fPoint::operator[](int i)
02585 {
02586   float* pd = (i<=0) ? &x : ( (i>=3) ? &w : (i==1)?&y:&z);
02587   return *pd;
02588 }
02589 
02590 float ON_4fPoint::operator[](unsigned int i) const
02591 {
02592   return ((i<=0)?x:((i>=3)?w:((i==1)?y:z)));
02593 }
02594 
02595 float& ON_4fPoint::operator[](unsigned int i)
02596 {
02597   float* pd = (i<=0) ? &x : ( (i>=3) ? &w : (i==1)?&y:&z);
02598   return *pd;
02599 }
02600 
02601 int ON_4fPoint::MaximumCoordinateIndex() const
02602 {
02603   const float* a = &x;
02604   int i = ( fabs(y) > fabs(x) ) ? 1 : 0;
02605   if (fabs(z) > fabs(a[i])) i = 2; if (fabs(w) > fabs(a[i])) i = 3;
02606   return i;
02607 }
02608 
02609 double ON_4fPoint::MaximumCoordinate() const
02610 {
02611   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);
02612   return c;
02613 }
02614 
02615 void ON_4fPoint::Zero()
02616 {
02617   x = y = z = w = 0.0;
02618 }
02619 
02620 ON_4fPoint operator*( float d, const ON_4fPoint& p )
02621 {
02622   return ON_4fPoint( d*p.x, d*p.y, d*p.z, d*p.w );
02623 }
02624 
02625 ON_4dPoint operator*( double d, const ON_4fPoint& p )
02626 {
02627   return ON_4dPoint( d*p.x, d*p.y, d*p.z, d*p.w );
02628 }
02629 
02631 //
02632 // ON_2fVector
02633 //
02634 
02635 // static
02636 const ON_2fVector& ON_2fVector::UnitVector(int index)
02637 {
02638   static ON_2fVector o(0.0,0.0);
02639   static ON_2fVector x(1.0,0.0);
02640   static ON_2fVector y(0.0,1.0);
02641   switch(index)
02642   {
02643   case 0:
02644     return x;
02645   case 1:
02646     return y;
02647   }
02648   return o;
02649 }
02650 
02651 ON_2fVector::ON_2fVector()
02652 {}
02653 
02654 ON_2fVector::ON_2fVector( const double* v )
02655 {
02656   if (v) {
02657     x = (float)v[0]; y = (float)v[1];
02658   }
02659   else {
02660     x = y = 0.0;
02661   }
02662 }
02663 
02664 ON_2fVector::ON_2fVector( const float* v )
02665 {
02666   if (v) {
02667     x = v[0]; y = v[1];
02668   }
02669   else {
02670     x = y = 0.0;
02671   }
02672 }
02673 
02674 ON_2fVector::ON_2fVector(float xx,float yy)
02675 {x=xx;y=yy;}
02676 
02677 ON_2fVector::ON_2fVector(const ON_3fVector& v)
02678 {x=v.x;y=v.y;}
02679 
02680 ON_2fVector::ON_2fVector(const ON_2fPoint& p)
02681 {x=p.x;y=p.y;}
02682 
02683 ON_2fVector::ON_2fVector(const ON_3fPoint& p)
02684 {x=p.x;y=p.y;}
02685 
02686 ON_2fVector::ON_2fVector(const ON_2dVector& v)
02687 {x=(float)v.x;y=(float)v.y;}
02688 
02689 ON_2fVector::ON_2fVector(const ON_3dVector& v)
02690 {x=(float)v.x;y=(float)v.y;}
02691 
02692 ON_2fVector::ON_2fVector(const ON_2dPoint& p)
02693 {x=(float)p.x;y=(float)p.y;}
02694 
02695 ON_2fVector::ON_2fVector(const ON_3dPoint& p)
02696 {x=(float)p.x;y=(float)p.y;}
02697 
02698 ON_2fVector::operator float*()
02699 {
02700   return &x;
02701 }
02702 
02703 ON_2fVector::operator const float*() const
02704 {
02705   return &x;
02706 }
02707 
02708 ON_2fVector& ON_2fVector::operator=(const double* v)
02709 {
02710   if ( v ) {
02711     x = (float)v[0];
02712     y = (float)v[1];
02713   }
02714   else {
02715     x = y = 0.0;
02716   }
02717   return *this;
02718 }
02719 
02720 ON_2fVector& ON_2fVector::operator=(const float* v)
02721 {
02722   if ( v ) {
02723     x = v[0];
02724     y = v[1];
02725   }
02726   else {
02727     x = y = 0.0;
02728   }
02729   return *this;
02730 }
02731 
02732 ON_2fVector& ON_2fVector::operator=(const ON_3fVector& v)
02733 {
02734   x = v.x;
02735   y = v.y;
02736   return *this;
02737 }
02738 
02739 ON_2fVector& ON_2fVector::operator=(const ON_2fPoint& p)
02740 {
02741   x = p.x;
02742   y = p.y;
02743   return *this;
02744 }
02745 
02746 ON_2fVector& ON_2fVector::operator=(const ON_3fPoint& p)
02747 {
02748   x = p.x;
02749   y = p.y;
02750   return *this;
02751 }
02752 
02753 
02754 ON_2fVector& ON_2fVector::operator=(const ON_2dVector& v)
02755 {
02756   x = (float)v.x;
02757   y = (float)v.y;
02758   return *this;
02759 }
02760 
02761 ON_2fVector& ON_2fVector::operator=(const ON_3dVector& v)
02762 {
02763   x = (float)v.x;
02764   y = (float)v.y;
02765   return *this;
02766 }
02767 
02768 ON_2fVector& ON_2fVector::operator=(const ON_2dPoint& p)
02769 {
02770   x = (float)p.x;
02771   y = (float)p.y;
02772   return *this;
02773 }
02774 
02775 ON_2fVector& ON_2fVector::operator=(const ON_3dPoint& p)
02776 {
02777   x = (float)p.x;
02778   y = (float)p.y;
02779   return *this;
02780 }
02781 
02782 ON_2fVector ON_2fVector::operator-() const
02783 {
02784   return ON_2fVector(-x,-y);
02785 }
02786 
02787 ON_2fVector& ON_2fVector::operator*=(float d)
02788 {
02789   x *= d;
02790   y *= d;
02791   return *this;
02792 }
02793 
02794 ON_2fVector& ON_2fVector::operator/=(float d)
02795 {
02796   const float one_over_d = 1.0f/d;
02797   x *= one_over_d;
02798   y *= one_over_d;
02799   return *this;
02800 }
02801 
02802 ON_2fVector& ON_2fVector::operator+=(const ON_2fVector& v)
02803 {
02804   x += v.x;
02805   y += v.y;
02806   return *this;
02807 }
02808 
02809 ON_2fVector& ON_2fVector::operator-=(const ON_2fVector& v)
02810 {
02811   x -= v.x;
02812   y -= v.y;
02813   return *this;
02814 }
02815 
02816 ON_2fVector ON_2fVector::operator*( int d ) const
02817 {
02818   return ON_2fVector(x*d,y*d);
02819 }
02820 
02821 ON_2fVector ON_2fVector::operator*( float d ) const
02822 {
02823   return ON_2fVector(x*d,y*d);
02824 }
02825 
02826 ON_2dVector ON_2fVector::operator*( double d ) const
02827 {
02828   return ON_2dVector(x*d,y*d);
02829 }
02830 
02831 float ON_2fVector::operator*( const ON_2fVector& v ) const
02832 {
02833   return (x*v.x + y*v.y);
02834 }
02835 
02836 float ON_2fVector::operator*( const ON_2fPoint& v ) const
02837 {
02838   return (x*v.x + y*v.y);
02839 }
02840 
02841 double ON_2fVector::operator*( const ON_2dVector& v ) const
02842 {
02843   return (x*v.x + y*v.y);
02844 }
02845 
02846 ON_2fVector ON_2fVector::operator/( int d ) const
02847 {
02848   const float one_over_d = 1.0f/((float)d);
02849   return ON_2fVector(x*one_over_d,y*one_over_d);
02850 }
02851 
02852 ON_2fVector ON_2fVector::operator/( float d ) const
02853 {
02854   const float one_over_d = 1.0f/d;
02855   return ON_2fVector(x*one_over_d,y*one_over_d);
02856 }
02857 
02858 ON_2dVector ON_2fVector::operator/( double d ) const
02859 {
02860   const double one_over_d = 1.0/d;
02861   return ON_2dVector(x*one_over_d,y*one_over_d);
02862 }
02863 
02864 ON_2fVector ON_2fVector::operator+( const ON_2fVector& v ) const
02865 {
02866   return ON_2fVector(x+v.x,y+v.y);
02867 }
02868 
02869 ON_2fPoint ON_2fVector::operator+( const ON_2fPoint& p ) const
02870 {
02871   return ON_2fPoint(x+p.x,y+p.y);
02872 }
02873 
02874 ON_2fVector ON_2fVector::operator-( const ON_2fVector& v ) const
02875 {
02876   return ON_2fVector(x-v.x,y-v.y);
02877 }
02878 
02879 ON_2fPoint ON_2fVector::operator-( const ON_2fPoint& v ) const
02880 {
02881   return ON_2fPoint(x-v.x,y-v.y);
02882 }
02883 
02884 ON_3fVector ON_2fVector::operator+( const ON_3fVector& v ) const
02885 {
02886   return ON_3fVector(x+v.x,y+v.y,v.z);
02887 }
02888 
02889 ON_3fPoint ON_2fVector::operator+( const ON_3fPoint& p ) const
02890 {
02891   return ON_3fPoint(x+p.x,y+p.y,p.z);
02892 }
02893 
02894 ON_3fVector ON_2fVector::operator-( const ON_3fVector& v ) const
02895 {
02896   return ON_3fVector(x-v.x,y-v.y,-v.z);
02897 }
02898 
02899 ON_3fPoint ON_2fVector::operator-( const ON_3fPoint& v ) const
02900 {
02901   return ON_3fPoint(x-v.x,y-v.y,-v.z);
02902 }
02903 
02905 
02906 
02907 ON_2dVector ON_2fVector::operator+( const ON_2dVector& v ) const
02908 {
02909   return ON_2dVector(x+v.x,y+v.y);
02910 }
02911 
02912 ON_2dPoint ON_2fVector::operator+( const ON_2dPoint& p ) const
02913 {
02914   return ON_2dPoint(x+p.x,y+p.y);
02915 }
02916 
02917 ON_2dVector ON_2fVector::operator-( const ON_2dVector& v ) const
02918 {
02919   return ON_2dVector(x-v.x,y-v.y);
02920 }
02921 
02922 ON_2dPoint ON_2fVector::operator-( const ON_2dPoint& v ) const
02923 {
02924   return ON_2dPoint(x-v.x,y-v.y);
02925 }
02926 
02927 ON_3dVector ON_2fVector::operator+( const ON_3dVector& v ) const
02928 {
02929   return ON_3dVector(x+v.x,y+v.y,v.z);
02930 }
02931 
02932 ON_3dPoint ON_2fVector::operator+( const ON_3dPoint& p ) const
02933 {
02934   return ON_3dPoint(x+p.x,y+p.y,p.z);
02935 }
02936 
02937 ON_3dVector ON_2fVector::operator-( const ON_3dVector& v ) const
02938 {
02939   return ON_3dVector(x-v.x,y-v.y,-v.z);
02940 }
02941 
02942 ON_3dPoint ON_2fVector::operator-( const ON_3dPoint& v ) const
02943 {
02944   return ON_3dPoint(x-v.x,y-v.y,-v.z);
02945 }
02946 
02947 
02948 float ON_2fVector::operator*(const ON_4fPoint& h) const
02949 {
02950   return x*h.x + y*h.y;
02951 }
02952 
02953 bool ON_2fVector::operator==( const ON_2fVector& v ) const
02954 {
02955   return (x==v.x&&y==v.y)?true:false;
02956 }
02957 
02958 bool ON_2fVector::operator!=( const ON_2fVector& v ) const
02959 {
02960   return (x!=v.x||y!=v.y)?true:false;
02961 }
02962 
02963 bool ON_2fVector::operator<=( const ON_2fVector& v ) const
02964 {
02965   // dictionary order
02966   return ((x<v.x)?true:((x==v.x&&y<=v.y)?true:false));
02967 }
02968 
02969 bool ON_2fVector::operator>=( const ON_2fVector& v ) const
02970 {
02971   // dictionary order
02972   return ((x>v.x)?true:((x==v.x&&y>=v.y)?true:false));
02973 }
02974 
02975 bool ON_2fVector::operator<( const ON_2fVector& v ) const
02976 {
02977   // dictionary order
02978   return ((x<v.x)?true:((x==v.x&&y<v.y)?true:false));
02979 }
02980 
02981 bool ON_2fVector::operator>( const ON_2fVector& v ) const
02982 {
02983   // dictionary order
02984   return ((x>v.x)?true:((x==v.x&&y>v.y)?true:false));
02985 }
02986 
02987 float ON_2fVector::operator[](int i) const
02988 {
02989   return ((i<=0)?x:y);
02990 }
02991 
02992 float& ON_2fVector::operator[](int i)
02993 {
02994   float* pd = (i<=0)? &x : &y;
02995   return *pd;
02996 }
02997 
02998 float ON_2fVector::operator[](unsigned int i) const
02999 {
03000   return ((i<=0)?x:y);
03001 }
03002 
03003 float& ON_2fVector::operator[](unsigned int i)
03004 {
03005   float* pd = (i<=0)? &x : &y;
03006   return *pd;
03007 }
03008 
03009 int ON_2fVector::MaximumCoordinateIndex() const
03010 {
03011   return ( (fabs(y)>fabs(x)) ? 1 : 0 );
03012 }
03013 
03014 double ON_2fVector::MaximumCoordinate() const
03015 {
03016   double c = fabs(x); if (fabs(y)>c) c=fabs(y);
03017   return c;
03018 }
03019 
03020 double ON_2fVector::LengthSquared() const
03021 {
03022   return (x*x + y*y);
03023 }
03024 
03025 double ON_2fVector::Length() const
03026 {
03027   return ON_Length2d((double)x,(double)y);
03028 }
03029 
03030 void ON_2fVector::Zero()
03031 {
03032   x = y = 0.0;
03033 }
03034 
03035 void ON_2fVector::Reverse()
03036 {
03037   x = -x;
03038   y = -y;
03039 }
03040 
03041 bool ON_2fVector::Unitize()
03042 {
03043   bool rc = false;
03044   // Since x,y are floats, d will not be denormalized and the
03045   // ON_DBL_MIN tests in ON_2dVector::Unitize() are not needed.
03046   double d = Length();
03047   if ( d > 0.0 ) 
03048   {
03049     double dx = (double)x;
03050     double dy = (double)y;
03051     x = (float)(dx/d);
03052     y = (float)(dy/d);
03053     rc = true;
03054   }
03055   return rc;
03056 }
03057 
03058 bool ON_2fVector::IsUnitVector() const
03059 {
03060   return (x != ON_UNSET_FLOAT && y != ON_UNSET_FLOAT && fabs(Length() - 1.0) <= 1.0e-5);
03061 }
03062 
03063 bool ON_3fVector::IsUnitVector() const
03064 {
03065   return (x != ON_UNSET_FLOAT && y != ON_UNSET_FLOAT && z != ON_UNSET_FLOAT && fabs(Length() - 1.0) <= 1.0e-5);
03066 }
03067 
03068 bool ON_2fVector::IsTiny( double tiny_tol ) const
03069 {
03070   return (fabs(x) <= tiny_tol && fabs(y) <= tiny_tol );
03071 }
03072 
03073 bool ON_2fVector::IsZero() const
03074 {
03075   return (x==0.0f && y==0.0f);
03076 }
03077 
03078 // set this vector to be perpendicular to another vector
03079 bool ON_2fVector::PerpendicularTo( // Result is not unitized. 
03080                       // returns false if input vector is zero
03081       const ON_2fVector& v
03082       )
03083 {
03084   y = v.x;
03085   x = -v.y;
03086   return (x!= 0.0f || y!= 0.0f) ? true : false;
03087 }
03088 
03089 // set this vector to be perpendicular to a line defined by 2 points
03090 bool ON_2fVector::PerpendicularTo( 
03091       const ON_2fPoint& p, 
03092       const ON_2fPoint& q
03093       )
03094 {
03095   return PerpendicularTo(q-p);
03096 }
03097 
03098 ON_2fVector operator*(int d, const ON_2fVector& v)
03099 {
03100   return ON_2fVector(d*v.x,d*v.y);
03101 }
03102 
03103 ON_2fVector operator*(float d, const ON_2fVector& v)
03104 {
03105   return ON_2fVector(d*v.x,d*v.y);
03106 }
03107 
03108 ON_2dVector operator*(double d, const ON_2fVector& v)
03109 {
03110   return ON_2dVector(d*v.x,d*v.y);
03111 }
03112 
03113 float ON_DotProduct( const ON_2fVector& a , const ON_2fVector& b )
03114 {
03115   // inner (dot) product between 3d vectors
03116   return (a.x*b.x + a.y*b.y );
03117 }
03118 
03119 ON_3fVector ON_CrossProduct( const ON_2fVector& a , const ON_2fVector& b )
03120 {
03121   return ON_3fVector(0.0, 0.0, a.x*b.y - b.x*a.y );
03122 }
03123 
03125 //
03126 // ON_3fVector
03127 //
03128 
03129 // static
03130 const ON_3fVector& ON_3fVector::UnitVector(int index)
03131 {
03132   static ON_3fVector o(0.0,0.0,0.0);
03133   static ON_3fVector x(1.0,0.0,0.0);
03134   static ON_3fVector y(0.0,1.0,0.0);
03135   static ON_3fVector z(0.0,0.0,1.0);
03136   switch(index)
03137   {
03138   case 0:
03139     return x;
03140   case 1:
03141     return y;
03142   case 2:
03143     return z;
03144   }
03145   return o;
03146 }
03147 
03148 ON_3fVector::ON_3fVector()
03149 {}
03150 
03151 ON_3fVector::ON_3fVector( const double* v )
03152 {
03153   if (v) {
03154     x = (float)v[0]; y = (float)v[1]; z = (float)v[2];
03155   }
03156   else {
03157     x = y = z = 0.0;
03158   }
03159 }
03160 
03161 ON_3fVector::ON_3fVector( const float* v )
03162 {
03163   if (v) {
03164     x = v[0]; y = v[1]; z = v[2];
03165   }
03166   else {
03167     x = y = z = 0.0;
03168   }
03169 }
03170 
03171 ON_3fVector::ON_3fVector(float xx,float yy,float zz)
03172 {x=xx;y=yy;z=zz;}
03173 
03174 ON_3fVector::ON_3fVector(const ON_2fVector& v)
03175 {x=v.x;y=v.y;z=0.0f;}
03176 
03177 ON_3fVector::ON_3fVector(const ON_2fPoint& p)
03178 {x=p.x;y=p.y;z=0.0f;}
03179 
03180 ON_3fVector::ON_3fVector(const ON_3fPoint& p)
03181 {x=p.x;y=p.y;z=p.z;}
03182 
03183 ON_3fVector::ON_3fVector(const ON_2dVector& v)
03184 {x=(float)v.x;y=(float)v.y;z=(float)0.0f;}
03185 
03186 ON_3fVector::ON_3fVector(const ON_3dVector& v)
03187 {x=(float)v.x;y=(float)v.y;z=(float)v.z;}
03188 
03189 ON_3fVector::ON_3fVector(const ON_2dPoint& p)
03190 {x=(float)p.x;y=(float)p.y;z=(float)0.0f;}
03191 
03192 ON_3fVector::ON_3fVector(const ON_3dPoint& p)
03193 {x=(float)p.x;y=(float)p.y;z=(float)p.z;}
03194 
03195 ON_3fVector::operator float*()
03196 {
03197   return &x;
03198 }
03199 
03200 ON_3fVector::operator const float*() const
03201 {
03202   return &x;
03203 }
03204 
03205 ON_3fVector& ON_3fVector::operator=(const double* v)
03206 {
03207   if ( v ) {
03208     x = (float)v[0];
03209     y = (float)v[1];
03210     z = (float)v[2];
03211   }
03212   else {
03213     x = y = z = 0.0;
03214   }
03215   return *this;
03216 }
03217 
03218 ON_3fVector& ON_3fVector::operator=(const float* v)
03219 {
03220   if ( v ) {
03221     x = v[0];
03222     y = v[1];
03223     z = v[2];
03224   }
03225   else {
03226     x = y = z = 0.0;
03227   }
03228   return *this;
03229 }
03230 
03231 ON_3fVector& ON_3fVector::operator=(const ON_2fVector& v)
03232 {
03233   x = v.x;
03234   y = v.y;
03235   z = 0.0;
03236   return *this;
03237 }
03238 
03239 ON_3fVector& ON_3fVector::operator=(const ON_2fPoint& p)
03240 {
03241   x = p.x;
03242   y = p.y;
03243   z = 0.0f;
03244   return *this;
03245 }
03246 
03247 ON_3fVector& ON_3fVector::operator=(const ON_3fPoint& p)
03248 {
03249   x = p.x;
03250   y = p.y;
03251   z = p.z;
03252   return *this;
03253 }
03254 
03255 
03256 ON_3fVector& ON_3fVector::operator=(const ON_2dVector& v)
03257 {
03258   x = (float)v.x;
03259   y = (float)v.y;
03260   z = 0.0f;
03261   return *this;
03262 }
03263 
03264 ON_3fVector& ON_3fVector::operator=(const ON_3dVector& v)
03265 {
03266   x = (float)v.x;
03267   y = (float)v.y;
03268   z = (float)v.z;
03269   return *this;
03270 }
03271 
03272 ON_3fVector& ON_3fVector::operator=(const ON_2dPoint& p)
03273 {
03274   x = (float)p.x;
03275   y = (float)p.y;
03276   z = 0.0f;
03277   return *this;
03278 }
03279 
03280 ON_3fVector& ON_3fVector::operator=(const ON_3dPoint& p)
03281 {
03282   x = (float)p.x;
03283   y = (float)p.y;
03284   z = (float)p.z;
03285   return *this;
03286 }
03287 
03288 ON_3fVector ON_3fVector::operator-() const
03289 {
03290   return ON_3fVector(-x,-y,-z);
03291 }
03292 
03293 ON_3fVector& ON_3fVector::operator*=(float d)
03294 {
03295   x *= d;
03296   y *= d;
03297   z *= d;
03298   return *this;
03299 }
03300 
03301 ON_3fVector& ON_3fVector::operator/=(float d)
03302 {
03303   const float one_over_d = 1.0f/d;
03304   x *= one_over_d;
03305   y *= one_over_d;
03306   z *= one_over_d;
03307   return *this;
03308 }
03309 
03310 ON_3fVector& ON_3fVector::operator+=(const ON_3fVector& v)
03311 {
03312   x += v.x;
03313   y += v.y;
03314   z += v.z;
03315   return *this;
03316 }
03317 
03318 ON_3fVector& ON_3fVector::operator-=(const ON_3fVector& v)
03319 {
03320   x -= v.x;
03321   y -= v.y;
03322   z -= v.z;
03323   return *this;
03324 }
03325 
03326 ON_3fVector ON_3fVector::operator*( int d ) const
03327 {
03328   return ON_3fVector(x*d,y*d,z*d);
03329 }
03330 
03331 ON_3fVector ON_3fVector::operator*( float d ) const
03332 {
03333   return ON_3fVector(x*d,y*d,z*d);
03334 }
03335 
03336 ON_3dVector ON_3fVector::operator*( double d ) const
03337 {
03338   return ON_3dVector(x*d,y*d,z*d);
03339 }
03340 
03341 float ON_3fVector::operator*( const ON_3fVector& v ) const
03342 {
03343   return (x*v.x + y*v.y + z*v.z);
03344 }
03345 
03346 float ON_3fVector::operator*( const ON_3fPoint& v ) const
03347 {
03348   return (x*v.x + y*v.y + z*v.z);
03349 }
03350 
03351 double ON_3fVector::operator*( const ON_3dVector& v ) const
03352 {
03353   return (x*v.x + y*v.y + z*v.z);
03354 }
03355 
03356 ON_3fVector ON_3fVector::operator/( int d ) const
03357 {
03358   const float one_over_d = 1.0f/((int)d);
03359   return ON_3fVector(x*one_over_d,y*one_over_d,z*one_over_d);
03360 }
03361 
03362 ON_3fVector ON_3fVector::operator/( float d ) const
03363 {
03364   const float one_over_d = 1.0f/d;
03365   return ON_3fVector(x*one_over_d,y*one_over_d,z*one_over_d);
03366 }
03367 
03368 ON_3dVector ON_3fVector::operator/( double d ) const
03369 {
03370   const double one_over_d = 1.0/d;
03371   return ON_3dVector(x*one_over_d,y*one_over_d,z*one_over_d);
03372 }
03373 
03374 ON_3fVector ON_3fVector::operator+( const ON_3fVector& v ) const
03375 {
03376   return ON_3fVector(x+v.x,y+v.y,z+v.z);
03377 }
03378 
03379 ON_3fPoint ON_3fVector::operator+( const ON_3fPoint& p ) const
03380 {
03381   return ON_3fPoint(x+p.x,y+p.y,z+p.z);
03382 }
03383 
03384 ON_3fVector ON_3fVector::operator-( const ON_3fVector& v ) const
03385 {
03386   return ON_3fVector(x-v.x,y-v.y,z-v.z);
03387 }
03388 
03389 ON_3fPoint ON_3fVector::operator-( const ON_3fPoint& v ) const
03390 {
03391   return ON_3fPoint(x-v.x,y-v.y,z-v.z);
03392 }
03393 
03394 ON_3fVector ON_3fVector::operator+( const ON_2fVector& v ) const
03395 {
03396   return ON_3fVector(x+v.x,y+v.y,z);
03397 }
03398 
03399 ON_3fPoint ON_3fVector::operator+( const ON_2fPoint& p ) const
03400 {
03401   return ON_3fPoint(x+p.x,y+p.y,z);
03402 }
03403 
03404 ON_3fVector ON_3fVector::operator-( const ON_2fVector& v ) const
03405 {
03406   return ON_3fVector(x-v.x,y-v.y,z);
03407 }
03408 
03409 ON_3fPoint ON_3fVector::operator-( const ON_2fPoint& v ) const
03410 {
03411   return ON_3fPoint(x-v.x,y-v.y,z);
03412 }
03413 
03415 
03416 
03417 ON_3dVector ON_3fVector::operator+( const ON_3dVector& v ) const
03418 {
03419   return ON_3dVector(x+v.x,y+v.y,z+v.z);
03420 }
03421 
03422 ON_3dPoint ON_3fVector::operator+( const ON_3dPoint& p ) const
03423 {
03424   return ON_3dPoint(x+p.x,y+p.y,z+p.z);
03425 }
03426 
03427 ON_3dVector ON_3fVector::operator-( const ON_3dVector& v ) const
03428 {
03429   return ON_3dVector(x-v.x,y-v.y,z-v.z);
03430 }
03431 
03432 ON_3dPoint ON_3fVector::operator-( const ON_3dPoint& v ) const
03433 {
03434   return ON_3dPoint(x-v.x,y-v.y,z-v.z);
03435 }
03436 
03437 ON_3dVector ON_3fVector::operator+( const ON_2dVector& v ) const
03438 {
03439   return ON_3dVector(x+v.x,y+v.y,z);
03440 }
03441 
03442 ON_3dPoint ON_3fVector::operator+( const ON_2dPoint& p ) const
03443 {
03444   return ON_3dPoint(x+p.x,y+p.y,z);
03445 }
03446 
03447 ON_3dVector ON_3fVector::operator-( const ON_2dVector& v ) const
03448 {
03449   return ON_3dVector(x-v.x,y-v.y,z);
03450 }
03451 
03452 ON_3dPoint ON_3fVector::operator-( const ON_2dPoint& v ) const
03453 {
03454   return ON_3dPoint(x-v.x,y-v.y,z);
03455 }
03456 
03457 
03458 float ON_3fVector::operator*(const ON_4fPoint& h) const
03459 {
03460   return x*h.x + y*h.y + z*h.z;
03461 }
03462 
03463 bool ON_3fVector::operator==( const ON_3fVector& v ) const
03464 {
03465   return (x==v.x&&y==v.y&&z==v.z)?true:false;
03466 }
03467 
03468 bool ON_3fVector::operator!=( const ON_3fVector& v ) const
03469 {
03470   return (x!=v.x||y!=v.y||z!=v.z)?true:false;
03471 }
03472 
03473 bool ON_3fVector::operator<=( const ON_3fVector& v ) const
03474 {
03475   // dictionary order
03476   return ((x<v.x)?true:((x==v.x)?((y<v.y)?true:(y==v.y&&z<=v.z)?true:false):false));
03477 }
03478 
03479 bool ON_3fVector::operator>=( const ON_3fVector& v ) const
03480 {
03481   // dictionary order
03482   return ((x>v.x)?true:((x==v.x)?((y>v.y)?true:(y==v.y&&z>=v.z)?true:false):false));
03483 }
03484 
03485 bool ON_3fVector::operator<( const ON_3fVector& v ) const
03486 {
03487   // dictionary order
03488   return ((x<v.x)?true:((x==v.x)?((y<v.y)?true:(y==v.y&&z<v.z)?true:false):false));
03489 }
03490 
03491 bool ON_3fVector::operator>( const ON_3fVector& v ) const
03492 {
03493   // dictionary order
03494   return ((x>v.x)?true:((x==v.x)?((y>v.y)?true:(y==v.y&&z>v.z)?true:false):false));
03495 }
03496 
03497 float ON_3fVector::operator[](int i) const
03498 {
03499   return ( (i<=0)?x:((i>=2)?z:y) );
03500 }
03501 
03502 float& ON_3fVector::operator[](int i)
03503 {
03504   float* pd = (i<=0)? &x : ( (i>=2) ?  &z : &y);
03505   return *pd;
03506 }
03507 
03508 float ON_3fVector::operator[](unsigned int i) const
03509 {
03510   return ( (i<=0)?x:((i>=2)?z:y) );
03511 }
03512 
03513 float& ON_3fVector::operator[](unsigned int i)
03514 {
03515   float* pd = (i<=0)? &x : ( (i>=2) ?  &z : &y);
03516   return *pd;
03517 }
03518 
03519 int ON_3fVector::MaximumCoordinateIndex() const
03520 {
03521   return (fabs(y)>fabs(x)) ? ((fabs(z)>fabs(y))?2:1) : ((fabs(z)>fabs(x))?2:0);
03522 }
03523 
03524 double ON_3fVector::MaximumCoordinate() const
03525 {
03526   double c = fabs(x); if (fabs(y)>c) c=fabs(y); if (fabs(z)>c) c=fabs(z);
03527   return c;
03528 }
03529 
03530 double ON_3fVector::LengthSquared() const
03531 {
03532   return (x*x + y*y + z*z);
03533 }
03534 
03535 double ON_3fVector::Length() const
03536 {
03537   return ON_Length3d((double)x,(double)y,(double)z);
03538 }
03539 
03540 void ON_3fVector::Zero()
03541 {
03542   x = y = z = 0.0;
03543 }
03544 
03545 void ON_3fVector::Reverse()
03546 {
03547   x = -x;
03548   y = -y;
03549   z = -z;
03550 }
03551 
03552 bool ON_3fVector::Unitize()
03553 {
03554   bool rc = false;
03555   // Since x,y,z are floats, d will not be denormalized and the
03556   // ON_DBL_MIN tests in ON_2dVector::Unitize() are not needed.
03557   double d = Length();
03558   if ( d > 0.0 ) 
03559   {
03560     double dx = x;
03561     double dy = y;
03562     double dz = z;
03563     x = (float)(dx/d);
03564     y = (float)(dy/d);
03565     z = (float)(dz/d);
03566     rc = true;
03567   }
03568   return rc;
03569 }
03570 
03571 bool ON_3fVector::IsTiny( double tiny_tol ) const
03572 {
03573   return (fabs(x) <= tiny_tol && fabs(y) <= tiny_tol && fabs(z) <= tiny_tol );
03574 }
03575 
03576 bool ON_3fVector::IsZero() const
03577 {
03578   return (x==0.0f && y==0.0f && z==0.0f);
03579 }
03580 
03581 
03582 ON_3fVector operator*(int d, const ON_3fVector& v)
03583 {
03584   return ON_3fVector(d*v.x,d*v.y,d*v.z);
03585 }
03586 
03587 ON_3fVector operator*(float d, const ON_3fVector& v)
03588 {
03589   return ON_3fVector(d*v.x,d*v.y,d*v.z);
03590 }
03591 
03592 ON_3dVector operator*(double d, const ON_3fVector& v)
03593 {
03594   return ON_3dVector(d*v.x,d*v.y,d*v.z);
03595 }
03596 
03597 float ON_DotProduct( const ON_3fVector& a , const ON_3fVector& b )
03598 {
03599   // inner (dot) product between 3d vectors
03600   return (a.x*b.x + a.y*b.y + a.z*b.z);
03601 }
03602 
03603 ON_3fVector ON_CrossProduct( const ON_3fVector& a , const ON_3fVector& b )
03604 {
03605   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 );
03606 }
03607 
03608 ON_3fVector ON_CrossProduct( const float* a, const float* b )
03609 {
03610   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] );
03611 }
03612 
03613 float ON_TripleProduct( const ON_3fVector& a, const ON_3fVector& b, const ON_3fVector& c )
03614 {
03615   // = a o (b x c )
03616   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));
03617 }
03618 
03619 float ON_TripleProduct( const float* a, const float* b, const float* c )
03620 {
03621   // = a o (b x c )
03622   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]));
03623 }
03624 
03626 //
03627 // ON_2dPoint
03628 //
03629 
03630 ON_2dPoint::ON_2dPoint()
03631 {}
03632 
03633 ON_2dPoint::ON_2dPoint( const float* p )
03634 {
03635   if (p) {
03636     x = (double)p[0]; y = (double)p[1];
03637   }
03638   else {
03639     x = y = 0.0;
03640   }
03641 }
03642 
03643 ON_2dPoint::ON_2dPoint( const double* p )
03644 {
03645   if (p) {
03646     x = p[0]; y = p[1];
03647   }
03648   else {
03649     x = y = 0.0;
03650   }
03651 }
03652 
03653 ON_2dPoint::ON_2dPoint(double xx,double yy)
03654 {x=xx;y=yy;}
03655 
03656 ON_2dPoint::ON_2dPoint(const ON_3dPoint& p)
03657 {x=p.x;y=p.y;}
03658 
03659 ON_2dPoint::ON_2dPoint(const ON_4dPoint& h)
03660 {
03661   x=h.x;y=h.y;
03662   const double w = (h.w != 1.0 && h.w != 0.0) ? 1.0/h.w : 1.0;
03663   x *= w;
03664   y *= w;
03665 }
03666 
03667 ON_2dPoint::ON_2dPoint(const ON_2dVector& v)
03668 {x=v.x;y=v.y;}
03669 
03670 ON_2dPoint::ON_2dPoint(const ON_3dVector& v)
03671 {x=v.x;y=v.y;}
03672 
03673 ON_2dPoint::ON_2dPoint(const ON_2fPoint& p)
03674 {x=p.x;y=p.y;}
03675 
03676 ON_2dPoint::ON_2dPoint(const ON_3fPoint& p)
03677 {x=p.x;y=p.y;}
03678 
03679 ON_2dPoint::ON_2dPoint(const ON_4fPoint& h)
03680 {
03681   const double w = (h.w != 1.0f && h.w != 0.0f) ? 1.0/((double)h.w) : 1.0;
03682   x *= w*h.x;
03683   y *= w*h.y;
03684 }
03685 
03686 ON_2dPoint::ON_2dPoint(const ON_2fVector& v)
03687 {x=v.x;y=v.y;}
03688 
03689 ON_2dPoint::ON_2dPoint(const ON_3fVector& v)
03690 {x=v.x;y=v.y;}
03691 
03692 ON_2dPoint::operator double*()
03693 {
03694   return &x;
03695 }
03696 
03697 ON_2dPoint::operator const double*() const
03698 {
03699   return &x;
03700 }
03701 
03702 ON_2dPoint& ON_2dPoint::operator=(const float* p)
03703 {
03704   if ( p ) {
03705     x = (double)p[0];
03706     y = (double)p[1];
03707   }
03708   else {
03709     x = y = 0.0;
03710   }
03711   return *this;
03712 }
03713 
03714 ON_2dPoint& ON_2dPoint::operator=(const double* p)
03715 {
03716   if ( p ) {
03717     x = p[0];
03718     y = p[1];
03719   }
03720   else {
03721     x = y = 0.0;
03722   }
03723   return *this;
03724 }
03725 
03726 ON_2dPoint& ON_2dPoint::operator=(const ON_3dPoint& p)
03727 {
03728   x = p.x;
03729   y = p.y;
03730   return *this;
03731 }
03732 
03733 ON_2dPoint& ON_2dPoint::operator=(const ON_4dPoint& h)
03734 {
03735   const double w = (h.w != 1.0 && h.w != 0.0) ? 1.0/h.w : 1.0;
03736   x = w*h.x;
03737   y = w*h.y;
03738   return *this;
03739 }
03740 
03741 ON_2dPoint& ON_2dPoint::operator=(const ON_2dVector& v)
03742 {
03743   x = v.x;
03744   y = v.y;
03745   return *this;
03746 }
03747 
03748 ON_2dPoint& ON_2dPoint::operator=(const ON_3dVector& v)
03749 {
03750   x = v.x;
03751   y = v.y;
03752   y = v.z;
03753   return *this;
03754 }
03755 
03756 ON_2dPoint& ON_2dPoint::operator=(const ON_2fPoint& p)
03757 {
03758   x = p.x;
03759   y = p.y;
03760   return *this;
03761 }
03762 
03763 ON_2dPoint& ON_2dPoint::operator=(const ON_3fPoint& p)
03764 {
03765   x = p.x;
03766   y = p.y;
03767   return *this;
03768 }
03769 
03770 ON_2dPoint& ON_2dPoint::operator=(const ON_4fPoint& h)
03771 {
03772   const double w = (h.w != 1.0f && h.w != 0.0f) ? 1.0/((double)h.w) : 1.0;
03773   x = w*h.x;
03774   y = w*h.y;
03775   return *this;
03776 }
03777 
03778 ON_2dPoint& ON_2dPoint::operator=(const ON_2fVector& v)
03779 {
03780   x = v.x;
03781   y = v.y;
03782   return *this;
03783 }
03784 
03785 ON_2dPoint& ON_2dPoint::operator=(const ON_3fVector& v)
03786 {
03787   x = v.x;
03788   y = v.y;
03789   y = v.z;
03790   return *this;
03791 }
03792 
03793 ON_2dPoint& ON_2dPoint::operator*=(double d)
03794 {
03795   x *= d;
03796   y *= d;
03797   return *this;
03798 }
03799 
03800 ON_2dPoint& ON_2dPoint::operator/=(double d)
03801 {
03802   const double one_over_d = 1.0/d;
03803   x *= one_over_d;
03804   y *= one_over_d;
03805   return *this;
03806 }
03807 
03808 ON_2dPoint& ON_2dPoint::operator+=(const ON_2dPoint& p)
03809 {
03810   x += p.x;
03811   y += p.y;
03812   return *this;
03813 }
03814 
03815 ON_2dPoint& ON_2dPoint::operator+=(const ON_2dVector& v)
03816 {
03817   x += v.x;
03818   y += v.y;
03819   return *this;
03820 }
03821 
03822 ON_2dPoint& ON_2dPoint::operator+=(const ON_3dVector& v)
03823 {
03824   x += v.x;
03825   y += v.y;
03826   return *this;
03827 }
03828 
03829 ON_2dPoint& ON_2dPoint::operator-=(const ON_2dPoint& p)
03830 {
03831   x -= p.x;
03832   y -= p.y;
03833   return *this;
03834 }
03835 
03836 ON_2dPoint& ON_2dPoint::operator-=(const ON_2dVector& v)
03837 {
03838   x -= v.x;
03839   y -= v.y;
03840   return *this;
03841 }
03842 
03843 ON_2dPoint& ON_2dPoint::operator-=(const ON_3dVector& v)
03844 {
03845   x -= v.x;
03846   y -= v.y;
03847   return *this;
03848 }
03849 
03850 ON_2dPoint ON_2dPoint::operator*( int i ) const
03851 {
03852   double d = i;
03853   return ON_2dPoint(x*d,y*d);
03854 }
03855 
03856 ON_2dPoint ON_2dPoint::operator*( float f ) const
03857 {
03858   double d = f;
03859   return ON_2dPoint(x*d,y*d);
03860 }
03861 
03862 ON_2dPoint ON_2dPoint::operator*( double d ) const
03863 {
03864   return ON_2dPoint(x*d,y*d);
03865 }
03866 
03867 ON_2dPoint ON_2dPoint::operator/( int i ) const
03868 {
03869   const double one_over_d = 1.0/((double)i);
03870   return ON_2dPoint(x*one_over_d,y*one_over_d);
03871 }
03872 
03873 ON_2dPoint ON_2dPoint::operator/( float f ) const
03874 {
03875   const double one_over_d = 1.0/((double)f);
03876   return ON_2dPoint(x*one_over_d,y*one_over_d);
03877 }
03878 
03879 ON_2dPoint ON_2dPoint::operator/( double d ) const
03880 {
03881   const double one_over_d = 1.0/d;
03882   return ON_2dPoint(x*one_over_d,y*one_over_d);
03883 }
03884 
03885 ON_2dPoint ON_2dPoint::operator+( const ON_2dPoint& p ) const
03886 {
03887   return ON_2dPoint(x+p.x,y+p.y);
03888 }
03889 
03890 ON_2dPoint ON_2dPoint::operator+( const ON_2dVector& v ) const
03891 {
03892   return ON_2dPoint(x+v.x,y+v.y);
03893 }
03894 
03895 ON_2dVector ON_2dPoint::operator-( const ON_2dPoint& p ) const
03896 {
03897   return ON_2dVector(x-p.x,y-p.y);
03898 }
03899 
03900 ON_2dPoint ON_2dPoint::operator-( const ON_2dVector& v ) const
03901 {
03902   return ON_2dPoint(x-v.x,y-v.y);
03903 }
03904 
03905 
03906 ON_3dPoint ON_2dPoint::operator+( const ON_3dPoint& p ) const
03907 {
03908   return ON_3dPoint(x+p.x,y+p.y,p.z);
03909 }
03910 
03911 ON_3dPoint ON_2dPoint::operator+( const ON_3dVector& v ) const
03912 {
03913   return ON_3dPoint(x+v.x,y+v.y,v.z);
03914 }
03915 
03916 ON_3dVector ON_2dPoint::operator-( const ON_3dPoint& p ) const
03917 {
03918   return ON_3dVector(x-p.x,y-p.y,-p.z);
03919 }
03920 
03921 ON_3dPoint ON_2dPoint::operator-( const ON_3dVector& v ) const
03922 {
03923   return ON_3dPoint(x-v.x,y-v.y,-v.z);
03924 }
03925 
03927 
03928 
03929 ON_2dPoint ON_2dPoint::operator+( const ON_2fPoint& p ) const
03930 {
03931   return ON_2dPoint(x+p.x,y+p.y);
03932 }
03933 
03934 ON_2dPoint ON_2dPoint::operator+( const ON_2fVector& v ) const
03935 {
03936   return ON_2dPoint(x+v.x,y+v.y);
03937 }
03938 
03939 ON_2dVector ON_2dPoint::operator-( const ON_2fPoint& p ) const
03940 {
03941   return ON_2dVector(x-p.x,y-p.y);
03942 }
03943 
03944 ON_2dPoint ON_2dPoint::operator-( const ON_2fVector& v ) const
03945 {
03946   return ON_2dPoint(x-v.x,y-v.y);
03947 }
03948 
03949 
03950 ON_3dPoint ON_2dPoint::operator+( const ON_3fPoint& p ) const
03951 {
03952   return ON_3dPoint(x+p.x,y+p.y,p.z);
03953 }
03954 
03955 ON_3dPoint ON_2dPoint::operator+( const ON_3fVector& v ) const
03956 {
03957   return ON_3dPoint(x+v.x,y+v.y,v.z);
03958 }
03959 
03960 ON_3dVector ON_2dPoint::operator-( const ON_3fPoint& p ) const
03961 {
03962   return ON_3dVector(x-p.x,y-p.y,-p.z);
03963 }
03964 
03965 ON_3dPoint ON_2dPoint::operator-( const ON_3fVector& v ) const
03966 {
03967   return ON_3dPoint(x-v.x,y-v.y,-v.z);
03968 }
03969 
03970 
03971 double ON_2dPoint::operator*(const ON_2dPoint& h) const
03972 {
03973   return x*h.x + y*h.y;
03974 }
03975 
03976 double ON_2dPoint::operator*(const ON_2dVector& h) const
03977 {
03978   return x*h.x + y*h.y;
03979 }
03980 
03981 double ON_2dPoint::operator*(const ON_4dPoint& h) const
03982 {
03983   return x*h.x + y*h.y + h.w;
03984 }
03985 
03986 bool ON_2dPoint::operator==( const ON_2dPoint& p ) const
03987 {
03988   return (x==p.x&&y==p.y)?true:false;
03989 }
03990 
03991 bool ON_2dPoint::operator!=( const ON_2dPoint& p ) const
03992 {
03993   return (x!=p.x||y!=p.y)?true:false;
03994 }
03995 
03996 bool ON_2dPoint::operator<=( const ON_2dPoint& p ) const
03997 {
03998   // dictionary order
03999   return ( (x<p.x) ? true : ((x==p.x&&y<=p.y)?true:false) );
04000 }
04001 
04002 bool ON_2dPoint::operator>=( const ON_2dPoint& p ) const
04003 {
04004   // dictionary order
04005   return ( (x>p.x) ? true : ((x==p.x&&y>=p.y)?true:false) );
04006 }
04007 
04008 bool ON_2dPoint::operator<( const ON_2dPoint& p ) const
04009 {
04010   // dictionary order
04011   return ( (x<p.x) ? true : ((x==p.x&&y<p.y)?true:false) );
04012 }
04013 
04014 bool ON_2dPoint::operator>( const ON_2dPoint& p ) const
04015 {
04016   // dictionary order
04017   return ( (x>p.x) ? true : ((x==p.x&&y>p.y)?true:false) );
04018 }
04019 
04020 double ON_2dPoint::operator[](int i) const
04021 {
04022   return (i<=0) ? x : y;
04023 }
04024 
04025 double& ON_2dPoint::operator[](int i)
04026 {
04027   double* pd = (i<=0)? &x : &y;
04028   return *pd;
04029 }
04030 
04031 double ON_2dPoint::operator[](unsigned int i) const
04032 {
04033   return (i<=0) ? x : y;
04034 }
04035 
04036 double& ON_2dPoint::operator[](unsigned int i)
04037 {
04038   double* pd = (i<=0)? &x : &y;
04039   return *pd;
04040 }
04041 
04042 double ON_2dPoint::DistanceTo( const ON_2dPoint& p ) const
04043 {
04044   return ON_Length2d(p.x-x,p.y-y);
04045 }
04046 
04047 int ON_2dPoint::MaximumCoordinateIndex() const
04048 {
04049   return (fabs(y)>fabs(x)) ? 1 : 0;
04050 }
04051 
04052 double ON_2dPoint::MaximumCoordinate() const
04053 {
04054   double c = fabs(x); if (fabs(y)>c) c=fabs(y);
04055   return c;
04056 }
04057 
04058 int ON_2dPoint::MinimumCoordinateIndex() const
04059 {
04060   return (fabs(y)<fabs(x)) ? 1 : 0;
04061 }
04062 
04063 double ON_2dPoint::MinimumCoordinate() const
04064 {
04065   double c = fabs(x); if (fabs(y)<c) c=fabs(y);
04066   return c;
04067 }
04068 
04069 
04070 void ON_2dPoint::Zero()
04071 {
04072   x = y = 0.0;
04073 }
04074 
04075 ON_2dPoint operator*(int i, const ON_2dPoint& p)
04076 {
04077   double d = i;
04078   return ON_2dPoint(d*p.x,d*p.y);
04079 }
04080 
04081 ON_2dPoint operator*(float f, const ON_2dPoint& p)
04082 {
04083   double d = f;
04084   return ON_2dPoint(d*p.x,d*p.y);
04085 }
04086 
04087 ON_2dPoint operator*(double d, const ON_2dPoint& p)
04088 {
04089   return ON_2dPoint(d*p.x,d*p.y);
04090 }
04091 
04093 //
04094 // ON_3dPoint
04095 //
04096 
04097 ON_3dPoint::ON_3dPoint()
04098 {}
04099 
04100 ON_3dPoint::ON_3dPoint( const float* p )
04101 {
04102   if (p) {
04103     x = (double)p[0]; y = (double)p[1]; z = (double)p[2];
04104   }
04105   else {
04106     x = y = z = 0.0;
04107   }
04108 }
04109 
04110 ON_3dPoint::ON_3dPoint(const ON_2fPoint& p)
04111 {x=(double)p.x;y=(double)p.y;z=0.0;}
04112 
04113 ON_3dPoint::ON_3dPoint(const ON_3fPoint& p)
04114 {x=(double)p.x;y=(double)p.y;z=(double)p.z;}
04115 
04116 ON_3dPoint::ON_3dPoint(const ON_4fPoint& p)
04117 {
04118   const double w = (p.w != 1.0f && p.w != 0.0f) ? 1.0/((double)p.w) : 1.0;
04119   x = w*((double)p.x);
04120   y = w*((double)p.y);
04121   z = w*((double)p.z);
04122 }
04123 
04124 ON_3dPoint::ON_3dPoint(const ON_2fVector& p)
04125 {x=(double)p.x;y=(double)p.y;z=0.0;}
04126 
04127 ON_3dPoint::ON_3dPoint(const ON_3fVector& p)
04128 {x=(double)p.x;y=(double)p.y;z=(double)p.z;}
04129 
04130 ON_3dRay::ON_3dRay()
04131 {}
04132 
04133 ON_3dRay::~ON_3dRay()
04134 {}
04135 
04136 ON_3dPoint::ON_3dPoint( const double* p )
04137 {
04138   if (p) {
04139     x = p[0]; y = p[1]; z = p[2];
04140   }
04141   else {
04142     x = y = z = 0.0;
04143   }
04144 }
04145 
04146 ON_3dPoint::ON_3dPoint(double xx,double yy,double zz)
04147 {x=xx;y=yy;z=zz;}
04148 
04149 ON_3dPoint::ON_3dPoint(const ON_2dPoint& p)
04150 {x=p.x;y=p.y;z=0.0;}
04151 
04152 ON_3dPoint::ON_3dPoint(const ON_4dPoint& p)
04153 {
04154   x=p.x;y=p.y;z=p.z;
04155   const double w = (p.w != 1.0 && p.w != 0.0) ? 1.0/p.w : 1.0;
04156   x *= w;
04157   y *= w;
04158   z *= w;
04159 }
04160 
04161 ON_3dPoint::ON_3dPoint(const ON_2dVector& v)
04162 {x=v.x;y=v.y;z=0.0;}
04163 
04164 ON_3dPoint::ON_3dPoint(const ON_3dVector& v)
04165 {x=v.x;y=v.y;z=v.z;}
04166 
04167 ON_3dPoint::operator double*()
04168 {
04169   return &x;
04170 }
04171 
04172 ON_3dPoint::operator const double*() const
04173 {
04174   return &x;
04175 }
04176 
04177 ON_3dPoint& ON_3dPoint::operator=(const float* p)
04178 {
04179   if ( p ) {
04180     x = (double)p[0];
04181     y = (double)p[1];
04182     z = (double)p[2];
04183   }
04184   else {
04185     x = y = z = 0.0;
04186   }
04187   return *this;
04188 }
04189 
04190 ON_3dPoint& ON_3dPoint::operator=(const double* p)
04191 {
04192   if ( p ) {
04193     x = p[0];
04194     y = p[1];
04195     z = p[2];
04196   }
04197   else {
04198     x = y = z = 0.0;
04199   }
04200   return *this;
04201 }
04202 
04203 ON_3dPoint& ON_3dPoint::operator=(const ON_2dPoint& p)
04204 {
04205   x = p.x;
04206   y = p.y;
04207   z = 0.0;
04208   return *this;
04209 }
04210 
04211 ON_3dPoint& ON_3dPoint::operator=(const ON_4dPoint& p)
04212 {
04213   const double w = (p.w != 1.0 && p.w != 0.0) ? 1.0/p.w : 1.0;
04214   x = w*p.x;
04215   y = w*p.y;
04216   z = w*p.z;
04217   return *this;
04218 }
04219 
04220 ON_3dPoint& ON_3dPoint::operator=(const ON_2dVector& v)
04221 {
04222   x = v.x;
04223   y = v.y;
04224   z = 0.0;
04225   return *this;
04226 }
04227 
04228 ON_3dPoint& ON_3dPoint::operator=(const ON_3dVector& v)
04229 {
04230   x = v.x;
04231   y = v.y;
04232   z = v.z;
04233   return *this;
04234 }
04235 
04236 ON_3dPoint& ON_3dPoint::operator=(const ON_2fPoint& p)
04237 {
04238   x = (double)p.x;
04239   y = (double)p.y;
04240   z = (double)0.0;
04241   return *this;
04242 }
04243 
04244 ON_3dPoint& ON_3dPoint::operator=(const ON_3fPoint& p)
04245 {
04246   x = (double)p.x;
04247   y = (double)p.y;
04248   z = (double)p.z;
04249   return *this;
04250 }
04251 
04252 ON_3dPoint& ON_3dPoint::operator=(const ON_4fPoint& p)
04253 {
04254   const double w = (p.w != 1.0f && p.w != 0.0f) ? 1.0/((double)p.w) : 1.0;
04255   x = w*((double)p.x);
04256   y = w*((double)p.y);
04257   z = w*((double)p.z);
04258   return *this;
04259 }
04260 
04261 ON_3dPoint& ON_3dPoint::operator=(const ON_2fVector& v)
04262 {
04263   x = v.x;
04264   y = v.y;
04265   z = 0.0;
04266   return *this;
04267 }
04268 
04269 ON_3dPoint& ON_3dPoint::operator=(const ON_3fVector& v)
04270 {
04271   x = v.x;
04272   y = v.y;
04273   z = v.z;
04274   return *this;
04275 }
04276 
04277 
04278 ON_3dPoint& ON_3dPoint::operator*=(double d)
04279 {
04280   x *= d;
04281   y *= d;
04282   z *= d;
04283   return *this;
04284 }
04285 
04286 ON_3dPoint& ON_3dPoint::operator/=(double d)
04287 {
04288   const double one_over_d = 1.0/d;
04289   x *= one_over_d;
04290   y *= one_over_d;
04291   z *= one_over_d;
04292   return *this;
04293 }
04294 
04295 ON_3dPoint& ON_3dPoint::operator+=(const ON_3dPoint& p)
04296 {
04297   x += p.x;
04298   y += p.y;
04299   z += p.z;
04300   return *this;
04301 }
04302 
04303 ON_3dPoint& ON_3dPoint::operator+=(const ON_3dVector& v)
04304 {
04305   x += v.x;
04306   y += v.y;
04307   z += v.z;
04308   return *this;
04309 }
04310 
04311 ON_3dPoint& ON_3dPoint::operator-=(const ON_3dPoint& p)
04312 {
04313   x -= p.x;
04314   y -= p.y;
04315   z -= p.z;
04316   return *this;
04317 }
04318 
04319 ON_3dPoint& ON_3dPoint::operator-=(const ON_3dVector& v)
04320 {
04321   x -= v.x;
04322   y -= v.y;
04323   z -= v.z;
04324   return *this;
04325 }
04326 
04327 ON_3dPoint ON_3dPoint::operator*( int i ) const
04328 {
04329   double d = i;
04330   return ON_3dPoint(x*d,y*d,z*d);
04331 }
04332 
04333 ON_3dPoint ON_3dPoint::operator*( float f ) const
04334 {
04335   double d = f;
04336   return ON_3dPoint(x*d,y*d,z*d);
04337 }
04338 
04339 ON_3dPoint ON_3dPoint::operator*( double d ) const
04340 {
04341   return ON_3dPoint(x*d,y*d,z*d);
04342 }
04343 
04344 ON_3dPoint ON_3dPoint::operator/( int i ) const
04345 {
04346   const double one_over_d = 1.0/((double)i);
04347   return ON_3dPoint(x*one_over_d,y*one_over_d,z*one_over_d);
04348 }
04349 
04350 ON_3dPoint ON_3dPoint::operator/( float f ) const
04351 {
04352   const double one_over_d = 1.0/((double)f);
04353   return ON_3dPoint(x*one_over_d,y*one_over_d,z*one_over_d);
04354 }
04355 
04356 ON_3dPoint ON_3dPoint::operator/( double d ) const
04357 {
04358   const double one_over_d = 1.0/d;
04359   return ON_3dPoint(x*one_over_d,y*one_over_d,z*one_over_d);
04360 }
04361 
04362 ON_3dPoint ON_3dPoint::operator+( const ON_3dPoint& p ) const
04363 {
04364   return ON_3dPoint(x+p.x,y+p.y,z+p.z);
04365 }
04366 
04367 ON_3dPoint ON_3dPoint::operator+( const ON_3dVector& v ) const
04368 {
04369   return ON_3dPoint(x+v.x,y+v.y,z+v.z);
04370 }
04371 
04372 ON_3dVector ON_3dPoint::operator-( const ON_3dPoint& p ) const
04373 {
04374   return ON_3dVector(x-p.x,y-p.y,z-p.z);
04375 }
04376 
04377 ON_3dPoint ON_3dPoint::operator-( const ON_3dVector& v ) const
04378 {
04379   return ON_3dPoint(x-v.x,y-v.y,z-v.z);
04380 }
04381 
04382 ON_3dPoint ON_3dPoint::operator+( const ON_2dPoint& p ) const
04383 {
04384   return ON_3dPoint(x+p.x,y+p.y,z);
04385 }
04386 
04387 ON_3dPoint ON_3dPoint::operator+( const ON_2dVector& v ) const
04388 {
04389   return ON_3dPoint(x+v.x,y+v.y,z);
04390 }
04391 
04392 ON_3dVector ON_3dPoint::operator-( const ON_2dPoint& p ) const
04393 {
04394   return ON_3dVector(x-p.x,y-p.y,z);
04395 }
04396 
04397 ON_3dPoint ON_3dPoint::operator-( const ON_2dVector& v ) const
04398 {
04399   return ON_3dPoint(x-v.x,y-v.y,z);
04400 }
04401 
04402 ON_3dPoint ON_3dPoint::operator+( const ON_3fPoint& p ) const
04403 {
04404   return ON_3dPoint(x+p.x,y+p.y,z+p.z);
04405 }
04406 
04407 ON_3dPoint ON_3dPoint::operator+( const ON_3fVector& v ) const
04408 {
04409   return ON_3dPoint(x+v.x,y+v.y,z+v.z);
04410 }
04411 
04412 ON_3dVector ON_3dPoint::operator-( const ON_3fPoint& p ) const
04413 {
04414   return ON_3dVector(x-p.x,y-p.y,z-p.z);
04415 }
04416 
04417 ON_3dPoint ON_3dPoint::operator-( const ON_3fVector& v ) const
04418 {
04419   return ON_3dPoint(x-v.x,y-v.y,z-v.z);
04420 }
04421 
04422 ON_3dPoint ON_3dPoint::operator+( const ON_2fPoint& p ) const
04423 {
04424   return ON_3dPoint(x+p.x,y+p.y,z);
04425 }
04426 
04427 ON_3dPoint ON_3dPoint::operator+( const ON_2fVector& v ) const
04428 {
04429   return ON_3dPoint(x+v.x,y+v.y,z);
04430 }
04431 
04432 ON_3dVector ON_3dPoint::operator-( const ON_2fPoint& p ) const
04433 {
04434   return ON_3dVector(x-p.x,y-p.y,z);
04435 }
04436 
04437 ON_3dPoint ON_3dPoint::operator-( const ON_2fVector& v ) const
04438 {
04439   return ON_3dPoint(x-v.x,y-v.y,z);
04440 }
04441 
04442 double ON_3dPoint::operator*(const ON_3dPoint& h) const
04443 {
04444   return x*h.x + y*h.y + z*h.z;
04445 }
04446 
04447 double ON_3dPoint::operator*(const ON_3dVector& h) const
04448 {
04449   return x*h.x + y*h.y + z*h.z;
04450 }
04451 
04452 double ON_3dPoint::operator*(const ON_4dPoint& h) const
04453 {
04454   return x*h.x + y*h.y + z*h.z + h.w;
04455 }
04456 
04457 bool ON_3dPoint::operator==( const ON_3dPoint& p ) const
04458 {
04459   return (x==p.x&&y==p.y&&z==p.z)?true:false;
04460 }
04461 
04462 bool ON_3dPoint::operator!=( const ON_3dPoint& p ) const
04463 {
04464   return (x!=p.x||y!=p.y||z!=p.z)?true:false;
04465 }
04466 
04467 bool ON_3dPoint::operator<=( const ON_3dPoint& p ) const
04468 {
04469   // dictionary order
04470   return ((x<p.x)?true:((x==p.x)?((y<p.y)?true:(y==p.y&&z<=p.z)?true:false):false));
04471 }
04472 
04473 bool ON_3dPoint::operator>=( const ON_3dPoint& p ) const
04474 {
04475   // dictionary order
04476   return ((x>p.x)?true:((x==p.x)?((y>p.y)?true:(y==p.y&&z>=p.z)?true:false):false));
04477 }
04478 
04479 bool ON_3dPoint::operator<( const ON_3dPoint& p ) const
04480 {
04481   // dictionary order
04482   return ((x<p.x)?true:((x==p.x)?((y<p.y)?true:(y==p.y&&z<p.z)?true:false):false));
04483 }
04484 
04485 bool ON_3dPoint::operator>( const ON_3dPoint& p ) const
04486 {
04487   // dictionary order
04488   return ((x>p.x)?true:((x==p.x)?((y>p.y)?true:(y==p.y&&z>p.z)?true:false):false));
04489 }
04490 
04491 double ON_3dPoint::operator[](int i) const
04492 {
04493   return ( (i<=0)?x:((i>=2)?z:y) );
04494 }
04495 
04496 double& ON_3dPoint::operator[](int i)
04497 {
04498   double* pd = (i<=0)? &x : ( (i>=2) ?  &z : &y);
04499   return *pd;
04500 }
04501 
04502 double ON_3dPoint::operator[](unsigned int i) const
04503 {
04504   return ( (i<=0)?x:((i>=2)?z:y) );
04505 }
04506 
04507 double& ON_3dPoint::operator[](unsigned int i)
04508 {
04509   double* pd = (i<=0)? &x : ( (i>=2) ?  &z : &y);
04510   return *pd;
04511 }
04512 
04513 double ON_3dPoint::DistanceTo( const ON_3dPoint& p ) const
04514 {
04515   return ON_Length3d(p.x-x,p.y-y,p.z-z);
04516 }
04517 
04518 int ON_3dPoint::MaximumCoordinateIndex() const
04519 {
04520   return (fabs(y)>fabs(x)) ? ((fabs(z)>fabs(y))?2:1) : ((fabs(z)>fabs(x))?2:0);
04521 }
04522 
04523 double ON_3dPoint::MaximumCoordinate() const
04524 {
04525   double c = fabs(x); if (fabs(y)>c) c=fabs(y); if (fabs(z)>c) c=fabs(z);
04526   return c;
04527 }
04528 
04529 int ON_3dPoint::MinimumCoordinateIndex() const
04530 {
04531   return (fabs(y)<fabs(x)) ? ((fabs(z)<fabs(y))?2:1) : ((fabs(z)<fabs(x))?2:0);
04532 }
04533 
04534 double ON_3dPoint::MinimumCoordinate() const
04535 {
04536   double c = fabs(x); if (fabs(y)<c) c=fabs(y); if (fabs(z)<c) c=fabs(z);
04537   return c;
04538 }
04539 
04540 void ON_3dPoint::Zero()
04541 {
04542   x = y = z = 0.0;
04543 }
04544 
04545 ON_3dPoint operator*(int i, const ON_3dPoint& p)
04546 {
04547   double d = i;
04548   return ON_3dPoint(d*p.x,d*p.y,d*p.z);
04549 }
04550 
04551 ON_3dPoint operator*(float f, const ON_3dPoint& p)
04552 {
04553   double d = f;
04554   return ON_3dPoint(d*p.x,d*p.y,d*p.z);
04555 }
04556 
04557 ON_3dPoint operator*(double d, const ON_3dPoint& p)
04558 {
04559   return ON_3dPoint(d*p.x,d*p.y,d*p.z);
04560 }
04561 
04563 //
04564 // ON_4dPoint
04565 //
04566 
04567 ON_4dPoint::ON_4dPoint()
04568 {}
04569 
04570 ON_4dPoint::ON_4dPoint( const float* p )
04571 {
04572   if (p) {
04573     x = (double)p[0]; y = (double)p[1]; z = (double)p[2]; w = (double)p[3];
04574   }
04575   else {
04576     x = y = z = 0.0; w = 1.0;
04577   }
04578 }
04579 
04580 ON_4dPoint::ON_4dPoint( const double* p )
04581 {
04582   if (p) {
04583     x = p[0]; y = p[1]; z = p[2]; w = p[3];
04584   }
04585   else {
04586     x = y = z = 0.0; w = 1.0;
04587   }
04588 }
04589 
04590 ON_4dPoint::ON_4dPoint(double xx,double yy,double zz,double ww)
04591 {x=xx;y=yy;z=zz;w=ww;}
04592 
04593 ON_4dPoint::ON_4dPoint(const ON_2dPoint& p)
04594 {x=p.x;y=p.y;z=0.0;w=1.0;}
04595 
04596 ON_4dPoint::ON_4dPoint(const ON_3dPoint& p)
04597 {
04598   x=p.x;y=p.y;z=p.z;w=1.0;
04599 }
04600 
04601 ON_4dPoint::ON_4dPoint(const ON_2dVector& v)
04602 {x=v.x;y=v.y;z=w=0.0;}
04603 
04604 ON_4dPoint::ON_4dPoint(const ON_3dVector& v)
04605 {x=v.x;y=v.y;z=v.z;w=0.0;}
04606 
04607 
04608 ON_4dPoint::ON_4dPoint(const ON_2fPoint& p)
04609 {x=p.x;y=p.y;z=0.0;w=1.0;}
04610 
04611 ON_4dPoint::ON_4dPoint(const ON_3fPoint& p)
04612 {
04613   x=p.x;y=p.y;z=p.z;w=1.0;
04614 }
04615 
04616 ON_4dPoint::ON_4dPoint(const ON_4fPoint& p)
04617 {
04618   x=p.x;y=p.y;z=p.z;w=p.w;
04619 }
04620 
04621 ON_4dPoint::ON_4dPoint(const ON_2fVector& v)
04622 {x=v.x;y=v.y;z=w=0.0;}
04623 
04624 ON_4dPoint::ON_4dPoint(const ON_3fVector& v)
04625 {x=v.x;y=v.y;z=v.z;w=0.0;}
04626 
04627 ON_4dPoint::operator double*()
04628 {
04629   return &x;
04630 }
04631 
04632 ON_4dPoint::operator const double*() const
04633 {
04634   return &x;
04635 }
04636 
04637 ON_4dPoint& ON_4dPoint::operator=(const float* p)
04638 {
04639   if ( p ) {
04640     x = (double)p[0];
04641     y = (double)p[1];
04642     z = (double)p[2];
04643     w = (double)p[3];
04644   }
04645   else {
04646     x = y = z = 0.0; w = 1.0;
04647   }
04648   return *this;
04649 }
04650 
04651 ON_4dPoint& ON_4dPoint::operator=(const double* p)
04652 {
04653   if ( p ) {
04654     x = p[0];
04655     y = p[1];
04656     z = p[2];
04657     w = p[3];
04658   }
04659   else {
04660     x = y = z = 0.0; w = 1.0;
04661   }
04662   return *this;
04663 }
04664 
04665 ON_4dPoint& ON_4dPoint::operator=(const ON_2dPoint& p)
04666 {
04667   x = p.x;
04668   y = p.y;
04669   z = 0.0;
04670   w = 1.0;
04671   return *this;
04672 }
04673 
04674 ON_4dPoint& ON_4dPoint::operator=(const ON_3dPoint& p)
04675 {
04676   x = p.x;
04677   y = p.y;
04678   z = p.z;
04679   w = 1.0;
04680   return *this;
04681 }
04682 
04683 ON_4dPoint& ON_4dPoint::operator=(const ON_2dVector& v)
04684 {
04685   x = v.x;
04686   y = v.y;
04687   z = 0.0;
04688   w = 0.0;
04689   return *this;
04690 }
04691 
04692 ON_4dPoint& ON_4dPoint::operator=(const ON_3dVector& v)
04693 {
04694   x = v.x;
04695   y = v.y;
04696   z = v.z;
04697   w = 0.0;
04698   return *this;
04699 }
04700 
04701 ON_4dPoint& ON_4dPoint::operator=(const ON_2fPoint& p)
04702 {
04703   x = (double)p.x;
04704   y = (double)p.y;
04705   z = 0.0;
04706   w = 1.0;
04707   return *this;
04708 }
04709 
04710 ON_4dPoint& ON_4dPoint::operator=(const ON_3fPoint& p)
04711 {
04712   x = (double)p.x;
04713   y = (double)p.y;
04714   z = (double)p.z;
04715   w = 1.0;
04716   return *this;
04717 }
04718 
04719 ON_4dPoint& ON_4dPoint::operator=(const ON_4fPoint& p)
04720 {
04721   x = (double)p.x;
04722   y = (double)p.y;
04723   z = (double)p.z;
04724   w = (double)p.w;
04725   return *this;
04726 }
04727 
04728 ON_4dPoint& ON_4dPoint::operator=(const ON_2fVector& v)
04729 {
04730   x = (double)v.x;
04731   y = (double)v.y;
04732   z = 0.0;
04733   w = 0.0;
04734   return *this;
04735 }
04736 
04737 ON_4dPoint& ON_4dPoint::operator=(const ON_3fVector& v)
04738 {
04739   x = (double)v.x;
04740   y = (double)v.y;
04741   z = (double)v.z;
04742   w = 0.0;
04743   return *this;
04744 }
04745 
04746 
04747 ON_4dPoint& ON_4dPoint::operator*=(double d)
04748 {
04749   x *= d;
04750   y *= d;
04751   z *= d;
04752   w *= d;
04753   return *this;
04754 }
04755 
04756 ON_4dPoint& ON_4dPoint::operator/=(double d)
04757 {
04758   const double one_over_d = 1.0/d;
04759   x *= one_over_d;
04760   y *= one_over_d;
04761   z *= one_over_d;
04762   w *= one_over_d;
04763   return *this;
04764 }
04765 
04766 ON_4dPoint& ON_4dPoint::operator+=(const ON_4dPoint& p)
04767 {
04768   // sum w = sqrt(w1*w2)
04769   if ( p.w == w ) {
04770     x += p.x;
04771     y += p.y;
04772     z += p.z;
04773   }
04774   else if (p.w == 0.0 ) {
04775     x += p.x;
04776     y += p.y;
04777     z += p.z;
04778   }
04779   else if ( w == 0.0 ) {
04780     x += p.x;
04781     y += p.y;
04782     z += p.z;
04783     w = p.w;
04784   }
04785   else {
04786     const double sw1 = (w>0.0) ? sqrt(w) : -sqrt(-w);
04787     const double sw2 = (p.w>0.0) ? sqrt(p.w) : -sqrt(-p.w);
04788     const double s1 = sw2/sw1;
04789     const double s2 = sw1/sw2;
04790     x = x*s1 + p.x*s2;
04791     y = y*s1 + p.y*s2;
04792     z = z*s1 + p.z*s2;
04793     w = sw1*sw2;
04794   }
04795   return *this;
04796 }
04797 
04798 ON_4dPoint& ON_4dPoint::operator-=(const ON_4dPoint& p)
04799 {
04800   // difference w = sqrt(w1*w2)
04801   if ( p.w == w ) {
04802     x -= p.x;
04803     y -= p.y;
04804     z -= p.z;
04805   }
04806   else if (p.w == 0.0 ) {
04807     x -= p.x;
04808     y -= p.y;
04809     z -= p.z;
04810   }
04811   else if ( w == 0.0 ) {
04812     x -= p.x;
04813     y -= p.y;
04814     z -= p.z;
04815     w = p.w;
04816   }
04817   else {
04818     const double sw1 = (w>0.0) ? sqrt(w) : -sqrt(-w);
04819     const double sw2 = (p.w>0.0) ? sqrt(p.w) : -sqrt(-p.w);
04820     const double s1 = sw2/sw1;
04821     const double s2 = sw1/sw2;
04822     x = x*s1 - p.x*s2;
04823     y = y*s1 - p.y*s2;
04824     z = z*s1 - p.z*s2;
04825     w = sw1*sw2;
04826   }
04827   return *this;
04828 }
04829 
04830 ON_4dPoint ON_4dPoint::operator+( const ON_4dPoint& p ) const
04831 {
04832   ON_4dPoint q(x,y,z,w);
04833   q+=p;
04834   return q;
04835 }
04836 
04837 ON_4dPoint ON_4dPoint::operator-( const ON_4dPoint& p ) const
04838 {
04839   ON_4dPoint q(x,y,z,w);
04840   q-=p;
04841   return q;
04842 }
04843 
04844 ON_4dPoint ON_4dPoint::operator*( double d ) const
04845 {
04846   return ON_4dPoint(x*d,y*d,z*d,w*d);
04847 }
04848 
04849 ON_4dPoint ON_4dPoint::operator/( double d ) const
04850 {
04851   const double one_over_d = 1.0/d;
04852   return ON_4dPoint(x*one_over_d,y*one_over_d,z*one_over_d,w*one_over_d);
04853 }
04854 
04855 double ON_4dPoint::operator*(const ON_4dPoint& h) const
04856 {
04857   return x*h.x + y*h.y + z*h.z + w*h.w;
04858 }
04859 
04860 bool ON_4dPoint::operator==( ON_4dPoint p ) const
04861 {
04862   ON_4dPoint a = *this; a.Normalize(); p.Normalize();
04863   if ( fabs(a.x-p.x) > ON_SQRT_EPSILON ) return false;
04864   if ( fabs(a.y-p.y) > ON_SQRT_EPSILON ) return false;
04865   if ( fabs(a.z-p.z) > ON_SQRT_EPSILON ) return false;
04866   if ( fabs(a.w-p.w) > ON_SQRT_EPSILON ) return false;
04867   return true;
04868 }
04869 
04870 bool ON_4dPoint::operator!=( const ON_4dPoint& p ) const
04871 {
04872   return (*this == p)?false:true;
04873 }
04874 
04875 double ON_4dPoint::operator[](int i) const
04876 {
04877   return ((i<=0)?x:((i>=3)?w:((i==1)?y:z)));
04878 }
04879 
04880 double& ON_4dPoint::operator[](int i)
04881 {
04882   double* pd = (i<=0) ? &x : ( (i>=3) ? &w : (i==1)?&y:&z);
04883   return *pd;
04884 }
04885 
04886 double ON_4dPoint::operator[](unsigned int i) const
04887 {
04888   return ((i<=0)?x:((i>=3)?w:((i==1)?y:z)));
04889 }
04890 
04891 double& ON_4dPoint::operator[](unsigned int i)
04892 {
04893   double* pd = (i<=0) ? &x : ( (i>=3) ? &w : (i==1)?&y:&z);
04894   return *pd;
04895 }
04896 
04897 int ON_4dPoint::MaximumCoordinateIndex() const
04898 {
04899   const double* a = &x;
04900   int i = ( fabs(y) > fabs(x) ) ? 1 : 0;
04901   if (fabs(z) > fabs(a[i])) i = 2; if (fabs(w) > fabs(a[i])) i = 3;
04902   return i;
04903 }
04904 
04905 double ON_4dPoint::MaximumCoordinate() const
04906 {
04907   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);
04908   return c;
04909 }
04910 
04911 int ON_4dPoint::MinimumCoordinateIndex() const
04912 {
04913   const double* a = &x;
04914   int i = ( fabs(y) < fabs(x) ) ? 1 : 0;
04915   if (fabs(z) < fabs(a[i])) i = 2; if (fabs(w) < fabs(a[i])) i = 3;
04916   return i;
04917 }
04918 
04919 double ON_4dPoint::MinimumCoordinate() const
04920 {
04921   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);
04922   return c;
04923 }
04924 
04925 
04926 void ON_4dPoint::Zero()
04927 {
04928   x = y = z = w = 0.0;
04929 }
04930 
04931 ON_4dPoint operator*( double d, const ON_4dPoint& p )
04932 {
04933   return ON_4dPoint( d*p.x, d*p.y, d*p.z, d*p.w );
04934 }
04935 
04937 //
04938 // ON_2dVector
04939 //
04940 
04941 // static
04942 const ON_2dVector& ON_2dVector::UnitVector(int index)
04943 {
04944   static ON_2dVector o(0.0,0.0);
04945   static ON_2dVector x(1.0,0.0);
04946   static ON_2dVector y(0.0,1.0);
04947   switch(index)
04948   {
04949   case 0:
04950     return x;
04951   case 1:
04952     return y;
04953   }
04954   return o;
04955 }
04956 
04957 ON_2dVector::ON_2dVector()
04958 {}
04959 
04960 ON_2dVector::ON_2dVector( const float* v )
04961 {
04962   if (v) {
04963     x = (double)v[0]; y = (double)v[1];
04964   }
04965   else {
04966     x = y = 0.0;
04967   }
04968 }
04969 
04970 ON_2dVector::ON_2dVector( const double* v )
04971 {
04972   if (v) {
04973     x = v[0]; y = v[1];
04974   }
04975   else {
04976     x = y = 0.0;
04977   }
04978 }
04979 
04980 ON_2dVector::ON_2dVector(double xx,double yy)
04981 {x=xx;y=yy;}
04982 
04983 ON_2dVector::ON_2dVector(const ON_3dVector& v)
04984 {x=v.x;y=v.y;}
04985 
04986 ON_2dVector::ON_2dVector(const ON_2dPoint& p)
04987 {x=p.x;y=p.y;}
04988 
04989 ON_2dVector::ON_2dVector(const ON_3dPoint& p)
04990 {x=p.x;y=p.y;}
04991 
04992 ON_2dVector::ON_2dVector(const ON_2fVector& v)
04993 {x=v.x;y=v.y;}
04994 
04995 ON_2dVector::ON_2dVector(const ON_3fVector& v)
04996 {x=v.x;y=v.y;}
04997 
04998 ON_2dVector::ON_2dVector(const ON_2fPoint& p)
04999 {x=p.x;y=p.y;}
05000 
05001 ON_2dVector::ON_2dVector(const ON_3fPoint& p)
05002 {x=p.x;y=p.y;}
05003 
05004 
05005 ON_2dVector::operator double*()
05006 {
05007   return &x;
05008 }
05009 
05010 ON_2dVector::operator const double*() const
05011 {
05012   return &x;
05013 }
05014 
05015 ON_2dVector& ON_2dVector::operator=(const float* v)
05016 {
05017   if ( v ) {
05018     x = (double)v[0];
05019     y = (double)v[1];
05020   }
05021   else {
05022     x = y = 0.0;
05023   }
05024   return *this;
05025 }
05026 
05027 ON_2dVector& ON_2dVector::operator=(const double* v)
05028 {
05029   if ( v ) {
05030     x = v[0];
05031     y = v[1];
05032   }
05033   else {
05034     x = y = 0.0;
05035   }
05036   return *this;
05037 }
05038 
05039 ON_2dVector& ON_2dVector::operator=(const ON_3dVector& v)
05040 {
05041   x = v.x;
05042   y = v.y;
05043   return *this;
05044 }
05045 
05046 ON_2dVector& ON_2dVector::operator=(const ON_2dPoint& p)
05047 {
05048   x = p.x;
05049   y = p.y;
05050   return *this;
05051 }
05052 
05053 ON_2dVector& ON_2dVector::operator=(const ON_3dPoint& p)
05054 {
05055   x = p.x;
05056   y = p.y;
05057   return *this;
05058 }
05059 
05060 ON_2dVector& ON_2dVector::operator=(const ON_2fVector& v)
05061 {
05062   x = v.x;
05063   y = v.y;
05064   return *this;
05065 }
05066 
05067 ON_2dVector& ON_2dVector::operator=(const ON_3fVector& v)
05068 {
05069   x = v.x;
05070   y = v.y;
05071   return *this;
05072 }
05073 
05074 ON_2dVector& ON_2dVector::operator=(const ON_2fPoint& p)
05075 {
05076   x = p.x;
05077   y = p.y;
05078   return *this;
05079 }
05080 
05081 ON_2dVector& ON_2dVector::operator=(const ON_3fPoint& p)
05082 {
05083   x = p.x;
05084   y = p.y;
05085   return *this;
05086 }
05087 
05088 ON_2dVector ON_2dVector::operator-() const
05089 {
05090   return ON_2dVector(-x,-y);
05091 }
05092 
05093 ON_2dVector& ON_2dVector::operator*=(double d)
05094 {
05095   x *= d;
05096   y *= d;
05097   return *this;
05098 }
05099 
05100 ON_2dVector& ON_2dVector::operator/=(double d)
05101 {
05102   const double one_over_d = 1.0/d;
05103   x *= one_over_d;
05104   y *= one_over_d;
05105   return *this;
05106 }
05107 
05108 ON_2dVector& ON_2dVector::operator+=(const ON_2dVector& v)
05109 {
05110   x += v.x;
05111   y += v.y;
05112   return *this;
05113 }
05114 
05115 ON_2dVector& ON_2dVector::operator-=(const ON_2dVector& v)
05116 {
05117   x -= v.x;
05118   y -= v.y;
05119   return *this;
05120 }
05121 
05122 ON_2dVector ON_2dVector::operator*( int i ) const
05123 {
05124   double d = i;
05125   return ON_2dVector(x*d,y*d);
05126 }
05127 
05128 ON_2dVector ON_2dVector::operator*( float f ) const
05129 {
05130   double d = f;
05131   return ON_2dVector(x*d,y*d);
05132 }
05133 
05134 ON_2dVector ON_2dVector::operator*( double d ) const
05135 {
05136   return ON_2dVector(x*d,y*d);
05137 }
05138 
05139 double ON_2dVector::operator*( const ON_2dVector& v ) const
05140 {
05141   return (x*v.x + y*v.y);
05142 }
05143 
05144 double ON_2dVector::operator*( const ON_2dPoint& v ) const
05145 {
05146   return (x*v.x + y*v.y);
05147 }
05148 
05149 double ON_2dVector::operator*( const ON_2fVector& v ) const
05150 {
05151   return (x*v.x + y*v.y);
05152 }
05153 
05154 ON_2dVector ON_2dVector::operator/( int i ) const
05155 {
05156   const double one_over_d = 1.0/((double)i);
05157   return ON_2dVector(x*one_over_d,y*one_over_d);
05158 }
05159 
05160 ON_2dVector ON_2dVector::operator/( float f ) const
05161 {
05162   const double one_over_d = 1.0/((double)f);
05163   return ON_2dVector(x*one_over_d,y*one_over_d);
05164 }
05165 
05166 ON_2dVector ON_2dVector::operator/( double d ) const
05167 {
05168   const double one_over_d = 1.0/d;
05169   return ON_2dVector(x*one_over_d,y*one_over_d);
05170 }
05171 
05172 ON_2dVector ON_2dVector::operator+( const ON_2dVector& v ) const
05173 {
05174   return ON_2dVector(x+v.x,y+v.y);
05175 }
05176 
05177 ON_2dPoint ON_2dVector::operator+( const ON_2dPoint& p ) const
05178 {
05179   return ON_2dPoint(x+p.x,y+p.y);
05180 }
05181 
05182 ON_2dVector ON_2dVector::operator-( const ON_2dVector& v ) const
05183 {
05184   return ON_2dVector(x-v.x,y-v.y);
05185 }
05186 
05187 ON_2dPoint ON_2dVector::operator-( const ON_2dPoint& v ) const
05188 {
05189   return ON_2dPoint(x-v.x,y-v.y);
05190 }
05191 
05192 
05193 ON_3dVector ON_2dVector::operator+( const ON_3dVector& v ) const
05194 {
05195   return ON_3dVector(x+v.x,y+v.y,v.z);
05196 }
05197 
05198 ON_3dPoint ON_2dVector::operator+( const ON_3dPoint& p ) const
05199 {
05200   return ON_3dPoint(x+p.x,y+p.y,p.z);
05201 }
05202 
05203 ON_3dVector ON_2dVector::operator-( const ON_3dVector& v ) const
05204 {
05205   return ON_3dVector(x-v.x,y-v.y,-v.z);
05206 }
05207 
05208 ON_3dPoint ON_2dVector::operator-( const ON_3dPoint& v ) const
05209 {
05210   return ON_3dPoint(x-v.x,y-v.y,-v.z);
05211 }
05212 
05213 ON_2dVector ON_2dVector::operator+( const ON_2fVector& v ) const
05214 {
05215   return ON_2dVector(x+v.x,y+v.y);
05216 }
05217 
05218 ON_2dPoint ON_2dVector::operator+( const ON_2fPoint& p ) const
05219 {
05220   return ON_2dPoint(x+p.x,y+p.y);
05221 }
05222 
05223 ON_2dVector ON_2dVector::operator-( const ON_2fVector& v ) const
05224 {
05225   return ON_2dVector(x-v.x,y-v.y);
05226 }
05227 
05228 ON_2dPoint ON_2dVector::operator-( const ON_2fPoint& v ) const
05229 {
05230   return ON_2dPoint(x-v.x,y-v.y);
05231 }
05232 
05233 
05234 ON_3dVector ON_2dVector::operator+( const ON_3fVector& v ) const
05235 {
05236   return ON_3dVector(x+v.x,y+v.y,v.z);
05237 }
05238 
05239 ON_3dPoint ON_2dVector::operator+( const ON_3fPoint& p ) const
05240 {
05241   return ON_3dPoint(x+p.x,y+p.y,p.z);
05242 }
05243 
05244 ON_3dVector ON_2dVector::operator-( const ON_3fVector& v ) const
05245 {
05246   return ON_3dVector(x-v.x,y-v.y,-v.z);
05247 }
05248 
05249 ON_3dPoint ON_2dVector::operator-( const ON_3fPoint& v ) const
05250 {
05251   return ON_3dPoint(x-v.x,y-v.y,-v.z);
05252 }
05253 
05254 
05255 
05256 double ON_2dVector::operator*(const ON_4dPoint& h) const
05257 {
05258   return x*h.x + y*h.y;
05259 }
05260 
05261 bool ON_2dVector::operator==( const ON_2dVector& v ) const
05262 {
05263   return (x==v.x&&y==v.y)?true:false;
05264 }
05265 
05266 bool ON_2dVector::operator!=( const ON_2dVector& v ) const
05267 {
05268   return (x!=v.x||y!=v.y)?true:false;
05269 }
05270 
05271 bool ON_2dVector::operator<=( const ON_2dVector& v ) const
05272 {
05273   // dictionary order
05274   return ((x<v.x)?true:((x==v.x&&y<=v.y)?true:false));
05275 }
05276 
05277 bool ON_2dVector::operator>=( const ON_2dVector& v ) const
05278 {
05279   // dictionary order
05280   return ((x>v.x)?true:((x==v.x&&y>=v.y)?true:false));
05281 }
05282 
05283 bool ON_2dVector::operator<( const ON_2dVector& v ) const
05284 {
05285   // dictionary order
05286   return ((x<v.x)?true:((x==v.x&&y<v.y)?true:false));
05287 }
05288 
05289 bool ON_2dVector::operator>( const ON_2dVector& v ) const
05290 {
05291   // dictionary order
05292   return ((x>v.x)?true:((x==v.x&&y>v.y)?true:false));
05293 }
05294 
05295 double ON_2dVector::operator[](int i) const
05296 {
05297   return ((i<=0)?x:y);
05298 }
05299 
05300 double& ON_2dVector::operator[](int i)
05301 {
05302   double* pd = (i<=0)? &x : &y;
05303   return *pd;
05304 }
05305 
05306 double ON_2dVector::operator[](unsigned int i) const
05307 {
05308   return ((i<=0)?x:y);
05309 }
05310 
05311 double& ON_2dVector::operator[](unsigned int i)
05312 {
05313   double* pd = (i<=0)? &x : &y;
05314   return *pd;
05315 }
05316 
05317 int ON_2dVector::MaximumCoordinateIndex() const
05318 {
05319   return ( (fabs(y)>fabs(x)) ? 1 : 0 );
05320 }
05321 
05322 double ON_2dVector::MaximumCoordinate() const
05323 {
05324   double c = fabs(x); if (fabs(y)>c) c=fabs(y);
05325   return c;
05326 }
05327 
05328 int ON_2dVector::MinimumCoordinateIndex() const
05329 {
05330   return (fabs(y)<fabs(x)) ? 1: 0;
05331 }
05332 
05333 double ON_2dVector::MinimumCoordinate() const
05334 {
05335   double c = fabs(x); if (fabs(y)<c) c=fabs(y);
05336   return c;
05337 }
05338 
05339 double ON_2dVector::LengthSquared() const
05340 {
05341   return (x*x + y*y);
05342 }
05343 
05344 double ON_Length2d( double x, double y )
05345 {
05346   double len;
05347   x = fabs(x);
05348   y = fabs(y);
05349   if ( y > x ) {
05350     len = x; x = y; y = len;
05351   }
05352  
05353   // 15 September 2003 Dale Lear
05354   //     For small denormalized doubles (positive but smaller
05355   //     than DBL_MIN), some compilers/FPUs set 1.0/fx to +INF.
05356   //     Without the ON_DBL_MIN test we end up with
05357   //     microscopic vectors that have infinte length!
05358   //
05359   //     This code is absolutely necessary.  It is a critical
05360   //     part of the bug fix for RR 11217.
05361   if ( x > ON_DBL_MIN )
05362   {
05363     y /= x;
05364     len = x*sqrt(1.0 + y*y);
05365   }
05366   else if ( x > 0.0 && ON_IS_FINITE(x) )
05367     len = x;
05368   else
05369     len = 0.0;
05370 
05371   return len;
05372 }
05373 
05374 double ON_2dVector::Length() const
05375 {
05376   return ON_Length2d(x,y);
05377 }
05378 
05379 double ON_2dVector::WedgeProduct(const ON_2dVector& B) const{
05380         return x*B.y - y*B.x;
05381 }
05382 
05383 void ON_2dVector::Zero()
05384 {
05385   x = y = 0.0;
05386 }
05387 
05388 void ON_2dVector::Reverse()
05389 {
05390   x = -x;
05391   y = -y;
05392 }
05393 
05394 bool ON_2dVector::Unitize()
05395 {
05396   // 15 September 2003 Dale Lear
05397   //     Added the ON_IS_FINITE and ON_DBL_MIN test.  See ON_2dVector::Length()
05398   //     for details.
05399   double d = Length();
05400   if ( ON_IS_FINITE(d) )
05401   {
05402     if ( d > ON_DBL_MIN ) 
05403     {
05404       x /= d;
05405       y /= d;
05406       return true;
05407     }
05408     
05409     if ( d > 0.0 )
05410     {
05411       // This code is rarely used and can be slow.
05412       // It multiplies by 2^1023 in an attempt to 
05413       // normalize the coordinates.
05414       // If the renormalization works, then we're
05415       // ok.  If the renormalization fails, we
05416       // return false.
05417       ON_2dVector tmp;
05418       tmp.x = x*8.9884656743115795386465259539451e+307;
05419       tmp.y = y*8.9884656743115795386465259539451e+307;
05420       d = tmp.Length();
05421       if ( ON_IS_FINITE(d) && d > ON_DBL_MIN )
05422       {
05423         x = tmp.x/d;
05424         y = tmp.y/d;
05425         return true;
05426       }
05427     }
05428   }
05429 
05430   x = 0.0;
05431   y = 0.0;
05432 
05433   return false;
05434 }
05435 
05436 bool ON_2dVector::IsTiny( double tiny_tol ) const
05437 {
05438   return (fabs(x) <= tiny_tol && fabs(y) <= tiny_tol );
05439 }
05440 
05441 bool ON_2dVector::IsZero() const
05442 {
05443   return (x==0.0 && y==0.0);
05444 }
05445 
05446 bool ON_2dVector::IsUnitVector() const
05447 {
05448   return (x != ON_UNSET_VALUE && y != ON_UNSET_VALUE && fabs(Length() - 1.0) <= ON_SQRT_EPSILON);
05449 }
05450 
05451 // set this vector to be perpendicular to another vector
05452 bool ON_2dVector::PerpendicularTo( // Result is not unitized. 
05453                       // returns false if input vector is zero
05454       const ON_2dVector& v
05455       )
05456 {
05457   y = v.x;
05458   x = -v.y;
05459   return (x!= 0.0 || y!= 0.0) ? true : false;
05460 }
05461 
05462 // set this vector to be perpendicular to a line defined by 2 points
05463 bool ON_2dVector::PerpendicularTo( 
05464       const ON_2dPoint& p, 
05465       const ON_2dPoint& q
05466       )
05467 {
05468   return PerpendicularTo(q-p);
05469 }
05470 
05471 ON_2dVector operator*(int i, const ON_2dVector& v)
05472 {
05473   double d = i;
05474   return ON_2dVector(d*v.x,d*v.y);
05475 }
05476 
05477 ON_2dVector operator*(float f, const ON_2dVector& v)
05478 {
05479   double d = f;
05480   return ON_2dVector(d*v.x,d*v.y);
05481 }
05482 
05483 ON_2dVector operator*(double d, const ON_2dVector& v)
05484 {
05485   return ON_2dVector(d*v.x,d*v.y);
05486 }
05487 
05488 double ON_DotProduct( const ON_2dVector& a , const ON_2dVector& b )
05489 {
05490   // inner (dot) product between 3d vectors
05491   return (a.x*b.x + a.y*b.y );
05492 }
05493 
05494 double ON_WedgeProduct( const ON_2dVector& a , const ON_2dVector& b )
05495 {
05496   // exterior (wedge) product between 2d vectors
05497   return (a.x*b.y - a.y*b.x );
05498 }
05499 
05500 ON_3dVector ON_CrossProduct( const ON_2dVector& a , const ON_2dVector& b )
05501 {
05502   return ON_3dVector(0.0, 0.0, a.x*b.y - b.x*a.y );
05503 }
05504 
05506 //
05507 // ON_3dVector
05508 //
05509 
05510 // static
05511 const ON_3dVector& ON_3dVector::UnitVector(int index)
05512 {
05513   static ON_3dVector o(0.0,0.0,0.0);
05514   static ON_3dVector x(1.0,0.0,0.0);
05515   static ON_3dVector y(0.0,1.0,0.0);
05516   static ON_3dVector z(0.0,0.0,1.0);
05517   switch(index)
05518   {
05519   case 0:
05520     return x;
05521   case 1:
05522     return y;
05523   case 2:
05524     return z;
05525   }
05526   return o;
05527 }
05528 
05529 ON_3dVector::ON_3dVector()
05530 {}
05531 
05532 ON_3dVector::ON_3dVector( const float* v )
05533 {
05534   if (v) {
05535     x = (double)v[0]; y = (double)v[1]; z = (double)v[2];
05536   }
05537   else {
05538     x = y = z = 0.0;
05539   }
05540 }
05541 
05542 ON_3dVector::ON_3dVector( const double* v )
05543 {
05544   if (v) {
05545     x = v[0]; y = v[1]; z = v[2];
05546   }
05547   else {
05548     x = y = z = 0.0;
05549   }
05550 }
05551 
05552 ON_3dVector::ON_3dVector(double xx,double yy,double zz)
05553 {x=xx;y=yy;z=zz;}
05554 
05555 ON_3dVector::ON_3dVector(const ON_2dVector& v)
05556 {x=v.x;y=v.y;z=0.0;}
05557 
05558 ON_3dVector::ON_3dVector(const ON_2dPoint& p)
05559 {x=p.x;y=p.y;z=0.0;}
05560 
05561 ON_3dVector::ON_3dVector(const ON_3dPoint& p)
05562 {x=p.x;y=p.y;z=p.z;}
05563 
05564 ON_3dVector::ON_3dVector(const ON_2fVector& v)
05565 {x=v.x;y=v.y;z=0.0;}
05566 
05567 ON_3dVector::ON_3dVector(const ON_3fVector& v)
05568 {x=v.x;y=v.y;z=v.z;}
05569 
05570 ON_3dVector::ON_3dVector(const ON_2fPoint& p)
05571 {x=p.x;y=p.y;z=0.0;}
05572 
05573 ON_3dVector::ON_3dVector(const ON_3fPoint& p)
05574 {x=p.x;y=p.y;z=p.z;}
05575 
05576 ON_3dVector::operator double*()
05577 {
05578   return &x;
05579 }
05580 
05581 ON_3dVector::operator const double*() const
05582 {
05583   return &x;
05584 }
05585 
05586 ON_3dVector& ON_3dVector::operator=(const float* v)
05587 {
05588   if ( v ) {
05589     x = (double)v[0];
05590     y = (double)v[1];
05591     z = (double)v[2];
05592   }
05593   else {
05594     x = y = z = 0.0;
05595   }
05596   return *this;
05597 }
05598 
05599 ON_3dVector& ON_3dVector::operator=(const double* v)
05600 {
05601   if ( v ) {
05602     x = v[0];
05603     y = v[1];
05604     z = v[2];
05605   }
05606   else {
05607     x = y = z = 0.0;
05608   }
05609   return *this;
05610 }
05611 
05612 ON_3dVector& ON_3dVector::operator=(const ON_2dVector& v)
05613 {
05614   x = v.x;
05615   y = v.y;
05616   z = 0.0;
05617   return *this;
05618 }
05619 
05620 ON_3dVector& ON_3dVector::operator=(const ON_2dPoint& p)
05621 {
05622   x = p.x;
05623   y = p.y;
05624   z = 0.0;
05625   return *this;
05626 }
05627 
05628 ON_3dVector& ON_3dVector::operator=(const ON_3dPoint& p)
05629 {
05630   x = p.x;
05631   y = p.y;
05632   z = p.z;
05633   return *this;
05634 }
05635 
05636 
05637 ON_3dVector& ON_3dVector::operator=(const ON_2fVector& v)
05638 {
05639   x = v.x;
05640   y = v.y;
05641   z = 0.0;
05642   return *this;
05643 }
05644 
05645 ON_3dVector& ON_3dVector::operator=(const ON_3fVector& v)
05646 {
05647   x = v.x;
05648   y = v.y;
05649   z = v.z;
05650   return *this;
05651 }
05652 
05653 ON_3dVector& ON_3dVector::operator=(const ON_2fPoint& p)
05654 {
05655   x = p.x;
05656   y = p.y;
05657   z = 0.0;
05658   return *this;
05659 }
05660 
05661 ON_3dVector& ON_3dVector::operator=(const ON_3fPoint& p)
05662 {
05663   x = p.x;
05664   y = p.y;
05665   z = p.z;
05666   return *this;
05667 }
05668 
05669 ON_3dVector ON_3dVector::operator-() const
05670 {
05671   return ON_3dVector(-x,-y,-z);
05672 }
05673 
05674 ON_3dVector& ON_3dVector::operator*=(double d)
05675 {
05676   x *= d;
05677   y *= d;
05678   z *= d;
05679   return *this;
05680 }
05681 
05682 ON_3dVector& ON_3dVector::operator/=(double d)
05683 {
05684   const double one_over_d = 1.0/d;
05685   x *= one_over_d;
05686   y *= one_over_d;
05687   z *= one_over_d;
05688   return *this;
05689 }
05690 
05691 ON_3dVector& ON_3dVector::operator+=(const ON_3dVector& v)
05692 {
05693   x += v.x;
05694   y += v.y;
05695   z += v.z;
05696   return *this;
05697 }
05698 
05699 ON_3dVector& ON_3dVector::operator-=(const ON_3dVector& v)
05700 {
05701   x -= v.x;
05702   y -= v.y;
05703   z -= v.z;
05704   return *this;
05705 }
05706 
05707 ON_3dVector ON_3dVector::operator*( int i ) const
05708 {
05709   double d = i;
05710   return ON_3dVector(x*d,y*d,z*d);
05711 }
05712 
05713 ON_3dVector ON_3dVector::operator*( float f ) const
05714 {
05715   double d = f;
05716   return ON_3dVector(x*d,y*d,z*d);
05717 }
05718 
05719 ON_3dVector ON_3dVector::operator*( double d ) const
05720 {
05721   return ON_3dVector(x*d,y*d,z*d);
05722 }
05723 
05724 double ON_3dVector::operator*( const ON_3dVector& v ) const
05725 {
05726   return (x*v.x + y*v.y + z*v.z);
05727 }
05728 
05729 double ON_3dVector::operator*( const ON_3dPoint& v ) const
05730 {
05731   return (x*v.x + y*v.y + z*v.z);
05732 }
05733 
05734 double ON_3dVector::operator*( const ON_3fVector& v ) const
05735 {
05736   return (x*v.x + y*v.y + z*v.z);
05737 }
05738 
05739 ON_3dVector ON_3dVector::operator/( int i ) const
05740 {
05741   const double one_over_d = 1.0/((double)i);
05742   return ON_3dVector(x*one_over_d,y*one_over_d,z*one_over_d);
05743 }
05744 
05745 ON_3dVector ON_3dVector::operator/( float f ) const
05746 {
05747   const double one_over_d = 1.0/((double)f);
05748   return ON_3dVector(x*one_over_d,y*one_over_d,z*one_over_d);
05749 }
05750 
05751 ON_3dVector ON_3dVector::operator/( double d ) const
05752 {
05753   const double one_over_d = 1.0/d;
05754   return ON_3dVector(x*one_over_d,y*one_over_d,z*one_over_d);
05755 }
05756 
05757 ON_3dVector ON_3dVector::operator+( const ON_3dVector& v ) const
05758 {
05759   return ON_3dVector(x+v.x,y+v.y,z+v.z);
05760 }
05761 
05762 ON_3dPoint ON_3dVector::operator+( const ON_3dPoint& p ) const
05763 {
05764   return ON_3dPoint(x+p.x,y+p.y,z+p.z);
05765 }
05766 
05767 ON_3dVector ON_3dVector::operator-( const ON_3dVector& v ) const
05768 {
05769   return ON_3dVector(x-v.x,y-v.y,z-v.z);
05770 }
05771 
05772 ON_3dPoint ON_3dVector::operator-( const ON_3dPoint& v ) const
05773 {
05774   return ON_3dPoint(x-v.x,y-v.y,z-v.z);
05775 }
05776 
05777 ON_3dVector ON_3dVector::operator+( const ON_2dVector& v ) const
05778 {
05779   return ON_3dVector(x+v.x,y+v.y,z);
05780 }
05781 
05782 ON_3dPoint ON_3dVector::operator+( const ON_2dPoint& p ) const
05783 {
05784   return ON_3dPoint(x+p.x,y+p.y,z);
05785 }
05786 
05787 ON_3dVector ON_3dVector::operator-( const ON_2dVector& v ) const
05788 {
05789   return ON_3dVector(x-v.x,y-v.y,z);
05790 }
05791 
05792 ON_3dPoint ON_3dVector::operator-( const ON_2dPoint& v ) const
05793 {
05794   return ON_3dPoint(x-v.x,y-v.y,z);
05795 }
05796 
05797 ON_3dVector ON_3dVector::operator+( const ON_3fVector& v ) const
05798 {
05799   return ON_3dVector(x+v.x,y+v.y,z+v.z);
05800 }
05801 
05802 ON_3dPoint ON_3dVector::operator+( const ON_3fPoint& p ) const
05803 {
05804   return ON_3dPoint(x+p.x,y+p.y,z+p.z);
05805 }
05806 
05807 ON_3dVector ON_3dVector::operator-( const ON_3fVector& v ) const
05808 {
05809   return ON_3dVector(x-v.x,y-v.y,z-v.z);
05810 }
05811 
05812 ON_3dPoint ON_3dVector::operator-( const ON_3fPoint& v ) const
05813 {
05814   return ON_3dPoint(x-v.x,y-v.y,z-v.z);
05815 }
05816 
05817 ON_3dVector ON_3dVector::operator+( const ON_2fVector& v ) const
05818 {
05819   return ON_3dVector(x+v.x,y+v.y,z);
05820 }
05821 
05822 ON_3dPoint ON_3dVector::operator+( const ON_2fPoint& p ) const
05823 {
05824   return ON_3dPoint(x+p.x,y+p.y,z);
05825 }
05826 
05827 ON_3dVector ON_3dVector::operator-( const ON_2fVector& v ) const
05828 {
05829   return ON_3dVector(x-v.x,y-v.y,z);
05830 }
05831 
05832 ON_3dPoint ON_3dVector::operator-( const ON_2fPoint& v ) const
05833 {
05834   return ON_3dPoint(x-v.x,y-v.y,z);
05835 }
05836 
05837 
05838 double ON_3dVector::operator*(const ON_4dPoint& h) const
05839 {
05840   return x*h.x + y*h.y + z*h.z;
05841 }
05842 
05843 bool ON_3dVector::operator==( const ON_3dVector& v ) const
05844 {
05845   return (x==v.x&&y==v.y&&z==v.z)?true:false;
05846 }
05847 
05848 bool ON_3dVector::operator!=( const ON_3dVector& v ) const
05849 {
05850   return (x!=v.x||y!=v.y||z!=v.z)?true:false;
05851 }
05852 
05853 bool ON_3dVector::operator<=( const ON_3dVector& v ) const
05854 {
05855   // dictionary order
05856   return ((x<v.x)?true:((x==v.x)?((y<v.y)?true:(y==v.y&&z<=v.z)?true:false):false));
05857 }
05858 
05859 bool ON_3dVector::operator>=( const ON_3dVector& v ) const
05860 {
05861   // dictionary order
05862   return ((x>v.x)?true:((x==v.x)?((y>v.y)?true:(y==v.y&&z>=v.z)?true:false):false));
05863 }
05864 
05865 bool ON_3dVector::operator<( const ON_3dVector& v ) const
05866 {
05867   // dictionary order
05868   return ((x<v.x)?true:((x==v.x)?((y<v.y)?true:(y==v.y&&z<v.z)?true:false):false));
05869 }
05870 
05871 bool ON_3dVector::operator>( const ON_3dVector& v ) const
05872 {
05873   // dictionary order
05874   return ((x>v.x)?true:((x==v.x)?((y>v.y)?true:(y==v.y&&z>v.z)?true:false):false));
05875 }
05876 
05877 double ON_3dVector::operator[](int i) const
05878 {
05879   return ( (i<=0)?x:((i>=2)?z:y) );
05880 }
05881 
05882 double& ON_3dVector::operator[](int i)
05883 {
05884   double* pd = (i<=0)? &x : ( (i>=2) ?  &z : &y);
05885   return *pd;
05886 }
05887 
05888 double ON_3dVector::operator[](unsigned int i) const
05889 {
05890   return ( (i<=0)?x:((i>=2)?z:y) );
05891 }
05892 
05893 double& ON_3dVector::operator[](unsigned int i)
05894 {
05895   double* pd = (i<=0)? &x : ( (i>=2) ?  &z : &y);
05896   return *pd;
05897 }
05898 
05899 int ON_3dVector::MaximumCoordinateIndex() const
05900 {
05901   return (fabs(y)>fabs(x)) ? ((fabs(z)>fabs(y))?2:1) : ((fabs(z)>fabs(x))?2:0);
05902 }
05903 
05904 double ON_3dVector::MaximumCoordinate() const
05905 {
05906   double c = fabs(x); if (fabs(y)>c) c=fabs(y); if (fabs(z)>c) c=fabs(z);
05907   return c;
05908 }
05909 
05910 int ON_3dVector::MinimumCoordinateIndex() const
05911 {
05912   return (fabs(y)<fabs(x)) ? ((fabs(z)<fabs(y))?2:1) : ((fabs(z)<fabs(x))?2:0);
05913 }
05914 
05915 double ON_3dVector::MinimumCoordinate() const
05916 {
05917   double c = fabs(x); if (fabs(y)<c) c=fabs(y); if (fabs(z)<c) c=fabs(z);
05918   return c;
05919 }
05920 
05921 double ON_3dVector::LengthSquared() const
05922 {
05923   return (x*x + y*y + z*z);
05924 }
05925 
05926 double ON_Length3d(double x, double y, double z)
05927 {
05928   double len;
05929   x = fabs(x);
05930   y = fabs(y);
05931   z = fabs(z);
05932   if ( y >= x && y >= z ) {
05933     len = x; x = y; y = len;
05934   }
05935   else if ( z >= x && z >= y ) {
05936     len = x; x = z; z = len;
05937   }
05938 
05939   // 15 September 2003 Dale Lear
05940   //     For small denormalized doubles (positive but smaller
05941   //     than DBL_MIN), some compilers/FPUs set 1.0/x to +INF.
05942   //     Without the ON_DBL_MIN test we end up with
05943   //     microscopic vectors that have infinte length!
05944   //
05945   //     This code is absolutely necessary.  It is a critical
05946   //     part of the bug fix for RR 11217.
05947   if ( x > ON_DBL_MIN ) 
05948   {
05949     y /= x;
05950     z /= x;
05951     len = x*sqrt(1.0 + y*y + z*z);
05952   }
05953   else if ( x > 0.0 && ON_IS_FINITE(x) )
05954     len = x;
05955   else
05956     len = 0.0;
05957 
05958   return len;
05959 }
05960 
05961 double ON_3dVector::Length() const
05962 {
05963   return ON_Length3d(x,y,z);
05964 }
05965 
05966 void ON_3dVector::Zero()
05967 {
05968   x = y = z = 0.0;
05969 }
05970 
05971 void ON_3dVector::Reverse()
05972 {
05973   x = -x;
05974   y = -y;
05975   z = -z;
05976 }
05977 
05978 bool ON_3dVector::Unitize()
05979 {
05980   // 15 September 2003 Dale Lear
05981   //     Added the ON_IS_FINITE and ON_DBL_MIN test.  See ON_3dVector::Length()
05982   //     for details.
05983   double d = Length();
05984 
05985   if ( ON_IS_FINITE(d) )
05986   {
05987     if ( d > ON_DBL_MIN )
05988     {
05989       x /= d;
05990       y /= d;
05991       z /= d;
05992       return true;
05993     }
05994     
05995     if ( d > 0.0 )
05996     {
05997       // This code is rarely used and can be slow.
05998       // It multiplies by 2^1023 in an attempt to 
05999       // normalize the coordinates.
06000       // If the renormalization works, then we're
06001       // ok.  If the renormalization fails, we
06002       // return false.
06003       ON_3dVector tmp;
06004       tmp.x = x*8.9884656743115795386465259539451e+307;
06005       tmp.y = y*8.9884656743115795386465259539451e+307;
06006       tmp.z = z*8.9884656743115795386465259539451e+307;
06007       d = tmp.Length();
06008       if ( ON_IS_FINITE(d) && d > ON_DBL_MIN )
06009       {
06010         x = tmp.x/d;
06011         y = tmp.y/d;
06012         z = tmp.z/d;
06013         return true;
06014       }
06015     }
06016   }
06017 
06018   x = 0.0;
06019   y = 0.0;
06020   z = 0.0;
06021 
06022   return false;
06023 }
06024 
06025 double ON_3dVector::LengthAndUnitize()
06026 {
06027   double d;
06028   double len = Length();
06029   if ( len > ON_DBL_MIN )
06030   {
06031     d = 1.0/len;
06032     x *= d;
06033     y *= d;
06034     z *= d;
06035   }
06036   else if ( len > 0.0 && ON_IS_FINITE(len) )
06037   {
06038     // This code is rarely used and can be slow.
06039     // It multiplies by 2^1023 in an attempt to 
06040     // normalize the coordinates.
06041     // If the renormalization works, then we're
06042     // ok.  If the renormalization fails, we
06043     // return false.
06044     ON_3dVector tmp;
06045     tmp.x = x*8.9884656743115795386465259539451e+307;
06046     tmp.y = y*8.9884656743115795386465259539451e+307;
06047     tmp.z = z*8.9884656743115795386465259539451e+307;
06048     d = tmp.Length();
06049     if ( d > ON_DBL_MIN )
06050     {
06051       d = 1.0/d;
06052       x = tmp.x*d;
06053       y = tmp.y*d;
06054       z = tmp.z*d;
06055     }
06056     else
06057     {
06058       len = 0.0;
06059       x = 0.0;
06060       y = 0.0;
06061       z = 0.0;
06062     }
06063   }
06064   else
06065   {
06066     len = 0.0;
06067     x = 0.0;
06068     y = 0.0;
06069     z = 0.0;
06070   }
06071 
06072   return len;
06073 }
06074 
06075 
06076 bool ON_3dVector::IsTiny( double tiny_tol ) const
06077 {
06078   return (fabs(x) <= tiny_tol && fabs(y) <= tiny_tol && fabs(z) <= tiny_tol );
06079 }
06080 
06081 bool ON_3dVector::IsZero() const
06082 {
06083   return (x==0.0 && y==0.0 && z==0.0);
06084 }
06085 
06086 bool ON_3dVector::IsUnitVector() const
06087 {
06088   return (x != ON_UNSET_VALUE && y != ON_UNSET_VALUE && z != ON_UNSET_VALUE && fabs(Length() - 1.0) <= ON_SQRT_EPSILON);
06089 }
06090 
06091 ON_3dVector operator*(int i, const ON_3dVector& v)
06092 {
06093   double d = i;
06094   return ON_3dVector(d*v.x,d*v.y,d*v.z);
06095 }
06096 
06097 ON_3dVector operator*(float f, const ON_3dVector& v)
06098 {
06099   double d = f;
06100   return ON_3dVector(d*v.x,d*v.y,d*v.z);
06101 }
06102 
06103 ON_3dVector operator*(double d, const ON_3dVector& v)
06104 {
06105   return ON_3dVector(d*v.x,d*v.y,d*v.z);
06106 }
06107 
06108 double ON_DotProduct( const ON_3dVector& a , const ON_3dVector& b )
06109 {
06110   // inner (dot) product between 3d vectors
06111   return (a.x*b.x + a.y*b.y + a.z*b.z);
06112 }
06113 
06114 ON_3dVector ON_CrossProduct( const ON_3dVector& a , const ON_3dVector& b )
06115 {
06116   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 );
06117 }
06118 
06119 ON_3dVector ON_CrossProduct( const double* a, const double* b )
06120 {
06121   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] );
06122 }
06123 
06124 double ON_TripleProduct( const ON_3dVector& a, const ON_3dVector& b, const ON_3dVector& c )
06125 {
06126   // = a o (b x c )
06127   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));
06128 }
06129 
06130 double ON_TripleProduct( const double* a, const double* b, const double* c )
06131 {
06132   // = a o (b x c )
06133   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]));
06134 }
06135 
06136 bool ON_2dVector::IsValid() const
06137 {
06138   return ( ON_IS_VALID(x) && ON_IS_VALID(y) ) ? true : false;
06139 }
06140 
06141 bool ON_2dVector::IsUnsetVector() const
06142 {
06143   return ( ON_UNSET_VALUE == x && ON_UNSET_VALUE == y );
06144 }
06145 
06146 bool ON_3dVector::IsValid() const
06147 {
06148   return ( ON_IS_VALID(x) && ON_IS_VALID(y) && ON_IS_VALID(z) ) ? true : false;
06149 }
06150 
06151 bool ON_3dVector::IsUnsetVector() const
06152 {
06153   return ( ON_UNSET_VALUE == x && ON_UNSET_VALUE == y && ON_UNSET_VALUE == z );
06154 }
06155 
06156 bool ON_2dPoint::IsValid() const
06157 {
06158   return (ON_IS_VALID(x) && ON_IS_VALID(y)) ? true : false;
06159 }
06160 
06161 bool ON_2dPoint::IsUnsetPoint() const
06162 {
06163   return ( ON_UNSET_VALUE == x && ON_UNSET_VALUE == y );
06164 }
06165 
06166 bool ON_3dPoint::IsValid() const
06167 {
06168   return (ON_IS_VALID(x) && ON_IS_VALID(y) && ON_IS_VALID(z) ) ? true : false;
06169 }
06170 
06171 bool ON_3dPoint::IsUnsetPoint() const
06172 {
06173   return ( ON_UNSET_VALUE == x && ON_UNSET_VALUE == y && ON_UNSET_VALUE == z );
06174 }
06175 
06176 bool ON_4dPoint::IsValid() const
06177 {
06178   return (ON_IS_VALID(x) && ON_IS_VALID(y) && ON_IS_VALID(z) && ON_IS_VALID(w)) ? true : false;
06179 }
06180 
06181 bool ON_4dPoint::IsUnsetPoint() const
06182 {
06183   return ( ON_UNSET_VALUE == x && ON_UNSET_VALUE == y && ON_UNSET_VALUE == z && ON_UNSET_VALUE == w );
06184 }
06185 
06186 
06187 void ON_2dPoint::Set(double xx, double yy)
06188 {
06189   x = xx; y = yy;
06190 }
06191 
06192 void ON_3dPoint::Set(double xx, double yy, double zz)
06193 {
06194   x = xx; y = yy; z = zz;
06195 }
06196 
06197 
06198 void ON_4dPoint::Set(double xx, double yy, double zz, double ww)
06199 {
06200   x = xx; y = yy; z = zz; w = ww;
06201 }
06202 
06203 void ON_2dVector::Set(double xx, double yy)
06204 {
06205   x = xx; y = yy;
06206 }
06207 
06208 void ON_3dVector::Set(double xx, double yy, double zz)
06209 {
06210   x = xx; y = yy; z = zz;
06211 }
06212 
06213 
06214 void ON_2fPoint::Set(float xx, float yy)
06215 {
06216   x = xx; y = yy;
06217 }
06218 
06219 void ON_3fPoint::Set(float xx, float yy, float zz)
06220 {
06221   x = xx; y = yy; z = zz;
06222 }
06223 
06224 
06225 void ON_4fPoint::Set(float xx, float yy, float zz, float ww)
06226 {
06227   x = xx; y = yy; z = zz; w = ww;
06228 }
06229 
06230 void ON_2fVector::Set(float xx, float yy)
06231 {
06232   x = xx; y = yy;
06233 }
06234 
06235 void ON_3fVector::Set(float xx, float yy, float zz)
06236 {
06237   x = xx; y = yy; z = zz;
06238 }
06239 
06240 bool ON_PlaneEquation::Create( ON_3dPoint P, ON_3dVector N )
06241 {
06242   bool rc = false;
06243   if ( P.IsValid() && N.IsValid() )
06244   {
06245     x = N.x;
06246     y = N.y;
06247     z = N.z;
06248     rc = ( fabs(1.0 - Length()) > ON_ZERO_TOLERANCE ) ? Unitize() : true;
06249     d = -(x*P.x + y*P.y + z*P.z);
06250   }
06251   return rc;
06252 }
06253 
06254 ON_PlaneEquation::ON_PlaneEquation()
06255 : ON_3dVector(0.0,0.0,0.0)
06256 , d(0.0)
06257 {}
06258 
06259 ON_PlaneEquation::ON_PlaneEquation(double xx, double yy, double zz, double dd)
06260 : ON_3dVector(xx,yy,zz)
06261 , d(dd)
06262 {}
06263 
06264 const ON_PlaneEquation ON_PlaneEquation::UnsetPlaneEquation(ON_UNSET_VALUE,ON_UNSET_VALUE,ON_UNSET_VALUE,ON_UNSET_VALUE);
06265 const ON_PlaneEquation ON_PlaneEquation::ZeroPlaneEquation(0.0,0.0,0.0,0.0);
06266 
06267 bool ON_PlaneEquation::IsValid() const
06268 {
06269   return ( ON_IS_VALID(x) && ON_IS_VALID(y) && ON_IS_VALID(z) && ON_IS_VALID(d) );
06270 }
06271 
06272 bool ON_PlaneEquation::IsSet() const
06273 {
06274   return ( ON_IS_VALID(x) && ON_IS_VALID(y) && ON_IS_VALID(z) && ON_IS_VALID(d) 
06275            && (0.0 != x || 0.0 != y || 0.0 != z) 
06276          );
06277 }
06278 
06279 double ON_PlaneEquation::ZeroTolerance() const
06280 {
06281   double zero_tolerance = 0.0;
06282   ON_3dVector N(x,y,z);
06283   if ( N.Unitize() && ON_IS_VALID(d) )
06284   {
06285     const ON_3dPoint P( -d*N.x, -d*N.y, -d*N.z  );
06286 
06287     zero_tolerance = fabs(ValueAt(P));
06288 
06289     ON_3dVector X;
06290     X.PerpendicularTo(N);
06291     X.Unitize();
06292     
06293     double t = fabs(ValueAt(P+X));
06294     if ( t > zero_tolerance )
06295       zero_tolerance = t;
06296     t = fabs(ValueAt(P-X));
06297     if ( t > zero_tolerance )
06298       zero_tolerance = t;
06299     t = fabs(ValueAt(P+d*X));
06300     if ( t > zero_tolerance )
06301       zero_tolerance = t;
06302     t = fabs(ValueAt(P-d*X));
06303     if ( t > zero_tolerance )
06304       zero_tolerance = t;
06305 
06306     ON_3dVector Y = ON_CrossProduct(N,X);
06307     Y.Unitize();
06308 
06309     t = fabs(ValueAt(P+Y));
06310     if ( t > zero_tolerance )
06311       zero_tolerance = t;
06312     t = fabs(ValueAt(P-Y));
06313     if ( t > zero_tolerance )
06314       zero_tolerance = t;
06315     t = fabs(ValueAt(P+d*Y));
06316     if ( t > zero_tolerance )
06317       zero_tolerance = t;
06318     t = fabs(ValueAt(P-d*Y));
06319     if ( t > zero_tolerance )
06320       zero_tolerance = t;
06321   }
06322 
06323   return zero_tolerance;
06324 }
06325 
06326 bool ON_PlaneEquation::Transform( const ON_Xform& xform )
06327 {
06328   bool rc = IsValid();
06329   if ( rc )
06330   {
06331     // Apply the inverse transpose to the equation parameters
06332     ON_Xform T(xform);
06333     rc = T.Invert();
06334     if ( rc )
06335     {
06336       const double xx=x;
06337       const double yy=y;
06338       const double zz=z;
06339       const double dd=d;
06340       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;
06341       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;
06342       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;
06343       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;
06344     }
06345   }
06346   return rc;
06347 }
06348 
06349 double ON_PlaneEquation::ValueAt(ON_3dPoint P) const
06350 {
06351   return (x*P.x + y*P.y + z*P.z + d);
06352 }
06353 
06354 double ON_PlaneEquation::ValueAt(ON_4dPoint P) const
06355 {
06356   return (x*P.x + y*P.y + z*P.z + d*P.w);
06357 }
06358 
06359 double ON_PlaneEquation::ValueAt(ON_3dVector P) const
06360 {
06361   return (x*P.x + y*P.y + z*P.z + d);
06362 }
06363 
06364 double ON_PlaneEquation::ValueAt(double xx, double yy, double zz) const
06365 {
06366   return (x*xx + y*yy + z*zz + d);
06367 }
06368 
06369 double* ON_PlaneEquation::ValueAt(
06370       int Pcount,
06371       const ON_3fPoint* P,
06372       double* value,
06373       double value_range[2]
06374       ) const
06375 {
06376   if ( Pcount <= 0 || 0 == P )
06377     return 0;
06378 
06379   int i;
06380   double s;
06381   const double* e = &x;
06382 
06383   if ( 0 == value )
06384     value =  (double*)onmalloc(Pcount * sizeof(*value) );
06385   if ( 0 == value )
06386     return 0;
06387 
06388   if ( 0 != value_range )
06389   {
06390     value[0] = s = e[0]*((double)P[0].x) + e[1]*((double)P[0].y) + e[2]*((double)P[0].z) + e[3];
06391     value_range[0] = s;
06392     value_range[1] = s;
06393     for ( i = 1; i < Pcount; i++ )
06394     {
06395       value[i] = s = e[0]*((double)P[i].x) + e[1]*((double)P[i].y) + e[2]*((double)P[i].z) + e[3];
06396       if ( s < value_range[0] )
06397         value_range[0] = s;
06398       else if ( s > value_range[1] )
06399         value_range[1] = s;
06400     }
06401   }
06402   else
06403   {
06404     for ( i = 0; i < Pcount; i++ )
06405     {
06406       value[i] = e[0]*((double)P[i].x) + e[1]*((double)P[i].y) + e[2]*((double)P[i].z) + e[3];
06407     }
06408   }
06409 
06410   return value;
06411 }
06412 
06413 double* ON_PlaneEquation::ValueAt(
06414       int Pcount,
06415       const ON_3dPoint* P,
06416       double* value,
06417       double value_range[2]
06418       ) const
06419 {
06420   if ( Pcount <= 0 || 0 == P )
06421     return 0;
06422 
06423   int i;
06424   double s;
06425   const double* e = &x;
06426 
06427   if ( 0 == value )
06428     value =  (double*)onmalloc(Pcount * sizeof(*value) );
06429   if ( 0 == value )
06430     return 0;
06431 
06432   if ( 0 != value_range )
06433   {
06434     value[0] = s = e[0]*(P[0].x) + e[1]*(P[0].y) + e[2]*(P[0].z) + e[3];
06435     value_range[0] = s;
06436     value_range[1] = s;
06437     for ( i = 1; i < Pcount; i++ )
06438     {
06439       value[i] = s = e[0]*(P[i].x) + e[1]*(P[i].y) + e[2]*(P[i].z) + e[3];
06440       if ( s < value_range[0] )
06441         value_range[0] = s;
06442       else if ( s > value_range[1] )
06443         value_range[1] = s;
06444     }
06445   }
06446   else
06447   {
06448     for ( i = 0; i < Pcount; i++ )
06449     {
06450       value[i] = e[0]*(P[i].x) + e[1]*(P[i].y) + e[2]*(P[i].z) + e[3];
06451     }
06452   }
06453 
06454   return value;
06455 }
06456 
06457 
06458 
06459 ON_3dPoint ON_PlaneEquation::ClosestPointTo( ON_3dPoint P ) const
06460 {
06461   const double t = -(x*P.x + y*P.y + z*P.z + d)/(x*x+y*y+z*z);
06462   return ON_3dPoint( P.x + t*x, P.y + t*y, P.z + t*z);
06463 }
06464 
06465 double ON_PlaneEquation::MinimumValueAt(const ON_BoundingBox& bbox) const
06466 {
06467   double xx, yy, zz, s;
06468 
06469   s = x*bbox.m_min.x;
06470   if ( s < (xx = x*bbox.m_max.x) ) xx = s;
06471 
06472   s = y*bbox.m_min.y;
06473   if ( s < (yy = y*bbox.m_max.y) ) yy = s;
06474 
06475   s = z*bbox.m_min.z;
06476   if ( s < (zz = z*bbox.m_max.z) ) zz = s;
06477 
06478   return (xx + yy + zz + d);
06479 }
06480 
06481 double ON_PlaneEquation::MaximumValueAt(const ON_BoundingBox& bbox) const
06482 {
06483   double xx, yy, zz, s;
06484 
06485   s = x*bbox.m_min.x;
06486   if ( s > (xx = x*bbox.m_max.x) ) xx = s;
06487 
06488   s = y*bbox.m_min.y;
06489   if ( s > (yy = y*bbox.m_max.y) ) yy = s;
06490 
06491   s = z*bbox.m_min.z;
06492   if ( s > (zz = z*bbox.m_max.z) ) zz = s;
06493 
06494   return (xx + yy + zz + d);
06495 }
06496 
06497 
06498 double ON_PlaneEquation::MaximumAbsoluteValueAt(
06499   bool bRational,
06500   int point_count,
06501   int point_stride,
06502   const double* points,
06503   double stop_value
06504   ) const
06505 {
06506   double value, max_value, w;
06507 
06508   if (    point_count < 1 
06509        || point_stride < (bRational?4:3) 
06510        || 0 == points
06511        )
06512   {
06513     return ON_UNSET_VALUE;
06514   }
06515 
06516   if ( ON_IsValid(stop_value) )
06517   {
06518     if ( bRational )
06519     {
06520       w = points[3];
06521       w = (0.0 != w) ? 1.0/w : 1.0;
06522       max_value = fabs(x*w*points[0]+y*w*points[1]+z*w*points[2]+points[3]);
06523       if ( max_value > stop_value )
06524         return max_value;
06525       for(point_count--; point_count--; /*empty iterator*/ )
06526       {
06527         points += point_stride;
06528         w = points[3];
06529         w = (0.0 != w) ? 1.0/w : 1.0;
06530         value = fabs(x*w*points[0]+y*w*points[1]+z*w*points[2]+points[3]);
06531         if ( value > max_value )
06532         {
06533           if ( (max_value = value) > stop_value )
06534             return max_value;
06535         }
06536       }
06537     }
06538     else
06539     {
06540       max_value = fabs(x*points[0]+y*points[1]+z*points[2]+d);
06541       if ( max_value > stop_value )
06542         return max_value;
06543       for(point_count--; point_count--; /*empty iterator*/ )
06544       {
06545         points += point_stride;
06546         value = fabs(x*points[0]+y*points[1]+z*points[2]+d);
06547         if ( value > max_value )
06548         {
06549           if ( (max_value = value) > stop_value )
06550             return max_value;
06551         }
06552       }
06553     }
06554   }
06555   else
06556   {
06557     if ( bRational )
06558     {
06559       w = points[3];
06560       w = (0.0 != w) ? 1.0/w : 1.0;
06561       max_value = fabs(x*w*points[0]+y*w*points[1]+z*w*points[2]+points[3]);
06562       for(point_count--; point_count--; /*empty iterator*/ )
06563       {
06564         points += point_stride;
06565         w = points[3];
06566         w = (0.0 != w) ? 1.0/w : 1.0;
06567         value = fabs(x*w*points[0]+y*w*points[1]+z*w*points[2]+points[3]);
06568         if ( value > max_value )
06569           max_value = value;
06570       }
06571     }
06572     else
06573     {
06574       max_value = fabs(x*points[0]+y*points[1]+z*points[2]+d);
06575       for(point_count--; point_count--; /*empty iterator*/ )
06576       {
06577         points += point_stride;
06578         value = fabs(x*points[0]+y*points[1]+z*points[2]+d);
06579         if ( value > max_value )
06580           max_value = value;
06581       }
06582     }
06583   }
06584 
06585   return max_value;
06586 }
06587 
06588 double ON_PlaneEquation::MaximumValueAt(
06589   bool bRational,
06590   int point_count,
06591   int point_stride,
06592   const double* points,
06593   double stop_value
06594   ) const
06595 {
06596   double value, max_value, w;
06597 
06598   if (    point_count < 1 
06599        || point_stride < (bRational?4:3) 
06600        || 0 == points
06601        )
06602   {
06603     return ON_UNSET_VALUE;
06604   }
06605 
06606   if ( ON_IsValid(stop_value) )
06607   {
06608     if ( bRational )
06609     {
06610       w = points[3];
06611       w = (0.0 != w) ? 1.0/w : 1.0;
06612       max_value = x*w*points[0]+y*w*points[1]+z*w*points[2]+points[3];
06613       if ( max_value > stop_value )
06614         return max_value;
06615       for(point_count--; point_count--; /*empty iterator*/ )
06616       {
06617         points += point_stride;
06618         w = points[3];
06619         w = (0.0 != w) ? 1.0/w : 1.0;
06620         value = x*w*points[0]+y*w*points[1]+z*w*points[2]+points[3];
06621         if ( value > max_value )
06622         {
06623           if ( (max_value = value) > stop_value )
06624             return max_value;
06625         }
06626       }
06627     }
06628     else
06629     {
06630       max_value = x*points[0]+y*points[1]+z*points[2]+d;
06631       if ( max_value > stop_value )
06632         return max_value;
06633       for(point_count--; point_count--; /*empty iterator*/ )
06634       {
06635         points += point_stride;
06636         value = x*points[0]+y*points[1]+z*points[2]+d;
06637         if ( value > max_value )
06638         {
06639           if ( (max_value = value) > stop_value )
06640             return max_value;
06641         }
06642       }
06643     }
06644   }
06645   else
06646   {
06647     if ( bRational )
06648     {
06649       w = points[3];
06650       w = (0.0 != w) ? 1.0/w : 1.0;
06651       max_value = x*w*points[0]+y*w*points[1]+z*w*points[2]+points[3];
06652       for(point_count--; point_count--; /*empty iterator*/ )
06653       {
06654         points += point_stride;
06655         w = points[3];
06656         w = (0.0 != w) ? 1.0/w : 1.0;
06657         value = x*w*points[0]+y*w*points[1]+z*w*points[2]+points[3];
06658         if ( value > max_value )
06659           max_value = value;
06660       }
06661     }
06662     else
06663     {
06664       max_value = x*points[0]+y*points[1]+z*points[2]+d;
06665       for(point_count--; point_count--; /*empty iterator*/ )
06666       {
06667         points += point_stride;
06668         value = x*points[0]+y*points[1]+z*points[2]+d;
06669         if ( value > max_value )
06670           max_value = value;
06671       }
06672     }
06673   }
06674 
06675   return max_value;
06676 }
06677 
06678 double ON_PlaneEquation::MinimumValueAt(
06679   bool bRational,
06680   int point_count,
06681   int point_stride,
06682   const double* points,
06683   double stop_value
06684   ) const
06685 {
06686   double value, min_value, w;
06687 
06688   if (    point_count < 1 
06689        || point_stride < (bRational?4:3) 
06690        || 0 == points
06691        )
06692   {
06693     return ON_UNSET_VALUE;
06694   }
06695 
06696   if ( ON_IsValid(stop_value) )
06697   {
06698     if ( bRational )
06699     {
06700       w = points[3];
06701       w = (0.0 != w) ? 1.0/w : 1.0;
06702       min_value = x*w*points[0]+y*w*points[1]+z*w*points[2]+points[3];
06703       if ( min_value < stop_value )
06704         return min_value;
06705       for(point_count--; point_count--; /*empty iterator*/ )
06706       {
06707         points += point_stride;
06708         w = points[3];
06709         w = (0.0 != w) ? 1.0/w : 1.0;
06710         value = x*w*points[0]+y*w*points[1]+z*w*points[2]+points[3];
06711         if ( value < min_value )
06712         {
06713           if ( (min_value = value) < stop_value )
06714             return min_value;
06715         }
06716       }
06717     }
06718     else
06719     {
06720       min_value = x*points[0]+y*points[1]+z*points[2]+d;
06721       if ( min_value < stop_value )
06722         return min_value;
06723       for(point_count--; point_count--; /*empty iterator*/ )
06724       {
06725         points += point_stride;
06726         value = x*points[0]+y*points[1]+z*points[2]+d;
06727         if ( value < min_value )
06728         {
06729           if ( (min_value = value) < stop_value )
06730             return min_value;
06731         }
06732       }
06733     }
06734   }
06735   else
06736   {
06737     if ( bRational )
06738     {
06739       w = points[3];
06740       w = (0.0 != w) ? 1.0/w : 1.0;
06741       min_value = x*w*points[0]+y*w*points[1]+z*w*points[2]+points[3];
06742       for(point_count--; point_count--; /*empty iterator*/ )
06743       {
06744         points += point_stride;
06745         w = points[3];
06746         w = (0.0 != w) ? 1.0/w : 1.0;
06747         value = x*w*points[0]+y*w*points[1]+z*w*points[2]+points[3];
06748         if ( value < min_value )
06749           min_value = value;
06750       }
06751     }
06752     else
06753     {
06754       min_value = x*points[0]+y*points[1]+z*points[2]+d;
06755       for(point_count--; point_count--; /*empty iterator*/ )
06756       {
06757         points += point_stride;
06758         value = x*points[0]+y*points[1]+z*points[2]+d;
06759         if ( value < min_value )
06760           min_value = value;
06761       }
06762     }
06763   }
06764 
06765   return min_value;
06766 }
06767 
06768 
06769 bool ON_PlaneEquation::IsNearerThan( 
06770         const ON_BezierCurve& bezcrv,
06771         double s0,
06772         double s1,
06773         int sample_count,
06774         double endpoint_tolerance,
06775         double interior_tolerance,
06776         double* smin,
06777         double* smax
06778         ) const
06779 {
06780   int i, n;
06781   double smn, smx, vmn, vmx, s, v, w;
06782   ON_3dPoint P;
06783   P.z = 0.0; // for 2d curves
06784 
06785   sample_count--;
06786   s = 0.5*(s0+s1);
06787   bezcrv.Evaluate(s,0,3,&P.x);
06788   vmn = vmx = x*P.x + y*P.y + z*P.z + d;
06789   smn = smx = s;
06790   if ( vmn > interior_tolerance )
06791   {
06792     if ( smin )
06793       *smin = s;
06794     if ( smax )
06795       *smax = s;
06796     return false;
06797   }
06798 
06799   if ( endpoint_tolerance >= 0.0 )
06800   {
06801     bezcrv.Evaluate(s0,0,3,&P.x);
06802     v = x*P.x + y*P.y + z*P.z + d;
06803     if (v > endpoint_tolerance )
06804     {
06805       if ( smin )
06806         *smin = smn;
06807       if ( smax )
06808         *smax = s0;
06809       return false;
06810     }
06811     if ( v < vmn ) { vmn = v; smn = s0; } else if (v > vmx) { vmx = v; smx = s0; }
06812 
06813     bezcrv.Evaluate(s1,0,3,&P.x);
06814     v = x*P.x + y*P.y + z*P.z + d;
06815     if (v > endpoint_tolerance )
06816     {
06817       if ( smin )
06818         *smin = smn;
06819       if ( smax )
06820         *smax = s1;
06821       return false;
06822     }
06823     if ( v < vmn ) { vmn = v; smn = s1; } else if (v > vmx) { vmx = v; smx = s1; }
06824   }
06825 
06826   w = 0.5;
06827   for ( n = 4; sample_count > 0; n *= 2 )
06828   {
06829     w *= 0.5;
06830     for ( i = 1; i < n; i+= 2 ) // do not test sample_count here
06831     {
06832       s = w*i;
06833       s = (1.0-s)*s0 + s*s1;
06834       bezcrv.Evaluate(s,0,3,&P.x);
06835       v = x*P.x + y*P.y + z*P.z + d;
06836 
06837       if ( v < vmn ) 
06838       { 
06839         vmn = v; 
06840         smn = s; 
06841       } 
06842       else if (v > vmx) 
06843       { 
06844         vmx = v; 
06845         smx = s; 
06846         if ( vmx > interior_tolerance )
06847         {
06848           if ( smin )
06849             *smin = smn;
06850           if ( smax )
06851             *smax = s;
06852           return false;
06853         }
06854       }
06855 
06856       sample_count--;
06857     }
06858   }
06859 
06860   if ( smin )
06861     *smin = smn;
06862   if ( smax )
06863     *smax = smx;
06864   return true;
06865 }
06866 
06867 bool ON_PlaneEquation::operator==( const ON_PlaneEquation& eq ) const
06868 {
06869   return (x==eq.x && y==eq.y && z==eq.z && d==eq.d)?true:false;
06870 }
06871 
06872 bool ON_PlaneEquation::operator!=( const ON_PlaneEquation& eq ) const
06873 {
06874   return (x!=eq.x || y!=eq.y || z!=eq.z || d!=eq.d)?true:false;
06875 }
06876 
06877 
06878 
06879 int ON_Get3dConvexHull( 
06880           const ON_SimpleArray<ON_3dPoint>& points, 
06881           ON_SimpleArray<ON_PlaneEquation>& hull 
06882           )
06883 {
06884   // This is a slow and stupid way to get the convex hull.
06885   // It works for small point sets.  If you need something
06886   // that is efficient, look elsewhere.
06887 
06888   const int point_count = points.Count();
06889   if ( point_count < 3 )
06890     return 0;
06891 
06892   const int count0 = hull.Count();
06893   hull.Reserve(count0+4);
06894 
06895   int i,j,k,n;
06896   ON_3dPoint A,B,C;
06897   ON_PlaneEquation e;
06898   double d0,d1,h0,h1,d;
06899   bool bGoodSide;
06900   for ( i = 0; i < point_count; i++ )
06901   {
06902     A = points[i];
06903     for ( j = i+1; j < point_count; j++ )
06904     {
06905       B = points[j];
06906       for (k = j+1; k < point_count; k++ )
06907       {
06908         C = points[k];
06909         e.ON_3dVector::operator=(ON_CrossProduct(B-A,C-A));
06910         if ( !e.ON_3dVector::Unitize() )
06911           continue;
06912         e.d = -(A.x*e.x + A.y*e.y + A.z*e.z);
06913         d0 = d1 = e.ValueAt(A);
06914         d = e.ValueAt(B); if ( d < d0 ) d0 = d; else if (d > d1) d1 = d;
06915         d = e.ValueAt(C); if ( d < d0 ) d0 = d; else if (d > d1) d1 = d;
06916         if ( d0 > -ON_ZERO_TOLERANCE )
06917           d0 = -ON_ZERO_TOLERANCE;
06918         if ( d1 < ON_ZERO_TOLERANCE )
06919           d1 = ON_ZERO_TOLERANCE;
06920 
06921         h0 = 0.0; h1 = 0.0;
06922 
06923         bGoodSide = true;
06924         for ( n = 0; n < point_count && bGoodSide; n++ )
06925         {
06926           d = e.ValueAt(points[n]);
06927           if ( d < h0 )
06928           {
06929             h0 = d;
06930             bGoodSide = (d0 <= h0 || h1 <= d1);
06931           }
06932           else if ( d > h1 )
06933           {
06934             h1 = d;
06935             bGoodSide = (d0 <= h0 || h1 <= d1);
06936           }
06937         }
06938 
06939         if ( bGoodSide )
06940         {
06941           if ( h1 <= d1 )
06942           {
06943             // all points are "below" the plane
06944             if ( d0 <= h0  )
06945             {
06946               // all points are also "above" the plane,
06947               hull.SetCount(count0);
06948               ON_PlaneEquation& e0 = hull.AppendNew();
06949               e0.x = -e.x;
06950               e0.y = -e.y;
06951               e0.z = -e.z;
06952               e0.d = -(e.d-h0);
06953             }
06954             ON_PlaneEquation& e1 = hull.AppendNew();
06955             e1.x = e.x;
06956             e1.y = e.y;
06957             e1.z = e.z;
06958             e1.d = (e.d-h1);
06959             if ( d0 <= h0  )
06960             {
06961               // points are (nearly) planar
06962               return 2;
06963             }
06964           }
06965           else if ( d0 <= h0  )
06966           {
06967             // all points are "above" the plane
06968             ON_PlaneEquation& e0 = hull.AppendNew();
06969             e0.x = -e.x;
06970             e0.y = -e.y;
06971             e0.z = -e.z;
06972             e0.d = -(e.d-h0);
06973           }
06974         }
06975       }
06976     }
06977   }
06978 
06979   if ( hull.Count() < count0 + 4 )
06980     hull.SetCount(count0);
06981 
06982   return hull.Count() - count0;
06983 }
06984 
06985 bool ON_BoundingBox::IsValid() const 
06986 {
06987         return (    m_min.x <= m_max.x
06988           && ON_IS_VALID(m_min.x)
06989           && ON_IS_VALID(m_max.x)
06990           && m_min.y <= m_max.y 
06991           && ON_IS_VALID(m_min.y)
06992           && ON_IS_VALID(m_max.y)
06993           && m_min.z <= m_max.z
06994           && ON_IS_VALID(m_min.z)
06995           && ON_IS_VALID(m_max.z)
06996          );
06997 };
06998 
06999 void ON_BoundingBox::Dump(ON_TextLog& text_log) const
07000 {
07001   text_log.Print("Bounding box: ");
07002   if ( !IsValid() )
07003   {
07004     text_log.Print("not valid ");
07005   }
07006   text_log.Print("%.17g to %.17g, %.17g to %.17g, %.17g to %.17g\n",
07007     m_min.x,m_max.x,
07008     m_min.y,m_max.y,
07009     m_min.z,m_max.z
07010     );
07011 }
07012 
07013 bool ON_IsDegenrateConicHelper(double A, double B, double C, double D, double E)
07014 {
07015   //
07016   // The conic is degenerate (lines and/or points) if the 
07017   //
07018   //     A   B/2 D/2
07019   //     B/2 C   E/2
07020   //     D/2 E/2 F
07021   //
07022   // has rank < 3
07023   // (F = 0 in our case here.)
07024 
07025   // zero_tol was tuned by 
07026   //  1) testing sets of equaly spaced colinear 
07027   //     points with coordinate sizes ranging from 0.001 to 1.0e4 and
07028   //     segment lengths from 0.001 to 1000.0.
07029   //  2) testing ellipses with axes lengths ranging from 0.001 to 1000
07030   //     where the major/minor ration <= 2000 and the centers had coordinates
07031   //     from 0.001 to 1.0e4.
07032   //  Do not change zero_tol without extensive testing.
07033   const double zero_tol = 1.0e-9;
07034 
07035   double x, y;
07036   double M[3][3];
07037   int i0, i1, i2;
07038 
07039   // scale matrix coefficients so largest is 1 to
07040   // make checking for a zero pivot easier.
07041   x = fabs(A);
07042   if ( x < (y=fabs(B)) ) x = y;
07043   if ( x < (y=fabs(C)) ) x = y;
07044   if ( x < (y=fabs(D)) ) x = y;
07045   if ( x < (y=fabs(E)) ) x = y;
07046   if ( x <= 1.0e-12 )
07047     return true; // rank 0
07048 
07049   x = 1.0/x;
07050 
07051   // set up matrix
07052   M[0][0] = x*A;
07053   M[1][1] = x*C;
07054   x *= 0.5;
07055   M[0][1] = M[1][0] = x*B;
07056   M[0][2] = M[2][0] = x*D;
07057   M[1][2] = M[2][1] = x*E;
07058   M[2][2] = 0.0;
07059 
07060   // since M is symmetric, just use partial pivoting
07061 
07062   // get first pivot ic column M[][0]
07063   i0 = 0;
07064   x = fabs(M[0][0]);
07065   if ( x < (y=fabs(M[1][0])) ) {x=y;i0=1;}
07066   if ( x < (y=fabs(M[2][0])) ) {x=y;i0=2;}
07067   if ( x <= zero_tol )
07068     return true; // rank 0
07069 
07070   // first pivot row reduction
07071   x = 1.0/M[i0][0]; 
07072   M[i0][1] *= x; 
07073   M[i0][2] *= x;
07074   i1 = (i0+1)%3;
07075   if ( 0.0 != (y = -M[i1][0]) )
07076   {
07077     M[i1][1] += y*M[i0][1];
07078     M[i1][2] += y*M[i0][2];
07079   }
07080   i2 = (i0+2)%3;
07081   if ( 0.0 != (y = -M[i2][0]) )
07082   {
07083     M[i2][1] += y*M[i0][1]; 
07084     M[i2][2] += y*M[i0][2];
07085   }
07086 
07087   // get second pivot in column M[][1]
07088   if ( fabs(M[i1][1]) < fabs(M[i2][1]) )
07089   {
07090     i1 = i2;
07091     i2 = (i0+1)%3;
07092   }
07093   if ( fabs(M[i1][1]) <= zero_tol )
07094     return true; // rank 1
07095 
07096   // second pivot row reduction
07097   x = 1.0/M[i1][1]; 
07098   M[i1][2] *= x;
07099   if ( 0.0 != (y = -M[i2][1]) )
07100     M[i2][2] += y*M[i1][2];
07101 
07102   // test third and final pivot
07103   if ( fabs(M[i2][2]) <= zero_tol )
07104     return true;  // rank 2
07105 
07106   return false;
07107 }
07108 
07109 bool ON_GetConicEquationThrough6Points( 
07110         int stride, 
07111         const double* points2d, 
07112         double conic[6],
07113         double* max_pivot,
07114         double* min_pivot,
07115         double* zero_pivot
07116         )
07117 {
07118   // Sets conic[] to the coefficents = (A,B,C,D,E,F), 
07119   // such that A*x*x + B*x*y + C*y*y + D*x + E*y + F = 0
07120   // for each of the 6 input points.
07121 
07122   // This code is long and ugly.  The reason for unrolling the 
07123   // obvious loops is to make it as efficient as possible.  
07124   // Rhino calls this function in time critical situations.
07125   //
07126 
07127   ON_2dPoint pts[6], bboxmin, bboxmax;
07128   double scale, x, y, M[5][5], N[5][5], max_piv, min_piv;
07129   const double* p;
07130   int i, j, k;
07131 
07132   if ( 0 == conic )
07133     return false;
07134   memset(conic,0,6*sizeof(conic[0]));
07135   if ( max_pivot )
07136     *max_pivot = 0.0;
07137   if ( min_pivot )
07138     *min_pivot = 0.0;
07139   if ( zero_pivot )
07140     *zero_pivot = 0.0;
07141 
07142   // copy input points into pts[6] and calculate bounding box
07143   bboxmin.x = bboxmax.x = pts[0].x = points2d[0];
07144   bboxmin.y = bboxmax.y = pts[0].y = points2d[1];
07145   if ( !pts[0].IsValid() )
07146     return false;
07147   for ( i = 1; i < 6; i++ )
07148   {
07149     points2d += stride;
07150     pts[i].x = points2d[0];
07151     pts[i].y = points2d[1];
07152     if ( !pts[i].IsValid() )
07153       return false;
07154     if ( pts[i].x < bboxmin.x ) bboxmin.x = pts[i].x; 
07155     else if ( pts[i].x > bboxmax.x ) bboxmax.x = pts[i].x;
07156     if ( pts[i].y < bboxmin.y ) bboxmin.y = pts[i].y; 
07157     else if ( pts[i].y > bboxmax.y ) bboxmax.y = pts[i].y;
07158   }
07159 
07160   // translate and scale pts[] so pts[5] is at the origin and
07161   // (pts[0],...pts[4]) have and have a "diameter" near 1.
07162   // This keeps the starting coefficients in M[][] less than 5
07163   // with the largest generally near one.
07164   x = bboxmax.x-bboxmin.x;
07165   y = bboxmax.y-bboxmin.y;
07166   if ( x >= y )
07167   {
07168     if ( x > 0.0 )
07169     {
07170       y /= x;
07171       scale = x*sqrt(1.0 + y*y);
07172     }
07173     else
07174       return false;
07175   }
07176   else 
07177   {
07178     x /= y;
07179     scale = y*sqrt(1.0 + x*x);
07180   }
07181   if ( scale > 0.0 )
07182     scale = 1.0/scale;
07183   else
07184     return false;
07185 
07186   for ( i = 0; i < 5; i++ )
07187   {
07188     x = scale*(pts[i].x - pts[5].x);
07189     y = scale*(pts[i].y - pts[5].y);
07190     M[i][0] = x*x;
07191     M[i][1] = x*y;
07192     M[i][2] = y*y;
07193     M[i][3] = x;
07194     M[i][4] = y;
07195   }
07196 
07197   memset( N,0,sizeof(N) );
07198   N[0][0] = N[1][1] = N[2][2] = N[3][3] = N[4][4] = 1.0;
07199 
07200   // The conic (A,B,C,D,E) is the kernel of M.
07201 
07203   //
07204   // find first pivot
07205   //
07206   j = 0;
07207   p = &M[0][0];
07208   x = fabs(*p);
07209   for ( i = 1; i < 25; i++ )
07210   {
07211     if ( x < (y = fabs(*(++p))) )
07212     {
07213       x = y;
07214       j = i;
07215     }
07216   }
07217   max_piv = min_piv = x;
07218   if ( 0.0 == x )
07219     return false; // all input points are equal
07220   i = j/5;
07221   j %= 5;
07222 
07223   if ( 0 != i )
07224   {
07225     // swap rows M[0][] and M[i][]
07226     // Do not modify N because row ops act on the left of M.
07227     for ( k = 0; k < 5; k++ )
07228     {
07229       y = M[0][k]; M[0][k] = M[i][k]; M[i][k] = y;
07230     }
07231   }
07232   if ( 0 != j )
07233   {
07234     // Swap columns M[][0] and M[][j]
07235     // Also swap N[][] columns because column swap
07236     // matrix acts on the right of M.
07237     for ( k = 0; k < 5; k++ )
07238     {
07239       y = M[k][0]; M[k][0] = M[k][j]; M[k][j] = y;
07240       y = N[k][0]; N[k][0] = N[k][j]; N[k][j] = y;
07241     }
07242   }
07243 
07244   // scale row M[0][] so that M[0][0] = 1.
07245   // Do not modify N because row ops act on the left of M.
07246   x = 1.0/M[0][0];
07247   M[0][0] = 1.0; 
07248   M[0][1] *= x; M[0][2] *= x; M[0][3] *= x; M[0][4] *= x;
07249 
07250   // kill column M[1,2,3,4][0]
07251   for ( i = 1; i < 5; i++)
07252   {
07253     if ( 0.0 != (y = -M[i][0]) )
07254     {
07255       // use row op M[i][] += y*M[0][]
07256       // Do not modify N because row ops act on the left of M.
07257       M[i][0] = 0.0; // set to zero so search for pivot is faster
07258       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];
07259     }
07260   }
07261 
07262 
07264   //
07265   // find second pivot
07266   //
07267   j = 6;
07268   p = &M[1][1];
07269   x = fabs(*p);
07270   for ( i = 7; i < 25; i++ )
07271   {
07272     if ( x < (y = fabs(*(++p))) )
07273     {
07274       x = y;
07275       j = i;
07276     }
07277   }
07278   if ( x > max_piv ) max_piv = x; else if ( x < min_piv ) min_piv = x;
07279   if ( 0.0 == x )
07280   {
07281     if ( 0 != max_pivot )
07282       *max_pivot = max_piv;
07283     return false; // two distinct points in input point list.
07284   }
07285   i = j/5;  // should always be >= 1
07286   j %= 5;   // should always be >= 1
07287 
07288   if ( i > 1 )
07289   {
07290     // swap rows M[1][] and M[i][]
07291     // Do not modify N because row ops act on the left of M.
07292     for ( k = 1; k < 5; k++ )
07293     {
07294       y = M[1][k]; M[1][k] = M[i][k]; M[i][k] = y;
07295     }
07296   }
07297   if ( j > 1 )
07298   {
07299     // Swap columns M[][1] and M[][j]
07300     // Also swap N[][] columns because column swap
07301     // matrix acts on the right of M.
07302     for ( k = 0; k < 5; k++ )
07303     {
07304       y = M[k][1]; M[k][1] = M[k][j]; M[k][j] = y;
07305       y = N[k][1]; N[k][1] = N[k][j]; N[k][j] = y;
07306     }
07307   }
07308 
07309   // scale row M[1][] so that M[1][1] = 1.
07310   // Do not modify N because row ops act on the left of M.
07311   x = 1.0/M[1][1];
07312   M[1][1] = 1.0; 
07313   M[1][2] *= x; M[1][3] *= x; M[1][4] *= x;
07314 
07315   // kill column M[2,3,4][1]
07316   for ( i = 2; i < 5; i++)
07317   {
07318     if ( 0.0 != (y = -M[i][1]) )
07319     {
07320       // use row op M[i][] += y*M[0][]
07321       // Do not modify N because row ops act on the left of M.
07322       M[i][1] = 0.0; // set to zero so search for pivot is faster
07323       M[i][2] += y*M[1][2]; M[i][3] += y*M[1][3]; M[i][4] += y*M[1][4];
07324     }
07325   }
07326 
07327 
07329   //
07330   // find third pivot
07331   //
07332   j = 12;
07333   p = &M[2][2];
07334   x = fabs(*p);
07335   for ( i = 13; i < 25; i++ )
07336   {
07337     if ( x < (y = fabs(*(++p))) )
07338     {
07339       x = y;
07340       j = i;
07341     }
07342   }
07343   if ( x > max_piv ) max_piv = x; else if ( x < min_piv ) min_piv = x;
07344   if ( 0.0 == x )
07345   {
07346     if ( 0 != max_pivot )
07347       *max_pivot = max_piv;
07348     return false; // three distinct points in input point list.
07349   }
07350   i = j/5;  // should always be >= 2
07351   j %= 5;   // should always be >= 2
07352 
07353   if ( i > 2 )
07354   {
07355     // swap rows M[2][] and M[i][]
07356     // Do not modify N because row ops act on the left of M.
07357     for ( k = 2; k < 5; k++ )
07358     {
07359       y = M[2][k]; M[2][k] = M[i][k]; M[i][k] = y;
07360     }
07361   }
07362   if ( j > 2 )
07363   {
07364     // Swap columns M[][2] and M[][j]
07365     // Also swap N[][] columns because column swap
07366     // matrix acts on the right of M.
07367     for ( k = 0; k < 5; k++ )
07368     {
07369       y = M[k][2]; M[k][2] = M[k][j]; M[k][j] = y;
07370       y = N[k][2]; N[k][2] = N[k][j]; N[k][j] = y;
07371     }
07372   }
07373 
07374   // scale row M[2][] so that M[2][2] = 1.
07375   // Do not modify N because row ops act on the left of M.
07376   x = 1.0/M[2][2];
07377   M[2][2] = 1.0; M[2][3] *= x; M[2][4] *= x;
07378 
07379   // kill column M[3,4][2]
07380   for ( i = 3; i < 5; i++)
07381   {
07382     if ( 0.0 != (y = -M[i][2]) )
07383     {
07384       // use row op M[i][] += y*M[0][]
07385       // Do not modify N because row ops act on the left of M.
07386       M[i][2] = 0.0; // set to zero so search for pivot is faster
07387       M[i][3] += y*M[2][3]; M[i][4] += y*M[2][4];
07388     }
07389   }
07390 
07392   //
07393   // find fourth pivot
07394   //
07395   i = j = 3;
07396   x = fabs(M[3][3]);
07397   if ( x < (y = fabs(M[3][4])) )
07398   {
07399     x = y; j = 4;
07400   }
07401   if ( x < (y = fabs(M[4][3])) )
07402   {
07403     x = y; i = 4; j = 3;
07404   }
07405   if ( x < (y = fabs(M[4][4])) )
07406   {
07407     x = y; i = j = 4;
07408   }
07409   if ( x > max_piv ) max_piv = x; else if ( x < min_piv ) min_piv = x;
07410   if ( 0.0 == x )
07411   {
07412     if ( 0 != max_pivot )
07413       *max_pivot = max_piv;
07414     return false; // four distinct points in the input point list.
07415   }
07416 
07417   if ( i > 3 )
07418   {
07419     // swap rows M[3][] and M[i][]
07420     // Do not modify N[][] because row ops act on the left of M.
07421     y = M[3][3]; M[3][3] = M[4][3]; M[4][3] = y;
07422     y = M[3][4]; M[3][4] = M[i][4]; M[4][4] = y;
07423   }
07424   if ( j > 3 )
07425   {
07426     // Swap columns M[][3] and M[][j]
07427     // Also swap N[][] columns because column swap
07428     // matrix acts on the right of M.
07429     for ( k = 0; k < 5; k++ )
07430     {
07431       y = M[k][3]; M[k][3] = M[k][4]; M[k][4] = y;
07432       y = N[k][3]; N[k][3] = N[k][4]; N[k][4] = y;
07433     }
07434   }
07435 
07436   // scale row M[3][] so that M[3][3] = 1.
07437   // Do not modify N because row ops act on the left of M.
07438   x = 1.0/M[3][3];
07439   M[3][3] = 1.0; 
07440   M[3][4] *= x;
07441 
07442   // kill column M[4][3]
07443   if ( 0.0 != M[4][3] )
07444   {
07445     // use row op M[i][] += y*M[3][]
07446     // Do not modify N because row ops act on the left of M.
07447     M[4][4] -= M[4][3]*M[3][4];
07448     M[4][3] = 0.0; // set to zero so search for pivot is faster
07449   }
07450 
07451   // By construction, M[][] is singular and M[4][4] should be nearly zero.
07452   // It should be upper triangluar with diagonal 1,1,1,1,0-ish
07453   if ( max_pivot )
07454     *max_pivot = max_piv;
07455   if ( min_pivot )
07456     *min_pivot = max_piv;
07457   if ( zero_pivot )
07458     *zero_pivot = fabs(M[4][4]);
07459 
07460   // Use column operations to make M[][] the identity.
07461   // The operations must also be applied to N[][] in order to
07462   // calculate the kernel of the original M[][].
07463   for ( i = 0; i < 4; i++ )
07464   {
07465     for (j = i+1; j < 5; j++ )
07466     {
07467       if ( 0.0 != (y = -M[i][j]) )
07468       {
07469         // waste of time // M[i][j] = 0.0;
07470         for ( k = 0; k < 5; k++ )
07471         {
07472           //M[k][j] += y*M[k][i];
07473           N[k][j] += y*N[k][i];
07474         }
07475       }
07476     }
07477   }
07478 
07479   // At this point, M[][] should be reduced to a diagonal matrix with 
07480   // 1,1,1,1,0 on the diagonal. The vector (A,B,C,D,E) = N*Transpose(0,0,0,0,1)
07481   // will be in the kernel of the original M[][]. The conic through the 
07482   // six points( scale*(pts[0]-pts[5]),...,scale*(pts[4]-pts[5]),(0,0) ) 
07483   // is Ax^2 + Bxy + Cy^2 + Dx + Ey = 0.
07484   // We need to apply the inverse of the scale and then translate by 
07485   // (pts[5].x,pts[5].y) to get the equation of the conic through the 
07486   // input point list.
07487 
07488   double A = N[0][4];
07489   double B = N[1][4];
07490   double C = N[2][4];
07491   double D = N[3][4];
07492   double E = N[4][4];
07493   // F = 0
07494 
07495   // check for colinear point set
07496   if ( ON_IsDegenrateConicHelper(A,B,C,D,E) )
07497   {
07498     // points lie on one or two lines
07499     return false;
07500   }
07501 
07502   // points are not colinear
07503 
07504   // undo the scale we applied when we calculated M[][]
07505   x = scale*scale;
07506   A *= x;
07507   B *= x;
07508   C *= x;
07509   D *= scale;
07510   E *= scale;
07511 
07512   // undo the translation of pts[5] to (0,0) we applied when we calculated M[][]
07513   x = -pts[5].x;
07514   y = -pts[5].y;
07515   double F = A*x*x + B*x*y + C*y*y + D*x + E*y;
07516   D += 2.0*A*x + B*y;
07517   E += 2.0*C*y + B*x;
07518 
07519   if ( (fabs(A) >= fabs(C)) ? (A<0.0):(C<0.0) )
07520   {
07521     // Make the largest A/C coefficent positive.
07522     A = -A; B = -B; C = -C; D = -D; E = -E; F = -F;
07523   }
07524 
07525   conic[0] = A; conic[1] = B; conic[2] = C;
07526   conic[3] = D; conic[4] = E; conic[5] = F;
07527 
07528   //
07529   j = 0;
07530   x = fabs(conic[0]);
07531   for ( i = 0; i < 6; i++ )
07532   {
07533     if ( x < (y = fabs(conic[i])) )
07534     {
07535       x = y;
07536       j = i;
07537     }
07538   }
07539   if ( !(conic[j] != 0.0) )
07540     return false;
07541   y = 1.0/conic[j];
07542   conic[0] *= y; conic[1] *= y; conic[2] *= y; 
07543   conic[3] *= y; conic[4] *= y; conic[5] *= y; 
07544   conic[j] = 1.0;
07545 
07546   return true;
07547 }
07548 
07549 bool ON_IsConicEquationAnEllipse( 
07550         const double conic[6], 
07551         ON_2dPoint& center, 
07552         ON_2dVector& major_axis, 
07553         ON_2dVector& minor_axis, 
07554         double* major_radius, 
07555         double* minor_radius
07556         )
07557 {
07558   double A, C, D, E, F, x0, y0;
07559   double X[2], Y[2], P[2];
07560 
07561   if (    !ON_IsValid(conic[0]) 
07562        || !ON_IsValid(conic[1]) 
07563        || !ON_IsValid(conic[2]) 
07564        || !ON_IsValid(conic[3]) 
07565        || !ON_IsValid(conic[4]) 
07566        || !ON_IsValid(conic[5]) 
07567      )
07568   {
07569     return false;
07570   }
07571 
07572   if ( fabs(conic[1]) > 1.0e-14*fabs(conic[0]+fabs(conic[2])) ) 
07573   {
07574     // "B" is non zero - remove "rotation" from conic equation
07575     const double alpha = 0.5*atan2(conic[1],conic[0]-conic[2]);
07576     const double s = sin(alpha);
07577     const double c = cos(alpha);
07578     X[0] =  c; X[1] = s;
07579     Y[0] = -s; Y[1] = c;
07580 
07581     A = conic[0]*c*c + conic[1]*c*s + conic[2]*s*s;
07582     // B = conic[1]*(c*c-s*s) + 2.0*(conic[2]-conic[0])*s*c; // (B = 0)
07583     C = conic[0]*s*s - conic[1]*c*s + conic[2]*c*c;
07584     D = conic[3]*c + conic[4]*s;
07585     E = conic[4]*c - conic[3]*s;
07586     // F = conic[5]; // F not changed by rotation
07587   }
07588   else
07589   {
07590     A = conic[0];
07591     // B = conic[1];
07592     C = conic[2];
07593     D = conic[3];
07594     E = conic[4];
07595     // F = conic[5]; 
07596     X[0] = 1.0; X[1] = 0.0;
07597     Y[0] = 0.0; Y[1] = 1.0;
07598   }
07599 
07600   F = conic[5];
07601 
07602   // the if (!(...)) insures we exit if A or C is a NaN
07603   if ( !((A > 0.0 && C > 0.0) || (A < 0.0 && C < 0.0)) )
07604     return false; // conic is not an ellipse 
07605 
07606   // set P = center
07607   x0 = -0.5*D/A;
07608   y0 = -0.5*E/C;
07609   P[0] = x0*X[0] + y0*Y[0];
07610   P[1] = x0*X[1] + y0*Y[1];
07611 
07612   // set A and C to elipse axes lengths
07613   F = conic[5] -(A*x0*x0 + C*y0*y0);
07614   if ( !(0.0 != F) )
07615     return false; // F is 0.0 or a NaN
07616 
07617   // We know A and C have the same sign and F has the opposite sign.
07618   A = sqrt(-F/A);
07619   C = sqrt(-F/C);
07620 
07621   if ( A == C )
07622   {
07623     // circle
07624     major_axis.x = 1.0;
07625     major_axis.y = 0.0;
07626     minor_axis.x = 0.0;
07627     minor_axis.y = 1.0;
07628     *major_radius = A;
07629     *minor_radius = C;
07630   }
07631   else if ( A > C )
07632   {
07633     // X = major axis, Y = minor axis
07634     major_axis.x = X[0];
07635     major_axis.y = X[1];
07636     minor_axis.x = Y[0];
07637     minor_axis.y = Y[1];
07638     *major_radius = A;
07639     *minor_radius = C;
07640   }
07641   else if ( C > A )
07642   {
07643     // Y = major axis, -X = minor axis
07644     major_axis.x = Y[0];
07645     major_axis.y = Y[1];
07646     minor_axis.x = -X[0];
07647     minor_axis.y = -X[1];
07648     *major_radius = C;
07649     *minor_radius = A;
07650   }
07651   else
07652   {
07653     // A or C is a NaN
07654     return false;
07655   }
07656 
07657   center.x = P[0];
07658   center.y = P[1];
07659 
07660   return true;
07661 }
07662 
07663 bool ON_GetEllipseConicEquation( 
07664     double a, double b, 
07665     double x0, double y0, 
07666     double alpha,
07667     double conic[6]
07668     )
07669 {
07670   if ( 0 == conic )
07671     return false;
07672 
07673   if ( !(a > 0.0 && b > 0.0 && ON_IsValid(x0) && ON_IsValid(y0) && ON_IsValid(alpha)) )
07674   {
07675     return false;
07676   }
07677 
07678   int k;
07679   double e, y;
07680   double a2 = a*a;
07681   double b2 = b*b;
07682 
07683   double A0 = 1.0/a2;                    // A*x*x
07684   double B0 = 0.0;                       // B*x*y
07685   double C0 = 1.0/b2;                    // C*y*y
07686   double D0 = 0.0;                       // D*x
07687   double E0 = 0.0;                       // E*y
07688   double F0 = -1.0;                      // F
07689 
07690   // rotate
07691   const double ca = cos(-alpha);
07692   const double sa = sin(-alpha);
07693   const double A = A0*ca*ca + B0*ca*sa + C0*sa*sa;
07694   const double B = B0*(ca*ca - sa*sa) + 2.0*(C0-A0)*sa*ca;
07695   const double C = C0*ca*ca - B0*sa*ca + A0*sa*sa; 
07696   const double D = D0*ca + E0*sa;
07697   const double E = E0*ca - D0*sa;
07698   const double F = F0;
07699 
07700   if ( !((A > 0.0 && C > 0.0) || (A < 0.0 && C < 0.0)) )
07701   {
07702     return false;
07703   }
07704 
07705   // translate center to (x0,y0)
07706   conic[0] = A;
07707   conic[1] = B;
07708   conic[2] = C;
07709   conic[3] = D - 2.0*A*x0 - B*y0;
07710   conic[4] = E - 2.0*C*y0 - B*x0;
07711   conic[5] = F + A*x0*x0 + B*x0*y0 + C*y0*y0 - D*x0 - E*y0;
07712 
07713   k = 0;
07714   e = fabs(conic[0]);
07715   if ( e < (y=fabs(conic[1])) ) {e=y;k=1;}
07716   if ( e < (y=fabs(conic[2])) ) {e=y;k=2;}
07717   if ( e < (y=fabs(conic[3])) ) {e=y;k=3;}
07718   if ( e < (y=fabs(conic[4])) ) {e=y;k=4;}
07719   if ( e < (y=fabs(conic[5])) ) {e=y;k=5;}
07720   e = 1.0/conic[k];
07721   conic[0] *= e; conic[1] *= e; conic[2] *= e;
07722   conic[3] *= e; conic[4] *= e; conic[5] *= e;
07723   conic[k] = 1.0;
07724   if ( conic[0] < 0.0 )
07725   {
07726     conic[0] = -conic[0]; conic[1] = -conic[1]; conic[2] = -conic[2];
07727     conic[3] = -conic[3]; conic[4] = -conic[4]; conic[5] = -conic[5];
07728   }
07729 
07730   return true;
07731 }


pcl
Author(s): Open Perception
autogenerated on Wed Aug 26 2015 15:27:02