opennurbs_beziervolume.cpp
Go to the documentation of this file.
00001 /* $NoKeywords: $ */
00002 /*
00003 //
00004 // Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved.
00005 // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
00006 // McNeel & Associates.
00007 //
00008 // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
00009 // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
00010 // MERCHANTABILITY ARE HEREBY DISCLAIMED.
00011 //                              
00012 // For complete openNURBS copyright information see <http://www.opennurbs.org>.
00013 //
00015 */
00016 
00017 #include "pcl/surface/3rdparty/opennurbs/opennurbs.h"
00018 
00019 bool ON_BezierCage::Read(ON_BinaryArchive& archive)
00020 {
00021   Destroy();
00022 
00023   int major_version = 0;
00024   int minor_version = 0;
00025   bool rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
00026   if ( rc )
00027   {
00028     while(rc)
00029     {
00030       if ( major_version != 1 )
00031       {
00032         ON_ERROR("ON_BezierCage::Read - old code unable to read new version of chunk");
00033         rc = false;
00034         break;
00035       }
00036 
00037       int dim=0,order0=0,order1=0,order2=0;
00038       bool is_rat=false;
00039 
00040       rc = archive.ReadInt(&dim);
00041       if (!rc)
00042         break;
00043       if (dim < 1 || dim > 10000)
00044       {
00045         ON_ERROR("ON_BezierCage::Read - invalid dim");
00046         rc=false;
00047         break;
00048       }
00049 
00050       rc = archive.ReadBool(&is_rat);
00051       if (!rc)
00052         break;
00053 
00054       rc = archive.ReadInt(&order0);
00055       if (!rc)
00056         break;
00057       if ( order0 < 2 || order0 > 10000 )
00058       {
00059         ON_ERROR("ON_BezierCage::Read - invalid order0");
00060         rc=false;
00061         break;
00062       }
00063 
00064       rc = archive.ReadInt(&order1);
00065       if (!rc)
00066         break;
00067       if ( order1 < 2 || order1 > 10000 )
00068       {
00069         ON_ERROR("ON_BezierCage::Read - invalid order1");
00070         rc=false;
00071         break;
00072       }
00073 
00074       rc = archive.ReadInt(&order2);
00075       if (!rc)
00076         break;
00077       if ( order2 < 2 || order2 > 10000 )
00078       {
00079         ON_ERROR("ON_BezierCage::Read - invalid order2");
00080         rc=false;
00081         break;
00082       }
00083 
00084       rc = Create(dim,is_rat,order0,order1,order2);
00085       if (!rc)
00086         break;
00087 
00088       int i,j,k;
00089       const int cv_dim = m_is_rat?(m_dim+1):m_dim;
00090       for(i = 0; i < order0 && rc; i++)
00091       {
00092         for(j = 0; j < order1 && rc; j++)
00093         {
00094           for ( k = 0; k < order2 && rc; k++)
00095           {
00096             rc = archive.ReadDouble(cv_dim,CV(i,j,k));
00097           }
00098         }
00099       }
00100 
00101       break;
00102     }
00103 
00104     if ( !archive.EndRead3dmChunk() )
00105     {
00106       rc = false;
00107     }
00108   }
00109   return rc;
00110 }
00111 
00112 bool ON_BezierCage::Write(ON_BinaryArchive& archive) const
00113 {
00114   bool rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0);
00115 
00116   if (rc)
00117   {
00118     rc = archive.WriteInt(m_dim);
00119     if(rc)
00120       rc = archive.WriteInt(m_is_rat);
00121     if (rc)
00122       rc = archive.WriteInt(m_order[0]);
00123     if (rc)
00124       rc = archive.WriteInt(m_order[1]);
00125     if (rc)
00126       rc = archive.WriteInt(m_order[2]);
00127     int i,j,k;
00128     const int cv_dim = m_is_rat?(m_dim+1):m_dim;
00129     double* bogus_cv = (double*)alloca(cv_dim*sizeof(*bogus_cv));
00130     for ( i = 0; i < cv_dim; i++ )
00131       bogus_cv[i] = ON_UNSET_VALUE;
00132     for(i = 0; i < m_order[0] && rc; i++)
00133     {
00134       for(j = 0; j < m_order[1] && rc; j++)
00135       {
00136         for ( k = 0; k < m_order[2] && rc; k++)
00137         {
00138           const double* cv = CV(i,j,k);
00139           if ( !cv )
00140             cv = bogus_cv;
00141           rc = archive.WriteDouble(cv_dim,cv);
00142         }
00143       }
00144     }
00145 
00146     if ( !archive.EndWrite3dmChunk() )
00147     {
00148       rc = false;
00149     }
00150   }
00151 
00152   return rc;
00153 }
00154 
00155 
00156 
00157 ON_BezierCage::ON_BezierCage()
00158 : m_dim(0),m_is_rat(0),m_cv_capacity(0),m_cv(0)
00159 {
00160   m_order[0] = 0;
00161   m_order[1] = 0;
00162   m_order[2] = 0;
00163   m_cv_stride[0] = 0;
00164   m_cv_stride[1] = 0;
00165   m_cv_stride[2] = 0;
00166 }
00167 
00168 ON_BezierCage::ON_BezierCage( int dim, bool is_rat, int order0, int order1, int order2 )
00169                  : m_dim(0),m_is_rat(0),m_cv_capacity(0),m_cv(0)
00170 {
00171   m_order[0] = 0;
00172   m_order[1] = 0;
00173   m_order[2] = 0;
00174   m_cv_stride[0] = 0;
00175   m_cv_stride[1] = 0;
00176   m_cv_stride[2] = 0;
00177   Create( dim, is_rat, order0, order1, order2 );
00178 }
00179 
00180 ON_BezierCage::ON_BezierCage( const ON_BoundingBox& bbox, int order0, int order1, int order2 )
00181 : m_dim(0),m_is_rat(0),m_cv_capacity(0),m_cv(0)
00182 {
00183   Create(bbox,order0,order1,order2);
00184 }
00185 
00186 ON_BezierCage::ON_BezierCage( const ON_3dPoint* box_corners, int order0, int order1, int order2 )
00187 : m_dim(0),m_is_rat(0),m_cv_capacity(0),m_cv(0)
00188 {
00189   Create(box_corners,order0,order1,order2);
00190 }
00191 
00192 ON_BezierCage::~ON_BezierCage()
00193 {
00194   Destroy();
00195 }
00196   
00197 ON_BezierCage::ON_BezierCage(const ON_BezierCage& src)
00198                  : m_dim(0),m_is_rat(0),m_cv_capacity(0),m_cv(0)
00199 {
00200   m_order[0] = 0;
00201   m_order[1] = 0;
00202   m_order[2] = 0;
00203   m_cv_stride[0] = 0;
00204   m_cv_stride[1] = 0;
00205   m_cv_stride[2] = 0;
00206   *this = src;
00207 }
00208 
00209 ON_BezierCage& ON_BezierCage::operator=(const ON_BezierCage& src)
00210 {
00211   if ( this != &src ) {
00212     if ( Create( src.m_dim, src.m_is_rat, 
00213          src.m_order[0], src.m_order[1], src.m_order[2] ) )
00214     {
00215       const int sizeof_cv = src.CVSize()*sizeof(m_cv[0]);
00216       int i, j, k;
00217       for ( i = 0; i < m_order[0]; i++ ) 
00218       for ( j = 0; j < m_order[1]; j++ ) 
00219       for ( k = 0; k < m_order[2]; k++ ) 
00220       {
00221         memcpy( CV(i,j,k), src.CV(i,j,k), sizeof_cv );
00222       }
00223     }
00224     else 
00225     {
00226       Destroy();
00227     }
00228   }
00229   return *this;
00230 }
00231 
00232 bool ON_BezierCage::IsValid() const
00233 {
00234   if ( m_cv == NULL )
00235     return false;
00236 
00237   if ( m_order[0] < 2 )
00238     return false;
00239   if ( m_order[1] < 2 )
00240     return false;
00241   if ( m_order[2] < 2 )
00242     return false;
00243 
00244   if ( m_dim <= 0 )
00245     return false;
00246   if ( m_is_rat != 0 && m_is_rat != 1 )
00247     return false;
00248 
00249   const int cvdim = m_is_rat ? (m_dim+1) : m_dim;
00250 
00251   if ( m_cv_capacity > 0 && m_cv_capacity < cvdim*m_order[0]*m_order[1]*m_order[2] )
00252     return false;
00253 
00254   int i[3];
00255   i[0] = (m_cv_stride[0] <= m_cv_stride[1]) ? 0 : 1;
00256   i[1] = 1-i[0];
00257   if ( m_cv_stride[2] < m_cv_stride[i[0]] )
00258   {
00259     i[2] = i[1];
00260     i[1] = i[0];
00261     i[0] = 2;
00262   }
00263   else if ( m_cv_stride[2] < m_cv_stride[i[1]] )
00264   {
00265     i[2] = i[1];
00266     i[1] = 2;
00267   }
00268   else
00269   {
00270     i[2] = 2;
00271   }
00272 
00273   if ( m_cv_stride[i[0]] < cvdim )
00274     return false;
00275   if ( m_cv_stride[i[1]] < m_cv_stride[i[0]]*m_order[i[0]] )
00276     return false;
00277   if ( m_cv_stride[i[2]] < m_cv_stride[i[1]]*m_order[i[1]] )
00278     return false;
00279 
00280   return true;
00281 }
00282 
00283 void ON_BezierCage::Dump( ON_TextLog& dump ) const
00284 {
00285   dump.Print( "ON_BezierCage dim = %d is_rat = %d\n"
00286                "        order = (%d, %d, %d) \n",
00287                m_dim, m_is_rat, m_order[0], m_order[1], m_order[2] );
00288   dump.Print( "Control Points  %d %s points\n"
00289                "  index               value\n",
00290                m_order[0]*m_order[1]*m_order[2], 
00291                (m_is_rat) ? "rational" : "non-rational" );
00292   if ( !m_cv ) 
00293   {
00294     dump.Print("  NULL cv array\n");
00295   }
00296   else 
00297   {
00298     int i,j;
00299     char sPreamble[128]; 
00300     memset(sPreamble,0,sizeof(sPreamble));
00301     for ( i = 0; i < m_order[0]; i++ )
00302     {
00303       for ( j = 0; j < m_order[1]; j++ )
00304       {
00305         if ( i > 0 || j > 0)
00306           dump.Print("\n");
00307         sPreamble[0] = 0;
00308         sprintf(sPreamble,"  CV[%2d][%2d]",i,j);
00309         dump.PrintPointList( m_dim, m_is_rat, 
00310                           m_order[2], m_cv_stride[2],
00311                           CV(i,j,0), 
00312                           sPreamble );
00313       }
00314       if ( i < m_order[0]-1)
00315         dump.Print("\n");
00316     }
00317   }
00318 }
00319 
00320 int ON_BezierCage::Dimension() const
00321 {
00322   return m_dim;
00323 }
00324 
00325 bool ON_BezierCage::Create( const ON_BoundingBox& bbox, int order0, int order1, int order2 )
00326 {
00327   /*
00328             7______________6
00329             |\             |\
00330             | \            | \
00331             |  \ _____________\
00332             |   4          |   5
00333             |   |          |   |
00334             |   |          |   |
00335             3---|----------2   |
00336             \   |          \   |
00337              \  |z          \  |
00338             y \ |            \ |
00339                \0_____________\1
00340                        x
00341   */
00342   ON_3dPoint box_corners[8];
00343   box_corners[0] = bbox.Corner(0,0,0);
00344   box_corners[1] = bbox.Corner(1,0,0);
00345   box_corners[2] = bbox.Corner(1,1,0);
00346   box_corners[3] = bbox.Corner(0,1,0);
00347   box_corners[4] = bbox.Corner(0,0,1);
00348   box_corners[5] = bbox.Corner(1,0,1);
00349   box_corners[6] = bbox.Corner(1,1,1);
00350   box_corners[7] = bbox.Corner(0,1,1);
00351   return Create(box_corners,order0,order1,order2);
00352 }
00353 
00354 bool ON_BezierCage::Create( int dim, bool is_rat, int order0, int order1, int order2 )
00355 {
00356   if ( m_cv_capacity < 1 )
00357     m_cv = 0;
00358   m_dim = (dim>0) ? dim : 0;
00359   m_is_rat = is_rat ? 1 : 0;
00360   m_order[0] = (order0 >= 2) ? order0 : 0;
00361   m_order[1] = (order1 >= 2) ? order1 : 0;
00362   m_order[2] = (order2 >= 2) ? order2 : 0;
00363   m_cv_stride[2] = (m_dim > 0) ? m_dim+m_is_rat : 0;
00364   m_cv_stride[1] = m_cv_stride[2]*m_order[2];
00365   m_cv_stride[0] = m_cv_stride[1]*m_order[1];
00366   m_cv_capacity = m_cv_stride[0]*m_order[0];
00367   m_cv = (double*)onrealloc( m_cv, m_cv_capacity*sizeof(m_cv[0]) );
00368   return IsValid() ? true : false;
00369 }
00370 
00371 bool ON_BezierCage::Create(
00372   const ON_3dPoint* box_corners,
00373   int order0,
00374   int order1,
00375   int order2
00376   )
00377 {
00378   int i, j, k;
00379   double r,s,t;
00380 
00381   if ( 0 == box_corners )
00382     return false;
00383   for( i = 0; i < 8; i++ )
00384   {
00385     if ( !box_corners[i].IsValid() )
00386       return false;
00387   }
00388 
00389   // create trilinear "cube" to make it easy
00390   // to calculate CV locations.
00391   ON_BezierCage cube(3,0,2,2,2);
00392   cube.SetCV(0,0,0,box_corners[0]);
00393   cube.SetCV(1,0,0,box_corners[1]);
00394   cube.SetCV(1,1,0,box_corners[2]);
00395   cube.SetCV(0,1,0,box_corners[3]);
00396   cube.SetCV(0,0,1,box_corners[4]);
00397   cube.SetCV(1,0,1,box_corners[5]);
00398   cube.SetCV(1,1,1,box_corners[6]);
00399   cube.SetCV(0,1,1,box_corners[7]);
00400 
00401   if ( 2 == order0 && 2 == order1 && 2 == order2 )
00402   {
00403     operator=(cube);
00404   }
00405   else
00406   {
00407     if (!Create(3,0,order0,order1,order2))
00408       return false;
00409     const int d0 = Degree(0);
00410     const int d1 = Degree(1);
00411     const int d2 = Degree(2);
00412 
00413     for (i = 0; i <= d0; i++)
00414     {
00415       r = ((double)i)/((double)d0);
00416       for (j = 0; j <= d1; j++)
00417       {
00418         s = ((double)j)/((double)d1);
00419         for (k = 0; k <= d2; k++)
00420         {
00421           t = ((double)k)/((double)d2);
00422           SetCV(i,j,k,cube.PointAt(r,s,t));
00423         }
00424       }
00425     }
00426   }
00427   return IsValid();
00428 }
00429 
00430 
00431 void ON_BezierCage::Destroy()
00432 {
00433   if ( m_cv && m_cv_capacity > 0 )
00434     onfree(m_cv);
00435   m_cv_capacity = 0;
00436   m_cv_stride[0] = 0;
00437   m_cv_stride[1] = 0;
00438   m_cv_stride[2] = 0;
00439   m_cv = 0;
00440   m_dim = 0;
00441   m_is_rat = 0;
00442   m_order[0] = 0;
00443   m_order[1] = 0;
00444   m_order[2] = 0;
00445 }
00446 
00447 void ON_BezierCage::EmergencyDestroy()
00448 {
00449   m_cv_capacity = 0;
00450   m_cv_stride[0] = 0;
00451   m_cv_stride[1] = 0;
00452   m_cv_stride[2] = 0;
00453   m_cv = 0;
00454   m_dim = 0;
00455   m_is_rat = 0;
00456   m_order[0] = 0;
00457   m_order[1] = 0;
00458   m_order[2] = 0;
00459 }
00460 
00461 
00462 bool ON_BezierCage::GetBBox( // returns true if successful
00463        double* boxmin,    // minimum
00464        double* boxmax,    // maximum
00465        int bGrowBox  // true means grow box
00466        ) const
00467 {
00468   int i, j;
00469   bool rc = (m_order[0] > 0 && m_order[1] > 0 && m_order[2] > 0) ? true : false;
00470   for ( i = 0; rc && i < m_order[0]; i++ ) 
00471   for ( j = 0; rc && j < m_order[1]; j++ ) 
00472   {
00473     rc = ON_GetPointListBoundingBox( m_dim, m_is_rat, m_order[2], m_cv_stride[2],
00474                                     CV(i,j,0), boxmin, boxmax, bGrowBox );
00475     bGrowBox = true;
00476   }
00477   return rc;
00478 }
00479 
00480 bool ON_BezierCage::Transform( const ON_Xform& xform )
00481 {
00482   int i,j;
00483   bool rc = (m_order[0] > 0 && m_order[1] > 0 && m_order[2]) ? true : false;
00484   if (rc)
00485   {  
00486     if ( 0 == m_is_rat )
00487     {
00488       if ( xform.m_xform[3][0] != 0.0 || xform.m_xform[3][1] != 0.0 || xform.m_xform[3][2] != 0.0 )
00489       {
00490         MakeRational();
00491       }
00492     }
00493   
00494     for ( i = 0; rc && i < m_order[0]; i++ ) 
00495     {
00496       for ( j = 0; rc && j < m_order[1]; j++ ) 
00497       {
00498         rc = ON_TransformPointList( m_dim, m_is_rat, 
00499                                     m_order[2], m_cv_stride[2], 
00500                                     CV(i,j,0), xform );
00501       }
00502     }
00503   }
00504   return rc;
00505 }
00506 
00507 bool ON_BezierCage::Rotate(
00508       double sin_angle,          // sin(angle)
00509       double cos_angle,          // cos(angle)
00510       const ON_3dVector& axis, // axis of rotation
00511       const ON_3dPoint& center // center of rotation
00512       )
00513 {
00514   ON_Xform rot;
00515   rot.Rotation( sin_angle, cos_angle, axis, center );
00516   return Transform( rot );
00517 }
00518 
00519 bool ON_BezierCage::Rotate(
00520       double angle,              // angle in radians
00521       const ON_3dVector& axis, // axis of rotation
00522       const ON_3dPoint& center // center of rotation
00523       )
00524 {
00525   return Rotate( sin(angle), cos(angle), axis, center );
00526 }
00527 
00528 bool ON_BezierCage::Translate( const ON_3dVector& delta )
00529 {
00530   ON_Xform tr;
00531   tr.Translation( delta );
00532   return Transform( tr );
00533 }
00534 
00535 bool ON_BezierCage::Scale( double x )
00536 {
00537   ON_Xform s;
00538   s.Scale( x, x, x );
00539   return Transform( s );
00540 }
00541 
00542 ON_Interval ON_BezierCage::Domain( 
00543       int // dir - formal parameter intentionally ignored in this virtual function
00544       ) const
00545 {
00546   return ON_Interval(0.0,1.0);
00547 }
00548 
00549 bool ON_BezierCage::Evaluate( // returns false if unable to evaluate
00550        double r, double s, double t,       // evaluation parameter
00551        int der_count,            // number of derivatives (>=0)
00552        int v_stride,             // array stride (>=Dimension())
00553        double* v                 // array of length stride*(ndir+1)*(ndir+2)/2
00554        ) const
00555 {  
00556   const int cvdim = m_is_rat?(m_dim+1):m_dim;
00557   int i,j,k,n;
00558   double Barray[64], vtmparray[10*4], Bi, Bij, Bijk, *Bj, *Bk, *vtmp;
00559   const double* CVi;
00560   const double* CVij;
00561   const double* CVijk;
00562 
00563   if ( der_count > 0 )
00564   {
00565     // TODO - time to add support for derivative evaluation
00566     ON_ERROR("ON_BezierCage::Evaluate does not evaluate derivatives");
00567   }
00568 
00569   i = cvdim*sizeof(*vtmp);
00570   vtmp = m_is_rat ? (i < ((int)(10*4*sizeof(vtmparray[0]))) ? vtmparray : (double*)alloca(i)) : v;
00571   memset(vtmp,0,i);
00572 
00573   // get arrays to hold values of Bernstein basis functions
00574   Bj = ((m_order[1]+m_order[2]) <= 64) 
00575     ? &Barray[0] 
00576     : ((double*)alloca((m_order[1]+m_order[2])*sizeof(*Bj)));
00577   Bk = Bj + m_order[1];
00578 
00579   const int d2 = m_order[2]-1;
00580   for ( k = 0; k <= d2; k++)
00581   {
00582     Bk[k] = ON_EvaluateBernsteinBasis(d2,k,t);
00583   }
00584 
00585   const int d1 = m_order[1]-1;
00586   for ( j = 0; j <= d1; j++)
00587   {
00588     Bj[j] = ON_EvaluateBernsteinBasis(d1,j,s);
00589   }
00590 
00591   const int d0 = m_order[0]-1;
00592 
00593   for ( i = 0; i <= d0; i++ )
00594   {
00595     CVi = m_cv + i*m_cv_stride[0];
00596     Bi = ON_EvaluateBernsteinBasis(d0,i,r);
00597     for ( j = 0; j <= d1; j++ )
00598     {
00599       CVij = CVi + j*m_cv_stride[1];
00600       Bij = Bi*Bj[j];
00601       for ( k = 0; k <= d2; k++ )
00602       {
00603         CVijk = CVij + k*m_cv_stride[2];
00604         Bijk = Bij*Bk[k];
00605         n = cvdim;
00606         while(n--)
00607         {
00608           *vtmp++ += *CVijk++ * Bijk;
00609         }
00610         vtmp -= cvdim;
00611       }
00612     }
00613   }
00614 
00615   if ( m_is_rat )
00616   {
00617 
00618     Bi = (vtmp[m_dim] != 0.0) ? (1.0/vtmp[m_dim]) : 1.0;
00619     for ( n = 0; n < m_dim; n++ )
00620     {
00621       v[n] = vtmp[n]*Bi;
00622     }
00623   }
00624 
00625   return (0 == der_count);
00626 }
00627 
00628 ON_3dPoint ON_BezierCage::PointAt(
00629         double r, 
00630         double s, 
00631         double t
00632         ) const
00633 {
00634   ON_3dPoint pt;
00635   if ( m_dim <= 3 )
00636   {
00637     pt.x  = 0.0;
00638     pt.y  = 0.0;
00639     pt.z  = 0.0;
00640     Evaluate(r,s,t,0,3,&pt.x);
00641   }
00642   else
00643   {
00644     double* v = (double*)alloca(m_dim*sizeof(*v));
00645     v[0] = 0.0;
00646     v[1] = 0.0;
00647     v[2] = 0.0;
00648     Evaluate(r,s,t,0,m_dim,v);
00649     pt.x = v[0];
00650     pt.y = v[1];
00651     pt.z = v[2];
00652   }
00653   return pt;
00654 }
00655 
00656 ON_3dPoint ON_BezierCage::PointAt( ON_3dPoint rst ) const
00657 {
00658   ON_3dPoint pt;
00659   if ( m_dim <= 3 )
00660   {
00661     pt.x  = 0.0;
00662     pt.y  = 0.0;
00663     pt.z  = 0.0;
00664     Evaluate(rst.x,rst.y,rst.z,0,3,&pt.x);
00665   }
00666   else
00667   {
00668     double* v = (double*)alloca(m_dim*sizeof(*v));
00669     v[0] = 0.0;
00670     v[1] = 0.0;
00671     v[2] = 0.0;
00672     Evaluate(rst.x,rst.y,rst.z,0,m_dim,v);
00673     pt.x = v[0];
00674     pt.y = v[1];
00675     pt.z = v[2];
00676   }
00677   return pt;
00678 }
00679 
00680 bool ON_BezierCage::IsRational() const
00681 {
00682   return m_is_rat ? true : false;
00683 }
00684 
00685 int ON_BezierCage::CVSize() const
00686 {
00687   return ( m_is_rat && m_dim>0 ) ? m_dim+1 : m_dim;
00688 }
00689 
00690 int ON_BezierCage::Order( int dir ) const
00691 {
00692   return (dir>=0&&dir<=2) ? m_order[dir] : 0;
00693 }
00694 
00695 int ON_BezierCage::Degree(int dir) const
00696 {
00697   int order = Order(dir);
00698   return (order>=2) ? order-1 : 0;
00699 }
00700 
00701 double* ON_BezierCage::CV( int i, int j, int k ) const
00702 {
00703 #if defined(ON_DEBUG)
00704   if ( 0 == m_cv )
00705   {
00706     ON_ERROR("ON_BezierCage::CV - NULL m_cv");
00707     return 0;
00708   }
00709   if ( i < 0 || i >= m_order[0] || j< 0 || j >= m_order[1] || k < 0 || k >= m_order[2])
00710   {
00711     ON_ERROR("ON_BezierCage::CV - (i,j,k) out of range");
00712     return 0;
00713   }
00714 #endif
00715   return (m_cv) ? (m_cv + i*m_cv_stride[0] + j*m_cv_stride[1] + k*m_cv_stride[2]) : 0;
00716 }
00717 
00718 ON::point_style ON_BezierCage::CVStyle() const
00719 {
00720   return m_is_rat ? ON::homogeneous_rational : ON::not_rational;
00721 }
00722 
00723 double ON_BezierCage::Weight( int i, int j, int k ) const
00724 {
00725   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;
00726 }
00727 
00728 
00729 bool ON_BezierCage::SetWeight( int i, int j, int k, double w )
00730 {
00731   bool rc = false;
00732   if ( m_is_rat ) 
00733   {
00734     double* cv = CV(i,j,k);
00735     if (cv) 
00736     {
00737       cv[m_dim] = w;
00738       rc = true;
00739     }
00740   }
00741   else if ( w == 1.0 ) 
00742   {
00743     rc = true;
00744   }
00745   return rc;
00746 }
00747 
00748 bool ON_BezierCage::SetCV( int i, int j, int k, ON::point_style style, const double* Point )
00749 {
00750   bool rc = true;
00751   int n;
00752   double w;
00753 
00754   double* cv = CV(i,j,k);
00755   if ( !cv )
00756     return false;
00757 
00758   switch ( style ) {
00759 
00760   case ON::not_rational:  // input Point is not rational
00761     memcpy( cv, Point, m_dim*sizeof(*cv) );
00762     if ( IsRational() ) {
00763       // NURBS surface is rational - set weight to one
00764       cv[m_dim] = 1.0;
00765     }
00766     break;
00767 
00768   case ON::homogeneous_rational:  // input Point is homogeneous rational
00769     if ( IsRational() ) {
00770       // NURBS surface is rational
00771       memcpy( cv, Point, (m_dim+1)*sizeof(*cv) );
00772     }
00773     else {
00774       // NURBS surface is not rational
00775       w = (Point[m_dim] != 0.0) ? 1.0/Point[m_dim] : 1.0;
00776       for ( n = 0; n < m_dim; n++ ) {
00777         cv[n] = w*Point[n];
00778       }
00779     }
00780     break;
00781 
00782   case ON::euclidean_rational:  // input Point is euclidean rational
00783     if ( IsRational() ) {
00784       // NURBS surface is rational - convert euclean point to homogeneous form
00785       w = Point[m_dim];
00786       for ( n = 0; n < m_dim; n++ )
00787         cv[i] = w*Point[i];
00788       cv[m_dim] = w;
00789     }
00790     else {
00791       // NURBS surface is not rational
00792       memcpy( cv, Point, m_dim*sizeof(*cv) );
00793     }
00794     break;
00795 
00796   case ON::intrinsic_point_style:
00797     n = m_is_rat?m_dim+1:m_dim;
00798     memcpy(cv,Point,n*sizeof(*cv));
00799     break;
00800     
00801   default:
00802     rc = false;
00803     break;
00804   }
00805   return rc;
00806 }
00807 
00808 bool ON_BezierCage::SetCV( int i, int j, int k, const ON_3dPoint& point )
00809 {
00810   bool rc = false;
00811   double* cv = CV(i,j,k);
00812   if ( cv ) {
00813     cv[0] = point.x;
00814     if ( m_dim > 1 ) {
00815       cv[1] = point.y;
00816       if ( m_dim > 2 )
00817         cv[2] = point.z;
00818     }
00819     if ( m_is_rat ) {
00820       cv[m_dim] = 1.0;
00821     }
00822     rc = true;
00823   }
00824   return rc;
00825 }
00826 
00827 bool ON_BezierCage::SetCV( int i, int j, int k, const ON_4dPoint& point )
00828 {
00829   bool rc = false;
00830   double* cv = CV(i,j,k);
00831   if ( cv ) {
00832     if ( m_is_rat ) {
00833       cv[0] = point.x;
00834       if ( m_dim > 1 ) {
00835         cv[1] = point.y;
00836         if ( m_dim > 2 )
00837           cv[2] = point.z;
00838       }
00839       cv[m_dim] = point.w;
00840       rc = true;
00841     }
00842     else {
00843       double w;
00844       if ( point.w != 0.0 ) {
00845         w = 1.0/point.w;
00846         rc = true;
00847       }
00848       else {
00849         w = 1.0;
00850       }
00851       cv[0] = w*point.x;
00852       if ( m_dim > 1 ) {
00853         cv[1] = w*point.y;
00854         if ( m_dim > 2 ) {
00855           cv[2] = w*point.z;
00856         }
00857       }
00858     }
00859   }
00860   return rc;
00861 }
00862 
00863 bool ON_BezierCage::GetCV( int i, int j, int k, ON::point_style style, double* Point ) const
00864 {
00865   const double* cv = CV(i,j,k);
00866   if ( !cv )
00867     return false;
00868   int dim = Dimension();
00869   double w = ( IsRational() ) ? cv[dim] : 1.0;
00870   switch(style) {
00871   case ON::euclidean_rational:
00872     Point[dim] = w;
00873     // no break here
00874   case ON::not_rational:
00875     if ( w == 0.0 )
00876       return false;
00877     w = 1.0/w;
00878     while(dim--) *Point++ = *cv++ * w;
00879     break;
00880   case ON::homogeneous_rational:
00881     Point[dim] = w;
00882     memcpy( Point, cv, dim*sizeof(*Point) );
00883     break;
00884   default:
00885     return false;
00886   }
00887   return true;
00888 }
00889 
00890 bool ON_BezierCage::GetCV( int i, int j, int k, ON_3dPoint& point ) const
00891 {
00892   bool rc = false;
00893   const double* cv = CV(i,j,k);
00894   if ( cv ) {
00895     if ( m_is_rat ) {
00896       if (cv[m_dim] != 0.0) {
00897         const double w = 1.0/cv[m_dim];
00898         point.x = cv[0]*w;
00899         point.y = (m_dim>1)? cv[1]*w : 0.0;
00900         point.z = (m_dim>2)? cv[2]*w : 0.0;
00901         rc = true;
00902       }
00903     }
00904     else {
00905       point.x = cv[0];
00906       point.y = (m_dim>1)? cv[1] : 0.0;
00907       point.z = (m_dim>2)? cv[2] : 0.0;
00908       rc = true;
00909     }
00910   }
00911   return rc;
00912 }
00913 
00914 bool ON_BezierCage::GetCV( int i, int j, int k, ON_4dPoint& point ) const
00915 {
00916   bool rc = false;
00917   const double* cv = CV(i,j,k);
00918   if ( cv ) {
00919     point.x = cv[0];
00920     point.y = (m_dim>1)? cv[1] : 0.0;
00921     point.z = (m_dim>2)? cv[2] : 0.0;
00922     point.w = (m_is_rat) ? cv[m_dim] : 1.0;
00923     rc = true;
00924   }
00925   return rc;
00926 }
00927 
00928 bool ON_BezierCage::ZeroCVs()
00929 {
00930   // zeros control vertices and, if rational, sets weights to 1
00931   bool rc = false;
00932   int i,j,k;
00933   if ( m_cv ) {
00934     if ( m_cv_capacity > 0 ) {
00935       memset( m_cv, 0, m_cv_capacity*sizeof(*m_cv) );
00936       if ( m_is_rat ) {
00937         for ( i = 0; i < m_order[0]; i++ ) {
00938           for ( j = 0; j < m_order[1]; j++ ) {
00939             for ( k = 0; k < m_order[2]; k++ ) {
00940               SetWeight( i,j,k, 1.0 );
00941             }
00942           }
00943         }
00944       }
00945       rc = true;
00946     }
00947     else {
00948       double* cv;
00949       int s = CVSize()*sizeof(*cv);
00950       for ( i = 0; i < m_order[0]; i++ ) {
00951         for ( j = 0; j < m_order[1]; j++ ) {
00952           for ( k = 0; k < m_order[2]; k++ ) {
00953             cv = CV(i,j,k);
00954             memset(cv,0,s);
00955             if ( m_is_rat )
00956               cv[m_dim] = 1.0;
00957           }
00958         }
00959       }
00960       rc = (i>0) ? true : false;
00961     }
00962   }
00963   return rc;
00964 }
00965 
00966 bool ON_BezierCage::MakeRational()
00967 {
00968   if ( !IsRational() ) 
00969   {
00970     ON_ERROR("TODO: fill in ON_BezierCage::MakeRational()");
00971     /*
00972     const int dim = Dimension();
00973     if ( m_order[0] > 0 && m_order[1] > 0 && m_order[2] > 0 && dim > 0 ) {
00974       const double* old_cv;
00975       double* new_cv;
00976       int cvi, cvj, j, cvstride;
00977       if ( m_cv_stride[0] < m_cv_stride[1] ) {
00978         cvstride = m_cv_stride[0] > dim ? m_cv_stride[0] : dim+1;
00979         ReserveCVCapacity( cvstride*m_order[0]*m_order[1] );
00980         new_cv = m_cv + cvstride*m_order[0]*m_order[1]-1;
00981                                 for ( cvj = m_order[1]-1; cvj >= 0; cvj-- ) {
00982           for ( cvi = m_order[0]-1; cvi >= 0; cvi-- ) {
00983             old_cv = CV(cvi,cvj)+dim-1;
00984             *new_cv-- = 1.0;
00985             for ( j = 0; j < dim; j++ ) {
00986               *new_cv-- = *old_cv--;
00987             }
00988           }
00989         }
00990         m_cv_stride[0] = dim+1;
00991         m_cv_stride[1] = (dim+1)*m_order[0];
00992       }
00993       else {
00994         cvstride = m_cv_stride[1] > dim ? m_cv_stride[1] : dim+1;
00995         ReserveCVCapacity( cvstride*m_order[0]*m_order[1] );
00996         new_cv = m_cv + cvstride*m_order[0]*m_order[1]-1;
00997         for ( cvi = m_order[0]-1; cvi >= 0; cvi-- ) {
00998           for ( cvj = m_order[1]-1; cvj >= 0; cvj-- ) {
00999             old_cv = CV(cvi,cvj)+dim-1;
01000             *new_cv-- = 1.0;
01001             for ( j = 0; j < dim; j++ ) {
01002               *new_cv-- = *old_cv--;
01003             }
01004           }
01005         }
01006         m_cv_stride[1] = dim+1;
01007         m_cv_stride[0] = (dim+1)*m_order[1];
01008       }
01009       m_is_rat = 1;
01010     }
01011     */
01012   }
01013   return IsRational();
01014 }
01015 
01016 bool ON_BezierCage::MakeNonRational()
01017 {
01018   if ( IsRational() ) 
01019   {
01020     ON_ERROR("TODO: fill in ON_BezierCage::MakeNonRational()");
01021     /*
01022     const int dim = Dimension();
01023     if ( m_order[0] > 0 && m_order[1] > 0 && dim > 0 ) {
01024       double w;
01025       const double* old_cv;
01026       double* new_cv = m_cv;
01027       int cvi, cvj, j;
01028       if ( m_cv_stride[0] < m_cv_stride[1] ) {
01029         for ( cvj = 0; cvj < m_order[1]; cvj++ ) {
01030           for ( cvi = 0; cvi < m_order[0]; cvi++ ) {
01031             old_cv = CV(cvi,cvj);
01032             w = old_cv[dim];
01033             w = ( w != 0.0 ) ? 1.0/w : 1.0;
01034             for ( j = 0; j < dim; j++ ) {
01035               *new_cv++ = w*(*old_cv++);
01036             }
01037           }
01038         }
01039         m_cv_stride[0] = dim;
01040         m_cv_stride[1] = dim*m_order[0];
01041       }
01042       else {
01043         for ( cvi = 0; cvi < m_order[0]; cvi++ ) {
01044           for ( cvj = 0; cvj < m_order[1]; cvj++ ) {
01045             old_cv = CV(cvi,cvj);
01046             w = old_cv[dim];
01047             w = ( w != 0.0 ) ? 1.0/w : 1.0;
01048             for ( j = 0; j < dim; j++ ) {
01049               *new_cv++ = w*(*old_cv++);
01050             }
01051           }
01052         }
01053         m_cv_stride[1] = dim;
01054         m_cv_stride[0] = dim*m_order[1];
01055       }
01056       m_is_rat = 0;
01057     }
01058     */
01059   }
01060   return ( !IsRational() ) ? true : false;
01061 }
01062 
01064 // Tools for managing CV and knot memory
01065 bool ON_BezierCage::ReserveCVCapacity(
01066   int capacity// number of doubles to reserve
01067   )
01068 {
01069   if ( m_cv_capacity < capacity ) {
01070     if ( m_cv ) {
01071       if ( m_cv_capacity ) {
01072         m_cv = (double*)onrealloc( m_cv, capacity*sizeof(*m_cv) );
01073         m_cv_capacity = (m_cv) ? capacity : 0;
01074       }
01075       // else user supplied m_cv[] array
01076     }
01077     else {
01078       m_cv = (double*)onmalloc( capacity*sizeof(*m_cv) );
01079       m_cv_capacity = (m_cv) ? capacity : 0;
01080     }
01081   }
01082   return ( m_cv ) ? true : false;
01083 }
01084 
01085 
01086 
01087 bool ON_BezierCage::IsSingular(          // true if surface side is collapsed to a point
01088        int side                                                                                                          // side of parameter space to test
01089                                                                                                                                                         // 0 = south, 1 = east, 2 = north, 3 = west, 4 = bottom, 5 =top
01090                                 ) const
01091 {
01092   ON_ERROR("TODO: fill in ON_BezierCage::IsSingular\n");
01093   return false;
01094 }
01095 
01096 
01097 
01098 const ON_Xform& ON_BezierCageMorph::WorldToUnitCube() const
01099 {
01100   // maps world point into unit cube that can be morphed by
01101   // evaluation of the BezierCage() function.
01102   return m_xyz2rst;
01103 }
01104 
01105 const ON_BezierCage& ON_BezierCageMorph::BezierCage() const
01106 {
01107   // morphs a point in the unit cube into a world point.
01108   return m_rst2xyz;
01109 }
01110 
01111 
01112 bool ON_BezierCageMorph::Transform(const ON_Xform& xform)
01113 {
01114   // transforms the VolumeMorph as a piece of geometry
01115   return m_rst2xyz.Transform(xform);
01116 }
01117 
01118 bool ON_BezierCageMorph::Read(ON_BinaryArchive& archive)
01119 {
01120   int major_version = 0;
01121   int minor_version = 0;
01122   bool rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
01123   if ( rc )
01124   {
01125     if ( major_version != 1 )
01126       rc = false;
01127     if (rc)
01128       rc = archive.ReadXform(m_xyz2rst);
01129     if(rc)
01130       rc = m_rst2xyz.Read(archive);
01131     if ( !archive.EndRead3dmChunk() )
01132       rc = false;
01133   }
01134   return rc;
01135 }
01136 
01137 bool ON_BezierCageMorph::Write(ON_BinaryArchive& archive) const
01138 {
01139   bool rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0);
01140   if (rc)
01141   {
01142     if (rc)
01143       rc = archive.WriteXform(m_xyz2rst);
01144     if(rc)
01145       rc = m_rst2xyz.Write(archive);
01146     if ( !archive.EndWrite3dmChunk() )
01147       rc = false;
01148   }
01149   return rc;
01150 }
01151 
01152 
01153 ON_BezierCageMorph::ON_BezierCageMorph() : m_bValid(0)
01154 {
01155 }
01156 
01157 ON_BezierCageMorph::~ON_BezierCageMorph()
01158 {
01159 }
01160 
01161 bool ON_BezierCageMorph::Create(
01162     ON_3dPoint P0,
01163     ON_3dPoint P1,
01164     ON_3dPoint P2,
01165     ON_3dPoint P3,
01166     int point_countX,
01167     int point_countY,
01168     int point_countZ
01169     )
01170 {
01171   if ( point_countX < 2 || point_countY < 2 || point_countZ < 2 
01172       || !P0.IsValid()
01173       || !P1.IsValid()
01174       || !P2.IsValid()
01175       || !P3.IsValid() )
01176   {
01177     ON_ERROR("ON_BezierCageMorph::Create - invalid input");
01178   }
01179 
01180   m_bValid = false;
01181   ON_3dVector X = P1-P0;
01182   ON_3dVector Y = P2-P0;
01183   ON_3dVector Z = P3-P0;
01184   ON_Xform xform(1.0);
01185   xform[0][0] = X.x;
01186   xform[1][0] = X.y;
01187   xform[2][0] = X.z;
01188   xform[0][1] = Y.x;
01189   xform[1][1] = Y.y;
01190   xform[2][1] = Y.z;
01191   xform[0][2] = Z.x;
01192   xform[1][2] = Z.y;
01193   xform[2][2] = Z.z;
01194   xform[0][3] = P0.x;
01195   xform[1][3] = P0.y;
01196   xform[2][3] = P0.z;
01197   double min_pivot = 0.0;
01198   m_bValid = xform.Invert(&min_pivot);
01199   if (m_bValid)
01200   {
01201     ON_3dPoint box_corners[8];
01202     box_corners[0] = P0;
01203     box_corners[1] = P1;
01204     box_corners[2] = P0+X+Y;
01205     box_corners[3] = P2;
01206     box_corners[4] = P3;
01207     box_corners[5] = P3+X;
01208     box_corners[6] = P3+X+Y;
01209     box_corners[7] = P3+Y;
01210     m_bValid = m_rst2xyz.Create(box_corners,point_countX,point_countY,point_countZ);
01211     m_xyz2rst = xform;
01212   }
01213   else
01214   {
01215     ON_ERROR("ON_BezierCageMorph::Create - invalid input - P0,P1,P2,P3 are coplanar");
01216     m_rst2xyz.Destroy();
01217   }
01218   return m_bValid;
01219 }
01220 
01221 bool ON_BezierCageMorph::SetXform( ON_Xform world2unitcube )
01222 {
01223   m_xyz2rst = world2unitcube;
01224   m_bValid = m_xyz2rst.IsValid() && m_rst2xyz.IsValid();
01225   return m_bValid;
01226 }
01227 
01228 bool ON_BezierCageMorph::SetBezierCage( ON_BezierCage& unitcube2world )
01229 {
01230   m_rst2xyz = unitcube2world;
01231   m_bValid = m_xyz2rst.IsValid() && m_rst2xyz.IsValid();
01232   return m_bValid;
01233 }


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