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_OBJECT_IMPLEMENT(ON_NurbsCage,ON_Geometry,"06936AFB-3D3C-41ac-BF70-C9319FA480A1");
00020
00021 ON_OBJECT_IMPLEMENT(ON_MorphControl,ON_Geometry,"D379E6D8-7C31-4407-A913-E3B7040D034A");
00022
00023
00024 ON_BOOL32 ON_NurbsCage::Read(ON_BinaryArchive& archive)
00025 {
00026 Destroy();
00027
00028 int major_version = 0;
00029 int minor_version = 0;
00030 bool rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
00031 if ( rc )
00032 {
00033 while(rc)
00034 {
00035 if ( major_version != 1 )
00036 {
00037 ON_ERROR("ON_NurbsCage::Read - old code unable to read new version of chunk");
00038 rc = false;
00039 break;
00040 }
00041
00042 int dim=0;
00043 int order0=0,order1=0,order2=0;
00044 int cv_count0=0,cv_count1=0,cv_count2=0;
00045 int is_rat=0;
00046
00047 rc = archive.ReadInt(&dim);
00048 if (!rc)
00049 break;
00050 if (dim < 1 || dim > 10000)
00051 {
00052 ON_ERROR("ON_NurbsCage::Read - invalid dim");
00053 rc=false;
00054 break;
00055 }
00056
00057 rc = archive.ReadInt(&is_rat);
00058 if (!rc)
00059 break;
00060 if (is_rat != 0 && is_rat != 1)
00061 {
00062 ON_ERROR("ON_NurbsCage::Read - invalid is_rat");
00063 rc=false;
00064 break;
00065 }
00066
00067 rc = archive.ReadInt(&order0);
00068 if (!rc)
00069 break;
00070 if ( order0 < 2 || order0 > 10000 )
00071 {
00072 ON_ERROR("ON_NurbsCage::Read - invalid order0");
00073 rc=false;
00074 break;
00075 }
00076
00077 rc = archive.ReadInt(&order1);
00078 if (!rc)
00079 break;
00080 if ( order1 < 2 || order1 > 10000 )
00081 {
00082 ON_ERROR("ON_NurbsCage::Read - invalid order1");
00083 rc=false;
00084 break;
00085 }
00086
00087 rc = archive.ReadInt(&order2);
00088 if (!rc)
00089 break;
00090 if ( order2 < 2 || order2 > 10000 )
00091 {
00092 ON_ERROR("ON_NurbsCage::Read - invalid order2");
00093 rc=false;
00094 break;
00095 }
00096
00097 rc = archive.ReadInt(&cv_count0);
00098 if (!rc)
00099 break;
00100 if ( cv_count0 < order0 || cv_count0 > 100000 )
00101 {
00102 ON_ERROR("ON_NurbsCage::Read - invalid cv_count0");
00103 rc=false;
00104 break;
00105 }
00106
00107 rc = archive.ReadInt(&cv_count1);
00108 if (!rc)
00109 break;
00110 if ( cv_count1 < order1 || cv_count1 > 100000 )
00111 {
00112 ON_ERROR("ON_NurbsCage::Read - invalid cv_count1");
00113 rc=false;
00114 break;
00115 }
00116
00117 rc = archive.ReadInt(&cv_count2);
00118 if (!rc)
00119 break;
00120 if ( cv_count2 < order2 || cv_count2 > 100000 )
00121 {
00122 ON_ERROR("ON_NurbsCage::Read - invalid cv_count2");
00123 rc=false;
00124 break;
00125 }
00126
00127 rc = Create(dim,is_rat==1,order0,order1,order2,cv_count0,cv_count1,cv_count2);
00128 if (!rc)
00129 break;
00130
00131 if (rc)
00132 rc = archive.ReadDouble(KnotCount(0),m_knot[0]);
00133 if (rc)
00134 rc = archive.ReadDouble(KnotCount(1),m_knot[1]);
00135 if (rc)
00136 rc = archive.ReadDouble(KnotCount(2),m_knot[2]);
00137
00138 int i,j,k;
00139 const int cv_dim = m_is_rat?(m_dim+1):m_dim;
00140 for(i = 0; i < cv_count0 && rc; i++)
00141 {
00142 for(j = 0; j < cv_count1 && rc; j++)
00143 {
00144 for ( k = 0; k < cv_count2 && rc; k++)
00145 {
00146 rc = archive.ReadDouble(cv_dim,CV(i,j,k));
00147 }
00148 }
00149 }
00150
00151
00152
00153 break;
00154 }
00155
00156 if ( !archive.EndRead3dmChunk() )
00157 {
00158 rc = false;
00159 }
00160 }
00161 return rc;
00162 }
00163
00164 ON_BOOL32 ON_NurbsCage::Write(ON_BinaryArchive& archive) const
00165 {
00166 bool rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0);
00167
00168 if (rc)
00169 {
00170 rc = archive.WriteInt(m_dim);
00171 if(rc)
00172 rc = archive.WriteInt(m_is_rat);
00173
00174 if (rc)
00175 rc = archive.WriteInt(m_order[0]);
00176 if (rc)
00177 rc = archive.WriteInt(m_order[1]);
00178 if (rc)
00179 rc = archive.WriteInt(m_order[2]);
00180
00181 if (rc)
00182 rc = archive.WriteInt(m_cv_count[0]);
00183 if (rc)
00184 rc = archive.WriteInt(m_cv_count[1]);
00185 if (rc)
00186 rc = archive.WriteInt(m_cv_count[2]);
00187
00188 if (rc)
00189 rc = archive.WriteDouble(KnotCount(0),m_knot[0]);
00190 if (rc)
00191 rc = archive.WriteDouble(KnotCount(1),m_knot[1]);
00192 if (rc)
00193 rc = archive.WriteDouble(KnotCount(2),m_knot[2]);
00194
00195 int i,j,k;
00196 const int cv_dim = m_is_rat?(m_dim+1):m_dim;
00197 double* bogus_cv = (double*)alloca(cv_dim*sizeof(*bogus_cv));
00198 for ( i = 0; i < cv_dim; i++ )
00199 bogus_cv[i] = ON_UNSET_VALUE;
00200 for(i = 0; i < m_cv_count[0] && rc; i++)
00201 {
00202 for(j = 0; j < m_cv_count[1] && rc; j++)
00203 {
00204 for ( k = 0; k < m_cv_count[2] && rc; k++)
00205 {
00206 const double* cv = CV(i,j,k);
00207 if ( !cv )
00208 cv = bogus_cv;
00209 rc = archive.WriteDouble(cv_dim,cv);
00210 }
00211 }
00212 }
00213
00214 if ( !archive.EndWrite3dmChunk() )
00215 {
00216 rc = false;
00217 }
00218 }
00219
00220 return rc;
00221 }
00222
00223
00224
00225 ON_NurbsCage::ON_NurbsCage()
00226 : m_dim(0),m_is_rat(0),m_cv_capacity(0),m_cv(0)
00227 {
00228 m_order[0] = 0;
00229 m_order[1] = 0;
00230 m_order[2] = 0;
00231 m_cv_count[0] = 0;
00232 m_cv_count[1] = 0;
00233 m_cv_count[2] = 0;
00234 m_knot_capacity[0] = 0;
00235 m_knot_capacity[1] = 0;
00236 m_knot_capacity[2] = 0;
00237 m_knot[0] = 0;
00238 m_knot[1] = 0;
00239 m_knot[2] = 0;
00240 m_cv_stride[0] = 0;
00241 m_cv_stride[1] = 0;
00242 m_cv_stride[2] = 0;
00243 }
00244
00245 ON_NurbsCage::ON_NurbsCage( int dim, bool is_rat,
00246 int order0,
00247 int order1,
00248 int order2,
00249 int cv_count0,
00250 int cv_count1,
00251 int cv_count2
00252 )
00253 : m_dim(0),m_is_rat(0),m_cv_capacity(0),m_cv(0)
00254 {
00255 m_order[0] = 0;
00256 m_order[1] = 0;
00257 m_order[2] = 0;
00258 m_cv_count[0] = 0;
00259 m_cv_count[1] = 0;
00260 m_cv_count[2] = 0;
00261 m_knot_capacity[0] = 0;
00262 m_knot_capacity[1] = 0;
00263 m_knot_capacity[2] = 0;
00264 m_knot[0] = 0;
00265 m_knot[1] = 0;
00266 m_knot[2] = 0;
00267 m_cv_stride[0] = 0;
00268 m_cv_stride[1] = 0;
00269 m_cv_stride[2] = 0;
00270 Create( dim, is_rat, order0, order1, order2, cv_count0, cv_count1, cv_count2 );
00271 }
00272
00273 ON_NurbsCage::ON_NurbsCage( const ON_BoundingBox& bbox,
00274 int order0, int order1, int order2,
00275 int cv_count0, int cv_count1, int cv_count2
00276 )
00277 : m_dim(0),m_is_rat(0),m_cv_capacity(0),m_cv(0)
00278 {
00279 m_order[0] = 0;
00280 m_order[1] = 0;
00281 m_order[2] = 0;
00282 m_cv_count[0] = 0;
00283 m_cv_count[1] = 0;
00284 m_cv_count[2] = 0;
00285 m_knot_capacity[0] = 0;
00286 m_knot_capacity[1] = 0;
00287 m_knot_capacity[2] = 0;
00288 m_knot[0] = 0;
00289 m_knot[1] = 0;
00290 m_knot[2] = 0;
00291 m_cv_stride[0] = 0;
00292 m_cv_stride[1] = 0;
00293 m_cv_stride[2] = 0;
00294 Create(bbox,order0,order1,order2, cv_count0, cv_count1, cv_count2);
00295 }
00296
00297 bool ON_NurbsCage::IsParallelogram(double tolerance) const
00298 {
00299 int i,j,k;
00300 double r,s,t;
00301 double x,y,z,dist;
00302 ON_Interval d[3];
00303 ON_3dPoint P, X, Y, Z, Q, B;
00304
00305 bool rc = IsValid()?true:false;
00306
00307 for ( i = 0; i < 3 && rc; i++ )
00308 {
00309 d[i] = Domain(i);
00310 rc = ( d[i][0] == m_knot[i][0]
00311 && d[i][1] == m_knot[i][m_cv_count[i]+m_order[i]-3]
00312 );
00313 }
00314
00315 if (rc)
00316 {
00317 GetCV(0,0,0,P);
00318 GetCV(m_cv_count[0]-1,0,0,X);
00319 GetCV(0,m_cv_count[1]-1,0,Y);
00320 GetCV(0,0,m_cv_count[2]-1,Z);
00321
00322 if ( tolerance < ON_ZERO_TOLERANCE )
00323 tolerance = ON_ZERO_TOLERANCE;
00324
00325 for ( i = 0; i < m_cv_count[0]; i++ )
00326 {
00327 r = ON_GrevilleAbcissa(m_order[0],m_knot[0]+i);
00328 x = d[0].NormalizedParameterAt(r);
00329 for ( j = 0; j < m_cv_count[1]; j++ )
00330 {
00331 s = ON_GrevilleAbcissa(m_order[1],m_knot[1]+j);
00332 y = d[1].NormalizedParameterAt(s);
00333 for ( k = 0; k < m_cv_count[2]; k++ )
00334 {
00335 t = ON_GrevilleAbcissa(m_order[2],m_knot[2]+k);
00336 z = d[2].NormalizedParameterAt(t);
00337 Evaluate(r,s,t,0,3,&Q.x);
00338 B = (1.0-x-y-z)*P + x*X + y*Y + z*Z;
00339 dist = B.DistanceTo(Q);
00340 if ( dist > tolerance )
00341 return false;
00342 }
00343 }
00344 }
00345 }
00346
00347 return rc;
00348 }
00349
00350
00351 ON_NurbsCage::ON_NurbsCage( const ON_3dPoint* box_corners,
00352 int order0, int order1, int order2,
00353 int cv_count0, int cv_count1, int cv_count2
00354 )
00355 : m_dim(0),m_is_rat(0),m_cv_capacity(0),m_cv(0)
00356 {
00357 m_order[0] = 0;
00358 m_order[1] = 0;
00359 m_order[2] = 0;
00360 m_cv_count[0] = 0;
00361 m_cv_count[1] = 0;
00362 m_cv_count[2] = 0;
00363 m_knot_capacity[0] = 0;
00364 m_knot_capacity[1] = 0;
00365 m_knot_capacity[2] = 0;
00366 m_knot[0] = 0;
00367 m_knot[1] = 0;
00368 m_knot[2] = 0;
00369 m_cv_stride[0] = 0;
00370 m_cv_stride[1] = 0;
00371 m_cv_stride[2] = 0;
00372 Create(box_corners,order0,order1,order2, cv_count0, cv_count1, cv_count2);
00373 }
00374
00375 ON_NurbsCage::ON_NurbsCage( const ON_BezierCage& src )
00376 : m_dim(0),m_is_rat(0),m_cv_capacity(0),m_cv(0)
00377 {
00378 m_order[0] = 0;
00379 m_order[1] = 0;
00380 m_order[2] = 0;
00381 m_cv_count[0] = 0;
00382 m_cv_count[1] = 0;
00383 m_cv_count[2] = 0;
00384 m_knot_capacity[0] = 0;
00385 m_knot_capacity[1] = 0;
00386 m_knot_capacity[2] = 0;
00387 m_knot[0] = 0;
00388 m_knot[1] = 0;
00389 m_knot[2] = 0;
00390 m_cv_stride[0] = 0;
00391 m_cv_stride[1] = 0;
00392 m_cv_stride[2] = 0;
00393 *this = src;
00394 }
00395
00396 ON_NurbsCage::~ON_NurbsCage()
00397 {
00398 Destroy();
00399 }
00400
00401 int ON_NurbsCage::KnotCount(int dir) const
00402 {
00403 return (dir>=0 && dir<=2) ? ON_KnotCount(m_order[dir],m_cv_count[dir]) : 0;
00404 }
00405
00406 double ON_NurbsCage::GrevilleAbcissa(
00407 int dir,
00408 int gindex
00409 ) const
00410 {
00411 return (dir >= 0 && dir <= 2)
00412 ? ON_GrevilleAbcissa( m_order[dir], m_knot[dir] + gindex )
00413 : ON_UNSET_VALUE;
00414 }
00415
00416 bool ON_NurbsCage::MakeDeformable()
00417 {
00418 return true;
00419 }
00420
00421 bool ON_NurbsCage::IsDeformable() const
00422 {
00423 return true;
00424 }
00425
00426 bool ON_NurbsCage::GetTightBoundingBox( ON_BoundingBox& tight_bbox,int bGrowBox,const ON_Xform* xform) const
00427 {
00428 if ( bGrowBox && !tight_bbox.IsValid() )
00429 {
00430 bGrowBox = false;
00431 }
00432
00433 if ( !bGrowBox )
00434 {
00435 tight_bbox.Destroy();
00436 }
00437
00438 if( xform && !xform->IsIdentity() )
00439 {
00440 ON_3dPoint P;
00441 int i,j,k;
00442 for ( i = 0; i < m_cv_count[0]; i++ )
00443 {
00444 for ( j = 0; j < m_cv_count[1]; j++ )
00445 {
00446 for ( k = 0; k < m_cv_count[2]; k++ )
00447 {
00448 GetCV(i,j,k,P);
00449 P = (*xform)*P;
00450 if ( tight_bbox.Set(P,bGrowBox) )
00451 {
00452 bGrowBox = true;
00453 }
00454 }
00455 }
00456 }
00457 }
00458 else
00459 {
00460 if ( GetBoundingBox(tight_bbox,bGrowBox) )
00461 bGrowBox = true;
00462 }
00463
00464 return bGrowBox?true:false;
00465 }
00466
00467 int ON_NurbsCage::CVCount() const
00468 {
00469 return CVCount(0)*CVCount(1)*CVCount(2);
00470 }
00471
00472 int ON_NurbsCage::CVCount(int dir) const
00473 {
00474 return (dir>=0&&dir<=2) ? m_cv_count[dir] : 0;
00475 }
00476
00477 void ON_NurbsCage::DestroyRuntimeCache(bool bDelete)
00478 {
00479 ON_Geometry::DestroyRuntimeCache(bDelete);
00480 }
00481
00482 ON::object_type ON_NurbsCage::ObjectType() const
00483 {
00484 return ON::cage_object;
00485 }
00486
00487 ON_NurbsCage& ON_NurbsCage::operator=( const ON_BezierCage& src )
00488 {
00489 if ( Create(src.m_dim,src.m_is_rat,
00490 src.m_order[0],src.m_order[1],src.m_order[2],
00491 src.m_order[0],src.m_order[1],src.m_order[2]) )
00492 {
00493 int i,j,k;
00494 for ( i = 0; i < m_cv_count[0]; i++ )
00495 {
00496 for ( j = 0; j < m_cv_count[1]; j++ )
00497 {
00498 for ( k = 0; k < m_cv_count[2]; k++ )
00499 {
00500 SetCV(i,j,k,ON::intrinsic_point_style,src.CV(i,j,k));
00501 }
00502 }
00503 }
00504 }
00505 return *this;
00506 }
00507
00508 unsigned int ON_NurbsCage::SizeOf() const
00509 {
00510 unsigned int sz = ON_Geometry::SizeOf();
00511 sz += (sizeof(*this) - sizeof(ON_Geometry));
00512 sz += (KnotCount(0) + KnotCount(1) + KnotCount(2) + CVSize()*CVCount())*sizeof(double);
00513 return sz;
00514 }
00515
00516 ON__UINT32 ON_NurbsCage::DataCRC(ON__UINT32 current_remainder) const
00517 {
00518 current_remainder = ON_CRC32(current_remainder,sizeof(m_dim),&m_dim);
00519 current_remainder = ON_CRC32(current_remainder,sizeof(m_is_rat),&m_is_rat);
00520 current_remainder = ON_CRC32(current_remainder,3*sizeof(m_order[0]),&m_order[0]);
00521 current_remainder = ON_CRC32(current_remainder,3*sizeof(m_cv_count[0]),&m_cv_count[0]);
00522 if ( m_cv_count[0] > 0 && m_cv_count[1] > 0 && m_cv_count[2] > 0
00523 && m_cv_stride[0] > 0 && m_cv_stride[1] > 0 && m_cv_stride[2] > 0
00524 && m_cv )
00525 {
00526 size_t sizeof_cv = CVSize()*sizeof(m_cv[0]);
00527 const double* cv = m_cv;
00528 int i, j, k;
00529 for ( i = 0; i < m_cv_count[0]; i++ )
00530 {
00531 for ( j = 0; j < m_cv_count[1]; j++ )
00532 {
00533 cv = CV(i,j,0);
00534 for (k = 0; i < m_cv_count[2]; k++ )
00535 {
00536 current_remainder = ON_CRC32(current_remainder,sizeof_cv,cv);
00537 cv += m_cv_stride[2];
00538 }
00539 }
00540 }
00541 }
00542 current_remainder = ON_CRC32(current_remainder,KnotCount(0)*sizeof(m_knot[0][0]),m_knot[0]);
00543 current_remainder = ON_CRC32(current_remainder,KnotCount(1)*sizeof(m_knot[1][0]),m_knot[1]);
00544 current_remainder = ON_CRC32(current_remainder,KnotCount(2)*sizeof(m_knot[2][0]),m_knot[2]);
00545
00546 return current_remainder;
00547 }
00548
00549 ON_NurbsCage::ON_NurbsCage(const ON_NurbsCage& src)
00550 : ON_Geometry(src),
00551 m_dim(0),m_is_rat(0),m_cv_capacity(0),m_cv(0)
00552 {
00553 m_order[0] = 0;
00554 m_order[1] = 0;
00555 m_order[2] = 0;
00556 m_cv_count[0] = 0;
00557 m_cv_count[1] = 0;
00558 m_cv_count[2] = 0;
00559 m_knot_capacity[0] = 0;
00560 m_knot_capacity[1] = 0;
00561 m_knot_capacity[2] = 0;
00562 m_knot[0] = 0;
00563 m_knot[1] = 0;
00564 m_knot[2] = 0;
00565 m_cv_stride[0] = 0;
00566 m_cv_stride[1] = 0;
00567 m_cv_stride[2] = 0;
00568
00569 *this = src;
00570 }
00571
00572
00573 ON_NurbsCage& ON_NurbsCage::operator=(const ON_NurbsCage& src)
00574 {
00575 if ( this != &src )
00576 {
00577 ON_Geometry::operator=(src);
00578 if ( Create( src.m_dim, src.m_is_rat,
00579 src.m_order[0], src.m_order[1], src.m_order[2],
00580 src.m_cv_count[0], src.m_cv_count[1], src.m_cv_count[2]
00581 ) )
00582 {
00583 if ( m_order[0] >= 2 && m_cv_count[0] >= m_order[0] && m_knot[0] && src.m_knot[0] )
00584 memcpy( m_knot[0], src.m_knot[0], KnotCount(0)*sizeof(m_knot[0][0]));
00585 if ( m_order[1] >= 2 && m_cv_count[1] >= m_order[1] && m_knot[1] && src.m_knot[1] )
00586 memcpy( m_knot[1], src.m_knot[1], KnotCount(1)*sizeof(m_knot[1][0]));
00587 if ( m_order[2] >= 2 && m_cv_count[2] >= m_order[2] && m_knot[2] && src.m_knot[2] )
00588 memcpy( m_knot[2], src.m_knot[2], KnotCount(2)*sizeof(m_knot[2][0]));
00589
00590 if ( m_cv && src.m_cv && m_cv_stride[0] > 0 && m_cv_stride[1] > 0 && m_cv_stride[2] > 0 )
00591 {
00592 const int cv_dim = CVSize();
00593 const int sizeofcv = cv_dim*sizeof(m_cv[0]);
00594 if ( m_cv_stride[0] == src.m_cv_stride[0]
00595 && m_cv_stride[1] == src.m_cv_stride[1]
00596 && m_cv_stride[2] == src.m_cv_stride[2] )
00597 {
00598 memcpy(m_cv,src.m_cv,m_cv_count[0]*m_cv_count[1]*m_cv_count[2]*sizeofcv);
00599 }
00600 else
00601 {
00602 int i, j, k;
00603 double* cv = m_cv;
00604 for ( i = 0; i < m_cv_count[0]; i++ )
00605 for ( j = 0; j < m_cv_count[1]; j++ )
00606 for ( k = 0; k < m_cv_count[2]; k++ )
00607 {
00608 memcpy( cv, src.CV(i,j,k), sizeofcv );
00609 cv += cv_dim;
00610 }
00611 }
00612 }
00613 }
00614 else
00615 {
00616 Destroy();
00617 }
00618 }
00619 return *this;
00620 }
00621
00622 ON_BOOL32 ON_NurbsCage::IsValid(
00623 ON_TextLog*
00624 ) const
00625 {
00626 if ( 0 == m_cv )
00627 return false;
00628
00629 if ( 0 == m_knot[0] )
00630 return false;
00631
00632 if ( 0 == m_knot[1] )
00633 return false;
00634
00635 if ( 0 == m_knot[2] )
00636 return false;
00637
00638 if ( m_order[0] < 2 )
00639 return false;
00640 if ( m_order[1] < 2 )
00641 return false;
00642 if ( m_order[2] < 2 )
00643 return false;
00644
00645 if ( m_cv_count[0] < m_order[0] )
00646 return false;
00647 if ( m_cv_count[1] < m_order[1] )
00648 return false;
00649 if ( m_cv_count[2] < m_order[2] )
00650 return false;
00651
00652 if ( m_dim <= 0 )
00653 return false;
00654 if ( m_is_rat != 0 && m_is_rat != 1 )
00655 return false;
00656
00657 const int cvdim = m_is_rat ? (m_dim+1) : m_dim;
00658
00659 if ( m_cv_capacity > 0 && m_cv_capacity < cvdim*m_cv_count[0]*m_cv_count[1]*m_cv_count[2] )
00660 return false;
00661
00662 int i[3];
00663 i[0] = (m_cv_stride[0] <= m_cv_stride[1]) ? 0 : 1;
00664 i[1] = 1-i[0];
00665 if ( m_cv_stride[2] < m_cv_stride[i[0]] )
00666 {
00667 i[2] = i[1];
00668 i[1] = i[0];
00669 i[0] = 2;
00670 }
00671 else if ( m_cv_stride[2] < m_cv_stride[i[1]] )
00672 {
00673 i[2] = i[1];
00674 i[1] = 2;
00675 }
00676 else
00677 {
00678 i[2] = 2;
00679 }
00680
00681 if ( m_cv_stride[i[0]] < cvdim )
00682 return false;
00683 if ( m_cv_stride[i[1]] < m_cv_stride[i[0]]*m_cv_count[i[0]] )
00684 return false;
00685 if ( m_cv_stride[i[2]] < m_cv_stride[i[1]]*m_cv_count[i[1]] )
00686 return false;
00687
00688 return true;
00689 }
00690
00691 void ON_NurbsCage::Dump( ON_TextLog& dump ) const
00692 {
00693 dump.Print( "ON_NurbsCage dim = %d is_rat = %d\n"
00694 " order = (%d, %d, %d) \n",
00695 " cv_count = (%d, %d, %d) \n",
00696 m_dim, m_is_rat,
00697 m_order[0], m_order[1], m_order[2],
00698 m_cv_count[0], m_cv_count[1], m_cv_count[2] );
00699
00700 int dir;
00701 for ( dir = 0; dir < 3; dir++ )
00702 {
00703 dump.Print( "Knot Vector %d ( %d knots )\n", dir, KnotCount(dir) );
00704 dump.PrintKnotVector( m_order[dir], m_cv_count[dir], m_knot[dir] );
00705 }
00706
00707 dump.Print( "Control Points %d %s points\n"
00708 " index value\n",
00709 m_cv_count[0]*m_cv_count[1]*m_cv_count[2],
00710 (m_is_rat) ? "rational" : "non-rational" );
00711 if ( !m_cv )
00712 {
00713 dump.Print(" NULL cv array\n");
00714 }
00715 else
00716 {
00717 int i,j;
00718 char sPreamble[128];
00719 memset(sPreamble,0,sizeof(sPreamble));
00720 for ( i = 0; i < m_order[0]; i++ )
00721 {
00722 for ( j = 0; j < m_order[1]; j++ )
00723 {
00724 if ( i > 0 || j > 0)
00725 dump.Print("\n");
00726 sPreamble[0] = 0;
00727 sprintf(sPreamble," CV[%2d][%2d]",i,j);
00728 dump.PrintPointList( m_dim, m_is_rat,
00729 m_cv_count[2], m_cv_stride[2],
00730 CV(i,j,0),
00731 sPreamble );
00732 }
00733 if ( i < m_order[0]-1)
00734 dump.Print("\n");
00735 }
00736 }
00737 }
00738
00739 int ON_NurbsCage::Dimension() const
00740 {
00741 return m_dim;
00742 }
00743
00744 bool ON_NurbsCage::Create( const ON_BoundingBox& bbox,
00745 int order0, int order1, int order2,
00746 int cv_count0, int cv_count1, int cv_count2
00747 )
00748 {
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764 ON_3dPoint box_corners[8];
00765 box_corners[0] = bbox.Corner(0,0,0);
00766 box_corners[1] = bbox.Corner(1,0,0);
00767 box_corners[2] = bbox.Corner(1,1,0);
00768 box_corners[3] = bbox.Corner(0,1,0);
00769 box_corners[4] = bbox.Corner(0,0,1);
00770 box_corners[5] = bbox.Corner(1,0,1);
00771 box_corners[6] = bbox.Corner(1,1,1);
00772 box_corners[7] = bbox.Corner(0,1,1);
00773 return Create(box_corners,order0,order1,order2,cv_count0,cv_count1,cv_count2);
00774 }
00775
00776
00777 bool ON_NurbsCage::Create( int dim, bool is_rat,
00778 int order0, int order1, int order2,
00779 int cv_count0, int cv_count1, int cv_count2
00780 )
00781 {
00782 Destroy();
00783 if ( order0 < 2 || order1 < 2 || order2 < 2 )
00784 {
00785 if ( 0 == dim && 0 == is_rat
00786 && 0 == order0 && 0 == order1 && 0 == order2
00787 && 0 == cv_count0 && 0 == cv_count1 && 0 == cv_count2 )
00788 {
00789 return true;
00790 }
00791 ON_ERROR("ON_NurbsCage::Create - invalid orders");
00792 return false;
00793 }
00794
00795 if ( cv_count0 < order0 || cv_count1 < order1 || cv_count2 < order2 )
00796 {
00797 ON_ERROR("ON_NurbsCage::Create - invalid cv counts");
00798 return false;
00799 }
00800
00801 if ( dim < 1 )
00802 {
00803 ON_ERROR("ON_NurbsCage::Create - invalid dim");
00804 return false;
00805 }
00806
00807 if ( is_rat != true && is_rat != false )
00808 {
00809 ON_ERROR("ON_NurbsCage::Create - invalid is_rat");
00810 return false;
00811 }
00812
00813 m_dim = dim;
00814 m_is_rat = is_rat ? 1 : 0;
00815
00816 m_order[0] = order0;
00817 m_order[1] = order1;
00818 m_order[2] = order2;
00819
00820 m_cv_count[0] = cv_count0;
00821 m_cv_count[1] = cv_count1;
00822 m_cv_count[2] = cv_count2;
00823
00824
00825
00826
00827
00828
00829 m_cv_stride[2] = m_dim+m_is_rat;
00830 m_cv_stride[1] = m_cv_stride[2]*m_cv_count[2];
00831 m_cv_stride[0] = m_cv_stride[1]*m_cv_count[1];
00832
00833 ReserveCVCapacity(m_cv_stride[0]*m_cv_count[0]);
00834
00835 ReserveKnotCapacity(0,ON_KnotCount(m_order[0],m_cv_count[0]));
00836 ReserveKnotCapacity(1,ON_KnotCount(m_order[1],m_cv_count[1]));
00837 ReserveKnotCapacity(2,ON_KnotCount(m_order[2],m_cv_count[2]));
00838
00839 ON_MakeClampedUniformKnotVector(m_order[0],m_cv_count[0],m_knot[0],1.0);
00840 ON_MakeClampedUniformKnotVector(m_order[1],m_cv_count[1],m_knot[1],1.0);
00841 ON_MakeClampedUniformKnotVector(m_order[2],m_cv_count[2],m_knot[2],1.0);
00842
00843 ON_SetKnotVectorDomain( m_order[0], m_cv_count[0], m_knot[0], 0.0, 1.0);
00844 ON_SetKnotVectorDomain( m_order[1], m_cv_count[1], m_knot[1], 0.0, 1.0);
00845 ON_SetKnotVectorDomain( m_order[2], m_cv_count[2], m_knot[2], 0.0, 1.0);
00846
00847 return IsValid() ? true : false;
00848 }
00849
00850 bool ON_NurbsCage::Create(
00851 const ON_3dPoint* box_corners,
00852 int order0, int order1, int order2,
00853 int cv_count0, int cv_count1, int cv_count2
00854 )
00855 {
00856 int i, j, k;
00857 double r,s,t;
00858
00859 if ( 0 == box_corners )
00860 return false;
00861 for( i = 0; i < 8; i++ )
00862 {
00863 if ( !box_corners[i].IsValid() )
00864 return false;
00865 }
00866
00867
00868
00869 ON_BezierCage cube(3,0,2,2,2);
00870 cube.SetCV(0,0,0,box_corners[0]);
00871 cube.SetCV(1,0,0,box_corners[1]);
00872 cube.SetCV(1,1,0,box_corners[2]);
00873 cube.SetCV(0,1,0,box_corners[3]);
00874 cube.SetCV(0,0,1,box_corners[4]);
00875 cube.SetCV(1,0,1,box_corners[5]);
00876 cube.SetCV(1,1,1,box_corners[6]);
00877 cube.SetCV(0,1,1,box_corners[7]);
00878
00879 if ( 2 == cv_count0 && 2 == cv_count1 && 2 == cv_count2 )
00880 {
00881 operator=(cube);
00882 }
00883 else
00884 {
00885 if (!Create(3,0,order0,order1,order2,cv_count0,cv_count1,cv_count2))
00886 return false;
00887
00888 double* g0 = (double*)onmalloc(m_cv_count[0]*m_cv_count[1]*m_cv_count[2]*sizeof(*g0));
00889 double* g1 = g0 + m_cv_count[0];
00890 double* g2 = g1 + m_cv_count[1];
00891
00892 ON_GetGrevilleAbcissae(m_order[0],m_cv_count[0],m_knot[0],false,g0);
00893 ON_GetGrevilleAbcissae(m_order[1],m_cv_count[1],m_knot[1],false,g1);
00894 ON_GetGrevilleAbcissae(m_order[2],m_cv_count[2],m_knot[2],false,g2);
00895
00896 for (i = 0; i < m_cv_count[0]; i++)
00897 {
00898 r = g0[i];
00899 for (j = 0; j < m_cv_count[1]; j++)
00900 {
00901 s = g1[j];
00902 for (k = 0; k < m_cv_count[2]; k++)
00903 {
00904 t = g2[k];
00905 SetCV(i,j,k,cube.PointAt(r,s,t));
00906 }
00907 }
00908 }
00909
00910 onfree(g0);
00911 }
00912 return IsValid()?true:false;
00913 }
00914
00915
00916 void ON_NurbsCage::Destroy()
00917 {
00918 DestroyRuntimeCache();
00919
00920 if ( m_cv && m_cv_capacity > 0 )
00921 {
00922 onfree(m_cv);
00923 m_cv = 0;
00924 }
00925
00926 if ( m_knot[0] && m_knot_capacity[0] > 0 )
00927 {
00928 onfree(m_knot[0]);
00929 m_knot[0] = 0;
00930 }
00931
00932 if ( m_knot[1] && m_knot_capacity[1] > 0 )
00933 {
00934 onfree(m_knot[1]);
00935 m_knot[1] = 0;
00936 }
00937
00938 if ( m_knot[2] && m_knot_capacity[2] > 0 )
00939 {
00940 onfree(m_knot[2]);
00941 m_knot[2] = 0;
00942 }
00943
00944 m_cv_capacity = 0;
00945 m_knot_capacity[0] = 0;
00946 m_knot_capacity[1] = 0;
00947 m_knot_capacity[2] = 0;
00948
00949 m_cv_stride[0] = 0;
00950 m_cv_stride[1] = 0;
00951 m_cv_stride[2] = 0;
00952
00953 m_dim = 0;
00954 m_is_rat = 0;
00955
00956 m_order[0] = 0;
00957 m_order[1] = 0;
00958 m_order[2] = 0;
00959 }
00960
00961 void ON_NurbsCage::EmergencyDestroy()
00962 {
00963 DestroyRuntimeCache(false);
00964 m_cv = 0;
00965 m_knot[0] = 0;
00966 m_knot[1] = 0;
00967 m_knot[2] = 0;
00968 m_cv_capacity = 0;
00969 m_knot_capacity[0] = 0;
00970 m_knot_capacity[1] = 0;
00971 m_knot_capacity[2] = 0;
00972 m_cv_stride[0] = 0;
00973 m_cv_stride[1] = 0;
00974 m_cv_stride[2] = 0;
00975 m_dim = 0;
00976 m_is_rat = 0;
00977 m_order[0] = 0;
00978 m_order[1] = 0;
00979 m_order[2] = 0;
00980 }
00981
00982
00983 ON_BOOL32 ON_NurbsCage::GetBBox(
00984 double* boxmin,
00985 double* boxmax,
00986 ON_BOOL32 bGrowBox
00987 ) const
00988 {
00989 int i, j;
00990 bool rc = ( 0 != m_cv
00991 && m_cv_count[0] >= 2 && m_cv_count[1] >= 2 && m_cv_count[2] >= 2
00992 && m_cv_stride[0] > 0 && m_cv_stride[1] > 0 && m_cv_stride[2] > 0 ) ? true : false;
00993 if ( !rc )
00994 {
00995 ON_ERROR("ON_NurbsCage::GetBBox - invalid input");
00996 }
00997 else
00998 {
00999 for ( i = 0; rc && i < m_cv_count[0]; i++ )
01000 for ( j = 0; rc && j < m_cv_count[1]; j++ )
01001 {
01002 rc = ON_GetPointListBoundingBox( m_dim, m_is_rat, m_cv_count[2], m_cv_stride[2],
01003 CV(i,j,0),
01004 boxmin, boxmax, bGrowBox?true:false );
01005 bGrowBox = true;
01006 }
01007 }
01008 return rc;
01009 }
01010
01011 ON_BOOL32 ON_NurbsCage::Transform( const ON_Xform& xform )
01012 {
01013 int i,j;
01014 bool rc = (m_cv_count[0] > 0 && m_cv_count[1] > 0 && m_cv_count[2]) ? true : false;
01015 if ( rc || !xform.IsIdentity() )
01016 {
01017 if ( 0 == m_is_rat )
01018 {
01019 if ( xform.m_xform[3][0] != 0.0 || xform.m_xform[3][1] != 0.0 || xform.m_xform[3][2] != 0.0 )
01020 {
01021 MakeRational();
01022 }
01023 }
01024
01025 for ( i = 0; rc && i < m_cv_count[0]; i++ )
01026 {
01027 for ( j = 0; rc && j < m_cv_count[1]; j++ )
01028 {
01029 rc = ON_TransformPointList( m_dim, m_is_rat,
01030 m_cv_count[2], m_cv_stride[2],
01031 CV(i,j,0), xform );
01032 }
01033 }
01034 }
01035 return rc;
01036 }
01037
01038 ON_Interval ON_NurbsCage::Domain(
01039 int dir
01040 ) const
01041 {
01042 ON_Interval d;
01043 if ( dir < 0 || dir > 2 || !ON_GetKnotVectorDomain( m_order[dir], m_cv_count[dir], m_knot[dir], &d.m_t[0], &d.m_t[1] ) )
01044 d.Destroy();
01045 return d;
01046 }
01047
01048
01049
01050
01051
01052 bool ON_EvaluateNurbsCageSpan(
01053 int dim,
01054 int is_rat,
01055 int order0, int order1, int order2,
01056 const double* knot0,
01057 const double* knot1,
01058 const double* knot2,
01059 int cv_stride0, int cv_stride1, int cv_stride2,
01060 const double* cv0,
01061 int der_count,
01062 double t0, double t1, double t2,
01063 int v_stride,
01064 double* v
01065 )
01066 {
01067 double c;
01068 double* N_0, *N_1, *N_2, *P, *P0, *P00;
01069 const double *cv;
01070 int j0, j1, j2, d0, d1, d2, d;
01071 const int cvdim = is_rat ? (dim+1) : dim;
01072 const int dcv2 = cv_stride2 - cvdim;
01073 const int der_count0 = (der_count >= order0) ? order0-1 : der_count;
01074 const int der_count1 = (der_count >= order1) ? order1-1 : der_count;
01075 const int der_count2 = (der_count >= order1) ? order2-2 : der_count;
01076 int Pcount = der_count*(der_count*(der_count*2 + 9)+13)/6 + 1;
01077 int Psize = cvdim<<3;
01078 int i = order0*order0;
01079 int j = order1*order1;
01080 int k = order2*order2;
01081
01082
01083
01084
01085
01086 N_0 = (double*)alloca( ((i+j+k)*sizeof(*N_0)) + Pcount*Psize);
01087 N_1 = N_0 + i;
01088 N_2 = N_1 + j;
01089 P0 = N_2 + k;
01090 memset( P0, 0, Pcount*Psize );
01091
01092 ON_EvaluateNurbsBasis( order0, knot0, t0, N_0 );
01093 ON_EvaluateNurbsBasis( order1, knot1, t1, N_1 );
01094 ON_EvaluateNurbsBasis( order2, knot2, t2, N_2 );
01095 if ( der_count0 > 0 )
01096 {
01097 ON_EvaluateNurbsBasisDerivatives( order0, knot0, der_count0, N_0 );
01098 ON_EvaluateNurbsBasisDerivatives( order1, knot1, der_count1, N_1 );
01099 ON_EvaluateNurbsBasisDerivatives( order2, knot2, der_count2, N_2 );
01100 }
01101
01102
01103 P = P0;
01104 for ( j0 = 0; j0 < order0; j0++)
01105 {
01106 for ( j1 = 0; j1 < order1; j1++ )
01107 {
01108 cv = cv0 + j0*cv_stride0 + j1*cv_stride1;
01109 for ( j2 = 0; j2 < order2; j2++ )
01110 {
01111 c = N_0[j0]*N_1[j1]*N_2[j2];
01112 j = cvdim;
01113 while (j--)
01114 {
01115 *P++ += c* *cv++;
01116 }
01117 P -= cvdim;
01118 cv += dcv2;
01119 }
01120 }
01121 }
01122
01123 if ( der_count > 0 )
01124 {
01125
01126 P += cvdim;
01127 for ( j0 = 0; j0 < order0; j0++)
01128 {
01129 for ( j1 = 0; j1 < order1; j1++ )
01130 {
01131 cv = cv0 + j0*cv_stride0 + j1*cv_stride1;
01132 for ( j2 = 0; j2 < order2; j2++ )
01133 {
01134
01135 c = N_0[j0+order0]*N_1[j1]*N_2[j2];
01136 j = cvdim;
01137 while (j--)
01138 *P++ += c* *cv++;
01139 cv -= cvdim;
01140
01141
01142 c = N_0[j0]*N_1[j1+order1]*N_2[j2];
01143 j = cvdim;
01144 while (j--)
01145 *P++ += c* *cv++;
01146 cv -= cvdim;
01147
01148
01149 c = N_0[j0]*N_1[j1]*N_2[j2+order2];
01150 j = cvdim;
01151 while (j--)
01152 *P++ += c* *cv++;
01153
01154 P -= 3*cvdim;
01155 cv += dcv2;
01156 }
01157 }
01158 }
01159
01160
01161 for ( d = 2; d <= der_count; d++ )
01162 {
01163
01164 P += (cvdim*d*(d+1))>>1;
01165
01166 if ( der_count0+der_count1+der_count2 > 1 )
01167 {
01168 for ( j0 = 0; j0 < order0; j0++)
01169 {
01170 for ( j1 = 0; j1 < order1; j1++)
01171 {
01172 cv = cv0 + j0*cv_stride0 + j1*cv_stride1;
01173 for ( j2 = 0; j2 < order2; j2++ )
01174 {
01175 P00 = P;
01176 for ( d0 = d; d0 >= 0; d0-- )
01177 {
01178 for ( d1 = d-d0; d1 >= 0; d1-- )
01179 {
01180 d2 = d-d0-d1;
01181 if ( d0 > der_count0 || d1 > der_count1 || d2 > der_count2 )
01182 {
01183
01184 P += cvdim;
01185 }
01186 else
01187 {
01188 c = N_0[j0 + d0*order0]*N_1[j1 + d1*order1]*N_2[j2 + d2*order2];
01189 j = cvdim;
01190 while(j--)
01191 *P++ += c* *cv++;
01192 cv -= cvdim;
01193 }
01194 }
01195 }
01196 P = P00;
01197 cv += cv_stride2;
01198 }
01199 }
01200 }
01201 }
01202 }
01203
01204 }
01205
01206 if ( is_rat )
01207 {
01208 ON_EvaluateQuotientRule3( dim, der_count, cvdim, P0 );
01209 Psize -= 8;
01210 }
01211
01212 Pcount = (der_count+1)*(der_count+2)*(der_count+3)/6;
01213 for ( i = 0; i < Pcount; i++)
01214 {
01215 memcpy( v, P0, Psize );
01216 v += v_stride;
01217 P0 += cvdim;
01218 }
01219
01220 return true;
01221 }
01222
01223 bool ON_NurbsCage::Evaluate(
01224 double r, double s, double t,
01225 int der_count,
01226 int v_stride,
01227 double* v,
01228 int side,
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238 int* hint
01239 ) const
01240 {
01241 int side0 = (side&&(side==2||side==3||side==6||side==7))?-1:1;
01242 int side1 = (side&&(side==3||side==4||side==7||side==8))?-1:1;
01243 int side2 = (side>=5&&side<=8)?-1:1;
01244
01245 int hint0 = (hint) ? hint[0] : 0;
01246 int hint1 = (hint) ? hint[1] : 0;
01247 int hint2 = (hint) ? hint[2] : 0;
01248 const int span_index0 = ON_NurbsSpanIndex(m_order[0],m_cv_count[0],m_knot[0],r,side0,hint0);
01249 const int span_index1 = ON_NurbsSpanIndex(m_order[1],m_cv_count[1],m_knot[1],s,side1,hint1);
01250 const int span_index2 = ON_NurbsSpanIndex(m_order[2],m_cv_count[2],m_knot[2],t,side2,hint2);
01251
01252 bool rc = ON_EvaluateNurbsCageSpan(m_dim,m_is_rat,
01253 m_order[0],m_order[1],m_order[2],
01254 m_knot[0]+span_index0,
01255 m_knot[1]+span_index1,
01256 m_knot[2]+span_index2,
01257 m_cv_stride[0],m_cv_stride[1],m_cv_stride[2],
01258 m_cv + (m_cv_stride[0]*span_index0+m_cv_stride[1]*span_index1+m_cv_stride[2]*span_index2),
01259 der_count,
01260 r,s,t,
01261 v_stride,v);
01262
01263 if( hint )
01264 {
01265 hint[0] = span_index0;
01266 hint[1] = span_index1;
01267 hint[2] = span_index2;
01268 }
01269
01270 return rc;
01271 }
01272
01273 ON_3dPoint ON_NurbsCage::PointAt(
01274 double r,
01275 double s,
01276 double t
01277 ) const
01278 {
01279 ON_3dPoint pt;
01280 if ( m_dim <= 3 )
01281 {
01282 pt.x = 0.0;
01283 pt.y = 0.0;
01284 pt.z = 0.0;
01285 Evaluate(r,s,t,0,3,&pt.x);
01286 }
01287 else
01288 {
01289 double* v = (double*)alloca(m_dim*sizeof(*v));
01290 v[0] = 0.0;
01291 v[1] = 0.0;
01292 v[2] = 0.0;
01293 Evaluate(r,s,t,0,m_dim,v);
01294 pt.x = v[0];
01295 pt.y = v[1];
01296 pt.z = v[2];
01297 }
01298 return pt;
01299 }
01300
01301 ON_3dPoint ON_NurbsCage::PointAt( ON_3dPoint rst ) const
01302 {
01303 ON_3dPoint pt;
01304 if ( m_dim <= 3 )
01305 {
01306 pt.x = 0.0;
01307 pt.y = 0.0;
01308 pt.z = 0.0;
01309 Evaluate(rst.x,rst.y,rst.z,0,3,&pt.x);
01310 }
01311 else
01312 {
01313 double* v = (double*)alloca(m_dim*sizeof(*v));
01314 v[0] = 0.0;
01315 v[1] = 0.0;
01316 v[2] = 0.0;
01317 Evaluate(rst.x,rst.y,rst.z,0,m_dim,v);
01318 pt.x = v[0];
01319 pt.y = v[1];
01320 pt.z = v[2];
01321 }
01322 return pt;
01323 }
01324
01325 ON_NurbsSurface* ON_NurbsCage::IsoSurface(
01326 int dir,
01327 double c,
01328 ON_NurbsSurface* srf
01329 ) const
01330 {
01331
01332
01333
01334 if ( dir < 0 || dir > 2 )
01335 {
01336 ON_ERROR("ON_NurbsCage::IsoSurface - invalid dir parameter");
01337 return 0;
01338 }
01339 if ( m_order[dir] < 2 || m_cv_count[dir] < m_order[dir] || 0 == m_knot[dir] )
01340 {
01341 ON_ERROR("ON_NurbsCage::IsoSurface - invalid NURBS cage");
01342 return 0;
01343 }
01344
01345 const int cage_cvdim = CVSize();
01346
01347 int span_index = ON_NurbsSpanIndex(m_order[dir],m_cv_count[dir],m_knot[dir],c,0,0);
01348 ON_NurbsCurve nurbs_curve;
01349 nurbs_curve.m_dim = cage_cvdim*m_cv_count[0]*m_cv_count[1]*m_cv_count[2]/m_cv_count[dir];
01350 nurbs_curve.m_is_rat = 0;
01351 nurbs_curve.m_order = m_order[dir];
01352 nurbs_curve.m_cv_count = nurbs_curve.m_order;
01353 nurbs_curve.ReserveCVCapacity(nurbs_curve.m_dim*nurbs_curve.m_cv_count);
01354 nurbs_curve.m_cv_stride = nurbs_curve.m_dim;
01355 nurbs_curve.m_knot = m_knot[dir] + span_index;
01356 nurbs_curve.m_knot_capacity = 0;
01357
01358 int ii,jj,kk;
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370 ii = dir;
01371 switch(dir)
01372 {
01373 case 0:
01374 jj = 1;
01375 kk = 2;
01376 break;
01377 case 1:
01378 jj = 0;
01379 kk = 2;
01380 break;
01381 case 2:
01382 jj = 0;
01383 kk = 1;
01384 break;
01385 default:
01386 ii = 0;
01387 jj = 1;
01388 kk = 2;
01389 break;
01390 };
01391
01392
01393 double* cv;
01394 const int cage_sizeofcv = cage_cvdim*sizeof(*cv);
01395
01396 int i1 = span_index+m_order[ii];
01397 int j1 = m_cv_count[jj];
01398 int k1 = m_cv_count[kk];
01399
01400 int i,j,k;
01401 int cage_ijk[3];
01402 for ( i = span_index; i < i1; i++)
01403 {
01404 cv = nurbs_curve.CV(i-span_index);
01405 cage_ijk[ii] = i;
01406 for ( j = 0; j < j1; j++ )
01407 {
01408 cage_ijk[jj] = j;
01409 for ( k = 0; k < k1; k++ )
01410 {
01411 cage_ijk[kk] = k;
01412 memcpy(cv,CV(cage_ijk[0],cage_ijk[1],cage_ijk[2]),cage_sizeofcv);
01413 cv += cage_cvdim;
01414 }
01415 }
01416 }
01417
01418 ON_NurbsSurface* iso_srf = srf ? srf : ON_NurbsSurface::New();
01419 iso_srf->Create(m_dim,m_is_rat,m_order[jj],m_order[kk],m_cv_count[jj],m_cv_count[kk]);
01420 nurbs_curve.Evaluate(c,0,nurbs_curve.m_dim,iso_srf->m_cv,0,0);
01421 nurbs_curve.m_knot = 0;
01422 memcpy(iso_srf->m_knot[0],m_knot[jj],iso_srf->KnotCount(0)*sizeof(*iso_srf->m_knot[0]));
01423 memcpy(iso_srf->m_knot[1],m_knot[kk],iso_srf->KnotCount(1)*sizeof(*iso_srf->m_knot[1]));
01424
01425 return iso_srf;
01426 }
01427
01428 bool ON_NurbsCage::IsRational() const
01429 {
01430 return m_is_rat ? true : false;
01431 }
01432
01433 int ON_NurbsCage::CVSize() const
01434 {
01435 return ( m_is_rat && m_dim>0 ) ? m_dim+1 : m_dim;
01436 }
01437
01438 int ON_NurbsCage::Order( int dir ) const
01439 {
01440 return (dir>=0&&dir<=2) ? m_order[dir] : 0;
01441 }
01442
01443 int ON_NurbsCage::Degree(int dir) const
01444 {
01445 int order = Order(dir);
01446 return (order>=2) ? order-1 : 0;
01447 }
01448
01449 bool ON_NurbsCage::IsClosed(int dir) const
01450 {
01451 bool bIsClosed = false;
01452 if ( dir >= 0 && dir <= 2 && m_dim > 0)
01453 {
01454 if ( ON_IsKnotVectorClamped( m_order[dir], m_cv_count[dir], m_knot[dir] ) )
01455 {
01456 const double *cv0, *cv1;
01457 int i,j,k,d[3] = {0,0,0};
01458 d[dir] = m_cv_count[dir] - 1;
01459 for ( i = 0; i+d[0] < m_cv_count[0]; i++ )
01460 {
01461 for ( j = 0; j+d[1] < m_cv_count[1]; j++ )
01462 {
01463 for ( k = 0; k+d[2] < m_cv_count[2]; k++ )
01464 {
01465 cv0 = CV(i,j,k);
01466 cv1 = CV(i+d[0],j+d[1],k+d[2]);
01467 if ( false == ON_PointsAreCoincident( m_dim, m_is_rat, cv0, cv1 ) )
01468 return false;
01469 }
01470 }
01471 }
01472 bIsClosed = true;
01473 }
01474 else
01475 {
01476 bIsClosed = IsPeriodic(dir);
01477 }
01478 }
01479 return bIsClosed;
01480 }
01481
01482 bool ON_NurbsCage::IsPeriodic(int dir) const
01483 {
01484 bool bIsPeriodic = false;
01485 if ( dir >= 0 && dir <= 2 && m_dim > 0 )
01486 {
01487 bIsPeriodic = ON_IsKnotVectorPeriodic( m_order[dir], m_cv_count[dir], m_knot[dir] );
01488 if ( bIsPeriodic )
01489 {
01490 const double *cv0, *cv1;
01491 int i,j,k,d[3] = {0,0,0};
01492 d[dir] = m_cv_count[dir] - (m_order[dir]-1);
01493 for ( i = 0; i+d[0] < m_cv_count[0]; i++ )
01494 {
01495 for ( j = 0; j+d[1] < m_cv_count[1]; j++ )
01496 {
01497 for ( k = 0; k+d[2] < m_cv_count[2]; k++ )
01498 {
01499 cv0 = CV(i,j,k);
01500 cv1 = CV(i+d[0],j+d[1],k+d[2]);
01501 if ( false == ON_PointsAreCoincident(m_dim, m_is_rat, cv0, cv1 ) )
01502 return false;
01503 }
01504 }
01505 }
01506 }
01507 }
01508 return bIsPeriodic;
01509 }
01510
01511 double* ON_NurbsCage::CV( int i, int j, int k ) const
01512 {
01513
01514 #if defined(ON_DEBUG)
01515 if ( 0 == m_cv )
01516 {
01517 ON_ERROR("ON_NurbsCage::CV - NULL m_cv");
01518 return 0;
01519 }
01520 if ( i < 0 || i >= m_cv_count[0] || j< 0 || j >= m_cv_count[1] || k < 0 || k >= m_cv_count[2])
01521 {
01522 ON_ERROR("ON_NurbsCage::CV - (i,j,k) out of range");
01523 return 0;
01524 }
01525 #endif
01526
01527 return (m_cv) ? (m_cv + i*m_cv_stride[0] + j*m_cv_stride[1] + k*m_cv_stride[2]) : 0;
01528 }
01529
01530 ON::point_style ON_NurbsCage::CVStyle() const
01531 {
01532 return m_is_rat ? ON::homogeneous_rational : ON::not_rational;
01533 }
01534
01535 double ON_NurbsCage::Weight( int i, int j, int k ) const
01536 {
01537 return (m_cv && m_is_rat) ? m_cv[i*m_cv_stride[0] + j*m_cv_stride[1] + k*m_cv_stride[2] + + m_dim] : 1.0;
01538 }
01539
01540
01541 bool ON_NurbsCage::SetWeight( int i, int j, int k, double w )
01542 {
01543 bool rc = false;
01544 if ( m_is_rat )
01545 {
01546 double* cv = CV(i,j,k);
01547 if (cv)
01548 {
01549 cv[m_dim] = w;
01550 rc = true;
01551 }
01552 }
01553 else if ( w == 1.0 )
01554 {
01555 rc = true;
01556 }
01557 return rc;
01558 }
01559
01560 bool ON_NurbsCage::SetCV( int i, int j, int k, ON::point_style style, const double* Point )
01561 {
01562 bool rc = true;
01563 int n;
01564 double w;
01565
01566 double* cv = CV(i,j,k);
01567 if ( !cv )
01568 return false;
01569
01570 switch ( style ) {
01571
01572 case ON::not_rational:
01573 memcpy( cv, Point, m_dim*sizeof(*cv) );
01574 if ( IsRational() ) {
01575
01576 cv[m_dim] = 1.0;
01577 }
01578 break;
01579
01580 case ON::homogeneous_rational:
01581 if ( IsRational() ) {
01582
01583 memcpy( cv, Point, (m_dim+1)*sizeof(*cv) );
01584 }
01585 else {
01586
01587 w = (Point[m_dim] != 0.0) ? 1.0/Point[m_dim] : 1.0;
01588 for ( n = 0; n < m_dim; n++ ) {
01589 cv[n] = w*Point[n];
01590 }
01591 }
01592 break;
01593
01594 case ON::euclidean_rational:
01595 if ( IsRational() ) {
01596
01597 w = Point[m_dim];
01598 for ( n = 0; n < m_dim; n++ )
01599 cv[i] = w*Point[i];
01600 cv[m_dim] = w;
01601 }
01602 else {
01603
01604 memcpy( cv, Point, m_dim*sizeof(*cv) );
01605 }
01606 break;
01607
01608 case ON::intrinsic_point_style:
01609 n = m_is_rat?m_dim+1:m_dim;
01610 memcpy(cv,Point,n*sizeof(*cv));
01611 break;
01612
01613 default:
01614 rc = false;
01615 break;
01616 }
01617 return rc;
01618 }
01619
01620 bool ON_NurbsCage::SetCV( int i, int j, int k, const ON_3dPoint& point )
01621 {
01622 bool rc = false;
01623 double* cv = CV(i,j,k);
01624 if ( cv ) {
01625 cv[0] = point.x;
01626 if ( m_dim > 1 ) {
01627 cv[1] = point.y;
01628 if ( m_dim > 2 )
01629 cv[2] = point.z;
01630 }
01631 if ( m_is_rat ) {
01632 cv[m_dim] = 1.0;
01633 }
01634 rc = true;
01635 }
01636 return rc;
01637 }
01638
01639 bool ON_NurbsCage::SetCV( int i, int j, int k, const ON_4dPoint& point )
01640 {
01641 bool rc = false;
01642 double* cv = CV(i,j,k);
01643 if ( cv ) {
01644 if ( m_is_rat ) {
01645 cv[0] = point.x;
01646 if ( m_dim > 1 ) {
01647 cv[1] = point.y;
01648 if ( m_dim > 2 )
01649 cv[2] = point.z;
01650 }
01651 cv[m_dim] = point.w;
01652 rc = true;
01653 }
01654 else {
01655 double w;
01656 if ( point.w != 0.0 ) {
01657 w = 1.0/point.w;
01658 rc = true;
01659 }
01660 else {
01661 w = 1.0;
01662 }
01663 cv[0] = w*point.x;
01664 if ( m_dim > 1 ) {
01665 cv[1] = w*point.y;
01666 if ( m_dim > 2 ) {
01667 cv[2] = w*point.z;
01668 }
01669 }
01670 }
01671 }
01672 return rc;
01673 }
01674
01675 bool ON_NurbsCage::GetCV( int i, int j, int k, ON::point_style style, double* Point ) const
01676 {
01677 const double* cv = CV(i,j,k);
01678 if ( !cv )
01679 return false;
01680 int dim = Dimension();
01681 double w = ( IsRational() ) ? cv[dim] : 1.0;
01682 switch(style) {
01683 case ON::euclidean_rational:
01684 Point[dim] = w;
01685
01686 case ON::not_rational:
01687 if ( w == 0.0 )
01688 return false;
01689 w = 1.0/w;
01690 while(dim--) *Point++ = *cv++ * w;
01691 break;
01692 case ON::homogeneous_rational:
01693 Point[dim] = w;
01694 memcpy( Point, cv, dim*sizeof(*Point) );
01695 break;
01696 default:
01697 return false;
01698 }
01699 return true;
01700 }
01701
01702 bool ON_NurbsCage::GetCV( int i, int j, int k, ON_3dPoint& point ) const
01703 {
01704 bool rc = false;
01705 const double* cv = CV(i,j,k);
01706 if ( cv ) {
01707 if ( m_is_rat ) {
01708 if (cv[m_dim] != 0.0) {
01709 const double w = 1.0/cv[m_dim];
01710 point.x = cv[0]*w;
01711 point.y = (m_dim>1)? cv[1]*w : 0.0;
01712 point.z = (m_dim>2)? cv[2]*w : 0.0;
01713 rc = true;
01714 }
01715 }
01716 else {
01717 point.x = cv[0];
01718 point.y = (m_dim>1)? cv[1] : 0.0;
01719 point.z = (m_dim>2)? cv[2] : 0.0;
01720 rc = true;
01721 }
01722 }
01723 return rc;
01724 }
01725
01726 bool ON_NurbsCage::GetCV( int i, int j, int k, ON_4dPoint& point ) const
01727 {
01728 bool rc = false;
01729 const double* cv = CV(i,j,k);
01730 if ( cv ) {
01731 point.x = cv[0];
01732 point.y = (m_dim>1)? cv[1] : 0.0;
01733 point.z = (m_dim>2)? cv[2] : 0.0;
01734 point.w = (m_is_rat) ? cv[m_dim] : 1.0;
01735 rc = true;
01736 }
01737 return rc;
01738 }
01739
01740
01741
01742 bool ON_NurbsCage::SetKnot(
01743 int dir,
01744 int knot_index,
01745 double knot_value
01746 )
01747 {
01748 bool rc;
01749
01750
01751
01752
01753 if ( dir >= 0 && dir < 3
01754 && 0 != m_knot[dir]
01755 && knot_index >= 0
01756 && knot_index < m_order[dir]+m_cv_count[dir]-2
01757 )
01758 {
01759 m_knot[dir][knot_index] = knot_value;
01760 rc = true;
01761 }
01762 else
01763 {
01764 ON_ERROR("ON_NurbsCage::SetKnot - invalid input parameters");
01765 rc = false;
01766 }
01767 return rc;
01768 }
01769
01770 double ON_NurbsCage::Knot(
01771 int dir,
01772 int knot_index
01773 ) const
01774 {
01775 double knot_value;
01776
01777
01778
01779
01780 if ( dir >= 0 && dir < 3
01781 && 0 != m_knot[dir]
01782 && knot_index >= 0
01783 && knot_index < m_order[dir]+m_cv_count[dir]-2
01784 )
01785 {
01786 knot_value = m_knot[dir][knot_index];
01787 }
01788 else
01789 {
01790 ON_ERROR("ON_NurbsCage::Knot - invalid input parameters");
01791 knot_value = ON_UNSET_VALUE;
01792 }
01793 return knot_value;
01794 }
01795
01796 bool ON_NurbsCage::ZeroCVs()
01797 {
01798
01799 bool rc = false;
01800 int i,j,k;
01801 if ( m_cv ) {
01802 if ( m_cv_capacity > 0 ) {
01803 memset( m_cv, 0, m_cv_capacity*sizeof(*m_cv) );
01804 if ( m_is_rat ) {
01805 for ( i = 0; i < m_order[0]; i++ ) {
01806 for ( j = 0; j < m_order[1]; j++ ) {
01807 for ( k = 0; k < m_order[2]; k++ ) {
01808 SetWeight( i,j,k, 1.0 );
01809 }
01810 }
01811 }
01812 }
01813 rc = true;
01814 }
01815 else {
01816 double* cv;
01817 int s = CVSize()*sizeof(*cv);
01818 for ( i = 0; i < m_order[0]; i++ ) {
01819 for ( j = 0; j < m_order[1]; j++ ) {
01820 for ( k = 0; k < m_order[2]; k++ ) {
01821 cv = CV(i,j,k);
01822 memset(cv,0,s);
01823 if ( m_is_rat )
01824 cv[m_dim] = 1.0;
01825 }
01826 }
01827 }
01828 rc = (i>0) ? true : false;
01829 }
01830 }
01831 return rc;
01832 }
01833
01834 bool ON_NurbsCage::MakeRational()
01835 {
01836 if ( !IsRational() )
01837 {
01838 const int dim = Dimension();
01839 if ( m_cv_count[0] > 0 && m_cv_count[1] > 0 && m_cv_count[2] > 0 && dim > 0 )
01840 {
01841 int i,j,k;
01842 if ( m_cv_stride[0] <= dim || m_cv_stride[1] <= dim || m_cv_stride[2] <= dim )
01843 {
01844
01845 double* new_cv = (double*)onmalloc(m_cv_count[0]*m_cv_count[1]*m_cv_count[2]*(dim+1)*sizeof(*new_cv));
01846 double* cv1 = new_cv;
01847 const int sizeofoldcv = dim*sizeof(*cv1);
01848 for (i = 0; i < m_cv_count[0]; i++)
01849 {
01850 for(j = 0; j < m_cv_count[1]; j++)
01851 {
01852 for(k = 0; k < m_cv_count[2]; k++)
01853 {
01854 memcpy(cv1,CV(i,j,k),sizeofoldcv);
01855 cv1 += dim;
01856 *cv1++ = 1.0;
01857 }
01858 }
01859 }
01860 m_is_rat = 1;
01861 ReserveCVCapacity(m_cv_count[0]*m_cv_count[1]*m_cv_count[2]*(dim+1));
01862 memcpy(m_cv,new_cv,m_cv_count[0]*m_cv_count[1]*m_cv_count[2]*(dim+1)*sizeof(*m_cv));
01863 onfree(new_cv);
01864 m_cv_stride[2] = dim+1;
01865 m_cv_stride[1] = m_cv_stride[2]*m_cv_count[2];
01866 m_cv_stride[0] = m_cv_stride[1]*m_cv_count[1];
01867 }
01868 else
01869 {
01870
01871 for (i = 0; i < m_cv_count[0]; i++)
01872 {
01873 for(j = 0; j < m_cv_count[1]; j++)
01874 {
01875 for(k = 0; k < m_cv_count[2]; k++)
01876 {
01877 CV(i,j,k)[dim] = 1.0;
01878 }
01879 }
01880 }
01881 m_is_rat = 1;
01882 }
01883 }
01884 }
01885 return IsRational();
01886 }
01887
01888 bool ON_NurbsCage::MakeNonRational()
01889 {
01890 if ( IsRational() && m_dim > 0 )
01891 {
01892 int i,j,k,n;
01893 double* cv;
01894 double w;
01895
01896 for (i = 0; i < m_cv_count[0]; i++)
01897 for (j = 0; j < m_cv_count[1]; j++)
01898 for (k = 0; k < m_cv_count[2]; k++)
01899 {
01900 cv = CV(i,j,k);
01901 w = cv[m_dim];
01902 if ( w != 1.0 && w != 0.0 )
01903 {
01904 w = 1.0/w;
01905 n = m_dim;
01906 while(n--)
01907 {
01908 *cv++ *= w;
01909 }
01910 *cv = 1.0;
01911 }
01912 }
01913
01914 m_is_rat = 0;
01915 }
01916 return ( IsRational() ) ? false : true;
01917 }
01918
01920
01921 bool ON_NurbsCage::ReserveCVCapacity(
01922 int capacity
01923 )
01924 {
01925 if ( capacity > 0 && m_cv_capacity < capacity )
01926 {
01927 if ( m_cv )
01928 {
01929 if ( m_cv_capacity )
01930 {
01931 m_cv = (double*)onrealloc( m_cv, capacity*sizeof(*m_cv) );
01932 m_cv_capacity = (m_cv) ? capacity : 0;
01933 }
01934
01935 }
01936 else
01937 {
01938 m_cv = (double*)onmalloc( capacity*sizeof(*m_cv) );
01939 m_cv_capacity = (m_cv) ? capacity : 0;
01940 }
01941 }
01942 return ( m_cv ) ? true : false;
01943 }
01944
01945 bool ON_NurbsCage::ReserveKnotCapacity(
01946 int dir,
01947 int knot_capacity
01948 )
01949 {
01950 bool rc = false;
01951 if ( dir >= 0 && dir <= 2 && knot_capacity > 0 )
01952 {
01953 if ( m_knot_capacity[dir] < knot_capacity )
01954 {
01955 if ( m_knot[dir] )
01956 {
01957 if( m_knot_capacity[dir] )
01958 {
01959 m_knot[dir] = (double*)onrealloc(m_knot[dir],knot_capacity*sizeof(m_knot[dir][0]));
01960 m_knot_capacity[dir] = m_knot[dir] ? knot_capacity : 0;
01961 }
01962
01963 }
01964 else
01965 {
01966 m_knot[dir] = (double*)onmalloc(knot_capacity*sizeof(m_knot[dir][0]));
01967 m_knot_capacity[dir] = m_knot[dir] ? knot_capacity : 0;
01968 }
01969 }
01970 rc = m_knot[dir] != 0;
01971 }
01972 return rc;
01973 }
01974
01975
01976
01977 bool ON_NurbsCage::IsSingular(
01978 int
01979
01980 ) const
01981 {
01982 ON_ERROR("TODO: fill in ON_NurbsCage::IsSingular\n");
01983 return false;
01984 }
01985
01986 bool ON_GetCageXform( const ON_NurbsCage& cage, ON_Xform& cage_xform )
01987 {
01988 bool rc = false;
01989 cage_xform.Identity();
01990 if ( cage.IsValid() )
01991 {
01992 ON_3dPoint P000, P100, P010, P001;
01993 if ( !cage.GetCV(0,0,0,P000) )
01994 return false;
01995 if ( !cage.GetCV(cage.CVCount(0)-1,0,0,P100))
01996 return false;
01997 if (!cage.GetCV(0,cage.CVCount(1)-1,0,P010))
01998 return false;
01999 if (!cage.GetCV(0,0,cage.CVCount(2)-1,P001))
02000 return false;
02001
02002 ON_3dVector X0 = P100 - P000;
02003 ON_3dVector Y0 = P010 - P000;
02004 ON_3dVector Z0 = P001 - P000;
02005
02006 double dx0 = X0.Length();
02007 double dy0 = Y0.Length();
02008 double dz0 = Z0.Length();
02009
02010 ON_Interval d0 = cage.Domain(0);
02011 ON_Interval d1 = cage.Domain(1);
02012 ON_Interval d2 = cage.Domain(2);
02013
02014 X0.Unitize();
02015 Y0.Unitize();
02016 Z0.Unitize();
02017
02018 ON_Xform x1;
02019 x1.Rotation(
02020 P000, X0, Y0, Z0,
02021 ON_origin, ON_xaxis, ON_yaxis, ON_zaxis
02022 );
02023
02024 ON_Xform x2;
02025 x2.Scale( d0.Length()/dx0, d1.Length()/dy0, d2.Length()/dz0 );
02026
02027 ON_Xform x3;
02028 x3.Translation( d0[0],d1[0],d2[0]);
02029
02030
02031 cage_xform = x3*(x2*x1);
02032 rc = true;
02033 }
02034 return rc;
02035 }
02036
02037 ON_CageMorph::ON_CageMorph()
02038 {
02039 m_control = 0;
02040 }
02041
02042 ON_CageMorph::~ON_CageMorph()
02043 {
02044 m_control = 0;
02045 }
02046
02047 bool ON_MorphControl::IsIdentity( const ON_BoundingBox& bbox ) const
02048 {
02049 int i, count = m_localizers.Count();
02050 bool rc = (count > 0);
02051 for (i = 0; i < count && rc; i++ )
02052 {
02053 rc = m_localizers[i].IsZero(bbox);
02054 }
02055 return rc;
02056 }
02057
02058 bool ON_CageMorph::IsIdentity( const ON_BoundingBox& bbox ) const
02059 {
02060 return m_control ? m_control->IsIdentity(bbox) : true;
02061 }
02062
02063 ON_MorphControl::ON_MorphControl()
02064 : m_varient(0),
02065 m_nurbs_cage0(1.0)
02066 {
02067 m_sporh_tolerance = 0.0;
02068 m_sporh_bQuickPreview = false;
02069 m_sporh_bPreserveStructure = false;
02070 }
02071
02072
02073 ON_MorphControl::~ON_MorphControl()
02074 {
02075 }
02076
02077 void ON_MorphControl::Destroy()
02078 {
02079 m_varient = 0;
02080 m_nurbs_cage0.Identity();
02081 m_nurbs_curve0.Destroy();
02082 m_nurbs_curve.Destroy();
02083 m_nurbs_curve_domain.Destroy();
02084 m_nurbs_surface0.Destroy();
02085 m_nurbs_surface.Destroy();
02086 m_nurbs_surface_domain[0].Destroy();
02087 m_nurbs_surface_domain[1].Destroy();
02088 m_nurbs_cage.Destroy();
02089 m_captive_id.Empty();
02090 m_localizers.Destroy();
02091 m_sporh_tolerance = 0.0;
02092 m_sporh_bQuickPreview = false;
02093 m_sporh_bPreserveStructure = false;
02094 }
02095
02096
02097 void ON_MorphControl::MemoryRelocate()
02098 {
02099 m_nurbs_curve0.MemoryRelocate();
02100 m_nurbs_curve.MemoryRelocate();
02101 m_nurbs_surface0.MemoryRelocate();
02102 m_nurbs_surface.MemoryRelocate();
02103 m_nurbs_cage.MemoryRelocate();
02104 ON_Geometry::MemoryRelocate();
02105 }
02106
02107 ON_BOOL32 ON_MorphControl::IsValid( ON_TextLog* text_log ) const
02108 {
02109 ON_BOOL32 rc = false;
02110 switch(m_varient)
02111 {
02112 case 1:
02113 rc = m_nurbs_curve0.IsValid(text_log);
02114 if (rc)
02115 rc = m_nurbs_curve.IsValid(text_log);
02116 break;
02117
02118 case 2:
02119 rc = m_nurbs_surface0.IsValid(text_log);
02120 if (rc)
02121 rc = m_nurbs_surface.IsValid(text_log);
02122 break;
02123
02124 case 3:
02125 rc = m_nurbs_cage.IsValid(text_log);
02126 break;
02127
02128 default:
02129 rc = false;
02130 if ( text_log )
02131 {
02132 text_log->Print("m_varient = %d - should be 1, 2, or 3\n",m_varient);
02133 }
02134 break;
02135 }
02136 return rc;
02137 }
02138
02139 void ON_MorphControl::Dump( ON_TextLog& text_log ) const
02140 {
02141 text_log.Print("Varient: %d\n",m_varient);
02142 text_log.Print("Control object:\n");
02143 text_log.PushIndent();
02144 switch(m_varient)
02145 {
02146 case 1:
02147 m_nurbs_curve0.Dump(text_log);
02148 m_nurbs_curve.Dump(text_log);
02149 break;
02150 case 2:
02151 m_nurbs_surface0.Dump(text_log);
02152 m_nurbs_surface.Dump(text_log);
02153 break;
02154 case 3:
02155 text_log.Print(m_nurbs_cage0);
02156 m_nurbs_cage.Dump(text_log);
02157 break;
02158 }
02159 text_log.PopIndent();
02160 }
02161
02162 unsigned int ON_MorphControl::SizeOf() const
02163 {
02164 unsigned int sz = sizeof(*this)
02165 - 2*sizeof(ON_NurbsCurve)
02166 - 2*sizeof(ON_NurbsSurface)
02167 - sizeof(m_nurbs_cage);
02168 sz += m_nurbs_curve0.SizeOf();
02169 sz += m_nurbs_curve.SizeOf();
02170 sz += m_nurbs_surface0.SizeOf();
02171 sz += m_nurbs_surface.SizeOf();
02172 sz += m_nurbs_cage.SizeOf();
02173 sz += m_localizers.SizeOfArray();
02174
02175 return sz;
02176 }
02177
02178
02179 ON::object_type ON_MorphControl::ObjectType() const
02180 {
02181 return ON::morph_control_object;
02182 }
02183
02184 void ON_MorphControl::DestroyRuntimeCache( bool bDelete )
02185 {
02186 m_nurbs_curve.DestroyRuntimeCache(bDelete);
02187 m_nurbs_surface.DestroyRuntimeCache(bDelete);
02188 m_nurbs_cage.DestroyRuntimeCache(bDelete);
02189 }
02190
02191 int ON_MorphControl::Dimension() const
02192 {
02193 int dim = 0;
02194 switch(m_varient)
02195 {
02196 case 1:
02197 dim = m_nurbs_curve.Dimension();
02198 break;
02199 case 2:
02200 dim = m_nurbs_surface.Dimension();
02201 break;
02202 case 3:
02203 dim = m_nurbs_cage.Dimension();
02204 break;
02205 }
02206 return dim;
02207 }
02208
02209 ON_BOOL32 ON_MorphControl::GetBBox(
02210 double* boxmin,
02211 double* boxmax,
02212 int bGrowBox
02213 ) const
02214 {
02215 ON_BOOL32 rc = false;
02216 switch(m_varient)
02217 {
02218 case 1:
02219 rc = m_nurbs_curve.GetBBox(boxmin,boxmax,bGrowBox);
02220 break;
02221 case 2:
02222 rc = m_nurbs_surface.GetBBox(boxmin,boxmax,bGrowBox);
02223 break;
02224 case 3:
02225 rc = m_nurbs_cage.GetBBox(boxmin,boxmax,bGrowBox);
02226 break;
02227 }
02228 return rc;
02229 }
02230
02231 bool ON_MorphControl::GetTightBoundingBox(
02232 ON_BoundingBox& tight_bbox,
02233 int bGrowBox,
02234 const ON_Xform* xform
02235 ) const
02236 {
02237 bool rc = false;
02238 switch(m_varient)
02239 {
02240 case 1:
02241 rc = m_nurbs_curve.GetTightBoundingBox(tight_bbox,bGrowBox);
02242 break;
02243 case 2:
02244 rc = m_nurbs_surface.GetTightBoundingBox(tight_bbox,bGrowBox);
02245 break;
02246 case 3:
02247 rc = m_nurbs_cage.GetTightBoundingBox(tight_bbox,bGrowBox);
02248 break;
02249 }
02250 return rc;
02251 }
02252
02253 void ON_MorphControl::ClearBoundingBox()
02254 {
02255 }
02256
02257 ON_BOOL32 ON_MorphControl::Transform(
02258 const ON_Xform& xform
02259 )
02260 {
02261 ON_BOOL32 rc = false;
02262
02263 switch(m_varient)
02264 {
02265 case 1:
02266 rc = m_nurbs_curve.Transform(xform);
02267 break;
02268
02269 case 2:
02270 rc = m_nurbs_surface.Transform(xform);
02271 break;
02272
02273 case 3:
02274 rc = m_nurbs_cage.Transform(xform);
02275 break;
02276 }
02277
02278 return rc;
02279 }
02280
02281 ON_BOOL32 ON_MorphControl::HasBrepForm() const
02282 {
02283 ON_BOOL32 rc = false;
02284
02285 switch(m_varient)
02286 {
02287 case 1:
02288 rc = m_nurbs_curve.HasBrepForm();
02289 break;
02290
02291 case 2:
02292 rc = m_nurbs_surface.HasBrepForm();
02293 break;
02294
02295 case 3:
02296 rc = m_nurbs_cage.HasBrepForm();
02297 break;
02298 }
02299
02300 return rc;
02301 }
02302
02303 ON_Brep* ON_MorphControl::BrepForm( ON_Brep* brep ) const
02304 {
02305 switch(m_varient)
02306 {
02307 case 1:
02308 brep = m_nurbs_curve.BrepForm(brep);
02309 break;
02310
02311 case 2:
02312 brep = m_nurbs_surface.BrepForm(brep);
02313 break;
02314
02315 case 3:
02316 brep = m_nurbs_cage.BrepForm(brep);
02317 break;
02318
02319 default:
02320 brep = 0;
02321 break;
02322 }
02323
02324 return brep;
02325 }
02326
02327
02328 bool ON_MorphControl::IsRational() const
02329 {
02330 bool rc = false;
02331 switch(m_varient)
02332 {
02333 case 1:
02334 rc = m_nurbs_curve.IsRational();
02335 break;
02336 case 2:
02337 rc = m_nurbs_surface.IsRational();
02338 break;
02339 case 3:
02340 rc = m_nurbs_cage.IsRational();
02341 break;
02342 }
02343 return rc;
02344 }
02345
02346 bool ON_MorphControl::MakeRational()
02347 {
02348 bool rc = false;
02349 switch(m_varient)
02350 {
02351 case 1:
02352 rc = m_nurbs_curve.MakeRational();
02353 break;
02354 case 2:
02355 rc = m_nurbs_surface.MakeRational();
02356 break;
02357 case 3:
02358 rc = m_nurbs_cage.MakeRational();
02359 break;
02360 }
02361 return rc;
02362 }
02363
02364 bool ON_MorphControl::MakeNonRational()
02365 {
02366 bool rc = false;
02367 switch(m_varient)
02368 {
02369 case 1:
02370 rc = m_nurbs_curve.MakeNonRational();
02371 break;
02372 case 2:
02373 rc = m_nurbs_surface.MakeNonRational();
02374 break;
02375 case 3:
02376 rc = m_nurbs_cage.MakeNonRational();
02377 break;
02378 }
02379 return rc;
02380 }
02381
02382 int ON_MorphControl::CVCount() const
02383 {
02384 int rc = 0;
02385 switch(m_varient)
02386 {
02387 case 1:
02388 rc = m_nurbs_curve.CVCount();
02389 break;
02390 case 2:
02391 rc = m_nurbs_surface.CVCount();
02392 break;
02393 case 3:
02394 rc = m_nurbs_cage.CVCount();
02395 break;
02396 }
02397 return rc;
02398 }
02399
02400 int ON_MorphControl::CVCount(int dir) const
02401 {
02402 int rc = 0;
02403 switch(m_varient)
02404 {
02405 case 1:
02406 rc = (0==dir) ? m_nurbs_curve.CVCount() : 0;
02407 break;
02408 case 2:
02409 rc = m_nurbs_surface.CVCount(dir);
02410 break;
02411 case 3:
02412 rc = m_nurbs_cage.CVCount(dir);
02413 break;
02414 }
02415 return rc;
02416 }
02417
02418 int ON_MorphControl::Order(int dir) const
02419 {
02420 int rc = 0;
02421 switch(m_varient)
02422 {
02423 case 1:
02424 rc = (0==dir) ? m_nurbs_curve.Order() : 0;
02425 break;
02426 case 2:
02427 rc = m_nurbs_surface.Order(dir);
02428 break;
02429 case 3:
02430 rc = m_nurbs_cage.Order(dir);
02431 break;
02432 }
02433 return rc;
02434 }
02435
02436 ON_3dex ON_MorphControl::MaxCVIndex() const
02437 {
02438 ON_3dex maxdex;
02439 maxdex.i = maxdex.j = maxdex.k = 0;
02440 switch(m_varient)
02441 {
02442 case 1:
02443 maxdex.i = m_nurbs_curve.CVCount();
02444 maxdex.j = maxdex.k = 1;
02445 break;
02446 case 2:
02447 maxdex.i = m_nurbs_surface.CVCount(0);
02448 maxdex.j = m_nurbs_surface.CVCount(1);
02449 maxdex.k = 1;
02450 break;
02451 case 3:
02452 maxdex.i = m_nurbs_cage.CVCount(0);
02453 maxdex.j = m_nurbs_cage.CVCount(1);
02454 maxdex.k = m_nurbs_cage.CVCount(2);
02455 break;
02456 }
02457 return maxdex;
02458 }
02459
02460 const double* ON_MorphControl::Knot(int dir) const
02461 {
02462 const double* knot = 0;
02463
02464 switch(m_varient)
02465 {
02466 case 1:
02467 knot = (0 == dir) ? m_nurbs_curve.m_knot : 0;
02468 break;
02469 case 2:
02470 knot = (0 == dir || 1 == dir) ? m_nurbs_surface.m_knot[dir] : 0;
02471 break;
02472 case 3:
02473 knot = (0 <= dir && dir <= 2) ? m_nurbs_cage.m_knot[dir] : 0;
02474 break;
02475 }
02476
02477 return knot;
02478 }
02479
02480 const double* ON_MorphControl::CV(ON_3dex ijk) const
02481 {
02482 const double* cv = 0;
02483 switch(m_varient)
02484 {
02485 case 1:
02486 cv = (0 == ijk.j && 0 == ijk.k) ? m_nurbs_curve.CV(ijk.i) : 0;
02487 break;
02488 case 2:
02489 cv = (0 == ijk.k) ? m_nurbs_surface.CV(ijk.i,ijk.j) : 0;
02490 break;
02491 case 3:
02492 cv = m_nurbs_cage.CV(ijk.i,ijk.j,ijk.k);
02493 break;
02494 }
02495 return cv;
02496 }
02497
02498 double ON_MorphControl::Weight(ON_3dex ijk) const
02499 {
02500 double w = 1.0;
02501
02502 switch(m_varient)
02503 {
02504 case 1:
02505 w = (0 == ijk.j && 0 == ijk.k) ? m_nurbs_curve.Weight(ijk.i) : 1.0;
02506 break;
02507 case 2:
02508 w = (0 == ijk.k) ? m_nurbs_surface.Weight(ijk.i,ijk.j) : 1.0;
02509 break;
02510 case 3:
02511 w = m_nurbs_cage.Weight(ijk.i,ijk.j,ijk.k);
02512 break;
02513 }
02514
02515 return w;
02516 }
02517
02518 bool ON_MorphControl::GetCageMorph(ON_CageMorph& cage_morph) const
02519 {
02520 cage_morph.m_control = this;
02521 cage_morph.SetPreserveStructure(m_sporh_bPreserveStructure);
02522 cage_morph.SetQuickPreview(m_sporh_bQuickPreview);
02523 cage_morph.SetTolerance(m_sporh_tolerance);
02524 return true;
02525 }
02526
02527 ON_BOOL32 ON_MorphControl::Read( ON_BinaryArchive& archive )
02528 {
02529 Destroy();
02530 int major_version = 0;
02531 int minor_version = 0;
02532 bool rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,
02533 &major_version,
02534 &minor_version);
02535 while(rc)
02536 {
02537 if ( 1 == major_version )
02538 {
02539 m_varient = 3;
02540 if (rc)
02541 rc = m_nurbs_cage.Read(archive)?true:false;
02542 if (rc)
02543 rc = m_captive_id.Read(archive);
02544 if (rc)
02545 rc = archive.ReadXform(m_nurbs_cage0);
02546 }
02547 else if ( 2 == major_version )
02548 {
02549 rc = archive.ReadInt(&m_varient);
02550 if (!rc) break;
02551
02552 int mjv = 0;
02553 int mnv = 0;
02554 rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&mjv,&mnv);
02555 if (!rc) break;
02556 rc = (1 == mjv);
02557 if (rc)
02558 {
02559 switch(m_varient)
02560 {
02561 case 1:
02562 rc = m_nurbs_curve0.Read(archive)?true:false;
02563 if (rc)
02564 m_nurbs_curve_domain = m_nurbs_curve0.Domain();
02565 break;
02566 case 2:
02567 rc = m_nurbs_surface0.Read(archive)?true:false;
02568 if (rc)
02569 {
02570 m_nurbs_surface_domain[0] = m_nurbs_surface0.Domain(0);
02571 m_nurbs_surface_domain[1] = m_nurbs_surface0.Domain(1);
02572 }
02573 break;
02574 case 3:
02575 rc = archive.ReadXform(m_nurbs_cage0);
02576 break;
02577 }
02578 }
02579 if ( !archive.EndRead3dmChunk() )
02580 rc = false;
02581
02582 if(!rc)
02583 break;
02584
02585 mjv = 0;
02586 mnv = 0;
02587 rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&mjv,&mnv);
02588 if (!rc) break;
02589 rc = (1 == mjv);
02590 if (rc)
02591 {
02592 switch(m_varient)
02593 {
02594 case 1:
02595 rc = m_nurbs_curve.Read(archive)?true:false;
02596 break;
02597 case 2:
02598 rc = m_nurbs_surface.Read(archive)?true:false;
02599 break;
02600 case 3:
02601 rc = m_nurbs_cage.Read(archive)?true:false;
02602 break;
02603 }
02604 }
02605 if ( !archive.EndRead3dmChunk() )
02606 rc = false;
02607
02608
02609 rc = m_captive_id.Read(archive);
02610 if (!rc)
02611 break;
02612
02613
02614 mjv = 0;
02615 mnv = 0;
02616 rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&mjv,&mnv);
02617 if (!rc)
02618 break;
02619 int i, count = 0;
02620 rc = (1 == mjv);
02621 if (rc)
02622 rc = archive.ReadInt(&count);
02623 if (rc)
02624 m_localizers.Reserve(count);
02625 for ( i = 0; i < count && rc; i++ )
02626 {
02627 m_localizers.AppendNew();
02628 rc = m_localizers[i].Read(archive);
02629 }
02630 if ( !archive.EndRead3dmChunk() )
02631 rc = false;
02632 if ( !rc)
02633 break;
02634
02635 if ( minor_version >= 1 )
02636 {
02637 rc = archive.ReadDouble(&m_sporh_tolerance);
02638 if (!rc)
02639 break;
02640 rc = archive.ReadBool(&m_sporh_bQuickPreview);
02641 if (!rc)
02642 break;
02643 rc = archive.ReadBool(&m_sporh_bPreserveStructure);
02644 if (!rc)
02645 break;
02646 }
02647 }
02648 else
02649 {
02650 rc = false;
02651 }
02652
02653 if ( !archive.EndRead3dmChunk() )
02654 rc = false;
02655 break;
02656 }
02657
02658 return rc;
02659 }
02660
02661 ON_BOOL32 ON_MorphControl::Write( ON_BinaryArchive& archive ) const
02662 {
02663 bool rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,2,1);
02664 if (!rc)
02665 return false;
02666
02667 while(rc)
02668 {
02669 rc = archive.WriteInt(m_varient);
02670 if (!rc) break;
02671
02672
02673 rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0);
02674 if (!rc) break;
02675 switch(m_varient)
02676 {
02677 case 1:
02678 rc = m_nurbs_curve0.Write(archive)?true:false;
02679 break;
02680 case 2:
02681 rc = m_nurbs_surface0.Write(archive)?true:false;
02682 break;
02683 case 3:
02684 rc = archive.WriteXform(m_nurbs_cage0);
02685 break;
02686 }
02687 if ( !archive.EndWrite3dmChunk() )
02688 rc = false;
02689
02690 if(!rc)
02691 break;
02692
02693
02694 rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0);
02695 if (!rc) break;
02696 switch(m_varient)
02697 {
02698 case 1:
02699 rc = m_nurbs_curve.Write(archive)?true:false;
02700 break;
02701 case 2:
02702 rc = m_nurbs_surface.Write(archive)?true:false;
02703 break;
02704 case 3:
02705 rc = m_nurbs_cage.Write(archive)?true:false;
02706 break;
02707 }
02708 if ( !archive.EndWrite3dmChunk() )
02709 rc = false;
02710
02711 if ( !rc)
02712 break;
02713
02714
02715 rc = m_captive_id.Write(archive);
02716 if (!rc)
02717 break;
02718
02719
02720 rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0);
02721 if (!rc)
02722 break;
02723 int i, count = m_localizers.Count();
02724 rc = archive.WriteInt(count);
02725 for ( i = 0; i < count && rc; i++ )
02726 {
02727 rc = m_localizers[i].Write(archive);
02728 }
02729 if ( !archive.EndWrite3dmChunk() )
02730 rc = false;
02731 if ( !rc)
02732 break;
02733
02734
02735 rc = archive.WriteDouble(m_sporh_tolerance);
02736 if (!rc)
02737 break;
02738 rc = archive.WriteBool(m_sporh_bQuickPreview);
02739 if (!rc)
02740 break;
02741 rc = archive.WriteBool(m_sporh_bPreserveStructure);
02742 if (!rc)
02743 break;
02744
02745 break;
02746 }
02747
02748 if ( !archive.EndWrite3dmChunk() )
02749 rc = false;
02750
02751 return rc;
02752 }
02753
02754 bool ON_MorphControl::AddControlLocalizer(
02755 double support_distance,
02756 double falloff_distance
02757 )
02758 {
02759 bool rc = (support_distance >= 0.0 && falloff_distance > 0.0 );
02760 if (rc)
02761 {
02762 switch(m_varient)
02763 {
02764 case 1:
02765 case 2:
02766 {
02767 ON_Localizer& localizer = m_localizers.AppendNew();
02768 localizer.m_type = ON_Localizer::distance_type;
02769 localizer.m_d.Set(support_distance+falloff_distance,support_distance);
02770 rc = true;
02771 }
02772 break;
02773
02774 case 3:
02775 {
02776 ON_Xform xform = m_nurbs_cage0;
02777 xform.Invert();
02778 ON_Interval d[3];
02779 d[0] = m_nurbs_cage.Domain(0);
02780 d[1] = m_nurbs_cage.Domain(1);
02781 d[2] = m_nurbs_cage.Domain(2);
02782
02783 ON_SimpleArray<ON_Plane> planes(6);
02784
02785 ON_3dPoint C(d[0].ParameterAt(0.5),d[1].ParameterAt(0.5),d[2].ParameterAt(0.5));
02786 ON_3dPoint P;
02787 ON_3dVector N;
02788 int i;
02789 double det = (xform.Determinant() < 0.0) ? -1.0 : 1.0;
02790 for ( i = 0; i < 3; i++ )
02791 {
02792 P = C;
02793 N.Zero();
02794
02795 N[i] = -det;
02796 P[i] = d[i][0];
02797 ON_Plane& plane0 = planes.AppendNew();
02798 plane0.CreateFromNormal(P,N);
02799 plane0.Transform(xform);
02800
02801 P[i] = d[i][1];
02802 N[i] = det;
02803 ON_Plane& plane1 = planes.AppendNew();
02804 plane1.CreateFromNormal(P,N);
02805 plane1.Transform(xform);
02806 }
02807
02808 rc = AddConvexPolygonLocalizer(planes,support_distance,falloff_distance);
02809 }
02810 break;
02811
02812 default:
02813 rc = false;
02814 break;
02815 }
02816 }
02817 return rc;
02818 }
02819
02820 bool ON_MorphControl::AddSphereLocalizer(
02821 ON_3dPoint center,
02822 double support_distance,
02823 double falloff_distance
02824 )
02825 {
02826 bool rc = (center.IsValid() && support_distance >= 0.0 && falloff_distance > 0.0 );
02827 if (rc)
02828 {
02829 ON_Localizer& localizer = m_localizers.AppendNew();
02830 rc = localizer.CreateSphereLocalizer(
02831 center,
02832 support_distance+falloff_distance,
02833 support_distance);
02834 }
02835 return rc;
02836 }
02837
02838 bool ON_MorphControl::AddCylinderLocalizer(
02839 ON_Line axis,
02840 double support_distance,
02841 double falloff_distance
02842 )
02843 {
02844 bool rc = (axis.IsValid() && support_distance >= 0.0 && falloff_distance > 0.0 );
02845 if (rc)
02846 {
02847 ON_Localizer& localizer = m_localizers.AppendNew();
02848 rc = localizer.CreateCylinderLocalizer(
02849 axis.from,axis.Tangent(),
02850 support_distance+falloff_distance,
02851 support_distance);
02852 }
02853 return rc;
02854 }
02855
02856 bool ON_MorphControl::AddBoxLocalizer(
02857 ON_BoundingBox bbox,
02858 double support_distance,
02859 double falloff_distance
02860 )
02861 {
02862 ON_SimpleArray<ON_Plane> planes(6);
02863 bool rc = (bbox.IsValid() && support_distance >= 0.0 && falloff_distance > 0.0 );
02864 if (rc)
02865 {
02866 ON_3dPoint C = bbox.Center();
02867 ON_3dVector N;
02868 ON_3dPoint P;
02869 int i;
02870 for ( i = 0; i < 3; i++ )
02871 {
02872 P = C;
02873 N.Zero();
02874 ON_Plane& plane0 = planes.AppendNew();
02875 P[i] = bbox.m_min[i];
02876 N[i] = -1.0;
02877 plane0.CreateFromNormal(P,N);
02878
02879 ON_Plane& plane1 = planes.AppendNew();
02880 P[i] = bbox.m_max[i];
02881 N[i] = 1.0;
02882 plane1.CreateFromNormal(P,N);
02883 }
02884 rc = AddConvexPolygonLocalizer(planes,support_distance,falloff_distance);
02885 }
02886 return rc;
02887 }
02888
02889 bool ON_MorphControl::AddPlaneLocalizer(
02890 const ON_Plane& plane,
02891 double support_distance,
02892 double falloff_distance
02893 )
02894 {
02895 ON_SimpleArray<ON_Plane> planes(1);
02896 planes.Append(plane);
02897 return AddConvexPolygonLocalizer(planes,support_distance,falloff_distance);
02898 }
02899
02900 bool ON_MorphControl::AddConvexPolygonLocalizer(
02901 const ON_SimpleArray<ON_Plane>& planes,
02902 double support_distance,
02903 double falloff_distance
02904 )
02905 {
02906 int i, count = planes.Count();
02907 bool rc = (support_distance >= 0.0 && falloff_distance > 0.0 );
02908 if (rc)
02909 {
02910 m_localizers.Reserve(m_localizers.Count() + count);
02911 for( i = 0; i < count && rc; i++)
02912 {
02913 const ON_Plane& plane = planes[i];
02914 ON_Localizer& localizer = m_localizers.AppendNew();
02915 rc = localizer.CreatePlaneLocalizer(
02916 plane.origin,plane.zaxis,
02917 support_distance+falloff_distance,
02918 support_distance);
02919 }
02920 }
02921 return rc;
02922 }
02923