00001
00002 #include "bsol_intrinsic_curve_3d.h"
00003
00004
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
00014
00015
00016
00017
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
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
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
00049
00050 bsol_intrinsic_curve_3d::~bsol_intrinsic_curve_3d()
00051 {
00052 delete storage_;
00053 }
00054
00055
00056
00057
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
00066
00067
00068
00069
00070
00071 bool bsol_intrinsic_curve_3d::operator==(const bsol_intrinsic_curve_3d &other) const
00072 {
00073
00074 if (this==&other)
00075 return true;
00076 if (size() != other.size())
00077 return false;
00078
00079
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
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
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
00105
00106
00107
00108 void bsol_intrinsic_curve_3d::computeProperties()
00109 {
00110 if (size() ==0)
00111 return;
00112
00113
00114 p0_ = (*storage_)[1];
00115 p1_ = (*storage_)[storage_->size()-1];
00116
00117
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
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
00148 if (size()>2) {
00149 phiss_.push_back(-1);
00150 thetass_.push_back(-1);
00151 torsion_.push_back(-1);
00152 }
00153
00154
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);
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
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);
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);
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
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
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
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
00263 void bsol_intrinsic_curve_3d::computeProperties_old()
00264 {
00265 if (size() ==0)
00266 return;
00267
00268 p0_ = (*storage_)[1];
00269 p1_ = (*storage_)[storage_->size()-1];
00270
00271
00272 arcLength_.clear();
00273 s_.clear();
00274 curvature_.clear();
00275 angle_.clear();
00276
00277
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
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);
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 }
00351
00352
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
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
00368
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
00376 Normal_[0] = Normal_[1];
00377 Normal_[size()-1] = Normal_[size()-2];
00378
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
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)
00426 isOpen_ = true;
00427 else
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
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
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 }