00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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,
00046 const ON_3dVector& N
00047 )
00048 {
00049 CreateFromNormal(P,N);
00050 }
00051
00052 ON_Plane::ON_Plane(
00053 const ON_3dPoint& P,
00054 const ON_3dVector& X,
00055 const ON_3dVector& Y
00056 )
00057 {
00058 CreateFromFrame(P,X,Y);
00059 }
00060
00061 ON_Plane::ON_Plane(
00062 const ON_3dPoint& P,
00063 const ON_3dPoint& Q,
00064 const ON_3dPoint& R
00065 )
00066 {
00067 CreateFromPoints(P,Q,R);
00068 }
00069
00070 ON_Plane::ON_Plane(
00071 const double e[4]
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(
00092 int dir,
00093
00094
00095
00096 double c
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
00114
00115 return ( point - origin)*zaxis;
00116 }
00117
00118 bool ON_Plane::GetDistanceToBoundingBox(const ON_BoundingBox& Box,
00119 double* min, double* max) const
00120 {
00121
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
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
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168 bool ON_Plane::UpdateEquation()
00169 {
00170
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,
00233 const ON_3dVector& N
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,
00251 const ON_3dVector& X,
00252 const ON_3dVector& Y
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
00267
00268 b = IsValid();
00269 if ( b )
00270 {
00271
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]
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,
00308 const ON_3dPoint& Q,
00309 const ON_3dPoint& R
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
00338
00339
00340
00341
00342
00343
00344
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
00371
00372
00373
00374
00375
00376
00377
00378 return IsValid();
00379 }
00380
00381 ON_3dPoint origin_pt = xform*origin;
00382
00383
00384
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
00414 bool ON_Plane::Rotate(
00415 double s,
00416 double c,
00417 const ON_3dVector& axis
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;
00431 }
00432 return rc;
00433 }
00434
00435 bool ON_Plane::Rotate(
00436 double angle,
00437 const ON_3dVector& axis
00438 )
00439 {
00440 return Rotate( sin(angle), cos(angle), axis );
00441 }
00442
00443
00444 bool ON_Plane::Rotate(
00445 double sin_angle,
00446 double cos_angle,
00447 const ON_3dVector& axis,
00448 const ON_3dPoint& center
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,
00469 const ON_3dVector& axis,
00470 const ON_3dPoint& origin_pt
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(
00497 int dim,
00498 int is_rat,
00499 int count,
00500 int stride, const double* point,
00501 const ON_BoundingBox& bbox,
00502 const ON_Plane& plane,
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
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
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