opennurbs_plane.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 const ON_Plane ON_xy_plane( ON_3dPoint(0.0,0.0,0.0),
00020                               ON_3dVector(1.0,0.0,0.0),
00021                               ON_3dVector(0.0,1.0,0.0) 
00022                               );
00023 
00024 const ON_Plane ON_yz_plane( ON_3dPoint(0.0,0.0,0.0),
00025                               ON_3dVector(0.0,1.0,0.0), 
00026                               ON_3dVector(0.0,0.0,1.0) 
00027                               );
00028 
00029 const ON_Plane ON_zx_plane( ON_3dPoint(0.0,0.0,0.0),
00030                               ON_3dVector(0.0,0.0,1.0),
00031                               ON_3dVector(1.0,0.0,0.0)
00032                               );
00033 
00034 const ON_Plane ON_Plane::World_xy=ON_xy_plane;
00035 
00036 ON_Plane::ON_Plane() 
00037         : origin(0.0,0.0,0.0), 
00038           xaxis(1.0,0.0,0.0), yaxis(0.0,1.0,0.0), zaxis(0.0,0.0,1.0)
00039 {
00040   plane_equation.x = plane_equation.y = plane_equation.d = 0.0;
00041   plane_equation.z = 1.0;
00042 }
00043 
00044 ON_Plane::ON_Plane(
00045     const ON_3dPoint&  P, // point on the plane
00046     const ON_3dVector& N  // non-zero normal to the plane
00047     )
00048 {
00049   CreateFromNormal(P,N);
00050 }
00051 
00052 ON_Plane::ON_Plane(
00053     const ON_3dPoint&  P, // point on the plane
00054     const ON_3dVector& X, // non-zero vector in plane
00055     const ON_3dVector& Y  // another vector in the plane not parallel to X
00056     )
00057 {
00058   CreateFromFrame(P,X,Y);
00059 }
00060 
00061 ON_Plane::ON_Plane(
00062     const ON_3dPoint& P,  // point on the plane
00063     const ON_3dPoint& Q,  // point on the plane
00064     const ON_3dPoint& R   // point on the plane
00065     )
00066 {
00067   CreateFromPoints(P,Q,R);
00068 }
00069 
00070 ON_Plane::ON_Plane(
00071     const double e[4]    // equation of plane
00072     )
00073 {
00074   CreateFromEquation(e);
00075 }
00076 
00077 ON_Plane::~ON_Plane()
00078 {}
00079 
00080 ON_3dPoint ON_Plane::PointAt( double s, double t ) const
00081 {
00082   return (origin + s*xaxis + t*yaxis);
00083 }
00084 
00085 ON_3dPoint ON_Plane::PointAt( double s, double t, double c ) const
00086 {
00087   return (origin + s*xaxis + t*yaxis + c*zaxis);
00088 }
00089 
00090 
00091 ON_Line ON_Plane::IsoLine( // iso parametric line
00092        int dir,              // 0 first parameter varies and second parameter is constant
00093                          //   e.g., line(t) = plane(t,c)
00094                          // 1 first parameter is constant and second parameter varies
00095                          //   e.g., line(t) = plane(c,t)
00096        double c           // c = value of constant parameter 
00097        ) const
00098 {
00099   ON_Line line;
00100   if ( dir ) {
00101     line.from = PointAt( 0.0, c );
00102     line.to   = PointAt( 1.0, c );
00103   }
00104   else {
00105     line.from = PointAt( c, 0.0 );
00106     line.to   = PointAt( c, 1.0 );
00107   }
00108   return line;
00109 }
00110 
00111 double ON_Plane::DistanceTo( const ON_3dPoint& point ) const
00112 {
00113   // signed distance
00114   // N.B. equation may not be normalized
00115   return ( point - origin)*zaxis;
00116 }
00117 
00118 bool ON_Plane::GetDistanceToBoundingBox(const ON_BoundingBox& Box,
00119                                                                 double* min, double* max) const
00120 {
00121   //min and max signed distance.  Returns false if plane normal has zero length.
00122 
00123   ON_3dVector UnitNormal = Normal();
00124   if (!UnitNormal.Unitize()) 
00125     return false;
00126 
00127   double mind, maxd;
00128   mind = maxd = (Box.Min() - Origin())*UnitNormal;
00129   int i0, i1, i2;
00130   for (i0=0;i0<2;i0++)
00131   {
00132     for(i1=0;i1<2;i1++) 
00133     {
00134       for (i2=0;i2<2;i2++) 
00135       {
00136         if (i0||i1||i2) 
00137         {
00138           ON_3dPoint P;
00139           P[0]=(i0)?Box.Max()[0]:Box.Min()[0];
00140           P[1]=(i1)?Box.Max()[1]:Box.Min()[1];
00141           P[2]=(i2)?Box.Max()[2]:Box.Min()[2];
00142           double d = (P - Origin())*UnitNormal;
00143           //double dd = P.DistanceTo(ClosestPointTo(P));
00144           if (d < mind) 
00145             mind=d;
00146           else if (d > maxd) 
00147             maxd=d;
00148         }
00149       }
00150     }
00151   }
00152   *min = mind;
00153   *max = maxd;
00154   return true;
00155 }
00156 
00157 
00158 //double ON_Plane::EquationAt( const ON_3dPoint& p) const
00159 //{
00160 //  return plane_equation.ValueAt(p);
00161 //}
00162 
00163 //double ON_Plane::EquationAt( const ON_4dPoint& p) const
00164 //{
00165 //  return plane_equation.ValueAt(p);
00166 //}
00167 
00168 bool ON_Plane::UpdateEquation()
00169 {
00170   // computes equation[] from origin and zaxis.
00171   return plane_equation.Create(origin,zaxis);
00172 }
00173 
00174 const ON_3dPoint& ON_Plane::Origin() const
00175 {
00176   return origin;
00177 }
00178 
00179 const ON_3dVector& ON_Plane::Xaxis() const
00180 {
00181   return xaxis;
00182 }
00183 
00184 const ON_3dVector& ON_Plane::Yaxis() const
00185 {
00186   return yaxis;
00187 }
00188 
00189 const ON_3dVector& ON_Plane::Normal() const
00190 {
00191   return zaxis;
00192 }
00193 
00194 void ON_Plane::SetOrigin( const ON_3dPoint& origin_point)
00195 {
00196   origin = origin_point;
00197   UpdateEquation();
00198 }
00199 
00200 
00201 bool ON_Plane::ClosestPointTo( ON_3dPoint p, double* s, double* t ) const
00202 {
00203   const ON_3dVector v = p - origin;
00204   if ( s )
00205     *s = v*xaxis;
00206   if ( t )
00207     *t = v*yaxis;
00208   return true;
00209 }
00210 
00211 ON_3dPoint ON_Plane::ClosestPointTo( ON_3dPoint p ) const
00212 {
00213   double s, t;
00214   ClosestPointTo( p, &s, &t );
00215   return PointAt( s, t );
00216 }
00217 
00218 
00219 bool ON_Plane::operator==(const ON_Plane& other) const
00220 {
00221   return (origin==other.origin && xaxis==other.xaxis && yaxis==other.yaxis && zaxis==other.zaxis)
00222     ? true : false;
00223 }
00224 
00225 bool ON_Plane::operator!=(const ON_Plane& other) const
00226 {
00227   return ON_Plane::operator==(other)?false:true;
00228 }
00229 
00230 
00231 bool ON_Plane::CreateFromNormal(
00232     const ON_3dPoint&  P, // point on the plane
00233     const ON_3dVector& N  // non-zero normal to the plane
00234     )
00235 {
00236   origin = P;
00237   zaxis = N;
00238   bool b = zaxis.Unitize();
00239   xaxis.PerpendicularTo( zaxis );
00240   xaxis.Unitize();
00241   yaxis = ON_CrossProduct( zaxis, xaxis );
00242   yaxis.Unitize();
00243 
00244   UpdateEquation();
00245 
00246   return b;
00247 }
00248 
00249 bool ON_Plane::CreateFromFrame(
00250     const ON_3dPoint&  P, // point on the plane
00251     const ON_3dVector& X, // non-zero vector in plane
00252     const ON_3dVector& Y  // another non-zero vector in the plane
00253     )
00254 {
00255   origin = P;
00256 
00257   xaxis = X;
00258   xaxis.Unitize();
00259   yaxis = Y - ON_DotProduct( Y, xaxis)*xaxis;
00260   yaxis.Unitize();
00261   zaxis = ON_CrossProduct( xaxis, yaxis );
00262   bool b = zaxis.Unitize();
00263   UpdateEquation();
00264   if ( b )
00265   {
00266     // 11 February 2004 Dale Lear
00267     //     Add more validation checks.
00268     b = IsValid();
00269     if ( b )
00270     {
00271       // make sure zaxis is perp to Y
00272       if ( fabs(Y*zaxis) > ON_SQRT_EPSILON*Y.Length() )
00273         b = false;
00274     }
00275   }
00276   return b;
00277 }
00278 
00279 bool ON_Plane::CreateFromEquation(
00280     const double e[4]    // equation of plane
00281     )
00282 {
00283   bool b = false;
00284   plane_equation.x = e[0];
00285   plane_equation.y = e[1];
00286   plane_equation.z = e[2];
00287   plane_equation.d = e[3];
00288 
00289   zaxis.x = e[0];
00290   zaxis.y = e[1];
00291   zaxis.z = e[2];
00292 
00293   double d = zaxis.Length();
00294   if ( d > 0.0 ) {
00295     d = 1.0/d;
00296     origin = (-d*plane_equation.d)*zaxis;
00297     b = true;
00298   }
00299   xaxis.PerpendicularTo( zaxis );
00300   xaxis.Unitize();
00301   yaxis = ON_CrossProduct( zaxis, xaxis );
00302   yaxis.Unitize();
00303   return b;
00304 }
00305 
00306 bool ON_Plane::CreateFromPoints(
00307           const ON_3dPoint& P,  // point on the plane
00308           const ON_3dPoint& Q,  // point on the plane
00309           const ON_3dPoint& R   // point on the plane
00310           )
00311 {
00312   origin = P;
00313   bool rc = zaxis.PerpendicularTo(P,Q,R);
00314   xaxis = Q - P;
00315   xaxis.Unitize();
00316   yaxis = ON_CrossProduct( zaxis, xaxis );
00317   yaxis.Unitize();
00318 
00319   if ( !plane_equation.Create(origin,zaxis) )
00320     rc = false;
00321 
00322   return rc;
00323 }
00324 
00325 bool ON_Plane::IsValid() const
00326 {
00327   if ( !plane_equation.IsValid() )
00328     return false;
00329 
00330 
00331   double x = plane_equation.ValueAt(origin);
00332   if ( fabs(x) >  ON_ZERO_TOLERANCE )
00333   {
00334     double tol = fabs(origin.MaximumCoordinate()) + fabs(plane_equation.d);
00335     if ( tol > 1000.0 && origin.IsValid() )
00336     {
00337       // 8 September 2003 Chuck and Dale:
00338       //   Fixing discrepancy between optimized and debug behavior.
00339       //   In this case, the ON_ZERO_TOLERANCE test worked in release
00340       //   and failed in debug. The principal behind this fix is valid
00341       //   for release builds too.
00342       //   For large point coordinates or planes far from the origin,
00343       //   the best we can hope for is to kill the first 15 or so decimal
00344       //   places.
00345       tol *= (ON_EPSILON*10.0);
00346       if ( fabs(x) > tol )
00347         return false;
00348     }
00349     else
00350       return false;
00351   }
00352 
00353   if ( !ON_IsRightHandFrame( xaxis, yaxis, zaxis ) )
00354     return false;
00355 
00356   ON_3dVector N = plane_equation;
00357   N.Unitize();
00358   x = ON_DotProduct( N, zaxis );
00359   if ( fabs(x-1.0) >  ON_SQRT_EPSILON )
00360     return false;
00361 
00362   return true;
00363 }
00364 
00365 
00366 bool ON_Plane::Transform( const ON_Xform& xform )
00367 {
00368   if ( xform.IsIdentity() )
00369   {
00370     // 27 October 2011 Dale Lear
00371     //    If the plane is valid and the transformation
00372     //    is the identity, then NO changes should be
00373     //    made to the plane's values.  In particular
00374     //    calling CreateFromFrame() can introduce
00375     //    slight fuzz.
00376     //
00377     //    Please discuss any changes with me.
00378     return IsValid();
00379   }
00380 
00381   ON_3dPoint origin_pt = xform*origin;
00382 
00383   // use care tranforming vectors to get
00384   // maximum precision and the right answer
00385   bool bUseVectorXform = (    0.0 == xform.m_xform[3][0] 
00386                            && 0.0 == xform.m_xform[3][1]
00387                            && 0.0 == xform.m_xform[3][2] 
00388                            && 1.0 == xform.m_xform[3][3]
00389                          );
00390 
00391   ON_3dVector xaxis_vec = bUseVectorXform ? (xform*xaxis) : ((xform*(origin+xaxis)) - origin_pt);
00392   ON_3dVector yaxis_vec = bUseVectorXform ? (xform*yaxis) : ((xform*(origin+yaxis)) - origin_pt);
00393 
00394   return CreateFromFrame( origin_pt, xaxis_vec, yaxis_vec );
00395 }
00396 
00397 
00398 bool ON_Plane::SwapCoordinates( int i, int j )
00399 {
00400   bool rc = false;
00401   if ( 0 <= i && i < 3 && 0 <= j && j < 3 ) {
00402     ON_Xform xform(1);
00403     xform[i][i] = 0.0;
00404     xform[j][j] = 0.0;
00405     xform[i][j] = 1.0;
00406     xform[j][i] = 1.0;
00407     rc = Transform(xform);
00408   }
00409   return rc;
00410 }
00411 
00412 
00413 // rotate plane about its origin_pt
00414 bool ON_Plane::Rotate(
00415       double s,                 // sin(angle)
00416       double c,                 // cos(angle)
00417       const ON_3dVector& axis // axis of rotation
00418       )
00419 {
00420   bool rc = true;
00421   if ( axis == zaxis ) {
00422     ON_3dVector x = c*xaxis + s*yaxis;
00423     ON_3dVector y = c*yaxis - s*xaxis;
00424     xaxis = x;
00425     yaxis = y;
00426   }
00427   else {
00428     ON_3dPoint origin_pt = origin;
00429     rc = Rotate( s, c, axis, origin );
00430     origin = origin_pt; // to kill any fuzz
00431   }
00432   return rc;
00433 }
00434 
00435 bool ON_Plane::Rotate(
00436       double angle,           // angle in radians
00437       const ON_3dVector& axis // axis of rotation
00438       )
00439 {
00440   return Rotate( sin(angle), cos(angle), axis );
00441 }
00442 
00443 // rotate plane about a point and axis
00444 bool ON_Plane::Rotate(
00445       double sin_angle,          // sin(angle)
00446       double cos_angle,          // cos(angle)
00447       const ON_3dVector& axis, // axis of rotation
00448       const ON_3dPoint& center // center of rotation
00449       )
00450 {
00451   bool rc = false;
00452   ON_Xform rot;
00453   if ( center == origin ) {
00454     rot.Rotation( sin_angle, cos_angle, axis, ON_origin );
00455     xaxis = rot*xaxis;
00456     yaxis = rot*yaxis;
00457     zaxis = rot*zaxis;
00458     rc = UpdateEquation();
00459   }
00460   else {
00461     rot.Rotation( sin_angle, cos_angle, axis, center );
00462     rc = Transform( rot );
00463   }
00464   return rc;
00465 }
00466 
00467 bool ON_Plane::Rotate(
00468       double a,                   // angle in radians
00469       const ON_3dVector& axis,  // axis of rotation
00470       const ON_3dPoint& origin_pt  // center of rotation
00471       )
00472 {
00473   return Rotate( sin(a), cos(a), axis, origin_pt );
00474 }
00475 
00476 bool ON_Plane::Translate(
00477       const ON_3dVector& delta
00478       )
00479 {
00480   ON_Xform tr;
00481   tr.Translation( delta );
00482   return Transform( tr );
00483 }
00484 
00485 bool ON_Plane::Flip()
00486 {
00487   ON_3dVector v = xaxis;
00488   xaxis = yaxis;
00489   yaxis = v;
00490   zaxis = -zaxis;
00491   UpdateEquation();
00492   return true;
00493 }
00494 
00495 
00496 int ON_ArePointsOnPlane( // returns 0=no, 1 = yes, 2 = pointset is (to tolerance) a single point on the line
00497         int dim,     // 2 or 3
00498         int is_rat,
00499         int count, 
00500         int stride, const double* point,
00501         const ON_BoundingBox& bbox, // if needed, use ON_GetBoundingBox(dim,is_rat,count,stride,point)
00502         const ON_Plane& plane,  // line to test
00503         double tolerance
00504         )
00505 {
00506   double w;
00507   int i, j, k;
00508 
00509   if ( count < 1 )
00510     return 0;
00511   if ( !plane.IsValid() )
00512   {
00513     ON_ERROR("plane parameter is not valid");
00514     return 0;
00515   }
00516   if ( !bbox.IsValid() )
00517   {
00518     ON_ERROR("bbox parameter is not valid");
00519     return 0;
00520   }
00521   if ( !ON_IsValid(tolerance) || tolerance < 0.0 )
00522   {
00523     ON_ERROR("tolerance must be >= 0.0");
00524     return 0;
00525   }
00526   if ( dim < 2 || dim > 3 )
00527   {
00528     ON_ERROR("dim must be 2 or 3");
00529     return 0;
00530   }
00531   if ( stride < (is_rat?(dim+1):dim) )
00532   {
00533     ON_ERROR("stride parameter is too small");
00534     return 0;
00535   }
00536   if ( 0 == point )
00537   {
00538     ON_ERROR("point parameter is null");
00539     return 0;
00540   }
00541 
00542   int rc = 0;
00543 
00544   if ( tolerance == 0.0 ) {
00545     tolerance = bbox.Tolerance();
00546   }
00547 
00548   ON_3dPoint Q;
00549 
00550   // test bounding box to quickly detect the common coordinate axis cases
00551   rc = (count == 1 || bbox.Diagonal().Length() <= tolerance) ? 2 : 1;
00552   for ( i = 0; rc && i < 2; i++ ) {
00553     Q.x = bbox[i].x;
00554     for ( j = 0; rc && j < 2; j++) {
00555       Q.y = bbox[j].y;
00556       for ( k = 0; rc && k < 2; k++) {
00557         Q.z = bbox[k].z;
00558         if ( Q.DistanceTo( plane.ClosestPointTo( Q ) ) > tolerance )
00559           rc = 0;
00560       }
00561     }
00562   }
00563 
00564   if ( !rc ) {
00565     // test points one by one
00566     Q.Zero();
00567     rc = (count == 1 || bbox.Diagonal().Length() <= tolerance) ? 2 : 1;
00568     if ( is_rat ) {
00569       for ( i = 0; i < count; i++ ) {
00570         w = point[dim];
00571         if ( w == 0.0 ) {
00572           ON_ERROR("rational point has zero weight");
00573           return 0;
00574         }
00575         ON_ArrayScale( dim, 1.0/w, point, &Q.x );
00576         if ( Q.DistanceTo( plane.ClosestPointTo( Q ) ) > tolerance ) {
00577           rc = 0;
00578           break;
00579         }
00580         point += stride;
00581       }
00582     }
00583     else {
00584       for ( i = 0; i < count; i++ ) {
00585         memcpy( &Q.x, point, dim*sizeof(Q.x) );
00586         if ( Q.DistanceTo( plane.ClosestPointTo( Q ) ) > tolerance ) {
00587           rc = 0;
00588           break;
00589         }
00590         point += stride;
00591       }
00592     }
00593   }
00594 
00595   return rc;
00596 }
00597 


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