contrib/brl/bbas/bsol/bsol_intrinsic_curve_3d.cxx
Go to the documentation of this file.
00001 // This is brl/bbas/bsol/bsol_intrinsic_curve_3d.cxx
00002 #include "bsol_intrinsic_curve_3d.h"
00003 //:
00004 // \file
00005 #include <vsol/vsol_point_3d.h>
00006 #include <vcl_cassert.h>
00007 #include <vcl_cstdio.h>
00008 #include <vcl_cmath.h>
00009 #include <vcl_cstring.h>
00010 #include <vnl/vnl_math.h>
00011 
00012 //***************************************************************************
00013 // Initialization
00014 //***************************************************************************
00015 
00016 //---------------------------------------------------------------------------
00017 //: Default Constructor
00018 //---------------------------------------------------------------------------
00019 bsol_intrinsic_curve_3d::bsol_intrinsic_curve_3d()
00020 {
00021   storage_=new vcl_vector<vsol_point_3d_sptr>();
00022   computeProperties();
00023 }
00024 
00025 //---------------------------------------------------------------------------
00026 //: Constructor from a vcl_vector of points
00027 //---------------------------------------------------------------------------
00028 
00029 bsol_intrinsic_curve_3d::bsol_intrinsic_curve_3d(const vcl_vector<vsol_point_3d_sptr> &new_vertices)
00030 {
00031   storage_=new vcl_vector<vsol_point_3d_sptr>(new_vertices);
00032   computeProperties();
00033 }
00034 
00035 //---------------------------------------------------------------------------
00036 // Copy constructor
00037 //---------------------------------------------------------------------------
00038 bsol_intrinsic_curve_3d::bsol_intrinsic_curve_3d(const bsol_intrinsic_curve_3d &other)
00039   : vsol_curve_3d(other)
00040 {
00041   storage_=new vcl_vector<vsol_point_3d_sptr>(*other.storage_);
00042   for (unsigned int i=0; i<storage_->size(); ++i)
00043     (*storage_)[i]=new vsol_point_3d(*((*other.storage_)[i]));
00044   computeProperties();
00045 }
00046 
00047 //---------------------------------------------------------------------------
00048 // Destructor
00049 //---------------------------------------------------------------------------
00050 bsol_intrinsic_curve_3d::~bsol_intrinsic_curve_3d()
00051 {
00052   delete storage_;
00053 }
00054 
00055 //---------------------------------------------------------------------------
00056 //: Clone `this': creation of a new object and initialization
00057 // See Prototype pattern
00058 //---------------------------------------------------------------------------
00059 vsol_spatial_object_3d* bsol_intrinsic_curve_3d::clone(void) const
00060 {
00061   return new bsol_intrinsic_curve_3d(*this);
00062 }
00063 
00064 //***************************************************************************
00065 // Comparison
00066 //***************************************************************************
00067 
00068 //---------------------------------------------------------------------------
00069 //: Has `this' the same points than `other' in the same order ?
00070 //---------------------------------------------------------------------------
00071 bool bsol_intrinsic_curve_3d::operator==(const bsol_intrinsic_curve_3d &other) const
00072 {
00073   // quick return if possible:
00074   if (this==&other)
00075     return true;
00076   if (size() != other.size())
00077     return false;
00078 
00079   // run through other list to find the point matching the first point of this:
00080   vcl_vector<vsol_point_3d_sptr>::const_iterator i1 = storage_->begin(),
00081                                                  i2 = other.storage_->begin();
00082   while (i2!=other.storage_->end() && *(*i1)!=*(*i2))
00083     ++i2;
00084   if (i2==other.storage_->end())
00085     return false;
00086 
00087   // now run through both lists in sync and compare points:
00088   while (++i2,++i1!=storage_->end()) {
00089     if (i2==other.storage_->end()) i2 = other.storage_->begin();
00090     if (*(*i1)!=*(*i2)) return false;
00091   }
00092 
00093   return true;
00094 }
00095 
00096 //: spatial object equality
00097 bool bsol_intrinsic_curve_3d::operator==(const vsol_spatial_object_3d& obj) const
00098 {
00099   return obj.is_a() == "bsol_intrinsic_curve_3d" &&
00100     operator==(static_cast<bsol_intrinsic_curve_3d const&>(obj));
00101 }
00102 
00103 //***************************************************************************
00104 // Status setting
00105 //***************************************************************************
00106 
00107 //: Compute the arcLength_[], s_[], curvature_[], angle_[]
00108 void bsol_intrinsic_curve_3d::computeProperties()
00109 {
00110   if (size() ==0)
00111     return;
00112 
00113   // 0) initialize starting point and end point.
00114   p0_ = (*storage_)[1];
00115   p1_ = (*storage_)[storage_->size()-1];
00116 
00117   // 1) Reset datastructures
00118   arcLength_.clear();
00119   s_.clear();
00120   phi_.clear();
00121   phis_.clear();
00122   phiss_.clear();
00123   theta_.clear();
00124   thetas_.clear();
00125   thetass_.clear();
00126   Tangent_.clear();
00127   Normal_.clear();
00128   Binormal_.clear();
00129   curvature_.clear();
00130   torsion_.clear();
00131 
00132   // 2) Setup the starting conditions
00133   arcLength_.push_back(-1);
00134   s_.push_back(-1);
00135   phi_.push_back(-1);
00136   phis_.push_back(-1); phis_.push_back(-1);
00137   phiss_.push_back(-1); phiss_.push_back(-1);
00138   theta_.push_back(-1);
00139   thetas_.push_back(-1); thetas_.push_back(-1);
00140   thetass_.push_back(-1); thetass_.push_back(-1);
00141   Tangent_.push_back(NULL);
00142   Normal_.push_back(NULL); Normal_.push_back(NULL);
00143   Binormal_.push_back(NULL); Binormal_.push_back(NULL);
00144   curvature_.push_back(-1.0); curvature_.push_back(-1.0);
00145   torsion_.push_back(-1); torsion_.push_back(-1);
00146 
00147   //The third order terms.
00148   if (size()>2) {
00149     phiss_.push_back(-1);
00150     thetass_.push_back(-1);
00151     torsion_.push_back(-1);
00152   }
00153 
00154   // 3) Compute the first derivative: arc length and angle.
00155   double prev_x = (*storage_)[0]->x();
00156   double prev_y = (*storage_)[0]->y();
00157   double prev_z = (*storage_)[0]->z();
00158   double length = 0;
00159   for (unsigned int i=1; i<size(); ++i)
00160   {
00161     double cur_x=(*storage_)[i]->x();
00162     double cur_y=(*storage_)[i]->y();
00163     double cur_z=(*storage_)[i]->z();
00164     double cur_dx = cur_x - prev_x;
00165     double cur_dy = cur_y - prev_y;
00166     double cur_dz = cur_z - prev_z;
00167     double dL = vcl_sqrt(cur_dx*cur_dx + cur_dy*cur_dy + cur_dz*cur_dz);
00168     s_.push_back(dL);
00169     length += dL;
00170     arcLength_.push_back(length);
00171 
00172     double phi = vcl_acos(cur_dz/dL);
00173     phi_.push_back(phi);
00174     double dLxy = dL*vcl_sin(phi);
00175     double theta = vcl_acos(cur_dx/dLxy);
00176     theta_.push_back(theta);
00177 
00178     vgl_vector_3d<double>* tangent = new vgl_vector_3d<double>(cur_dx, cur_dy, cur_dz);
00179     normalize(*tangent); //normalize the tangent vector.
00180     Tangent_.push_back(tangent);
00181 
00182     prev_x = cur_x;
00183     prev_y = cur_y;
00184     prev_z = cur_z;
00185   }
00186   assert (s_.size() == size());
00187   assert (arcLength_.size() == size());
00188   assert (phi_.size() == size());
00189   assert (theta_.size() == size());
00190   assert (Tangent_.size() == size());
00191 
00192   // 4) Compute the second derivative: phi_s, theta_s, normal, binormal, curvature
00193   totalCurvature_ = 0;
00194   totalAngleChange_ = 0;
00195   for (unsigned int i=2; i<size(); ++i)
00196   {
00197     double phis = (phi_[i] - phi_[i-1])/s_[i];
00198     phis_.push_back(phis);
00199     double thetas = (theta_[i] - theta_[i-1])/s_[i];
00200     thetas_.push_back(thetas);
00201     double curvature = vnl_math_hypot(phis, vcl_sin(phi_[i])*thetas);
00202     curvature_.push_back(curvature);
00203     totalCurvature_ += curvature;
00204     totalAngleChange_ += vcl_fabs(curvature);
00205 
00206     double cos_phi = vcl_cos(phi_[i]);
00207     double sin_phi = vcl_sin(phi_[i]);
00208     double cos_theta = vcl_cos(theta_[i]);
00209     double sin_theta = vcl_sin(theta_[i]);
00210     double normalx = cos_phi * cos_theta * phis -
00211                 sin_phi * sin_theta * thetas;
00212     double normaly = cos_phi * sin_theta * phis -
00213                 sin_phi * cos_theta * thetas;
00214     double normalz = - vcl_sin(phi_[i]) * phis;
00215     vgl_vector_3d<double>* normal = new vgl_vector_3d<double>(normalx, normaly, normalz);
00216     normalize(*normal); //normalize the normal vector.
00217     Normal_.push_back(normal);
00218 
00219     vgl_vector_3d<double>* binormal = new vgl_vector_3d<double>;
00220     *binormal = cross_product(*(Tangent_[i]), *normal);
00221     normalize(*binormal); //normalize the binormal vector.
00222     Binormal_.push_back(binormal);
00223   }
00224   assert (phis_.size() == size());
00225   assert (thetas_.size() == size());
00226   assert (curvature_.size() == size());
00227   assert (Normal_.size() == size());
00228   assert (Binormal_.size() == size());
00229 
00230   // 5) Compute the third derivative: phi_ss, theta_ss, torsion
00231   for (unsigned int i=3; i<size(); ++i) {
00232     double phiss = (phis_[i] - phis_[i-1])/s_[i];
00233     phiss_.push_back(phiss);
00234     double thetass = (thetas_[i] - thetas_[i-1])/s_[i];
00235     thetass_.push_back(thetass);
00236 
00237     //compute torsion. (this is a very noisy approach, without ENO).
00238 #if 0
00239     double sin_phi = vcl_sin(phi_[i]);
00240     double cos_phi = vcl_cos(phi_[i]);
00241     double torsion_n = 2*cos_phi*thetas_[i]*phis_[i]*phis_[i] +
00242                  sin_phi*phis_[i]*thetass_[i] +
00243                  sin_phi*thetas_[i]*
00244                   ( -phiss_[i] + sin_phi*cos_phi*thetas_[i]*thetas_[i] );
00245     double torsion_d = phis_[i]*phis_[i] + sin_phi*sin_phi*thetas_[i]*thetas_[i];
00246     double torsion = torsion_n / torsion_d;
00247     torsion_.push_back(torsion);
00248 #else // 0
00249     //torsion = -N dot B'. B' = (B[i]-B[i-1])/s[i]
00250     vgl_vector_3d<double> bp = (*Binormal_[i] - *Binormal_[i-1])/s_[i];
00251     normalize(bp);
00252     double torsion = - dot_product(*Normal_[i], bp);
00253     torsion_.push_back(torsion);
00254 #endif // 0
00255   }
00256   assert (phiss_.size() == size());
00257   assert (thetass_.size() == size());
00258   assert (torsion_.size() == size());
00259 }
00260 
00261 #if 0
00262 //: Compute the arcLength_[], s_[], curvature_[], angle_[]
00263 void bsol_intrinsic_curve_3d::computeProperties_old()
00264 {
00265   if (size() ==0)
00266     return;
00267   // initialize starting point and end point.
00268   p0_ = (*storage_)[1];
00269   p1_ = (*storage_)[storage_->size()-1];
00270 
00271   // 1)reset datastructures
00272   arcLength_.clear();
00273   s_.clear();
00274   curvature_.clear();
00275   angle_.clear();
00276 
00277   // 2)the arc length of the first point is defined to be zero.
00278   arcLength_.push_back(0.0);
00279   s_.push_back(0.0);
00280   angle_.push_back(0.0);
00281   totalAngleChange_ = 0.0;
00282   curvature_.push_back(0.0);
00283   totalCurvature_ = 0.0;
00284 
00285   vgl_vector_3d<double>* tangent = new vgl_vector_3d<double>;
00286   Tangent_.push_back(tangent);
00287 
00288   // 3)compute arc length for all other vertices
00289   double length = 0;
00290   double prev_x = (*storage_)[0]->x();
00291   double prev_y = (*storage_)[0]->y();
00292   double prev_z = (*storage_)[0]->z();
00293   double prev_dx = 0;
00294   double prev_dy = 0;
00295   double prev_dz = 0;
00296   double prev_dL = 0;
00297 
00298   for (unsigned int i=1; i<size(); ++i)
00299   {
00300     double cur_x=(*storage_)[i]->x();
00301     double cur_y=(*storage_)[i]->y();
00302     double cur_z=(*storage_)[i]->z();
00303 
00304     double cur_dx = cur_x-prev_x;
00305     double cur_dy = cur_y-prev_y;
00306     double cur_dz = cur_z-prev_z;
00307 
00308     tangent = new vgl_vector_3d<double>(cur_dx, cur_dy, cur_dz);
00309     normalize(*tangent); //normalize the tangent vector.
00310     Tangent_.push_back(tangent);
00311 
00312     double dL = vnl_math_hypot(cur_dx, cur_dy);
00313     length += dL;
00314     arcLength_.push_back(length);
00315     s_.push_back(dL);
00316 
00317      double theta = vcl_atan2(cur_dy, cur_dx);
00318     angle_.push_back(theta);
00319 
00320     double K;
00321     if (dL > ZERO_TOLERANCE) {
00322       double cdx = cur_dx/dL;
00323       double cdy = cur_dy/dL;
00324       double pdx, pdy;
00325       if (prev_dL > ZERO_TOLERANCE) {
00326         pdx = prev_dx/prev_dL;
00327         pdy = prev_dy/prev_dL;
00328       }
00329       else {
00330         pdx = 0;
00331         pdy = 0;
00332       }
00333       double d2x = (cdx-pdx)/dL;
00334       double d2y = (cdy-pdy)/dL;
00335       K = (d2y*cdx-d2x*cdy) / vcl_pow(cdx*cdx+cdy*cdy,3/2);
00336     }
00337     else {
00338       K = 0;
00339     }
00340     curvature_.push_back(K);
00341     totalCurvature_ += K;
00342 
00343     prev_x = cur_x;
00344     prev_y = cur_y;
00345     prev_z = cur_z;
00346     prev_dx = cur_dx;
00347     prev_dy = cur_dy;
00348     prev_dz = cur_dz;
00349     prev_dL = dL;
00350   }//end for i
00351 
00352   // 4) Compute the Normal vector. Note that N_i = T_i+1 - T_i
00353   vgl_vector_3d<double>* normal;
00354   for (unsigned int i=0; i+1<size(); ++i) {
00355     normal = new vgl_vector_3d<double>(*Tangent_[i+1] - *Tangent_[i]);
00356     Normal_.push_back(normal);
00357   }
00358   normal = new vgl_vector_3d<double>;
00359   Normal_.push_back(normal);
00360 
00361   // 5) Compute the Binormal vector. B_i = T_i * N_i
00362   for (unsigned int i=0; i<size(); ++i) {
00363     vgl_vector_3d<double>* binormal = new vgl_vector_3d<double>(cross_product(*Tangent_[i], *Normal_[i]));
00364     Binormal_.push_back(binormal);
00365   }
00366 
00367   // 6)Deal with the beginning part of the curve.
00368   //   set angle_[0] to angle_[1], and compute totalAngleChange
00369   if (size() > 1) {
00370     Tangent_[0] = Tangent_[1];
00371     angle_[0] = angle_[1];
00372     for (unsigned int i=1; i<size(); ++i)
00373       totalAngleChange_ += vcl_fabs(angle_[i]-angle_[i-1]);
00374 
00375     // 5-2)Deal with the ending part of the curve.
00376     Normal_[0] = Normal_[1];
00377     Normal_[size()-1] = Normal_[size()-2];
00378     // 5-3)Deal with the ending part of the curve.
00379     Binormal_[0] = Binormal_[1];
00380     Binormal_[size()-1] = Binormal_[size()-2];
00381   }
00382 }
00383 #endif
00384 
00385 void bsol_intrinsic_curve_3d::clear(void)
00386 {
00387   for (unsigned int i=0; i<size(); ++i) {
00388     delete Tangent_[i];
00389   }
00390 
00391   //reset the storage_
00392   delete storage_;
00393   storage_=new vcl_vector<vsol_point_3d_sptr>();
00394 
00395   arcLength_.clear();
00396   s_.clear();
00397   phi_.clear();
00398   phis_.clear();
00399   phiss_.clear();
00400   theta_.clear();
00401   thetas_.clear();
00402   thetass_.clear();
00403   Tangent_.clear();
00404   Normal_.clear();
00405   Binormal_.clear();
00406   curvature_.clear();
00407   torsion_.clear();
00408   totalCurvature_ = 0;
00409   totalAngleChange_ = 0;
00410 }
00411 
00412 bool bsol_intrinsic_curve_3d::LoadCON3File(vcl_string fileName)
00413 {
00414   vcl_FILE* fp;
00415   char buffer[128];
00416 
00417   if ((fp = vcl_fopen(fileName.c_str(), "r")) == NULL) {
00418     vcl_fprintf(stderr, "ERROR: Can't open input .con3 file %s.\n", fileName.c_str());
00419     return false;
00420   }
00421   CON3Filename_ = fileName;
00422 
00423   int ret = vcl_fscanf(fp, "CONTOUR\n"); assert (ret==0);
00424   ret = vcl_fscanf(fp, "%s\n", buffer); assert (ret==1);
00425   if (vcl_strcmp(buffer, "OPEN")==0) //the same
00426     isOpen_ = true;
00427   else //"CLOSE"
00428     isOpen_ = false;
00429   int numPoints=0;
00430   ret = vcl_fscanf(fp, "%d\n", &numPoints); assert (ret==1);
00431   if (numPoints<=0)
00432     vcl_fprintf(stderr, "WARNING: First line of file %s (number of points) should be strictly positive.\n",
00433                 fileName.c_str());
00434 
00435   for (int i=0; i<numPoints; ++i) {
00436     double x, y, z;
00437     ret = vcl_fscanf(fp, "%lf", &x); assert (ret==1);
00438     ret = vcl_fscanf(fp, "%lf", &y); assert (ret==1);
00439     ret = vcl_fscanf(fp, "%lf", &z); assert (ret==1);
00440     add_vertex(x, y, z);
00441   }
00442 
00443   //Note here that if the numPoints is wrong, the rest of the file is not read.
00444   vcl_fclose(fp);
00445 
00446   computeProperties();
00447 
00448   return true;
00449 }
00450 
00451 bool bsol_intrinsic_curve_3d::SaveCON3File(vcl_string fileName)
00452 {
00453   vcl_FILE* fp;
00454 
00455   if ((fp = vcl_fopen(fileName.c_str(), "w")) == NULL) {
00456     vcl_fprintf(stderr, "ERROR( bsol_intrinsic_curve_3d::SaveCON3File): Can't open output .con3 file %s.\n", fileName.c_str());
00457     return false;
00458   }
00459 
00460   vcl_fprintf(fp, "CONTOUR\n");
00461   if (isOpen_)
00462     vcl_fprintf(fp, "OPEN\n");
00463   else
00464     vcl_fprintf(fp, "CLOSE\n");
00465 
00466   vcl_fprintf(fp, "%d\n", size());
00467 
00468   for (unsigned int i=0; i<size(); ++i) {
00469     vcl_fprintf(fp, "%.10f %.10f %.10f\n", x(i), y(i), z(i));
00470   }
00471 
00472   vcl_fclose(fp);
00473   return true;
00474 }
00475 
00476 //---------------------------------------------------------------------------
00477 //: Compute the bounding box of `this'
00478 //---------------------------------------------------------------------------
00479 void bsol_intrinsic_curve_3d::compute_bounding_box(void) const
00480 {
00481   set_bounding_box((*storage_)[0]->x(), (*storage_)[0]->y(), (*storage_)[0]->z());
00482   for (unsigned int i=1; i<storage_->size(); ++i)
00483     add_to_bounding_box((*storage_)[i]->x(), (*storage_)[i]->y(), (*storage_)[i]->z());
00484 }