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
00021
00022 bool ON_BezierCurve::GetTightBoundingBox(
00023 ON_BoundingBox& tight_bbox,
00024 int bGrowBox,
00025 const ON_Xform* xform
00026 ) const
00027 {
00028
00029
00030 return ON_GetPointListBoundingBox(
00031 m_dim,
00032 m_is_rat,
00033 m_order,
00034 m_cv_stride,
00035 m_cv,
00036 tight_bbox,
00037 bGrowBox,
00038 xform
00039 );
00040 }
00041
00043
00044 ON_PolynomialCurve::ON_PolynomialCurve()
00045 : m_dim(0), m_is_rat(0), m_order(0), m_domain(0.0,1.0)
00046 {}
00047
00048 ON_PolynomialCurve::ON_PolynomialCurve( int dim, ON_BOOL32 is_rat, int order )
00049 : m_dim(0), m_is_rat(0), m_order(0), m_domain(0.0,1.0)
00050 {
00051 Create( dim, is_rat, order );
00052 }
00053
00054 ON_PolynomialCurve::~ON_PolynomialCurve()
00055 {
00056 Destroy();
00057 }
00058
00059 ON_PolynomialCurve::ON_PolynomialCurve(const ON_PolynomialCurve& src)
00060 : m_dim(0), m_is_rat(0), m_order(0), m_domain(0.0,1.0)
00061 {
00062 *this = src;
00063 }
00064
00065 ON_PolynomialCurve::ON_PolynomialCurve(const ON_BezierCurve& src)
00066 : m_dim(0), m_is_rat(0), m_order(0), m_domain(0.0,1.0)
00067 {
00068 *this = src;
00069 }
00070
00071 ON_BOOL32 ON_PolynomialCurve::Create( int dim, ON_BOOL32 is_rat, int order )
00072 {
00073 ON_BOOL32 rc = true;
00074 if ( dim > 0 ) m_dim = dim; else {m_dim = 0; rc = false;}
00075 m_is_rat = is_rat?1:0;
00076 if ( order >= 1 ) m_order = order; else {m_order = 0; rc = false;}
00077 m_cv.SetCapacity(m_order);
00078 m_domain.m_t[0] = 0.0;
00079 m_domain.m_t[1] = 1.0;
00080 return rc;
00081 }
00082
00083 void ON_PolynomialCurve::Destroy()
00084 {
00085 m_dim = 0;
00086 m_is_rat = 0;
00087 m_order = 0;
00088 m_cv.Destroy();
00089 m_domain.m_t[0] = 0.0;
00090 m_domain.m_t[1] = 1.0;
00091 }
00092
00093
00094 ON_PolynomialCurve& ON_PolynomialCurve::operator=(const ON_PolynomialCurve& src)
00095 {
00096 if ( this != &src ) {
00097 m_dim = src.m_dim;
00098 m_is_rat = src.m_is_rat;
00099 m_order = src.m_order;
00100 m_cv = src.m_cv;
00101 m_domain = src.m_domain;
00102 }
00103 return *this;
00104 }
00105
00106 ON_PolynomialCurve& ON_PolynomialCurve::operator=(const ON_BezierCurve& src)
00107 {
00108 int i;
00109 double d;
00110 m_dim = src.m_dim;
00111 m_is_rat = src.m_is_rat;
00112 m_order = src.m_order;
00113 m_cv.Reserve( src.m_order );
00114 m_cv.SetCount( src.m_order );
00115 m_cv.Zero();
00116
00117
00118 if ( m_order >= 2 && src.CVSize() <= 4 ) {
00119 ON_BezierCurve s;
00120 s.m_dim = src.m_is_rat ? src.m_dim+1 : src.m_dim;
00121 s.m_is_rat = 0;
00122 s.m_order = src.m_order;
00123 s.m_cv = src.m_cv;
00124
00125
00126 if ( s.Evaluate( 0.0, m_order-1, 4, &m_cv[0].x ) ) {
00127 if ( m_is_rat ) {
00128 if ( m_dim < 3 ) {
00129 for ( i = 0; i < m_order; i++ ) {
00130 ON_4dPoint& cv = m_cv[i];
00131 cv.w = cv[m_dim];
00132 cv[m_dim] = 0.0;
00133 }
00134 }
00135 }
00136 else {
00137 m_cv[0].w = 1.0;
00138 }
00139 for ( i = 2; i < m_order; i++ ) {
00140 d = 1.0/i;
00141 ON_4dPoint& cv = m_cv[i];
00142 cv.x *= d;
00143 cv.y *= d;
00144 cv.z *= d;
00145 cv.w *= d;
00146 }
00147 }
00148 else {
00149 m_cv.Zero();
00150 m_cv[0].w = 1.0;
00151 }
00152 s.m_cv = 0;
00153 }
00154
00155 return *this;
00156 }
00157
00158 ON_BOOL32 ON_PolynomialCurve::Evaluate(
00159 double t,
00160 int der_count,
00161 int v_stride,
00162 double* v
00163 ) const
00164 {
00165 ON_BOOL32 rc = false;
00166 if ( m_order >= 1 && m_cv.Count() == m_order )
00167 {
00168 if ( m_domain.m_t[0] != 0.0 || m_domain.m_t[1] != 1.0 )
00169 {
00170 t = (1.0-t)*m_domain.m_t[0] + t*m_domain.m_t[1];
00171 }
00172 ON_4dPointArray p(der_count+1);
00173 ON_4dPoint c;
00174 double s;
00175 int i, j, der;
00176 p.Zero();
00177 for ( i = m_order-1; i >= 0; i-- ) {
00178 c = m_cv[i];
00179 p[0].x = t*p[0].x + c.x;
00180 p[0].y = t*p[0].y + c.y;
00181 p[0].z = t*p[0].z + c.z;
00182 p[0].w = t*p[0].w + c.w;
00183 }
00184 if ( der_count >= 1 ) {
00185 for ( i = m_order-1; i >= 1; i-- ) {
00186 c = m_cv[i];
00187 p[1].x = t*p[1].x + i*c.x;
00188 p[1].y = t*p[1].y + i*c.y;
00189 p[1].z = t*p[1].z + i*c.z;
00190 p[1].w = t*p[1].w + i*c.w;
00191 }
00192 for ( der = 2; der <= der_count; der++ ) {
00193 for ( i = m_order-1; i >= der; i-- ) {
00194 s = i;
00195 for ( j = 1; j < der; j++ ) {
00196 s *= (i-j);
00197 }
00198 c = m_cv[i];
00199 p[der].x = t*p[der].x + s*c.x;
00200 p[der].y = t*p[der].y + s*c.y;
00201 p[der].z = t*p[der].z + s*c.z;
00202 p[der].w = t*p[der].w + s*c.w;
00203 }
00204 }
00205 if ( m_is_rat ) {
00206 ON_EvaluateQuotientRule( 3, der_count, 4, &p[0].x );
00207 }
00208 }
00209 const int sz = m_dim*sizeof(v[0]);
00210 for ( i = 0; i <= der_count; i++ ) {
00211 memcpy( v, &p[i].x, sz );
00212 v += v_stride;
00213 }
00214 rc = true;
00215 }
00216 return rc;
00217 }
00218
00219 ON_PolynomialSurface::ON_PolynomialSurface() : m_dim(0), m_is_rat(0)
00220 {
00221 m_order[0] = 0;
00222 m_order[1] = 0;
00223 m_domain[0].m_t[0] = 0.0;
00224 m_domain[0].m_t[1] = 1.0;
00225 m_domain[1].m_t[0] = 0.0;
00226 m_domain[1].m_t[1] = 1.0;
00227 }
00228
00229 ON_PolynomialSurface::ON_PolynomialSurface( int dim, ON_BOOL32 is_rat, int order0, int order1 )
00230 {
00231 Create( dim, is_rat, order0, order1 );
00232 }
00233
00234 ON_PolynomialSurface::~ON_PolynomialSurface()
00235 {
00236 Destroy();
00237 }
00238
00239 ON_PolynomialSurface::ON_PolynomialSurface(const ON_PolynomialSurface& src)
00240 {
00241 m_order[0] = 0;
00242 m_order[1] = 0;
00243 m_domain[0].m_t[0] = 0.0;
00244 m_domain[0].m_t[1] = 1.0;
00245 m_domain[1].m_t[0] = 0.0;
00246 m_domain[1].m_t[1] = 1.0;
00247 *this = src;
00248 }
00249
00250 ON_PolynomialSurface::ON_PolynomialSurface(const ON_BezierSurface& src)
00251 {
00252 m_order[0] = 0;
00253 m_order[1] = 0;
00254 m_domain[0].m_t[0] = 0.0;
00255 m_domain[0].m_t[1] = 1.0;
00256 m_domain[1].m_t[0] = 0.0;
00257 m_domain[1].m_t[1] = 1.0;
00258 *this = src;
00259 }
00260
00261 ON_PolynomialSurface& ON_PolynomialSurface::operator=(const ON_PolynomialSurface& src)
00262 {
00263 if ( this != &src ) {
00264 if ( Create( src.m_dim, src.m_is_rat, src.m_order[0], src.m_order[1] ) ) {
00265 m_cv = src.m_cv;
00266 m_domain[0] = src.m_domain[0];
00267 m_domain[1] = src.m_domain[1];
00268 }
00269 }
00270 return *this;
00271 }
00272
00273 ON_PolynomialSurface& ON_PolynomialSurface::operator=(const ON_BezierSurface& src)
00274 {
00275 if ( Create( src.m_dim, src.m_is_rat, src.m_order[0], src.m_order[1] ) ) {
00276
00277
00278
00279 }
00280 return *this;
00281 }
00282
00283 ON_BOOL32 ON_PolynomialSurface::Create( int dim, int is_rat, int order0, int order1 )
00284 {
00285 ON_BOOL32 rc = true;
00286 if ( dim > 0 ) m_dim = dim; else {m_dim = 0; rc = false;};
00287 m_is_rat = is_rat?1:0;
00288 if ( order0 > 0 ) m_order[0] = order0; else { m_order[0] = 0; rc = false;}
00289 if ( order1 > 0 ) m_order[1] = order1; else { m_order[1] = 0; rc = false;}
00290 m_cv.SetCapacity( m_order[0]*m_order[1] );
00291 if ( m_order[0] > 0 && m_order[1] > 0 ) {
00292 m_cv.Zero();
00293 m_cv[0].w = 1.0;
00294 }
00295 return rc;
00296 }
00297
00298 void ON_PolynomialSurface::Destroy()
00299 {
00300 m_dim = 0;
00301 m_is_rat = 0;
00302 m_order[0] = 0;
00303 m_order[1] = 0;
00304 m_cv.Destroy();
00305 }
00306
00307 ON_BOOL32 ON_PolynomialSurface::Evaluate(
00308 double s,
00309 double t,
00310 int der_count,
00311 int v_stride,
00312 double* v
00313 ) const
00314 {
00315 ON_ERROR("TODO: - finish ON_PolynomialSurface::Evaluate()\n");
00316 return false;
00317 }
00318
00319 ON_BezierCurve::ON_BezierCurve()
00320 : m_dim(0),
00321 m_is_rat(0),
00322 m_order(0),
00323 m_cv_stride(0),
00324 m_cv(0),
00325 m_cv_capacity(0)
00326 {
00327 #if 8 == ON_SIZEOF_POINTER
00328 m_reserved_ON_BezierCurve = 0;
00329 #endif
00330 }
00331
00332 ON_BezierCurve::ON_BezierCurve( int dim, ON_BOOL32 is_rat, int order )
00333 : m_dim(0),
00334 m_is_rat(0),
00335 m_order(0),
00336 m_cv_stride(0),
00337 m_cv(0),
00338 m_cv_capacity(0)
00339 {
00340 #if 8 == ON_SIZEOF_POINTER
00341 m_reserved_ON_BezierCurve = 0;
00342 #endif
00343 Create(dim,is_rat,order);
00344 }
00345
00346 ON_BezierCurve::~ON_BezierCurve()
00347 {
00348 Destroy();
00349 }
00350
00351 ON_BezierCurve::ON_BezierCurve(const ON_BezierCurve& src)
00352 : m_dim(0),
00353 m_is_rat(0),
00354 m_order(0),
00355 m_cv_stride(0),
00356 m_cv(0),
00357 m_cv_capacity(0)
00358 {
00359 #if 8 == ON_SIZEOF_POINTER
00360 m_reserved_ON_BezierCurve = 0;
00361 #endif
00362 *this = src;
00363 }
00364
00365 ON_BezierCurve::ON_BezierCurve(const ON_PolynomialCurve& src)
00366 : m_dim(0),
00367 m_is_rat(0),
00368 m_order(0),
00369 m_cv_stride(0),
00370 m_cv(0),
00371 m_cv_capacity(0)
00372 {
00373 #if 8 == ON_SIZEOF_POINTER
00374 m_reserved_ON_BezierCurve = 0;
00375 #endif
00376 *this = src;
00377 }
00378
00379 ON_BezierCurve::ON_BezierCurve(const ON_2dPointArray& cv)
00380 : m_dim(0),
00381 m_is_rat(0),
00382 m_order(0),
00383 m_cv_stride(0),
00384 m_cv(0),
00385 m_cv_capacity(0)
00386 {
00387 #if 8 == ON_SIZEOF_POINTER
00388 m_reserved_ON_BezierCurve = 0;
00389 #endif
00390 *this = cv;
00391 }
00392
00393 ON_BezierCurve::ON_BezierCurve(const ON_3dPointArray& cv)
00394 : m_dim(0),
00395 m_is_rat(0),
00396 m_order(0),
00397 m_cv_stride(0),
00398 m_cv(0),
00399 m_cv_capacity(0)
00400 {
00401 #if 8 == ON_SIZEOF_POINTER
00402 m_reserved_ON_BezierCurve = 0;
00403 #endif
00404 *this = cv;
00405 }
00406
00407 ON_BezierCurve::ON_BezierCurve(const ON_4dPointArray& cv)
00408 : m_dim(0),
00409 m_is_rat(0),
00410 m_order(0),
00411 m_cv_stride(0),
00412 m_cv(0),
00413 m_cv_capacity(0)
00414 {
00415 #if 8 == ON_SIZEOF_POINTER
00416 m_reserved_ON_BezierCurve = 0;
00417 #endif
00418 *this = cv;
00419 }
00420
00421 ON_BezierCurve& ON_BezierCurve::operator=(const ON_2dPointArray& cv)
00422 {
00423 if ( Create( 2, false, cv.Count() ) )
00424 {
00425 int i;
00426 for ( i = 0; i < m_order; i++ )
00427 SetCV( i, ON::intrinsic_point_style, cv[i] );
00428 }
00429 return *this;
00430 }
00431
00432 ON_BezierCurve& ON_BezierCurve::operator=(const ON_3dPointArray& cv)
00433 {
00434 if ( Create( 3, false, cv.Count() ) )
00435 {
00436 int i;
00437 for ( i = 0; i < m_order; i++ )
00438 SetCV( i, ON::intrinsic_point_style, cv[i] );
00439 }
00440 return *this;
00441 }
00442
00443 ON_BezierCurve& ON_BezierCurve::operator=(const ON_4dPointArray& cv)
00444 {
00445 if ( Create( 3, true, cv.Count() ) )
00446 {
00447 int i;
00448 for ( i = 0; i < m_order; i++ )
00449 SetCV( i, ON::intrinsic_point_style, cv[i] );
00450 }
00451 return *this;
00452 }
00453
00454
00455 ON_BezierCurve& ON_BezierCurve::operator=(const ON_BezierCurve& src)
00456 {
00457 int i;
00458 if ( this != &src ) {
00459
00460 if ( Create( src.m_dim, src.m_is_rat, src.m_order ) ) {
00461 const int sizeof_cv = CVSize()*sizeof(m_cv[0]);
00462 for ( i = 0; i < m_order; i++ ) {
00463 memcpy( CV(i), src.CV(i), sizeof_cv );
00464 }
00465 }
00466 }
00467 return *this;
00468 }
00469
00470 ON_BezierCurve& ON_BezierCurve::operator=(const ON_PolynomialCurve& src)
00471 {
00472
00473 if ( src.m_dim > 0 && src.m_cv.Count() == src.m_order && src.m_order >= 2 )
00474 {
00475 int i;
00476
00477 ON_PolynomialCurve s;
00478 s.m_dim = src.m_is_rat ? 4 : src.m_dim;
00479 s.m_is_rat = 0;
00480 s.m_domain.m_t[0] = 0.0;
00481 s.m_domain.m_t[1] = 1.0;
00482 s.m_order = src.m_order;
00483 s.m_cv = src.m_cv;
00484
00485 if ( src.m_is_rat ) {
00486 m_dim++;
00487 m_is_rat = 0;
00488 }
00489 const int degree = src.m_order-1;
00490 const double d = 1.0/degree;
00491 double t;
00492 ON_4dPointArray pt(src.m_order);
00493 for ( i = 0; i < src.m_order; i++ )
00494 {
00495 if ( i == 0 )
00496 t = 0.0;
00497 else if ( i < degree )
00498 t = i*d;
00499 else
00500 t = 1.0;
00501 s.Evaluate( t, 0, 4, pt[i] );
00502 }
00503 s.m_cv = 0;
00504 if ( src.m_is_rat && src.m_dim < 3 ) {
00505 for ( i = 0; i < src.m_order; i++ )
00506 pt[i][src.m_dim] = pt[i].w;
00507 }
00508 Loft( src.m_is_rat ? src.m_dim+1 : src.m_dim, src.m_order, 4, &pt[0].x, 0, NULL );
00509 if ( IsValid() && src.m_is_rat ) {
00510 m_is_rat = 1;
00511 m_dim--;
00512 }
00513 }
00514 else {
00515 Destroy();
00516 }
00517
00518 return *this;
00519 }
00520
00521 bool ON_BezierCurve::Loft( const ON_3dPointArray& pt )
00522 {
00523 const ON_3dPoint* p0 = pt.Array();
00524 return Loft( 3, pt.Count(), 3, p0?&p0->x:0, 0, NULL );
00525 }
00526
00527
00528 bool ON_BezierCurve::Loft( int pt_dim, int pt_count, int pt_stride, const double* pt,
00529 int t_stride, const double* t )
00530 {
00531 bool rc = false;
00532 if ( pt_dim >= 1 && pt_count >= 2 && pt_stride >= pt_dim && pt != NULL && (t_stride >= 1 || t == 0) ) {
00533 int i, j;
00534 ON_SimpleArray<double> uniform_t;
00535 double s;
00536 if ( !t ) {
00537 uniform_t.Reserve(pt_count);
00538 s = 1.0/(pt_count-1);
00539 for ( i = 0; i < pt_count; i++ ) {
00540 uniform_t.Append(i*s);
00541 }
00542 uniform_t[0] = 0.0;
00543 uniform_t[pt_count-1] = 1.0;
00544 t = uniform_t.Array();
00545 t_stride = 1;
00546 }
00547 Create( pt_dim, false, pt_count );
00548 const int sizeof_cv = CVSize()*sizeof(m_cv[0]);
00549 const int degree = m_order-1;
00550 const double t0 = t[0];
00551 const double t1 = t[t_stride*(pt_count-1)];
00552 const double tm = 0.5*(t1-t0);
00553 const double d = (t1-t0);
00554 ON_Matrix M( m_order, m_order );
00555 for ( i = 0; i < m_order; i++ ) {
00556 if ( t[i] <= tm ) {
00557 s = (t[i] - t[0])/d;
00558 }
00559 else {
00560 s = 1.0 - (t1 - t[i])/d;
00561 }
00562 for ( j = 0; j < m_order; j++ ) {
00563 M.m[i][j] = ON_EvaluateBernsteinBasis( degree, j, s );
00564 }
00565 memcpy( m_cv + i*m_cv_stride, pt + i*pt_stride, sizeof_cv );
00566 }
00567
00568 int rank = M.RowReduce( ON_EPSILON, m_dim, m_cv_stride, m_cv );
00569 M.BackSolve( ON_EPSILON, m_dim, m_order,
00570 m_cv_stride, m_cv,
00571 m_cv_stride, m_cv );
00572 if ( rank == m_order )
00573 rc = true;
00574 }
00575 return rc;
00576 }
00577
00578 bool ON_BezierCurve::IsValid() const
00579 {
00580 if ( m_dim <= 0 )
00581 return false;
00582 if ( m_is_rat != 0 && m_is_rat != 1 )
00583 return false;
00584 if ( m_order < 2 )
00585 return false;
00586 if ( m_cv_stride < m_dim+m_is_rat )
00587 return false;
00588 if ( m_cv_capacity > 0 && m_cv_capacity < m_cv_stride*m_order )
00589 return false;
00590 if ( m_cv == NULL )
00591 return false;
00592 return true;
00593 }
00594
00595 void ON_BezierCurve::Dump( ON_TextLog& dump ) const
00596 {
00597 dump.Print( "ON_BezierCurve dim = %d is_rat = %d\n"
00598 " order = %d \n",
00599 m_dim, m_is_rat, m_order );
00600 dump.Print( "Control Points %d %s points\n"
00601 " index value\n",
00602 m_order,
00603 (m_is_rat) ? "rational" : "non-rational" );
00604 if ( !m_cv ) {
00605 dump.Print(" NULL cv array\n");
00606 }
00607 else {
00608 dump.PrintPointList( m_dim, m_is_rat,
00609 m_order, m_cv_stride,
00610 m_cv,
00611 " CV" );
00612 }
00613 }
00614
00615 int ON_BezierCurve::Dimension() const
00616 {
00617 return m_dim;
00618 }
00619
00620 bool ON_BezierCurve::Create( int dim, int is_rat, int order )
00621 {
00622 m_dim = (dim>0) ? dim : 0;
00623 m_is_rat = is_rat ? 1 : 0;
00624
00625
00626
00627 m_order = (order >= 1) ? order : 0;
00628 m_cv_stride = (m_dim > 0) ? m_dim+m_is_rat : 0;
00629 m_cv_capacity = m_cv_stride*m_order;
00630 m_cv = (double*)onrealloc( m_cv, m_cv_capacity*sizeof(m_cv[0]) );
00631
00632
00633 return IsValid();
00634 }
00635
00636 void ON_BezierCurve::Destroy()
00637 {
00638 if ( m_cv && m_cv_capacity > 0 )
00639 onfree(m_cv);
00640 m_cv_capacity = 0;
00641 m_cv_stride = 0;
00642 m_cv = 0;
00643 m_dim = 0;
00644 m_is_rat = 0;
00645 m_order = 0;
00646
00647
00648 }
00649
00650 void ON_BezierCurve::EmergencyDestroy()
00651 {
00652 m_cv = 0;
00653 }
00654
00655 bool ON_BezierCurve::GetBBox(
00656 double* boxmin,
00657 double* boxmax,
00658 int bGrowBox
00659 ) const
00660 {
00661 return ON_GetPointListBoundingBox( m_dim, m_is_rat, m_order, m_cv_stride, m_cv, boxmin, boxmax, bGrowBox );
00662 }
00663
00664 bool ON_BezierCurve::GetBoundingBox(
00665 ON_BoundingBox& bbox,
00666 int bGrowBox
00667 ) const
00668 {
00669 double *boxmin, *boxmax;
00670 if ( m_dim > 3 )
00671 {
00672 boxmin = (double*)alloca(2*m_dim*sizeof(*boxmin));
00673 memset( boxmin, 0, 2*m_dim*sizeof(*boxmin) );
00674 boxmax = boxmin + m_dim;
00675 if ( bGrowBox ) {
00676 boxmin[0] = bbox.m_min.x;
00677 boxmin[1] = bbox.m_min.y;
00678 boxmin[2] = bbox.m_min.z;
00679 boxmax[0] = bbox.m_max.x;
00680 boxmax[1] = bbox.m_max.y;
00681 boxmax[2] = bbox.m_max.z;
00682 }
00683 }
00684 else {
00685 boxmin = &bbox.m_min.x;
00686 boxmax = &bbox.m_max.x;
00687 }
00688 bool rc = GetBBox( boxmin, boxmax, bGrowBox );
00689 if ( rc && m_dim > 3 ) {
00690 bbox.m_min = boxmin;
00691 bbox.m_max = boxmax;
00692 }
00693 return rc;
00694 }
00695
00696 ON_BoundingBox ON_BezierCurve::BoundingBox() const
00697 {
00698 ON_BoundingBox bbox;
00699 GetBoundingBox( bbox );
00700 return bbox;
00701 }
00702
00703 bool ON_WorldBBoxIsInTightBBox(
00704 const ON_BoundingBox& tight_bbox,
00705 const ON_BoundingBox& world_bbox,
00706 const ON_Xform* xform
00707 )
00708 {
00709 if ( xform && !xform->IsIdentity() )
00710 {
00711 ON_3dPoint P, Q;
00712 int i,j,k;
00713 for ( i = 0; i < 2; i++ )
00714 {
00715 P.x = (i) ? world_bbox.m_min.x : world_bbox.m_max.x;
00716 for ( j = 0; j < 2; j++ )
00717 {
00718 P.y = (j) ? world_bbox.m_min.y : world_bbox.m_max.y;
00719 for ( k = 0; k < 2; k++ )
00720 {
00721 P.z = (k) ? world_bbox.m_min.z : world_bbox.m_max.z;
00722 Q = (*xform)*P;
00723 if ( !tight_bbox.IsPointIn(Q) )
00724 {
00725 return false;
00726 }
00727 }
00728 }
00729 }
00730 return true;
00731 }
00732
00733 return ( tight_bbox.Includes(world_bbox) );
00734 }
00735
00736 bool ON_Line::GetTightBoundingBox(
00737 ON_BoundingBox& tight_bbox,
00738 int bGrowBox,
00739 const ON_Xform* xform
00740 ) const
00741 {
00742 if ( bGrowBox && !tight_bbox.IsValid() )
00743 {
00744 bGrowBox = false;
00745 }
00746
00747 if ( xform && !xform->IsIdentity() )
00748 {
00749 ON_3dPoint P = (*xform)*from;
00750 tight_bbox.Set(P,bGrowBox);
00751 bGrowBox = true;
00752 P = (*xform)*to;
00753 tight_bbox.Set(P,bGrowBox);
00754 }
00755 else
00756 {
00757 tight_bbox.Set(from,bGrowBox);
00758 bGrowBox = true;
00759 tight_bbox.Set(to,bGrowBox);
00760 }
00761
00762 return (0!=bGrowBox);
00763 }
00764
00765 bool ON_Arc::GetTightBoundingBox(
00766 ON_BoundingBox& tight_bbox,
00767 int bGrowBox,
00768 const ON_Xform* xform
00769 ) const
00770 {
00771 if ( IsCircle() && (0 == xform || xform->IsIdentity()) )
00772 {
00773 return ON_Circle::GetTightBoundingBox(tight_bbox,bGrowBox,0);
00774 }
00775
00776 if ( bGrowBox && !tight_bbox.IsValid() )
00777 {
00778 bGrowBox = false;
00779 }
00780 if ( !bGrowBox )
00781 {
00782 tight_bbox.Destroy();
00783 }
00784
00785
00786
00787 double nurbs_knot[10];
00788 ON_4dPoint nurbs_cv[9];
00789 ON_NurbsCurve nurbs_arc;
00790 nurbs_arc.m_knot = nurbs_knot;
00791 nurbs_arc.m_cv = &nurbs_cv[0].x;
00792 if ( GetNurbForm(nurbs_arc) )
00793 {
00794 if ( xform && !xform->IsIdentity() )
00795 {
00796 nurbs_arc.Transform(*xform);
00797 }
00798 ON_BezierCurve bez_arc;
00799 bez_arc.m_dim = nurbs_arc.m_dim;
00800 bez_arc.m_is_rat = nurbs_arc.m_is_rat;
00801 bez_arc.m_order = nurbs_arc.m_order;
00802 bez_arc.m_cv_stride = nurbs_arc.m_cv_stride;
00803 bez_arc.m_cv = nurbs_arc.m_cv;
00804 int i;
00805 for ( i = nurbs_arc.m_order-2; i < nurbs_arc.m_cv_count-1; i++, bez_arc.m_cv += bez_arc.m_cv_stride )
00806 {
00807 if ( nurbs_arc.m_knot[i] < nurbs_arc.m_knot[i+1] )
00808 {
00809 if ( bez_arc.GetTightBoundingBox( tight_bbox, bGrowBox, 0 ) )
00810 bGrowBox = true;
00811 }
00812 }
00813 bez_arc.m_cv = 0;
00814 }
00815 nurbs_arc.m_cv = 0;
00816 nurbs_arc.m_knot = 0;
00817
00818 return (0!=bGrowBox);
00819 }
00820
00821 bool ON_Circle::GetTightBoundingBox(
00822 ON_BoundingBox& tight_bbox,
00823 int bGrowBox,
00824 const ON_Xform* xform
00825 ) const
00826 {
00827
00828
00829 if ( 0 != xform && !xform->IsIdentity() )
00830 {
00831
00832
00833 ON_Arc arc(*this,2.0*ON_PI);
00834 return arc.GetTightBoundingBox(tight_bbox,bGrowBox,xform);
00835 }
00836
00837 if ( bGrowBox && !tight_bbox.IsValid() )
00838 {
00839 bGrowBox = false;
00840 }
00841
00842 const double rx = radius*ON_Length2d(plane.zaxis.y, plane.zaxis.z);
00843 const double ry = radius*ON_Length2d(plane.zaxis.z, plane.zaxis.x);
00844 const double rz = radius*ON_Length2d(plane.zaxis.x, plane.zaxis.y);
00845 if ( bGrowBox )
00846 {
00847 if ( plane.origin.x-rx < tight_bbox.m_min.x )
00848 tight_bbox.m_min.x = plane.origin.x-rx;
00849 if ( plane.origin.x+rx > tight_bbox.m_max.x )
00850 tight_bbox.m_max.x = plane.origin.x+rx;
00851 if ( plane.origin.y-ry < tight_bbox.m_min.y )
00852 tight_bbox.m_min.y = plane.origin.y-ry;
00853 if ( plane.origin.y+ry > tight_bbox.m_max.y )
00854 tight_bbox.m_max.y = plane.origin.y+ry;
00855 if ( plane.origin.z-rz < tight_bbox.m_min.z )
00856 tight_bbox.m_min.z = plane.origin.z-rz;
00857 if ( plane.origin.z+rz > tight_bbox.m_max.z )
00858 tight_bbox.m_max.z = plane.origin.z+rz;
00859 }
00860 else
00861 {
00862 tight_bbox.m_min.x = plane.origin.x-rx;
00863 tight_bbox.m_max.x = plane.origin.x+rx;
00864 tight_bbox.m_min.y = plane.origin.y-ry;
00865 tight_bbox.m_max.y = plane.origin.y+ry;
00866 tight_bbox.m_min.z = plane.origin.z-rz;
00867 tight_bbox.m_max.z = plane.origin.z+rz;
00868 }
00869
00870 return true;
00871 }
00872
00873 bool ON_ArcCurve::GetTightBoundingBox(
00874 ON_BoundingBox& tight_bbox,
00875 int bGrowBox,
00876 const ON_Xform* xform
00877 ) const
00878 {
00879 return m_arc.GetTightBoundingBox(tight_bbox,bGrowBox,xform);
00880 }
00881
00882 bool ON_LineCurve::GetTightBoundingBox(
00883 ON_BoundingBox& tight_bbox,
00884 int bGrowBox,
00885 const ON_Xform* xform
00886 ) const
00887 {
00888 return m_line.GetTightBoundingBox(tight_bbox,bGrowBox,xform);
00889 }
00890
00891 bool ON_PolylineCurve::GetTightBoundingBox(
00892 ON_BoundingBox& tight_bbox,
00893 int bGrowBox,
00894 const ON_Xform* xform
00895 ) const
00896 {
00897 return m_pline.GetTightBoundingBox(tight_bbox,bGrowBox,xform);
00898 }
00899
00900 bool ON_PolyCurve::GetTightBoundingBox(
00901 ON_BoundingBox& tight_bbox,
00902 int bGrowBox,
00903 const ON_Xform* xform
00904 ) const
00905 {
00906 return m_segment.GetTightBoundingBox(tight_bbox,bGrowBox,xform);
00907 }
00908
00909 bool ON_CurveArray::GetTightBoundingBox(
00910 ON_BoundingBox& tight_bbox,
00911 int bGrowBox,
00912 const ON_Xform* xform
00913 ) const
00914 {
00915 if ( 1 == m_count && m_a[0] )
00916 {
00917 return m_a[0]->GetTightBoundingBox(tight_bbox,bGrowBox,xform);
00918 }
00919
00920 if ( bGrowBox && !tight_bbox.IsValid() )
00921 {
00922 bGrowBox = false;
00923 }
00924 if ( !bGrowBox )
00925 {
00926 tight_bbox.Destroy();
00927 }
00928
00929 if ( m_count > 0 )
00930 {
00931 int i;
00932
00933 ON_3dPointArray P(2*m_count);
00934 for ( i = 0; i < m_count; i++ )
00935 {
00936 if ( m_a[i] )
00937 {
00938 P.Append( m_a[i]->PointAtStart() );
00939 P.Append( m_a[i]->PointAtEnd() );
00940 }
00941 }
00942 if ( P.GetTightBoundingBox(tight_bbox,bGrowBox,xform) )
00943 {
00944 bGrowBox = true;
00945 }
00946
00947 for ( i = 0; i < m_count; i++ )
00948 {
00949 if ( m_a[i] )
00950 {
00951 if ( m_a[i]->GetTightBoundingBox(tight_bbox,bGrowBox,xform) )
00952 {
00953 bGrowBox = true;
00954 }
00955 }
00956 }
00957 }
00958
00959 return (0!=bGrowBox);
00960 }
00961
00962 bool ON_3dPointArray::GetTightBoundingBox(
00963 ON_BoundingBox& tight_bbox,
00964 int bGrowBox,
00965 const ON_Xform* xform
00966 ) const
00967 {
00968 if ( bGrowBox && !tight_bbox.IsValid() )
00969 {
00970 bGrowBox = false;
00971 }
00972 if ( !bGrowBox )
00973 {
00974 tight_bbox.Destroy();
00975 }
00976 if ( m_count > 0 )
00977 {
00978 ON_BoundingBox points_bbox;
00979 if ( xform && !xform->IsIdentity() )
00980 {
00981 ON_3dPoint P;
00982 points_bbox.m_min = (*xform)*m_a[0];
00983 points_bbox.m_max = points_bbox.m_min;
00984 int i;
00985 for ( i = 1; i < m_count; i++ )
00986 {
00987 P = (*xform)*m_a[i];
00988 if ( P.x < points_bbox.m_min.x ) points_bbox.m_min.x = P.x; else if ( P.x > points_bbox.m_max.x ) points_bbox.m_max.x = P.x;
00989 if ( P.y < points_bbox.m_min.y ) points_bbox.m_min.y = P.y; else if ( P.y > points_bbox.m_max.y ) points_bbox.m_max.y = P.y;
00990 if ( P.z < points_bbox.m_min.z ) points_bbox.m_min.z = P.z; else if ( P.z > points_bbox.m_max.z ) points_bbox.m_max.z = P.z;
00991 }
00992 }
00993 else
00994 {
00995 points_bbox = BoundingBox();
00996 }
00997 tight_bbox.Union(points_bbox);
00998 bGrowBox = true;
00999 }
01000 return (0!=bGrowBox);
01001 }
01002
01003 bool ON_PointCloud::GetTightBoundingBox(
01004 ON_BoundingBox& tight_bbox,
01005 int bGrowBox,
01006 const ON_Xform* xform
01007 ) const
01008 {
01009 if ( bGrowBox && !tight_bbox.IsValid() )
01010 {
01011 bGrowBox = false;
01012 }
01013
01014 if ( !bGrowBox )
01015 {
01016 tight_bbox.Destroy();
01017 }
01018
01019 if ( m_P.Count() > 0 )
01020 {
01021 ON_BoundingBox pc_bbox = BoundingBox();
01022 if ( bGrowBox )
01023 {
01024 if ( ON_WorldBBoxIsInTightBBox( tight_bbox, pc_bbox, xform ) )
01025 return true;
01026 }
01027
01028 if ( xform && !xform->IsIdentity() )
01029 {
01030 if ( m_P.GetTightBoundingBox(tight_bbox,bGrowBox,xform) )
01031 bGrowBox = true;
01032 }
01033 else
01034 {
01035 tight_bbox.Union(pc_bbox);
01036 bGrowBox = tight_bbox.IsValid();
01037 }
01038 }
01039
01040 return (0!=bGrowBox);
01041 }
01042
01043
01044 bool ON_Mesh::GetTightBoundingBox(
01045 ON_BoundingBox& tight_bbox,
01046 int bGrowBox,
01047 const ON_Xform* xform
01048 ) const
01049 {
01050 if ( bGrowBox && !tight_bbox.IsValid() )
01051 {
01052 bGrowBox = false;
01053 }
01054
01055 ON_BoundingBox mesh_bbox = BoundingBox();
01056 if ( xform && !xform->IsIdentity() )
01057 {
01058 if ( ON_WorldBBoxIsInTightBBox( tight_bbox, mesh_bbox, xform ) )
01059 {
01060 return true;
01061 }
01062
01063 const int vcount = m_V.Count();
01064 if ( vcount > 0 )
01065 {
01066
01067 ON_3dPoint P(m_V[0]);
01068 mesh_bbox.m_min = (*xform)*P;
01069 mesh_bbox.m_max = mesh_bbox.m_min;
01070 int i;
01071 for ( i = 1; i < vcount; i++ )
01072 {
01073 P = m_V[i];
01074 P = (*xform)*P;
01075 if ( P.x < mesh_bbox.m_min.x ) mesh_bbox.m_min.x = P.x; else if (P.x > mesh_bbox.m_max.x) mesh_bbox.m_max.x = P.x;
01076 if ( P.y < mesh_bbox.m_min.y ) mesh_bbox.m_min.y = P.y; else if (P.y > mesh_bbox.m_max.y) mesh_bbox.m_max.y = P.y;
01077 if ( P.z < mesh_bbox.m_min.z ) mesh_bbox.m_min.z = P.z; else if (P.z > mesh_bbox.m_max.z) mesh_bbox.m_max.z = P.z;
01078 }
01079 }
01080 }
01081
01082 if ( !bGrowBox )
01083 {
01084 tight_bbox = mesh_bbox;
01085 bGrowBox = tight_bbox.IsValid();
01086 }
01087 else
01088 {
01089 tight_bbox.Union(mesh_bbox);
01090 }
01091
01092 return (0!=bGrowBox);
01093 }
01094
01095
01096
01097 bool ON_BezierCurve::Transform(
01098 const ON_Xform& xform
01099 )
01100 {
01101 if ( 0 == m_is_rat )
01102 {
01103 if ( xform.m_xform[3][0] != 0.0 || xform.m_xform[3][1] != 0.0 || xform.m_xform[3][2] != 0.0 )
01104 {
01105 MakeRational();
01106 }
01107 }
01108 return ON_TransformPointList( m_dim, m_is_rat, m_order, m_cv_stride, m_cv, xform );
01109 }
01110
01111 bool ON_BezierCurve::Rotate(
01112 double sin_angle,
01113 double cos_angle,
01114 const ON_3dVector& axis,
01115 const ON_3dPoint& center
01116 )
01117 {
01118 ON_Xform rot;
01119 rot.Rotation( sin_angle, cos_angle, axis, center );
01120 return Transform( rot );
01121 }
01122
01123 bool ON_BezierCurve::Rotate(
01124 double angle,
01125 const ON_3dVector& axis,
01126 const ON_3dPoint& center
01127 )
01128 {
01129 return Rotate( sin(angle), cos(angle), axis, center );
01130 }
01131
01132 bool ON_BezierCurve::Translate( const ON_3dVector& delta )
01133 {
01134 ON_Xform tr;
01135 tr.Translation( delta );
01136 return Transform( tr );
01137 }
01138
01139 bool ON_BezierCurve::Scale( double x )
01140 {
01141 ON_Xform s;
01142 s.Scale( x, x, x );
01143 return Transform( s );
01144 }
01145
01146
01147 ON_Interval ON_BezierCurve::Domain() const
01148 {
01149
01150 return ON_Interval(0.0,1.0);
01151 }
01152
01153 bool ON_BezierCurve::Reverse()
01154 {
01155 bool rc = ON_ReversePointList( m_dim, m_is_rat, m_order, m_cv_stride, m_cv )?true:false;
01156
01157
01158 return rc;
01159 }
01160
01161 bool ON_BezierCurve::Evaluate(
01162 double t,
01163 int der_count,
01164 int v_stride,
01165 double* v
01166 ) const
01167 {
01168 return ON_EvaluateBezier( m_dim, m_is_rat, m_order, m_cv_stride, m_cv,
01169 0.0, 1.0,
01170 der_count, t, v_stride, v )?true:false;
01171 }
01172
01173 bool ON_BezierCurve::GetNurbForm( ON_NurbsCurve& n ) const
01174 {
01175 bool rc = false;
01176 if ( n.Create( m_dim, m_is_rat, m_order, m_order ) ) {
01177 const int sizeof_cv = CVSize()*sizeof(m_cv[0]);
01178 int i;
01179 for ( i = 0; i < m_order; i++ ) {
01180 memcpy( n.CV(i), CV(i), sizeof_cv );
01181 }
01182 n.m_knot[m_order-2] = 0.0;
01183 n.m_knot[m_order-1] = 1.0;
01184 rc = ON_ClampKnotVector( n.m_order, n.m_cv_count, n.m_knot, 2 )?true:false;
01185 }
01186 return rc;
01187 }
01188
01189 bool ON_BezierCurve::IsRational() const
01190 {
01191 return m_is_rat ? true : false;
01192 }
01193
01194 int ON_BezierCurve::CVSize() const
01195 {
01196 return (m_dim>0&&m_is_rat) ? m_dim+1 : m_dim;
01197 }
01198
01199 int ON_BezierCurve::Order() const
01200 {
01201 return m_order;
01202 }
01203
01204 int ON_BezierCurve::Degree() const
01205 {
01206 return m_order>=2 ? m_order-1 : 0;
01207 }
01208
01209 double* ON_BezierCurve::CV( int i ) const
01210 {
01211 return m_cv ? m_cv + (i*m_cv_stride) : 0;
01212 }
01213
01214 ON::point_style ON_BezierCurve::CVStyle() const
01215 {
01216 return m_is_rat ? ON::homogeneous_rational : ON::not_rational;
01217 }
01218
01219 double ON_BezierCurve::Weight( int i ) const
01220 {
01221 return ( m_is_rat && m_cv ) ? CV(i)[m_dim] : 1.0;
01222 }
01223
01224 bool ON_BezierCurve::SetWeight( int i, double w )
01225 {
01226 bool rc = false;
01227 if ( m_is_rat ) {
01228 double* cv = CV(i);
01229 if (cv) {
01230 cv[m_dim] = w;
01231 rc = true;
01232 }
01233 }
01234 else if ( w == 1.0 ) {
01235 rc = true;
01236 }
01237 return rc;
01238 }
01239
01240 bool ON_BezierCurve::SetCV( int i, ON::point_style style, const double* Point )
01241 {
01242 bool rc = true;
01243 int k;
01244 double w;
01245
01246
01247 if ( !m_cv || i < 0 || i >= m_order )
01248 return false;
01249
01250 double* cv = m_cv + i*m_cv_stride;
01251
01252 switch ( style ) {
01253
01254 case ON::not_rational:
01255 memcpy( cv, Point, m_dim*sizeof(*cv) );
01256 if ( IsRational() ) {
01257
01258 cv[m_dim] = 1.0;
01259 }
01260 break;
01261
01262 case ON::homogeneous_rational:
01263 if ( IsRational() ) {
01264
01265 memcpy( cv, Point, (m_dim+1)*sizeof(*cv) );
01266 }
01267 else {
01268
01269 w = (Point[m_dim] != 0.0) ? 1.0/Point[m_dim] : 1.0;
01270 for ( k = 0; k < m_dim; k++ ) {
01271 cv[k] = w*Point[k];
01272 }
01273 }
01274 break;
01275
01276 case ON::euclidean_rational:
01277 if ( IsRational() ) {
01278
01279 w = Point[m_dim];
01280 for ( k = 0; k < m_dim; k++ )
01281 cv[k] = w*Point[k];
01282 cv[m_dim] = w;
01283 }
01284 else {
01285
01286 memcpy( cv, Point, m_dim*sizeof(*cv) );
01287 }
01288 break;
01289
01290 case ON::intrinsic_point_style:
01291 k = m_is_rat?m_dim+1:m_dim;
01292 memcpy(cv,Point,k*sizeof(cv[0]));
01293 break;
01294
01295 default:
01296 rc = false;
01297 break;
01298 }
01299
01300 return rc;
01301 }
01302
01303 bool ON_BezierCurve::SetCV( int i, const ON_3dPoint& point )
01304 {
01305 bool rc = false;
01306 double* cv = CV(i);
01307 if ( cv ) {
01308 cv[0] = point.x;
01309 if ( m_dim > 1 ) {
01310 cv[1] = point.y;
01311 if ( m_dim > 2 )
01312 cv[2] = point.z;
01313 if ( m_dim > 3 ) {
01314 memset( &cv[3], 0, (m_dim-3)*sizeof(*cv) );
01315 }
01316 }
01317 if ( m_is_rat ) {
01318 cv[m_dim] = 1.0;
01319 }
01320 rc = true;
01321 }
01322 return rc;
01323 }
01324
01325 bool ON_BezierCurve::SetCV( int i, const ON_4dPoint& point )
01326 {
01327 bool rc = false;
01328 double* cv = CV(i);
01329 if ( cv ) {
01330 if ( m_is_rat ) {
01331 cv[0] = point.x;
01332 if ( m_dim > 1 ) {
01333 cv[1] = point.y;
01334 if ( m_dim > 2 )
01335 cv[2] = point.z;
01336 if ( m_dim > 3 ) {
01337 memset( &cv[3], 0, (m_dim-3)*sizeof(*cv) );
01338 }
01339 }
01340 cv[m_dim] = point.w;
01341 rc = true;
01342 }
01343 else {
01344 double w;
01345 if ( point.w != 0.0 ) {
01346 w = 1.0/point.w;
01347 rc = true;
01348 }
01349 else {
01350 w = 1.0;
01351 }
01352 cv[0] = w*point.x;
01353 if ( m_dim > 1 ) {
01354 cv[1] = w*point.y;
01355 if ( m_dim > 2 ) {
01356 cv[2] = w*point.z;
01357 }
01358 if ( m_dim > 3 ) {
01359 memset( &cv[3], 0, (m_dim-3)*sizeof(*cv) );
01360 }
01361 }
01362 }
01363 }
01364 return rc;
01365 }
01366
01367 bool ON_BezierCurve::GetCV( int i, ON::point_style style, double* Point ) const
01368 {
01369 const double* cv = CV(i);
01370 if ( !cv )
01371 return false;
01372 int dim = Dimension();
01373 double w = ( IsRational() ) ? cv[dim] : 1.0;
01374 switch(style) {
01375 case ON::euclidean_rational:
01376 Point[dim] = w;
01377
01378 case ON::not_rational:
01379 if ( w == 0.0 )
01380 return false;
01381 w = 1.0/w;
01382 while(dim--) *Point++ = *cv++ * w;
01383 break;
01384 case ON::homogeneous_rational:
01385 Point[dim] = w;
01386 memcpy( Point, cv, dim*sizeof(*Point) );
01387 break;
01388 default:
01389 return false;
01390 }
01391 return true;
01392 }
01393
01394 bool ON_BezierCurve::GetCV( int i, ON_3dPoint& point ) const
01395 {
01396 bool rc = false;
01397 const double* cv = CV(i);
01398 if ( cv ) {
01399 if ( m_is_rat ) {
01400 if (cv[m_dim] != 0.0) {
01401 const double w = 1.0/cv[m_dim];
01402 point.x = cv[0]*w;
01403 point.y = (m_dim>1)? cv[1]*w : 0.0;
01404 point.z = (m_dim>2)? cv[2]*w : 0.0;
01405 rc = true;
01406 }
01407 }
01408 else {
01409 point.x = cv[0];
01410 point.y = (m_dim>1)? cv[1] : 0.0;
01411 point.z = (m_dim>2)? cv[2] : 0.0;
01412 rc = true;
01413 }
01414 }
01415 return rc;
01416 }
01417
01418 bool
01419 ON_BezierCurve::GetCV( int i, ON_4dPoint& point ) const
01420 {
01421 bool rc = false;
01422 const double* cv = CV(i);
01423 if ( cv ) {
01424 point.x = cv[0];
01425 point.y = (m_dim>1)? cv[1] : 0.0;
01426 point.z = (m_dim>2)? cv[2] : 0.0;
01427 point.w = (m_is_rat) ? cv[m_dim] : 1.0;
01428 rc = true;
01429 }
01430 return rc;
01431 }
01432
01433 bool ON_BezierCurve::ZeroCVs()
01434 {
01435 bool rc = false;
01436 int i;
01437 if ( m_cv ) {
01438 if ( m_cv_capacity > 0 ) {
01439 memset( m_cv, 0, m_cv_capacity*sizeof(*m_cv) );
01440 if ( m_is_rat ) {
01441 for ( i = 0; i < m_order; i++ ) {
01442 SetWeight( i, 1.0 );
01443 }
01444 }
01445 rc = true;
01446 }
01447 else {
01448 double* cv;
01449 int s = CVSize()*sizeof(*cv);
01450 for ( i = 0; i < m_order; i++ ) {
01451 cv = CV(i);
01452 memset(cv,0,s);
01453 if ( m_is_rat )
01454 cv[m_dim] = 1.0;
01455 }
01456 rc = (i>0) ? true : false;
01457 }
01458 }
01459 return rc;
01460 }
01461
01462 int ON_BezierCurve::CVCount() const
01463 {
01464 return Order();
01465 }
01466
01467 bool ON_BezierCurve::MakeRational()
01468 {
01469 if ( !IsRational() ) {
01470 const int dim = Dimension();
01471 const int cv_count = CVCount();
01472 if ( cv_count > 0 && m_cv_stride >= dim && dim > 0 ) {
01473 const int new_stride = (m_cv_stride == dim) ? dim+1 : m_cv_stride;
01474 ReserveCVCapacity( cv_count*new_stride );
01475 const double* old_cv;
01476 double* new_cv;
01477 int cvi, j;
01478 for ( cvi = cv_count-1; cvi>=0; cvi-- ) {
01479 old_cv = CV(cvi);
01480 new_cv = m_cv+(cvi*new_stride);
01481 for ( j = dim-1; j >= 0; j-- ) {
01482 new_cv[j] = old_cv[j];
01483 }
01484 new_cv[dim] = 1.0;
01485 }
01486 m_cv_stride = new_stride;
01487 m_is_rat = 1;
01488 }
01489 }
01490 return IsRational();
01491 }
01492
01493 bool ON_BezierCurve::MakeNonRational()
01494 {
01495 if ( IsRational() ) {
01496 const int dim = Dimension();
01497 const int cv_count = CVCount();
01498 if ( cv_count > 0 && m_cv_stride >= dim+1 && dim > 0 ) {
01499 double w;
01500 const double* old_cv;
01501 double* new_cv = m_cv;
01502 int cvi, j;
01503 for ( cvi = 0; cvi < cv_count; cvi++ ) {
01504 old_cv = CV(cvi);
01505 w = old_cv[dim];
01506 w = ( w != 0.0 ) ? 1.0/w : 1.0;
01507 for ( j = 0; j < dim; j++ ) {
01508 *new_cv++ = w*(*old_cv++);
01509 }
01510 }
01511 m_is_rat = 0;
01512 m_cv_stride = dim;
01513 }
01514 }
01515 return ( !IsRational() ) ? true : false;
01516 }
01517
01518 bool ON_BezierCurve::IncreaseDegree( int desired_degree )
01519 {
01520 bool rc = false;
01521 if ( desired_degree > 0 ) {
01522 if ( desired_degree == m_order-1 )
01523 rc = true;
01524 else if ( desired_degree >= m_order ) {
01525 ReserveCVCapacity( m_cv_stride*(desired_degree+1) );
01526 while ( m_order <= desired_degree ) {
01527 rc = ON_IncreaseBezierDegree( m_dim, m_is_rat, m_order, m_cv_stride, m_cv )?true:false;
01528 if ( !rc )
01529 break;
01530 m_order++;
01531 }
01532 }
01533 }
01534 return rc;
01535 }
01536
01538
01539 bool ON_BezierCurve::ReserveCVCapacity( int desired_capacity )
01540 {
01541 bool rc = false;
01542 if ( desired_capacity > m_cv_capacity ) {
01543 if ( !m_cv ) {
01544 m_cv = (double*)onmalloc(desired_capacity*sizeof(*m_cv));
01545 if ( !m_cv ) {
01546 m_cv_capacity = 0;
01547 }
01548 else {
01549 m_cv_capacity = desired_capacity;
01550 rc = true;
01551 }
01552 }
01553 else if ( m_cv_capacity > 0 ) {
01554 m_cv = (double*)onrealloc(m_cv,desired_capacity*sizeof(*m_cv));
01555 if ( !m_cv ) {
01556 m_cv_capacity = 0;
01557 }
01558 else {
01559 m_cv_capacity = desired_capacity;
01560 rc = true;
01561 }
01562 }
01563 }
01564 else
01565 rc =true;
01566 return rc;
01567 }
01568
01569 bool ON_BezierCurve::ChangeDimension( int dim )
01570 {
01571 ON_NurbsCurve c;
01572 c.m_dim = m_dim;
01573 c.m_is_rat = m_is_rat;
01574 c.m_order = m_order;
01575 c.m_cv_count = m_order;
01576 c.m_cv_capacity = m_cv_capacity;
01577 c.m_cv_stride = m_cv_stride;
01578 c.m_cv = m_cv;
01579 bool rc = c.ChangeDimension(dim);
01580 m_dim = c.m_dim;
01581 m_cv_stride = c.m_cv_stride;
01582 m_cv = c.m_cv;
01583 m_cv_capacity = c.m_cv_capacity;
01584
01585
01586 c.m_cv = 0;
01587 c.m_cv_capacity = 0;
01588 c.m_cv_stride = 0;
01589 return rc;
01590 }
01591
01592 double ON_BezierCurve::ControlPolygonLength() const
01593 {
01594 double length = 0.0;
01595 ON_GetPolylineLength( m_dim, m_is_rat, m_order, m_cv_stride, m_cv, &length );
01596 return length;
01597 }
01598
01599 bool ON_BezierCurve::Trim( const ON_Interval& n )
01600 {
01601 bool rc = n.IsIncreasing();
01602 if ( rc ) {
01603 double t0 = n.Min();
01604 double t1 = n.Max();
01605 int cvdim = CVSize();
01606 if ( t0 != 1.0 ) {
01607 double s1 = (t1-t0)/(1.0 - t0);
01608 ON_EvaluatedeCasteljau( cvdim, m_order, +1, m_cv_stride, m_cv, t0 );
01609 ON_EvaluatedeCasteljau( cvdim, m_order, -1, m_cv_stride, m_cv, s1 );
01610 }
01611 else {
01612 ON_EvaluatedeCasteljau( cvdim, m_order, -1, m_cv_stride, m_cv, t1 );
01613 if ( t0 != 0.0 )
01614 {
01615
01616 double s0 = t1/t0;
01617 ON_EvaluatedeCasteljau( cvdim, m_order, +1, m_cv_stride, m_cv, s0 );
01618 }
01619 }
01620 }
01621 return rc;
01622 }
01623
01624 bool ON_BezierCurve::Split(
01625 double t,
01626 ON_BezierCurve& left_bez,
01627 ON_BezierCurve& right_bez
01628 ) const
01629 {
01630 bool rc = ( 0.0 < t && t < 1.0 && IsValid() ) ? true : false;
01631 if ( rc ) {
01632 const int cvdim = CVSize();
01633 int i,j,k,n;
01634 double *p, *r, s;
01635 const double* q;
01636 double** b = (double**)alloca((2*m_order-1)*sizeof(*b));
01637
01638 if ( this != &left_bez )
01639 {
01640 if ( 0 == left_bez.m_cv || (0 < left_bez.m_cv_capacity && left_bez.m_cv_capacity < cvdim*m_order) )
01641 {
01642 left_bez.Create( m_dim, m_is_rat, m_order );
01643 }
01644 else if ( left_bez.m_dim != m_dim || left_bez.m_is_rat != m_is_rat || left_bez.m_order != m_order || left_bez.m_cv_stride < cvdim )
01645 {
01646 left_bez.m_dim = m_dim;
01647 left_bez.m_is_rat = m_is_rat?1:0;
01648 left_bez.m_order = m_order;
01649 left_bez.m_cv_stride = cvdim;
01650 }
01651 }
01652
01653 if ( this != &right_bez )
01654 {
01655 if ( !right_bez.m_cv || (0 < right_bez.m_cv_capacity && right_bez.m_cv_capacity < cvdim*m_order) )
01656 {
01657 right_bez.Create( m_dim, m_is_rat, m_order );
01658 }
01659 else if ( right_bez.m_dim != m_dim || right_bez.m_is_rat != m_is_rat || right_bez.m_order != m_order || right_bez.m_cv_stride < cvdim )
01660 {
01661 right_bez.m_dim = m_dim;
01662 right_bez.m_is_rat = m_is_rat?1:0;
01663 right_bez.m_order = m_order;
01664 right_bez.m_cv_stride = cvdim;
01665 }
01666 }
01667
01668 b[0] = left_bez.m_cv;
01669 b[m_order-1] = right_bez.m_cv;
01670 for ( i = 1, j = m_order; i < m_order; i++, j++ ) {
01671 b[j] = b[j-1]+cvdim;
01672 b[i] = b[i-1]+cvdim;
01673 }
01674
01675 if (m_cv == left_bez.m_cv) {
01676
01677 for (i = 2*m_order-2; i >= 0; i -= 2) {
01678 p = b[i]+cvdim;
01679 q = CV(i/2)+cvdim;
01680 k = cvdim;
01681 while(k--) *(--p) = *(--q);
01682 }
01683 }
01684 else {
01685
01686 for (i = 0; i < 2*m_order; i += 2) {
01687 p = b[i];
01688 q = CV(i/2);
01689 k = cvdim;
01690 while(k--) *p++ = *q++;
01691 }
01692 }
01693
01694 left_bez.m_dim = m_dim;
01695 left_bez.m_is_rat = m_is_rat;
01696 left_bez.m_order = m_order;
01697 left_bez.m_cv_stride = CVSize();
01698
01699 right_bez.m_dim = left_bez.m_dim;
01700 right_bez.m_is_rat = left_bez.m_is_rat;
01701 right_bez.m_order = left_bez.m_order;
01702 right_bez.m_cv_stride = left_bez.m_cv_stride;
01703
01704
01705 if (t == 0.5) {
01706
01707 for (i = 1, k = 2*m_order-2; i < k; i++, k--) {
01708 for (j = i; j < k; j++,j++) {
01709 p = b[j-1];
01710 q = b[j+1];
01711 r = b[j];
01712 n = cvdim;
01713 while(n--)
01714 *r++ = 0.5*(*p++ + *q++);
01715 }
01716 }
01717 }
01718 else {
01719 s = 1.0-t;
01720 for (i = 1, k = 2*m_order-2; i < k; i++, k--) {
01721 for (j = i; j < k; j++,j++) {
01722 p = b[j-1];
01723 q = b[j+1];
01724 r = b[j];
01725 n = cvdim;
01726 while(n--)
01727 *r++ = (*p++ * s + *q++ * t);
01728 }
01729 }
01730 }
01731
01732
01733 p = right_bez.CV(0);
01734 q = left_bez.CV(m_order-1);
01735 if (p != q) {
01736 j = cvdim;
01737 while(j--) *p++ = *q++;
01738 }
01739 }
01740 return rc;
01741 }
01742
01743 ON_BezierSurface::ON_BezierSurface()
01744 : m_dim(0),
01745 m_is_rat(0),
01746 m_cv(0),
01747 m_cv_capacity(0)
01748 {
01749 m_order[0] = 0;
01750 m_order[1] = 0;
01751 m_cv_stride[0] = 0;
01752 m_cv_stride[1] = 0;
01753 #if 8 == ON_SIZEOF_POINTER
01754 m_reserved_ON_BezierSurface = 0;
01755 #endif
01756 }
01757
01758 ON_BezierSurface::ON_BezierSurface( int dim, ON_BOOL32 is_rat, int order0, int order1 )
01759 : m_dim(0),
01760 m_is_rat(0),
01761 m_cv(0),
01762 m_cv_capacity(0)
01763 {
01764 m_order[0] = 0;
01765 m_order[1] = 0;
01766 m_cv_stride[0] = 0;
01767 m_cv_stride[1] = 0;
01768 #if 8 == ON_SIZEOF_POINTER
01769 m_reserved_ON_BezierSurface = 0;
01770 #endif
01771 Create( dim, is_rat, order0, order1 );
01772 }
01773
01774 ON_BezierSurface::~ON_BezierSurface()
01775 {
01776 Destroy();
01777 }
01778
01779 ON_BezierSurface::ON_BezierSurface(const ON_BezierSurface& src)
01780 : m_dim(0),
01781 m_is_rat(0),
01782 m_cv(0),
01783 m_cv_capacity(0)
01784 {
01785 m_order[0] = 0;
01786 m_order[1] = 0;
01787 m_cv_stride[0] = 0;
01788 m_cv_stride[1] = 0;
01789 #if 8 == ON_SIZEOF_POINTER
01790 m_reserved_ON_BezierSurface = 0;
01791 #endif
01792 *this = src;
01793 }
01794
01795 ON_BezierSurface::ON_BezierSurface(const ON_PolynomialSurface& src)
01796 : m_dim(0),
01797 m_is_rat(0),
01798 m_cv(0),
01799 m_cv_capacity(0)
01800 {
01801 m_order[0] = 0;
01802 m_order[1] = 0;
01803 m_cv_stride[0] = 0;
01804 m_cv_stride[1] = 0;
01805 #if 8 == ON_SIZEOF_POINTER
01806 m_reserved_ON_BezierSurface = 0;
01807 #endif
01808 *this = src;
01809 }
01810
01811 ON_BezierSurface& ON_BezierSurface::operator=(const ON_BezierSurface& src)
01812 {
01813 if ( this != &src ) {
01814 if ( Create( src.m_dim, src.m_is_rat, src.m_order[0], src.m_order[1] ) ) {
01815 const int sizeof_cv = src.CVSize()*sizeof(m_cv[0]);
01816 int i, j;
01817 for ( i = 0; i < m_order[0]; i++ ) for ( j = 0; j < m_order[1]; j++ ) {
01818 memcpy( CV(i,j), src.CV(i,j), sizeof_cv );
01819 }
01820 }
01821 else {
01822 Destroy();
01823 }
01824 }
01825 return *this;
01826 }
01827
01828 ON_BezierSurface& ON_BezierSurface::operator=(const ON_PolynomialSurface& src)
01829 {
01830 if ( Create( src.m_dim, src.m_is_rat, src.m_order[0], src.m_order[1] ) ) {
01831
01832 }
01833 return *this;
01834 }
01835
01836 bool ON_BezierSurface::IsValid() const
01837 {
01838 if ( m_dim <= 0 )
01839 return false;
01840 if ( m_is_rat != 0 && m_is_rat != 1 )
01841 return false;
01842 if ( m_order[0] < 2 )
01843 return false;
01844 if ( m_order[0] < 2 )
01845 return false;
01846 if ( m_cv_stride[0] < m_dim+m_is_rat )
01847 return false;
01848 if ( m_cv_stride[1] < m_dim+m_is_rat )
01849 return false;
01850 if ( m_cv_capacity > 0 && m_cv_capacity < (m_dim+m_is_rat)*m_order[0]*m_order[1] )
01851 return false;
01852
01853
01854
01855
01856 if ( m_cv == NULL )
01857 return false;
01858 return true;
01859 }
01860
01861 void ON_BezierSurface::Dump( ON_TextLog& dump ) const
01862 {
01863 dump.Print( "ON_BezierSurface dim = %d is_rat = %d\n"
01864 " order = (%d, %d) \n",
01865 m_dim, m_is_rat, m_order[0], m_order[1] );
01866 dump.Print( "Control Points %d %s points\n"
01867 " index value\n",
01868 m_order[0]*m_order[1],
01869 (m_is_rat) ? "rational" : "non-rational" );
01870 if ( !m_cv ) {
01871 dump.Print(" NULL cv array\n");
01872 }
01873 else {
01874 int i;
01875 char sPreamble[128];
01876 memset(sPreamble,0,sizeof(sPreamble));
01877 for ( i = 0; i < m_order[0]; i++ )
01878 {
01879 if ( i > 0 )
01880 dump.Print("\n");
01881 sPreamble[0] = 0;
01882 sprintf(sPreamble," CV[%2d]",i);
01883 dump.PrintPointList( m_dim, m_is_rat,
01884 m_order[1], m_cv_stride[1],
01885 CV(i,0),
01886 sPreamble );
01887 }
01888 }
01889 }
01890
01891 int ON_BezierSurface::Dimension() const
01892 {
01893 return m_dim;
01894 }
01895
01896 bool ON_BezierSurface::Create( int dim, ON_BOOL32 is_rat, int order0, int order1 )
01897 {
01898 if ( m_cv_capacity < 1 )
01899 m_cv = 0;
01900 m_dim = (dim>0) ? dim : 0;
01901 m_is_rat = is_rat ? 1 : 0;
01902 m_order[0] = (order0 >= 2) ? order0 : 0;
01903 m_order[1] = (order1 >= 2) ? order1 : 0;
01904 m_cv_stride[1] = (m_dim > 0) ? m_dim+m_is_rat : 0;
01905 m_cv_stride[0] = m_cv_stride[1]*m_order[1];
01906 m_cv_capacity = m_cv_stride[0]*m_order[0];
01907 m_cv = (double*)onrealloc( m_cv, m_cv_capacity*sizeof(m_cv[0]) );
01908
01909
01910
01911
01912 return IsValid();
01913 }
01914
01915 void ON_BezierSurface::Destroy()
01916 {
01917 if ( m_cv && m_cv_capacity > 0 )
01918 onfree(m_cv);
01919 m_cv_capacity = 0;
01920 m_cv_stride[0] = 0;
01921 m_cv_stride[1] = 0;
01922 m_cv = 0;
01923 m_dim = 0;
01924 m_is_rat = 0;
01925 m_order[0] = 0;
01926 m_order[1] = 0;
01927
01928
01929
01930
01931 }
01932
01933 void ON_BezierSurface::EmergencyDestroy()
01934 {
01935 m_cv = 0;
01936 }
01937
01938 bool ON_BezierSurface::Loft( const ON_ClassArray<ON_BezierCurve>& curve_list )
01939 {
01940 int i;
01941 int count = curve_list.Count();
01942 ON_SimpleArray<const ON_BezierCurve*> ptr_list(count);
01943 for (i = 0; i < count; i++ )
01944 {
01945 ptr_list.Append(&curve_list[i]);
01946 }
01947 return Loft(ptr_list.Count(),ptr_list.Array());
01948 }
01949
01950 bool ON_BezierSurface::Loft(
01951 int curve_count,
01952 const ON_BezierCurve* const* curve_list
01953 )
01954 {
01955
01956 bool rc = false;
01957 if (curve_count >= 2 && 0 != curve_list && 0 != curve_list[0] )
01958 {
01959
01960 int shape_order = curve_list[0]->m_order;
01961 int shape_dim = curve_list[0]->m_dim;
01962 int shape_is_rat = (0 != curve_list[0]->m_is_rat) ? 1 : 0;
01963 if ( shape_dim < 1 || shape_order < 2 )
01964 return false;
01965 int i, j, k;
01966 for ( i = 0; i < curve_count; i++ )
01967 {
01968 if ( curve_list[i]->m_order < 2 || curve_list[i]->m_dim < 1 || 0 == curve_list[i]->m_cv)
01969 return false;
01970 if ( curve_list[i]->m_dim != shape_dim )
01971 return false;
01972 if ( curve_list[i]->m_order > shape_order )
01973 shape_order = curve_list[i]->m_order;
01974 if ( 0 != curve_list[i]->m_is_rat )
01975 shape_is_rat = 1;
01976 }
01977
01978
01979 const int shape_cv_stride = (shape_is_rat) ? (shape_dim + 1) : shape_dim;
01980 ON_SimpleArray<double> meta_point(curve_count*shape_cv_stride*shape_order);
01981 ON_BezierCurve* temp_shape = 0;
01982 for ( i = 0; i < curve_count; i++ )
01983 {
01984 const ON_BezierCurve* shape = curve_list[i];
01985 if ( shape->m_order != shape_order
01986 || shape->m_is_rat != shape_is_rat
01987 || shape->m_cv_stride != shape_cv_stride )
01988 {
01989 if ( 0 == temp_shape )
01990 temp_shape = new ON_BezierCurve();
01991 temp_shape->operator=(*shape);
01992 if ( shape_is_rat )
01993 temp_shape->MakeRational();
01994 temp_shape->IncreaseDegree(shape_order-1);
01995 if ( temp_shape->m_dim != shape_dim
01996 || temp_shape->m_is_rat != shape_is_rat
01997 || temp_shape->m_order != shape_order
01998 || temp_shape->m_cv_stride != shape_cv_stride )
01999 {
02000 break;
02001 }
02002 shape = temp_shape;
02003 }
02004 for ( int j = 0; j < shape->m_order; j++ )
02005 {
02006 const double* cv = shape->CV(j);
02007 for ( int k = 0; k < shape_cv_stride; k++ )
02008 meta_point.Append(cv[k]);
02009 }
02010 }
02011 if ( 0 != temp_shape )
02012 {
02013 delete temp_shape;
02014 temp_shape = 0;
02015 }
02016 if ( meta_point.Count() == curve_count*shape_cv_stride*shape_order )
02017 {
02018 ON_BezierCurve bez;
02019 ON_SimpleArray<double>t(curve_count);
02020 double dt = 1.0/((double)curve_count);
02021 for ( i = 0; i < curve_count; i++ )
02022 {
02023 t.Append( i*dt );
02024 }
02025 t[curve_count-1] = 1.0;
02026
02027 rc = bez.Loft( shape_cv_stride*shape_dim, curve_count, shape_cv_stride*shape_dim, meta_point.Array(), 1, t.Array() )
02028 ? true : false;
02029 if (rc)
02030 {
02031 Create(shape_dim,shape_is_rat,curve_count,shape_order);
02032
02033 for ( i = 0; i < curve_count; i++ )
02034 {
02035 const double* bez_cv = bez.CV(i);
02036 for ( j = 0; j < shape_order; j++ )
02037 {
02038 double* srf_cv = CV(i,j);
02039 for ( k = 0; k < shape_cv_stride; k++ )
02040 srf_cv[k] = *bez_cv++;
02041 }
02042 }
02043 }
02044 }
02045 }
02046 return rc;
02047 }
02048
02049 bool ON_BezierSurface::GetBBox(
02050 double* boxmin,
02051 double* boxmax,
02052 int bGrowBox
02053 ) const
02054 {
02055 int i;
02056 bool rc = (m_order[0] > 0 && m_order[1] > 0) ? true : false;
02057 for ( i = 0; rc && i < m_order[0]; i++ ) {
02058 rc = ON_GetPointListBoundingBox( m_dim, m_is_rat, m_order[1], m_cv_stride[1],
02059 CV(i,0), boxmin, boxmax, bGrowBox );
02060 bGrowBox = true;
02061 }
02062 return rc;
02063 }
02064
02065 bool ON_BezierSurface::GetBoundingBox(
02066 ON_BoundingBox& bbox,
02067 int bGrowBox
02068 ) const
02069 {
02070 double *boxmin, *boxmax;
02071 if ( m_dim > 3 )
02072 {
02073 boxmin = (double*)alloca(2*m_dim*sizeof(*boxmin));
02074 memset( boxmin, 0, 2*m_dim*sizeof(*boxmin) );
02075 boxmax = boxmin + m_dim;
02076 if ( bGrowBox ) {
02077 boxmin[0] = bbox.m_min.x;
02078 boxmin[1] = bbox.m_min.y;
02079 boxmin[2] = bbox.m_min.z;
02080 boxmax[0] = bbox.m_max.x;
02081 boxmax[1] = bbox.m_max.y;
02082 boxmax[2] = bbox.m_max.z;
02083 }
02084 }
02085 else {
02086 boxmin = &bbox.m_min.x;
02087 boxmax = &bbox.m_max.x;
02088 }
02089 bool rc = GetBBox( boxmin, boxmax, bGrowBox );
02090 if ( rc && m_dim > 3 ) {
02091 bbox.m_min = boxmin;
02092 bbox.m_max = boxmax;
02093 }
02094 return rc;
02095 }
02096
02097 ON_BoundingBox ON_BezierSurface::BoundingBox() const
02098 {
02099 ON_BoundingBox bbox;
02100 if ( !GetBoundingBox(bbox,false) )
02101 bbox.Destroy();
02102 return bbox;
02103 }
02104
02105 bool ON_BezierSurface::Transform( const ON_Xform& xform )
02106 {
02107 int i;
02108 bool rc = (m_order[0] > 0 && m_order[1] > 0) ? true : false;
02109 if (rc)
02110 {
02111 if ( 0 == m_is_rat )
02112 {
02113 if ( xform.m_xform[3][0] != 0.0 || xform.m_xform[3][1] != 0.0 || xform.m_xform[3][2] != 0.0 )
02114 {
02115 MakeRational();
02116 }
02117 }
02118
02119 for ( i = 0; rc && i < m_order[0]; i++ )
02120 {
02121 rc = ON_TransformPointList( m_dim, m_is_rat,
02122 m_order[1], m_cv_stride[1],
02123 CV(i,0), xform );
02124 }
02125 }
02126 return rc;
02127 }
02128
02129 bool ON_BezierSurface::Rotate(
02130 double sin_angle,
02131 double cos_angle,
02132 const ON_3dVector& axis,
02133 const ON_3dPoint& center
02134 )
02135 {
02136 ON_Xform rot;
02137 rot.Rotation( sin_angle, cos_angle, axis, center );
02138 return Transform( rot );
02139 }
02140
02141 bool ON_BezierSurface::Rotate(
02142 double angle,
02143 const ON_3dVector& axis,
02144 const ON_3dPoint& center
02145 )
02146 {
02147 return Rotate( sin(angle), cos(angle), axis, center );
02148 }
02149
02150 bool ON_BezierSurface::Translate( const ON_3dVector& delta )
02151 {
02152 ON_Xform tr;
02153 tr.Translation( delta );
02154 return Transform( tr );
02155 }
02156
02157 bool ON_BezierSurface::Scale( double x )
02158 {
02159 ON_Xform s;
02160 s.Scale( x, x, x );
02161 return Transform( s );
02162 }
02163
02164 ON_Interval ON_BezierSurface::Domain(
02165 int
02166 ) const
02167 {
02168
02169 return ON_Interval(0.0,1.0);
02170 }
02171
02172 bool ON_BezierSurface::Reverse( int dir )
02173 {
02174 int i;
02175 bool rc = (m_order[0] > 0 && m_order[1] > 0) ? true : false;
02176 if ( dir > 0 ) {
02177 for ( i = 0; rc && i < m_order[0]; i++ ) {
02178 rc = ON_ReversePointList( m_dim, m_is_rat, m_order[1], m_cv_stride[1], CV(i,0) );
02179 }
02180
02181 }
02182 else {
02183 for ( i = 0; rc && i < m_order[1]; i++ ) {
02184 rc = ON_ReversePointList( m_dim, m_is_rat, m_order[0], m_cv_stride[0], CV(0,i) );
02185 }
02186
02187 }
02188 return rc;
02189 }
02190
02191 bool ON_BezierSurface::Transpose()
02192 {
02193
02194 int i = m_order[0]; m_order[0] = m_order[1]; m_order[1] = i;
02195 i = m_cv_stride[0]; m_cv_stride[0] = m_cv_stride[1]; m_cv_stride[1] = i;
02196
02197 return true;
02198 }
02199
02200 bool ON_BezierSurface::Evaluate(
02201 double s, double t,
02202 int der_count,
02203 int v_stride,
02204 double* v
02205 ) const
02206 {
02207
02208
02209 double *knot0, *knot1, *p;
02210 int deg0 = m_order[0]-1;
02211 int deg1 = m_order[1]-1;
02212 int i = (deg0<=deg1)?deg1 : deg0;
02213 p = knot0 = (double*)alloca(i*2*sizeof(*knot0));
02214 memset(p,0,i*sizeof(*p));
02215 p += i;
02216 while (i--) *p++ = 1.0;
02217 if ( deg0 >= deg1 ) {
02218 knot1 = knot0 + (deg0-deg1);
02219 }
02220 else {
02221 knot1 = knot0;
02222 knot0 = knot1 + (deg1-deg0);
02223 }
02224
02225 return ON_EvaluateNurbsSurfaceSpan(
02226 m_dim,
02227 m_is_rat,
02228 m_order[0], m_order[1],
02229 knot0,
02230 knot1,
02231 m_cv_stride[0], m_cv_stride[1],
02232 m_cv,
02233 der_count,
02234 s,t,
02235 v_stride,
02236 v
02237 );
02238 }
02239
02240 ON_3dPoint ON_BezierSurface::PointAt(double s, double t) const
02241 {
02242 ON_3dPoint P;
02243 Evaluate(s,t,0,3,&P.x);
02244 return P;
02245 }
02246
02247 ON_BezierCurve* ON_BezierSurface::IsoCurve(int dir, double t, ON_BezierCurve* pCrv) const
02248 {
02249 if( pCrv == NULL )
02250 {
02251 pCrv = new ON_BezierCurve(m_dim, m_is_rat, m_order[dir]);
02252 }
02253 else if ( pCrv->m_dim!=m_dim || pCrv->m_is_rat!= m_is_rat || pCrv->m_order!= m_order[dir])
02254 {
02255 pCrv->Create(m_dim, m_is_rat, m_order[dir]);
02256 }
02257
02258
02259 int bigdim = CVSize() * m_order[dir];
02260 int stride;
02261 double* cv = 0;
02262 double* workspace = 0;
02263 if( m_cv_stride[1-dir]>m_cv_stride[dir])
02264 {
02265 stride = m_cv_stride[1-dir];
02266 cv = m_cv;
02267 }
02268 else
02269 {
02270
02271 workspace = (double*)onmalloc((bigdim*m_order[1-dir])*sizeof(*workspace));
02272
02273 cv = workspace;
02274 stride = bigdim;
02275
02276 int i,j;
02277 int cvsize = CVSize();
02278 int cvsize_bytes = cvsize*sizeof(double);
02279 double* dst = workspace;
02280 for(i=0; i<m_order[1-dir] ; i++)
02281 {
02282 double* src = dir ? CV(i,0): CV(0,i);
02283 for(j=0; j<m_order[dir]; j++,dst+=cvsize, src+=m_cv_stride[dir] )
02284 memcpy(dst, src, cvsize_bytes );
02285 }
02286 }
02287
02288 ON_EvaluateBezier( bigdim, 0, m_order[1-dir], stride, cv, 0.0, 1.0, 0, t, bigdim, pCrv->m_cv );
02289
02290 if(workspace)
02291 {
02292
02293 onfree(workspace);
02294 }
02295
02296 return pCrv;
02297 }
02298
02299 bool ON_BezierSurface::GetNurbForm( ON_NurbsSurface& n ) const
02300 {
02301 bool rc = false;
02302 if ( n.Create( m_dim, m_is_rat, m_order[0], m_order[1], m_order[0], m_order[1] ) )
02303 {
02304 if ( n.m_cv == m_cv )
02305 {
02306 n.m_cv_stride[0] = m_cv_stride[0];
02307 n.m_cv_stride[1] = m_cv_stride[1];
02308 }
02309 else
02310 {
02311 const int sizeof_cv = CVSize()*sizeof(m_cv[0]);
02312 int i,j;
02313 for ( i = 0; i < m_order[0]; i++ ) for ( j = 0; j < m_order[1]; j++ ) {
02314 memcpy( n.CV(i,j), CV(i,j), sizeof_cv );
02315 }
02316 }
02317 n.m_knot[0][m_order[0]-2] = 0.0;
02318 n.m_knot[0][m_order[0]-1] = 1.0;
02319 n.m_knot[1][m_order[1]-2] = 0.0;
02320 n.m_knot[1][m_order[1]-1] = 1.0;
02321 rc = ON_ClampKnotVector( n.m_order[0], n.m_cv_count[0], n.m_knot[0], 2 );
02322 rc = ON_ClampKnotVector( n.m_order[1], n.m_cv_count[1], n.m_knot[1], 2 );
02323 }
02324 return rc;
02325 }
02326
02327 bool ON_BezierSurface::IsRational() const
02328 {
02329 return m_is_rat ? true : false;
02330 }
02331
02332 int ON_BezierSurface::CVSize() const
02333 {
02334 return ( m_is_rat && m_dim>0 ) ? m_dim+1 : m_dim;
02335 }
02336
02337 int ON_BezierSurface::Order( int dir ) const
02338 {
02339 return (dir>=0&&dir<=1) ? m_order[dir] : 0;
02340 }
02341
02342 int ON_BezierSurface::Degree(int dir) const
02343 {
02344 int order = Order(dir);
02345 return (order>=2) ? order-1 : 0;
02346 }
02347
02348 double* ON_BezierSurface::CV( int i, int j ) const
02349 {
02350 return (m_cv) ? (m_cv + i*m_cv_stride[0] + j*m_cv_stride[1]) : NULL;
02351 }
02352
02353 ON::point_style ON_BezierSurface::CVStyle() const
02354 {
02355 return m_is_rat ? ON::homogeneous_rational : ON::not_rational;
02356 }
02357
02358 double ON_BezierSurface::Weight( int i, int j ) const
02359 {
02360 return (m_cv && m_is_rat) ? m_cv[i*m_cv_stride[0] + j*m_cv_stride[1] + m_dim] : 1.0;
02361 }
02362
02363
02364 bool ON_BezierSurface::SetWeight( int i, int j, double w )
02365 {
02366 bool rc = false;
02367 if ( m_is_rat ) {
02368 double* cv = CV(i,j);
02369 if (cv) {
02370 cv[m_dim] = w;
02371 rc = true;
02372 }
02373 }
02374 else if ( w == 1.0 ) {
02375 rc = true;
02376 }
02377 return rc;
02378 }
02379
02380 bool ON_BezierSurface::SetCV( int i, int j, ON::point_style style, const double* Point )
02381 {
02382 bool rc = true;
02383 int k;
02384 double w;
02385
02386 double* cv = CV(i,j);
02387 if ( !cv )
02388 return false;
02389
02390 switch ( style ) {
02391
02392 case ON::not_rational:
02393 memcpy( cv, Point, m_dim*sizeof(*cv) );
02394 if ( IsRational() ) {
02395
02396 cv[m_dim] = 1.0;
02397 }
02398 break;
02399
02400 case ON::homogeneous_rational:
02401 if ( IsRational() ) {
02402
02403 memcpy( cv, Point, (m_dim+1)*sizeof(*cv) );
02404 }
02405 else {
02406
02407 w = (Point[m_dim] != 0.0) ? 1.0/Point[m_dim] : 1.0;
02408 for ( k = 0; k < m_dim; k++ ) {
02409 cv[k] = w*Point[k];
02410 }
02411 }
02412 break;
02413
02414 case ON::euclidean_rational:
02415 if ( IsRational() ) {
02416
02417 w = Point[m_dim];
02418 for ( k = 0; k < m_dim; k++ )
02419 cv[i] = w*Point[i];
02420 cv[m_dim] = w;
02421 }
02422 else {
02423
02424 memcpy( cv, Point, m_dim*sizeof(*cv) );
02425 }
02426 break;
02427
02428 case ON::intrinsic_point_style:
02429 k = m_is_rat?m_dim+1:m_dim;
02430 memcpy(cv,Point,k*sizeof(*cv));
02431 break;
02432
02433 default:
02434 rc = false;
02435 break;
02436 }
02437 return rc;
02438 }
02439
02440 bool ON_BezierSurface::SetCV( int i, int j, const ON_3dPoint& point )
02441 {
02442 bool rc = false;
02443 double* cv = CV(i,j);
02444 if ( cv ) {
02445 cv[0] = point.x;
02446 if ( m_dim > 1 ) {
02447 cv[1] = point.y;
02448 if ( m_dim > 2 )
02449 cv[2] = point.z;
02450 }
02451 if ( m_is_rat ) {
02452 cv[m_dim] = 1.0;
02453 }
02454 rc = true;
02455 }
02456 return rc;
02457 }
02458
02459 bool ON_BezierSurface::SetCV( int i, int j, const ON_4dPoint& point )
02460 {
02461 bool rc = false;
02462 double* cv = CV(i,j);
02463 if ( cv ) {
02464 if ( m_is_rat ) {
02465 cv[0] = point.x;
02466 if ( m_dim > 1 ) {
02467 cv[1] = point.y;
02468 if ( m_dim > 2 )
02469 cv[2] = point.z;
02470 }
02471 cv[m_dim] = point.w;
02472 rc = true;
02473 }
02474 else {
02475 double w;
02476 if ( point.w != 0.0 ) {
02477 w = 1.0/point.w;
02478 rc = true;
02479 }
02480 else {
02481 w = 1.0;
02482 }
02483 cv[0] = w*point.x;
02484 if ( m_dim > 1 ) {
02485 cv[1] = w*point.y;
02486 if ( m_dim > 2 ) {
02487 cv[2] = w*point.z;
02488 }
02489 }
02490 }
02491 }
02492 return rc;
02493 }
02494
02495 bool ON_BezierSurface::GetCV( int i, int j, ON::point_style style, double* Point ) const
02496 {
02497 const double* cv = CV(i,j);
02498 if ( !cv )
02499 return false;
02500 int dim = Dimension();
02501 double w = ( IsRational() ) ? cv[dim] : 1.0;
02502 switch(style) {
02503 case ON::euclidean_rational:
02504 Point[dim] = w;
02505
02506 case ON::not_rational:
02507 if ( w == 0.0 )
02508 return false;
02509 w = 1.0/w;
02510 while(dim--) *Point++ = *cv++ * w;
02511 break;
02512 case ON::homogeneous_rational:
02513 Point[dim] = w;
02514 memcpy( Point, cv, dim*sizeof(*Point) );
02515 break;
02516 default:
02517 return false;
02518 }
02519 return true;
02520 }
02521
02522 bool ON_BezierSurface::GetCV( int i, int j, ON_3dPoint& point ) const
02523 {
02524 bool rc = false;
02525 const double* cv = CV(i,j);
02526 if ( cv ) {
02527 if ( m_is_rat ) {
02528 if (cv[m_dim] != 0.0) {
02529 const double w = 1.0/cv[m_dim];
02530 point.x = cv[0]*w;
02531 point.y = (m_dim>1)? cv[1]*w : 0.0;
02532 point.z = (m_dim>2)? cv[2]*w : 0.0;
02533 rc = true;
02534 }
02535 }
02536 else {
02537 point.x = cv[0];
02538 point.y = (m_dim>1)? cv[1] : 0.0;
02539 point.z = (m_dim>2)? cv[2] : 0.0;
02540 rc = true;
02541 }
02542 }
02543 return rc;
02544 }
02545
02546 bool ON_BezierSurface::GetCV( int i, int j, ON_4dPoint& point ) const
02547 {
02548 bool rc = false;
02549 const double* cv = CV(i,j);
02550 if ( cv ) {
02551 point.x = cv[0];
02552 point.y = (m_dim>1)? cv[1] : 0.0;
02553 point.z = (m_dim>2)? cv[2] : 0.0;
02554 point.w = (m_is_rat) ? cv[m_dim] : 1.0;
02555 rc = true;
02556 }
02557 return rc;
02558 }
02559
02560 bool ON_BezierSurface::ZeroCVs()
02561 {
02562
02563 bool rc = false;
02564 int i,j;
02565 if ( m_cv ) {
02566 if ( m_cv_capacity > 0 ) {
02567 memset( m_cv, 0, m_cv_capacity*sizeof(*m_cv) );
02568 if ( m_is_rat ) {
02569 for ( i = 0; i < m_order[0]; i++ ) {
02570 for ( j = 0; j < m_order[1]; j++ ) {
02571 SetWeight( i,j, 1.0 );
02572 }
02573 }
02574 }
02575 rc = true;
02576 }
02577 else {
02578 double* cv;
02579 int s = CVSize()*sizeof(*cv);
02580 for ( i = 0; i < m_order[0]; i++ ) {
02581 for ( j = 0; j < m_order[1]; j++ ) {
02582 cv = CV(i,j);
02583 memset(cv,0,s);
02584 if ( m_is_rat )
02585 cv[m_dim] = 1.0;
02586 }
02587 }
02588 rc = (i>0) ? true : false;
02589 }
02590 }
02591 return rc;
02592 }
02593
02594 bool ON_BezierSurface::MakeRational()
02595 {
02596 if ( !IsRational() ) {
02597 const int dim = Dimension();
02598 if ( m_order[0] > 0 && m_order[1] > 0 && dim > 0 ) {
02599 const double* old_cv;
02600 double* new_cv;
02601 int cvi, cvj, j, cvstride;
02602 if ( m_cv_stride[0] < m_cv_stride[1] ) {
02603 cvstride = m_cv_stride[0] > dim ? m_cv_stride[0] : dim+1;
02604 ReserveCVCapacity( cvstride*m_order[0]*m_order[1] );
02605 new_cv = m_cv + cvstride*m_order[0]*m_order[1]-1;
02606 for ( cvj = m_order[1]-1; cvj >= 0; cvj-- ) {
02607 for ( cvi = m_order[0]-1; cvi >= 0; cvi-- ) {
02608 old_cv = CV(cvi,cvj)+dim-1;
02609 *new_cv-- = 1.0;
02610 for ( j = 0; j < dim; j++ ) {
02611 *new_cv-- = *old_cv--;
02612 }
02613 }
02614 }
02615 m_cv_stride[0] = dim+1;
02616 m_cv_stride[1] = (dim+1)*m_order[0];
02617 }
02618 else {
02619 cvstride = m_cv_stride[1] > dim ? m_cv_stride[1] : dim+1;
02620 ReserveCVCapacity( cvstride*m_order[0]*m_order[1] );
02621 new_cv = m_cv + cvstride*m_order[0]*m_order[1]-1;
02622 for ( cvi = m_order[0]-1; cvi >= 0; cvi-- ) {
02623 for ( cvj = m_order[1]-1; cvj >= 0; cvj-- ) {
02624 old_cv = CV(cvi,cvj)+dim-1;
02625 *new_cv-- = 1.0;
02626 for ( j = 0; j < dim; j++ ) {
02627 *new_cv-- = *old_cv--;
02628 }
02629 }
02630 }
02631 m_cv_stride[1] = dim+1;
02632 m_cv_stride[0] = (dim+1)*m_order[1];
02633 }
02634 m_is_rat = 1;
02635 }
02636 }
02637 return IsRational();
02638 }
02639
02640 bool ON_BezierSurface::MakeNonRational()
02641 {
02642 if ( IsRational() ) {
02643 const int dim = Dimension();
02644 if ( m_order[0] > 0 && m_order[1] > 0 && dim > 0 ) {
02645 double w;
02646 const double* old_cv;
02647 double* new_cv = m_cv;
02648 int cvi, cvj, j;
02649 if ( m_cv_stride[0] < m_cv_stride[1] ) {
02650 for ( cvj = 0; cvj < m_order[1]; cvj++ ) {
02651 for ( cvi = 0; cvi < m_order[0]; cvi++ ) {
02652 old_cv = CV(cvi,cvj);
02653 w = old_cv[dim];
02654 w = ( w != 0.0 ) ? 1.0/w : 1.0;
02655 for ( j = 0; j < dim; j++ ) {
02656 *new_cv++ = w*(*old_cv++);
02657 }
02658 }
02659 }
02660 m_cv_stride[0] = dim;
02661 m_cv_stride[1] = dim*m_order[0];
02662 }
02663 else {
02664 for ( cvi = 0; cvi < m_order[0]; cvi++ ) {
02665 for ( cvj = 0; cvj < m_order[1]; cvj++ ) {
02666 old_cv = CV(cvi,cvj);
02667 w = old_cv[dim];
02668 w = ( w != 0.0 ) ? 1.0/w : 1.0;
02669 for ( j = 0; j < dim; j++ ) {
02670 *new_cv++ = w*(*old_cv++);
02671 }
02672 }
02673 }
02674 m_cv_stride[1] = dim;
02675 m_cv_stride[0] = dim*m_order[1];
02676 }
02677 m_is_rat = 0;
02678 }
02679 }
02680 return ( !IsRational() ) ? true : false;
02681 }
02682
02684
02685 bool ON_BezierSurface::ReserveCVCapacity(
02686 int capacity
02687 )
02688 {
02689 if ( m_cv_capacity < capacity ) {
02690 if ( m_cv ) {
02691 if ( m_cv_capacity ) {
02692 m_cv = (double*)onrealloc( m_cv, capacity*sizeof(*m_cv) );
02693 m_cv_capacity = (m_cv) ? capacity : 0;
02694 }
02695
02696 }
02697 else {
02698 m_cv = (double*)onmalloc( capacity*sizeof(*m_cv) );
02699 m_cv_capacity = (m_cv) ? capacity : 0;
02700 }
02701 }
02702 return ( m_cv ) ? true : false;
02703 }
02704
02705 bool ON_BezierSurface::Trim(
02706 int dir,
02707 const ON_Interval& domain
02708 )
02709 {
02710 bool rc = false;
02711 ON_BezierCurve crv;
02712 double* cv;
02713 const int k = m_is_rat ? (m_dim+1) : m_dim;
02714 const int sizeofcv = k*sizeof(*cv);
02715
02716
02717
02718
02719 if( m_cv_stride[dir] > m_cv_stride[1-dir])
02720 {
02721
02722
02723 crv.m_cv = m_cv;
02724 crv.m_dim = crv.m_cv_stride = m_cv_stride[dir];
02725 crv.m_is_rat = false;
02726 crv.m_order = m_order[0];
02727
02728 rc = crv.Trim(domain);
02729
02730 crv.m_cv = NULL;
02731 crv.m_dim = crv.m_order = crv.m_cv_stride = 0;
02732 }
02733
02734 else
02735 {
02736
02737
02738
02739 crv.Create(k*m_order[1-dir],false,m_order[dir]);
02740 int ind[2];
02741 int& i= ind[dir];
02742 int& j= ind[1-dir];
02743 for( i=0; i<m_order[dir]; i++)
02744 {
02745 cv = crv.CV(i);
02746 for( j=0; j<m_order[1-dir]; j++){
02747 memcpy( cv, CV( ind[0],ind[1]), sizeofcv);
02748 cv += k;
02749 }
02750 }
02751
02752 rc = crv.Trim(domain);
02753
02754 if (rc)
02755 {
02756 for( i=0; i<m_order[dir]; i++)
02757 {
02758 cv = crv.CV(i);
02759 for( j=0; j<m_order[1-dir]; j++){
02760 memcpy( CV( ind[0],ind[1]), cv, sizeofcv);
02761 cv += k;
02762 }
02763 }
02764 }
02765 }
02766
02767
02768 return rc;
02769 }
02770
02771
02772 bool ON_BezierSurface::Split(
02773 int dir,
02774 double t,
02775 ON_BezierSurface& left_bez,
02776 ON_BezierSurface& right_bez
02777 ) const
02778 {
02779 bool rc = false;
02780 if ( 0.0 < t && t < 1.0 ) {
02781 double *crvcv;
02782 int i, j;
02783 const int hdim = (m_is_rat) ? m_dim+1 : m_dim;
02784 const int crvdim = hdim*m_order[dir?0:1];
02785 ON_BezierCurve leftcrv, rightcrv;
02786 ON_BezierCurve crv(crvdim,0,m_order[dir?1:0]);
02787 if (dir) {
02788 for ( j = 0; j < m_order[1]; j++ ) {
02789 crvcv = crv.CV(j);
02790 for ( i = 0; i < m_order[0]; i++) {
02791 memcpy( crvcv, CV(i,j), hdim*sizeof(crvcv[0]) );
02792 crvcv += hdim;
02793 }
02794 }
02795 }
02796 else {
02797 for ( i = 0; i < m_order[0]; i++) {
02798 crvcv = crv.CV(i);
02799 for ( j = 0; j < m_order[1]; j++ ) {
02800 memcpy( crvcv, CV(i,j), hdim*sizeof(crvcv[0]) );
02801 crvcv += hdim;
02802 }
02803 }
02804 }
02805
02806
02807 leftcrv.m_cv_capacity = left_bez.m_cv_capacity;
02808 leftcrv.m_cv = left_bez.m_cv;
02809 left_bez.m_cv = 0;
02810
02811 rightcrv.m_cv_capacity = right_bez.m_cv_capacity;
02812 rightcrv.m_cv = right_bez.m_cv;
02813 right_bez.m_cv = 0;
02814
02815
02816 rc = crv.Split( t, leftcrv, rightcrv );
02817
02818
02819 left_bez.m_cv_capacity = leftcrv.m_cv_capacity;
02820 left_bez.m_cv = leftcrv.m_cv;
02821 leftcrv.m_cv = 0;
02822
02823 right_bez.m_cv_capacity = rightcrv.m_cv_capacity;
02824 right_bez.m_cv = rightcrv.m_cv;
02825 rightcrv.m_cv = 0;
02826
02827 if ( rc )
02828 {
02829
02830 right_bez.m_dim = left_bez.m_dim = m_dim;
02831 right_bez.m_is_rat = left_bez.m_is_rat = m_is_rat;
02832 right_bez.m_order[0] = left_bez.m_order[0] = m_order[0];
02833 right_bez.m_order[1] = left_bez.m_order[1] = m_order[1];
02834 right_bez.m_cv_stride[1-dir] = left_bez.m_cv_stride[1-dir] = hdim;
02835 left_bez.m_cv_stride[dir] = leftcrv.m_cv_stride;
02836 right_bez.m_cv_stride[dir] = rightcrv.m_cv_stride;
02837 }
02838 }
02839
02840 return rc;
02841 }
02842
02843
02844 bool ON_BezierSurface::IsSingular(
02845 int side
02846
02847 ) const
02848 {
02849 const double* points = 0;
02850 int point_count = 0;
02851 int point_stride = 0;
02852
02853 switch ( side )
02854 {
02855 case 0:
02856 points = CV(0,0);
02857 point_count = m_order[0];
02858 point_stride = m_cv_stride[0];
02859 break;
02860
02861 case 1:
02862 points = CV(m_order[0]-1,0);
02863 point_count = m_order[1];
02864 point_stride = m_cv_stride[1];
02865 break;
02866
02867 case 2:
02868 points = CV(0,m_order[1]-1);
02869 point_count = m_order[0];
02870 point_stride = m_cv_stride[0];
02871 break;
02872
02873 case 3:
02874 points = CV(0,0);
02875 point_count = m_order[1];
02876 point_stride = m_cv_stride[1];
02877 break;
02878
02879 default:
02880 return false;
02881 break;
02882 }
02883
02884 return ON_PointsAreCoincident(m_dim,m_is_rat,point_count,point_stride,points);
02885 }
02886
02887 bool ON_ReparameterizeRationalBezierCurve(
02888 double c,
02889 int dim,
02890 int order,
02891 int cvstride,
02892 double* cv
02893 )
02894 {
02895 double d;
02896 int j;
02897
02898 if ( !ON_IsValid(c) || 0.0 == c )
02899 return false;
02900
02901 if (c == 1.0)
02902 return true;
02903
02904 d = c;
02905 cv += cvstride;
02906 dim++;
02907 cvstride -= dim;
02908 while(--order)
02909 {
02910 j = dim;
02911 while(j--)
02912 *cv++ *= d;
02913 cv += cvstride;
02914 d *= c;
02915 }
02916
02917 return true;
02918 }
02919
02920 bool ON_BezierCurve::Reparametrize( double c )
02921 {
02922 return Reparameterize(c);
02923 }
02924
02925 bool ON_BezierCurve::Reparameterize( double c )
02926 {
02927 if ( !ON_IsValid(c) || 0.0 == c )
02928 return false;
02929
02930 if (c == 1.0)
02931 return true;
02932
02933 MakeRational();
02934
02935 return ON_ReparameterizeRationalBezierCurve(c,m_dim,m_order,m_cv_stride,m_cv);
02936
02937
02938 }
02939
02940 bool ON_BezierCurve::ScaleConrolPoints( int i, double w )
02941 {
02942 if ( i < 0 || i >= m_order || w == 0.0 || w == ON_UNSET_VALUE )
02943 return false;
02944 if ( w == Weight(i) )
02945 return true;
02946
02947 if ( !IsRational() )
02948 MakeRational();
02949
02950 double c = Weight(i);
02951 if ( 0.0 == c || ON_UNSET_VALUE == c )
02952 return false;
02953 c = w/c;
02954
02955 int k, j;
02956 double* cv;
02957 int cvdim = CVSize();
02958 for ( k = 0; k < m_order; k++ )
02959 {
02960 cv = CV(k);
02961 j = cvdim;
02962 while(j--)
02963 *cv++ *= c;
02964 }
02965 CV(i)[m_dim] = w;
02966
02967 return true;
02968 }
02969
02970 bool ON_ChangeRationalBezierCurveWeights(
02971 int dim, int order, int cvstride, double* cv,
02972 int i0, double w0,
02973 int i1, double w1
02974 )
02975 {
02976
02977 double r, s, v0, v1;
02978 int i, j;
02979
02980 if ( !ON_IsValid(w0) || !ON_IsValid(w1) || 0.0 == w0 || 0.0 == w1 )
02981 return false;
02982 if ( i0 < 0 || i1 >= order )
02983 return false;
02984 if ( i0 == i1 && w0 != w1 )
02985 return false;
02986 if ( (w0 < 0.0 && w1 > 0.0) || (w0 > 0.0 && w0 < 0.0) )
02987 return false;
02988 if (i0 > i1)
02989 {
02990 i = i0; i0 = i1; i1 = i; r = w0; w0 = w1; w1 = r;
02991 }
02992
02993 v0 = cv[cvstride*i0 + dim];
02994 v1 = cv[cvstride*i1 + dim];
02995 if (!ON_IsValid(v0) || !ON_IsValid(v1) || v0 == 0.0 || v1 == 0.0)
02996 return false;
02997 if (v0 < 0.0 && v1 > 0.0)
02998 return false;
02999 if ( v0 > 0.0 && v1 < 0.0)
03000 return false;
03001
03002 if (i0 == 0 || i0 == i1)
03003 {
03004 s = w0/v0;
03005 r = (i0 != i1) ? pow( (w1/v1)/s, 1.0/((double)i1)) : 1.0;
03006 }
03007 else
03008 {
03009 r = pow( (w1/v1)*(v0/w0), 1.0/((double)(i1-i0)) );
03010 s = (w0/v0)/pow(r,(double)i0);
03011 }
03012 if ( !ON_IsValid(r) || r <= 0.0 )
03013 return false;
03014 if ( !ON_IsValid(s) || 0.0 == s )
03015 return false;
03016
03017 if (s != 1.0)
03018 {
03019 dim++;
03020 cvstride -= dim;
03021 for ( i = 0; i < order; i++ )
03022 {
03023 j = dim;
03024 while(j--)
03025 *cv++ *= s;
03026 cv += cvstride;
03027 }
03028 cvstride += dim;
03029 dim--;
03030 cv -= (cvstride*order);
03031 }
03032 if (r != 1.0)
03033 ON_ReparameterizeRationalBezierCurve(r,dim,order,cvstride,cv);
03034
03035
03036 cv[cvstride*i0+dim] = w0;
03037 cv[cvstride*i1+dim] = w1;
03038
03039 return true;
03040 }
03041
03042 bool ON_BezierCurve::ChangeWeights( int i0, double w0, int i1, double w1 )
03043 {
03044
03045 double v0, v1;
03046 int i;
03047
03048
03049 if ( i0 < 0 || i0 >= m_order || i1 < 0 || i1 >= m_order )
03050 return false;
03051 if ( 0.0 == w0 || !ON_IsValid(w0) || 0.0 == w1 || !ON_IsValid(w1) )
03052 return false;
03053 if ( w0 < 0.0 && w1 > 0.0 )
03054 return false;
03055 if ( w0 > 0.0 && w1 < 0.0 )
03056 return false;
03057 if ( i0 == i1 && w0 != w1 )
03058 return false;
03059
03060 if (i0 > i1)
03061 {
03062 i = i0; i0 = i1; i1 = i; v0 = w0; w0 = w1; w1 = v0;
03063 }
03064
03065 v0 = Weight(i0);
03066 v1 = Weight(i1);
03067 if ( w0 == v0 && w1 == v1 )
03068 return true;
03069
03070 MakeRational();
03071 return ON_ChangeRationalBezierCurveWeights(m_dim,m_order,m_cv_stride,m_cv,i0,w0,i1,w1);
03072
03073
03074
03075
03076
03077
03078
03079
03080
03081
03082
03083
03084
03085
03086
03087
03088
03089
03090
03091
03092
03093
03094
03095
03096
03097
03098
03099
03100
03101
03102
03103
03104
03105
03106
03107
03108
03109
03110
03111
03112
03113
03114
03115 }
03116
03118
03119
03120 ON_3dPoint ON_BezierCurve::PointAt( double t ) const
03121 {
03122 ON_3dPoint p(0.0,0.0,0.0);
03123 EvPoint(t,p);
03124 return p;
03125 }
03126
03127 ON_3dVector ON_BezierCurve::DerivativeAt( double t ) const
03128 {
03129 ON_3dPoint p(0.0,0.0,0.0);
03130 ON_3dVector d(0.0,0.0,0.0);
03131 Ev1Der(t,p,d);
03132 return d;
03133 }
03134
03135 ON_3dVector ON_BezierCurve::TangentAt( double t ) const
03136 {
03137 ON_3dPoint point;
03138 ON_3dVector tangent;
03139 EvTangent( t, point, tangent );
03140 return tangent;
03141 }
03142
03143 ON_3dVector ON_BezierCurve::CurvatureAt( double t ) const
03144 {
03145 ON_3dPoint point;
03146 ON_3dVector tangent, kappa;
03147 EvCurvature( t, point, tangent, kappa );
03148 return kappa;
03149 }
03150
03151 bool ON_BezierCurve::EvTangent(
03152 double t,
03153 ON_3dPoint& point,
03154 ON_3dVector& tangent
03155 ) const
03156 {
03157 ON_3dVector D1, D2;
03158 tangent.Zero();
03159 bool rc = Ev1Der( t, point, tangent );
03160 if ( rc && !tangent.Unitize() )
03161 {
03162 if ( Ev2Der( t, point, D1, D2 ) )
03163 {
03164
03165
03166
03167
03168
03169
03170 tangent = D2;
03171 rc = tangent.Unitize();
03172 if ( rc )
03173 {
03174 ON_Interval domain = Domain();
03175 double tminus = 0.0;
03176 double tplus = 0.0;
03177 if ( domain.IsIncreasing() && ON_GetParameterTolerance( domain[0], domain[1], t, &tminus, &tplus ) )
03178 {
03179 ON_3dPoint p;
03180 ON_3dVector d1, d2;
03181 double eps = 0.0;
03182 double d1od2tol = 0.0;
03183 double d1od2;
03184 double tt = t;
03185
03186
03187 if ( t < domain[1] )
03188 {
03189 eps = tplus-t;
03190 if ( eps <= 0.0 || t+eps > domain.ParameterAt(0.1) )
03191 return rc;
03192 }
03193 else
03194 {
03195 eps = tminus - t;
03196 if ( eps >= 0.0 || t+eps < domain.ParameterAt(0.9) )
03197 return rc;
03198 }
03199
03200 int i, negative_count=0, zero_count=0;
03201 int test_count = 3;
03202 for ( i = 0; i < test_count; i++, eps *= 0.5 )
03203 {
03204 tt = t + eps;
03205 if ( tt == t )
03206 break;
03207 if (!Ev2Der( tt, p, d1, d2 ))
03208 break;
03209 d1od2 = d1*d2;
03210 if ( d1od2 > d1od2tol )
03211 break;
03212 if ( d1od2 < d1od2tol )
03213 negative_count++;
03214 else
03215 zero_count++;
03216 }
03217 if ( negative_count > 0 && test_count == negative_count+zero_count )
03218 {
03219
03220
03221 tangent.Reverse();
03222 }
03223 }
03224 }
03225 }
03226 }
03227 return rc;
03228 }
03229
03230 bool ON_BezierCurve::EvCurvature(
03231 double t,
03232 ON_3dPoint& point,
03233 ON_3dVector& tangent,
03234 ON_3dVector& kappa
03235 ) const
03236 {
03237 ON_3dVector d1, d2;
03238 bool rc = Ev2Der( t, point, d1, d2 );
03239 if ( rc )
03240 {
03241 rc = ON_EvCurvature( d1, d2, tangent, kappa )?true:false;
03242 }
03243 return rc;
03244 }
03245
03246
03247 bool ON_BezierCurve::EvPoint(
03248 double t,
03249 ON_3dPoint& point
03250 ) const
03251 {
03252 bool rc = false;
03253 double ws[128];
03254 double* v;
03255 if ( Dimension() <= 3 ) {
03256 v = &point.x;
03257 point.x = 0.0;
03258 point.y = 0.0;
03259 point.z = 0.0;
03260 }
03261 else if ( Dimension() <= 128 ) {
03262 v = ws;
03263 }
03264 else {
03265 v = (double*)onmalloc(Dimension()*sizeof(*v));
03266 }
03267 rc = Evaluate( t, 0, Dimension(), v );
03268 if ( Dimension() > 3 ) {
03269 point.x = v[0];
03270 point.y = v[1];
03271 point.z = v[2];
03272 if ( Dimension() > 128 )
03273 onfree(v);
03274 }
03275 return rc;
03276 }
03277
03278 bool ON_BezierCurve::Ev1Der(
03279 double t,
03280 ON_3dPoint& point,
03281 ON_3dVector& derivative
03282 ) const
03283 {
03284 bool rc = false;
03285 const int dim = Dimension();
03286 double ws[2*64];
03287 double* v;
03288 point.x = 0.0;
03289 point.y = 0.0;
03290 point.z = 0.0;
03291 derivative.x = 0.0;
03292 derivative.y = 0.0;
03293 derivative.z = 0.0;
03294 if ( dim <= 64 ) {
03295 v = ws;
03296 }
03297 else {
03298 v = (double*)onmalloc(2*dim*sizeof(*v));
03299 }
03300 rc = Evaluate( t, 1, dim, v);
03301 point.x = v[0];
03302 derivative.x = v[dim];
03303 if ( dim > 1 ) {
03304 point.y = v[1];
03305 derivative.y = v[dim+1];
03306 if ( dim > 2 ) {
03307 point.z = v[2];
03308 derivative.z = v[dim+2];
03309 if ( dim > 64 )
03310 onfree(v);
03311 }
03312 }
03313
03314 return rc;
03315 }
03316
03317 bool ON_BezierCurve::Ev2Der(
03318 double t,
03319 ON_3dPoint& point,
03320 ON_3dVector& firstDervative,
03321 ON_3dVector& secondDervative
03322 ) const
03323 {
03324 bool rc = false;
03325 const int dim = Dimension();
03326 double ws[3*64];
03327 double* v;
03328 point.x = 0.0;
03329 point.y = 0.0;
03330 point.z = 0.0;
03331 firstDervative.x = 0.0;
03332 firstDervative.y = 0.0;
03333 firstDervative.z = 0.0;
03334 secondDervative.x = 0.0;
03335 secondDervative.y = 0.0;
03336 secondDervative.z = 0.0;
03337 if ( dim <= 64 ) {
03338 v = ws;
03339 }
03340 else {
03341 v = (double*)onmalloc(3*dim*sizeof(*v));
03342 }
03343 rc = Evaluate( t, 2, dim, v );
03344 point.x = v[0];
03345 firstDervative.x = v[dim];
03346 secondDervative.x = v[2*dim];
03347 if ( dim > 1 ) {
03348 point.y = v[1];
03349 firstDervative.y = v[dim+1];
03350 secondDervative.y = v[2*dim+1];
03351 if ( dim > 2 ) {
03352 point.z = v[2];
03353 firstDervative.z = v[dim+2];
03354 secondDervative.z = v[2*dim+2];
03355 if ( dim > 64 )
03356 onfree(v);
03357 }
03358 }
03359
03360 return rc;
03361 }
03362
03363
03364
03365
03366
03367