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 ON_Ellipse::ON_Ellipse()
00020 {
00021 radius[0] = radius[1] = 0.0;
00022 }
00023
00024
00025 ON_Ellipse::ON_Ellipse(
00026 const ON_Plane& p,
00027 double rx, double ry
00028 )
00029 {
00030 Create(p,rx,ry);
00031 }
00032
00033
00034 ON_Ellipse::ON_Ellipse(
00035 const ON_Circle& c
00036 )
00037 {
00038 Create(c);
00039 }
00040
00041 ON_Ellipse::~ON_Ellipse()
00042 {}
00043
00044 ON_Ellipse& ON_Ellipse::operator=(const ON_Circle& c)
00045 {
00046 Create( c );
00047 return *this;
00048 }
00049
00050 ON_BOOL32 ON_Ellipse::Create( const ON_Plane& p, double rx, double ry )
00051 {
00052 plane = p;
00053 radius[0] = rx;
00054 radius[1] = ry;
00055 return IsValid();
00056 }
00057
00058 ON_BOOL32 ON_Ellipse::Create( const ON_Circle& c )
00059 {
00060 return Create( c.Plane(), c.Radius(), c.Radius() );
00061 }
00062
00063 ON_BOOL32 ON_Ellipse::IsValid() const
00064 {
00065 return (plane.IsValid() && radius[0] > ON_ZERO_TOLERANCE && radius[1] > ON_ZERO_TOLERANCE) ? true : false;
00066 }
00067
00068 ON_BOOL32 ON_Ellipse::IsCircle() const
00069 {
00070 double r0 = radius[0];
00071 return ( ON_IsValid(r0) && fabs(r0-radius[1]) <= fabs(r0)*ON_ZERO_TOLERANCE && IsValid() ) ? true : false;
00072 }
00073
00074 double ON_Ellipse::Radius( int i ) const
00075 {
00076 return radius[(i)?1:0];
00077 }
00078
00079 const ON_3dPoint& ON_Ellipse::Center() const
00080 {
00081 return plane.origin;
00082 }
00083
00084 double ON_Ellipse::FocalDistance() const
00085 {
00086 int i = (fabs(radius[0]) >= fabs(radius[1])) ? 0 : 1;
00087 const double a = fabs(radius[i]);
00088 const double b = a > 0.0 ? fabs(radius[1-i])/a : 0.0;
00089 return a*sqrt(1.0 - b*b);
00090 }
00091
00092 bool ON_Ellipse::GetFoci( ON_3dPoint& F1, ON_3dPoint& F2 ) const
00093 {
00094 const double f = FocalDistance();
00095 const ON_3dVector& majorAxis = (radius[0] >= radius[1]) ? plane.xaxis : plane.yaxis;
00096 F1 = plane.origin + f*majorAxis;
00097 F2 = plane.origin - f*majorAxis;
00098 return true;
00099 }
00100
00101 const ON_3dVector& ON_Ellipse::Normal() const
00102 {
00103 return plane.zaxis;
00104 }
00105
00106 const ON_Plane& ON_Ellipse::Plane() const
00107 {
00108 return plane;
00109 }
00110
00111 ON_3dPoint ON_Ellipse::PointAt( double t ) const
00112 {
00113 return plane.PointAt( cos(t)*radius[0], sin(t)*radius[1] );
00114 }
00115
00116 ON_3dVector ON_Ellipse::DerivativeAt(
00117 int d,
00118 double t
00119 ) const
00120 {
00121 double r0 = radius[0];
00122 double r1 = radius[1];
00123 switch (abs(d)%4) {
00124 case 0:
00125 r0 *= cos(t);
00126 r1 *= sin(t);
00127 break;
00128 case 1:
00129 r0 *= -sin(t);
00130 r1 *= cos(t);
00131 break;
00132 case 2:
00133 r0 *= -cos(t);
00134 r1 *= -sin(t);
00135 break;
00136 case 3:
00137 r0 *= sin(t);
00138 r1 *= -cos(t);
00139 break;
00140 }
00141 return ( r0*plane.xaxis + r1*plane.yaxis );
00142 }
00143
00144 ON_3dVector ON_Ellipse::TangentAt(
00145 double t
00146 ) const
00147 {
00148 ON_3dVector T = DerivativeAt( 1, t );
00149 T.Unitize();
00150 return T;
00151 }
00152
00153 ON_3dVector ON_Ellipse::CurvatureAt(
00154 double t
00155 ) const
00156 {
00157 ON_3dVector T, K;
00158 ON_EvCurvature(DerivativeAt( 1, t ),DerivativeAt( 2, t ),T,K);
00159 return K;
00160 }
00161
00162 static int distSqToEllipse(void* p, double t, double* f, double* df )
00163 {
00164
00165 double dx, dy, st, ct;
00166 const double* a = (const double*)p;
00167
00168
00169
00170 ct = cos(t);
00171 st = sin(t);
00172 dx = ct*a[0] - a[2];
00173 dy = st*a[1] - a[3];
00174 if ( f ) {
00175 *f = dx*dx + dy*dy;
00176 }
00177 if ( df ) {
00178 *df = 2.0*(dy*a[1]*ct - dx*a[0]*st);
00179 }
00180 return 0;
00181 }
00182
00183 #if defined(ON_COMPILER_MSC)
00184
00185
00186
00187
00188
00189
00190
00191
00192 #pragma warning( push )
00193 #pragma warning( disable : 4127 )
00194 #endif
00195
00196 ON_BOOL32 ON_Ellipse::ClosestPointTo( const ON_3dPoint& point, double* t ) const
00197 {
00198 ON_BOOL32 rc = true;
00199 if ( t ) {
00200 ON_2dPoint uv;
00201 rc = plane.ClosestPointTo( point, &uv.x, &uv.y );
00202 if ( uv.x == 0.0 ) {
00203 if ( uv.y == 0.0 ) {
00204 *t = (radius[0] <= radius[1]) ? 0.0 : 0.5*ON_PI;
00205 return true;
00206 }
00207 if ( uv.y >= radius[1] ) {
00208 *t = 0.5*ON_PI;
00209 return true;
00210 }
00211 if ( uv.y <= -radius[1] ) {
00212 *t = 1.5*ON_PI;
00213 return true;
00214 }
00215 }
00216 else if ( uv.y == 0.0 ) {
00217 if ( uv.x >= radius[0] ) {
00218 *t = 0.0;
00219 return true;
00220 }
00221 if ( uv.x <= -radius[0] ) {
00222 *t = ON_PI;
00223 return true;
00224 }
00225 }
00226 {
00227
00228 double t0, t1;
00229 *t = atan2( uv.y, uv.x );
00230 if ( *t < 0.0 )
00231 {
00232 *t += 2.0*ON_PI;
00233 if ( 2.0*ON_PI <= *t)
00234 {
00235
00236 *t = 0.0;
00237 }
00238 }
00239 if ( radius[0] != radius[1] ) {
00240
00241 if ( uv.x >= 0.0 ) {
00242 if ( uv.y >= 0.0 ) {
00243
00244 t0 = 0.0;
00245 t1 = 0.5*ON_PI;
00246 }
00247 else {
00248
00249 t0 = 1.5*ON_PI;
00250 t1 = 2.0*ON_PI;
00251 }
00252 }
00253 else {
00254 if ( uv.y >= 0.0 ) {
00255
00256 t0 = 0.5*ON_PI;
00257 t1 = ON_PI;
00258 }
00259 else {
00260
00261 t0 = ON_PI;
00262 t1 = 1.5*ON_PI;
00263 }
00264 }
00265
00266
00267 {
00268
00269
00270
00271 double p[4], et, d0, d1, dt;
00272 int i;
00273 p[0] = radius[0];
00274 p[1] = radius[1];
00275 p[2] = uv.x;
00276 p[3] = uv.y;
00277 et = *t;
00278 if ( et <= t0 )
00279 et = 0.9*t0 + 0.1*t1;
00280 else if ( et >= t1 )
00281 et = 0.9*t1 + 0.1*t0;
00282 distSqToEllipse( p, t0, &d0, NULL );
00283 distSqToEllipse( p, t1, &d1, NULL );
00284 if ( d0 == 0.0 ) {
00285 *t = (t0 == 2.0*ON_PI) ? 0.0 : t0;
00286 return true;
00287 }
00288 if ( d1 == 0.0 ) {
00289 *t = (t1 == 2.0*ON_PI) ? 0.0 : t1;
00290 return true;
00291 }
00292 if ( d0 > d1 ) {
00293 dt = t0; t0 = t1; t1 = dt;
00294 dt = d0; d0 = d1; d1 = dt;
00295 }
00296 *t = (t0 == 2.0*ON_PI) ? 0.0 : t0;
00297 for ( i = 0; true; i++ ) {
00298 distSqToEllipse( p, et, &dt, NULL );
00299 if ( dt < d0 )
00300 {
00301 *t = (et >= 2.0*ON_PI) ? 0.0 : et;
00302 break;
00303 }
00304 if ( i >= 100 )
00305 {
00306 ON_3dPoint E0 = PointAt(t0);
00307 if ( sqrt(d0) <= ON_ZERO_TOLERANCE
00308 || sqrt(d0) <= ON_SQRT_EPSILON*E0.DistanceTo(Center())
00309 )
00310 {
00311
00312
00313 return true;
00314 }
00315 ON_3dVector T = TangentAt(t0);
00316 ON_3dVector V = E0 - point;
00317 if ( V.Unitize() )
00318 {
00319
00320
00321
00322 if ( fabs(V*T) <= 0.087155742747658173558064270837474 )
00323 return true;
00324 }
00325 return false;
00326 }
00327 et = (i) ? (0.5*(t0+et)) : 0.5*(t0+t1);
00328 if ( et == t0 )
00329 {
00330 return true;
00331 }
00332 }
00333
00334 rc = ON_FindLocalMinimum( distSqToEllipse, p,
00335 t0, et, t1,
00336 ON_EPSILON, ON_SQRT_EPSILON, 100,
00337 &et );
00338 rc = (rc > 0) ? true : false;
00339 if ( rc )
00340 *t = (et >= 2.0*ON_PI) ? 0.0 : et;
00341 }
00342 }
00343 }
00344 }
00345 return rc;
00346 }
00347
00348 #if defined(ON_COMPILER_MSC)
00349 #pragma warning( pop )
00350 #endif
00351
00352 ON_3dPoint ON_Ellipse::ClosestPointTo( const ON_3dPoint& point ) const
00353 {
00354 double t;
00355 ClosestPointTo( point, &t );
00356 return PointAt( t );
00357 }
00358
00359 double ON_Ellipse::EquationAt(
00360 const ON_2dPoint& p
00361 ) const
00362 {
00363 double e, x, y;
00364 if ( radius[0] != 0.0 && radius[1] != 0.0 ) {
00365 x = p.x/radius[0];
00366 y = p.y/radius[1];
00367 e = x*x + y*y - 1.0;
00368 }
00369 else {
00370 e = 0.0;
00371 }
00372 return e;
00373 }
00374
00375 ON_2dVector ON_Ellipse::GradientAt(
00376 const ON_2dPoint& p
00377 ) const
00378 {
00379 ON_2dVector g;
00380 if ( radius[0] != 0.0 && radius[1] != 0.0 ) {
00381 g.x = 2.0*p.x/(radius[0]*radius[0]);
00382 g.y = 2.0*p.y/(radius[1]*radius[1]);
00383 }
00384 else {
00385 g.Zero();
00386 }
00387 return g;
00388 }
00389
00390 ON_BOOL32 ON_Ellipse::Rotate(
00391 double sin_angle, double cos_angle,
00392 const ON_3dVector& axis
00393 )
00394 {
00395 return plane.Rotate( sin_angle, cos_angle, axis );
00396 }
00397
00398 ON_BOOL32 ON_Ellipse::Rotate(
00399 double angle,
00400 const ON_3dVector& axis
00401 )
00402 {
00403 return plane.Rotate( angle, axis );
00404 }
00405
00406 ON_BOOL32 ON_Ellipse::Rotate(
00407 double sin_angle, double cos_angle,
00408 const ON_3dVector& axis,
00409 const ON_3dPoint& point
00410 )
00411 {
00412 return plane.Rotate( sin_angle, cos_angle, axis, point );
00413 }
00414
00415 ON_BOOL32 ON_Ellipse::Rotate(
00416 double angle,
00417 const ON_3dVector& axis,
00418 const ON_3dPoint& point
00419 )
00420 {
00421 return plane.Rotate( angle, axis, point );
00422 }
00423
00424
00425 ON_BOOL32 ON_Ellipse::Translate(
00426 const ON_3dVector& delta
00427 )
00428 {
00429 return plane.Translate( delta );
00430 }
00431
00432 ON_BOOL32 ON_Ellipse::GetNurbForm( ON_NurbsCurve& nurbscurve ) const
00433 {
00434 int rc = 0;
00435 if ( IsValid() ) {
00436 nurbscurve.Create( 3, true, 3, 9 );
00437 nurbscurve.m_knot[0] = nurbscurve.m_knot[1] = 0.0;
00438 nurbscurve.m_knot[2] = nurbscurve.m_knot[3] = 0.5*ON_PI;
00439 nurbscurve.m_knot[4] = nurbscurve.m_knot[5] = ON_PI;
00440 nurbscurve.m_knot[6] = nurbscurve.m_knot[7] = 1.5*ON_PI;
00441 nurbscurve.m_knot[8] = nurbscurve.m_knot[9] = 2.0*ON_PI;
00442 ON_4dPoint* CV = (ON_4dPoint*)nurbscurve.m_cv;
00443
00444 CV[0] = plane.PointAt( radius[0], 0.0);
00445 CV[1] = plane.PointAt( radius[0], radius[1]);
00446 CV[2] = plane.PointAt( 0.0, radius[1]);
00447 CV[3] = plane.PointAt(-radius[0], radius[1]);
00448 CV[4] = plane.PointAt(-radius[0], 0.0);
00449 CV[5] = plane.PointAt(-radius[0], -radius[1]);
00450 CV[6] = plane.PointAt( 0.0, -radius[1]);
00451 CV[7] = plane.PointAt( radius[0], -radius[1]);
00452 CV[8] = CV[0];
00453
00454 const double w = 1.0/sqrt(2.0);
00455 int i;
00456 for ( i = 1; i < 8; i += 2 ) {
00457 CV[i].x *= w;
00458 CV[i].y *= w;
00459 CV[i].z *= w;
00460 CV[i].w = w;
00461 }
00462 rc = 2;
00463 }
00464 return rc;
00465 }