Contour utility class. More...
#include <util/contour.h>
Public Member Functions | |
Contour (std::string filename) | |
Constructor from file. | |
Contour (const Contour &) | |
Contour () | |
Default constructor. | |
const util::Vector< 3, double > & | getMax () const |
Return the maximum x, y and z coordinates. | |
const util::Vector< 3, double > & | getMin () const |
Return the minimum x, y and z coordinates. | |
double | length (double a, double b, double dt=0.01) |
Return the arc length for a parameter interval. | |
util::Vector< 3, double > | normal (double t, double dt=0.01) |
Finds the normal vector at a given parameter value. | |
util::Vector< 3, double > | operator() (double t) const |
Function operator. | |
Contour & | operator= (const Contour &) |
Copy constructor. | |
void | reread () |
Method to be implemented in subblasses to reread the file. | |
util::Vector< 3, double > | tangent (double t, double dt=0.01) |
Finds the tangent vector at a given parameter value. | |
double | travel (double t, double l, double dt=0.01) |
Return the paramter after traveling a given arc length. |
Contour utility class.
The Contour class encapsulates b-spline contours specified in the VLAB contour formats. Currently all versions are supported (original, ver. 1 1 and 1.4). Instances of Contour behave as function objects.
Definition at line 25 of file contour.h.
util::Contour::Contour | ( | ) |
Default constructor.
Definition at line 25 of file contour.cpp.
00026 : FileObject() 00027 , closed(true) 00028 , regular(true) 00029 {}
util::Contour::Contour | ( | std::string | filename | ) |
Constructor from file.
filename | The contour file to load. |
Definition at line 38 of file contour.cpp.
References reread().
00039 : FileObject(filename) 00040 , closed(true) 00041 , regular(true) 00042 { 00043 reread(); 00044 }
const Vector< 3, double > & util::Contour::getMax | ( | ) | const |
Return the maximum x, y and z coordinates.
Definition at line 447 of file contour.cpp.
const Vector< 3, double > & util::Contour::getMin | ( | ) | const |
Return the minimum x, y and z coordinates.
Definition at line 452 of file contour.cpp.
double util::Contour::length | ( | double | a, | |
double | b, | |||
double | dt = 0.01 | |||
) |
Return the arc length for a parameter interval.
a | Parameter for the start of the interval. | |
b | Parameter for the end of the interval. | |
dt | The step used for forward differencing. |
It is expected that a and b are both in the interval of [0, 1] and that dt is less than b - a.
Definition at line 464 of file contour.cpp.
Referenced by travel().
00464 { 00465 if (a < 0.0) a = 0.0; 00466 if (a > 1.0) a = 1.0; 00467 if (b > 1.0) b = 1.0; 00468 if (b < a + dt) return 0.0; 00469 00470 double l = 0.0; 00471 Vector<3,double> p = (*this)(a), q; 00472 while (a <= b) { 00473 a += dt; 00474 q = (*this)(a); 00475 l += norm(p-q); 00476 p = q; 00477 } 00478 return l; 00479 }
Vector< 3, double > util::Contour::normal | ( | double | t, | |
double | dt = 0.01 | |||
) |
Finds the normal vector at a given parameter value.
t | Parameter value for where to take the normal. | |
dt | The interval size used for the numerical evaluation. |
Definition at line 519 of file contour.cpp.
References tangent(), util::Vector< dim, T >::x(), and util::Vector< dim, T >::y().
00519 { 00520 Vector<3,double> tvec = tangent(t, dt); 00521 return Vector<3,double>(tvec.y(), tvec.x(), 0); 00522 }
Vector< 3, double > util::Contour::operator() | ( | double | t | ) | const |
Function operator.
t | Time along the curve, between zero and one. |
This calculates the 3-dimensional coordinates of the curve at time t, where t is between zero and one. If t is less then zero, it is set to zero. If it is larger than one, it is set to one.
Definition at line 431 of file contour.cpp.
00431 { 00432 if (t < 0.0) t = 0.0; 00433 else if (t > 1.0) t = 1.0; 00434 00435 double k = 1.0 + double(pts.size() - 3) * t; 00436 int i = int(k) + 2; 00437 double p = k - floor(k); 00438 00439 return 00440 pts[i - 3] * Basis0(p) 00441 + pts[i - 2] * Basis1(p) 00442 + pts[i - 1] * Basis2(p) 00443 + pts[i] * Basis3(p); 00444 }
Copy constructor.
Definition at line 415 of file contour.cpp.
void util::Contour::reread | ( | ) | [virtual] |
Method to be implemented in subblasses to reread the file.
Implements util::FileObject.
Definition at line 56 of file contour.cpp.
References QFile::close(), QString::fromStdString(), QFile::handle(), QString::mid(), QFile::open(), QString::size(), QString::split(), QString::startsWith(), and QString::trimmed().
Referenced by Contour().
00056 { 00057 closed = false; 00058 QString fn = QString::fromStdString(filename); 00059 QFile f(fn); 00060 if(!f.open(QIODevice::ReadOnly)) 00061 { 00062 err << "Error opening file " << QString::fromStdString(filename) << ": " << f.errorString() << endl; 00063 return; 00064 } 00065 #if defined(__APPLE__) || defined(linux) 00066 flock(f.handle(), LOCK_SH); 00067 #endif 00068 QTextStream ts(&f); 00069 int ptid = 0, line_nb = 1; 00070 00071 pts.clear(); 00072 00073 QString line = ts.readLine().trimmed(); 00074 QStringList ver = line.split(" "); 00075 if(ver.size() != 3 or ver[0] != "cver") 00076 { 00077 err << "The file '" << fn << "' doesn't containt a valid contour" << endl; 00078 return; 00079 } 00080 00081 bool ok; 00082 int vmaj = ver[1].toInt(&ok); 00083 if(!ok) 00084 { 00085 REPORT_ERROR(fn, line_nb, "The major version number is not a valid integer"); 00086 return; 00087 } 00088 00089 int vmin = ver[2].toInt(&ok); 00090 if(!ok) 00091 { 00092 REPORT_ERROR(fn, line_nb, "The minor version number is not a valid integer"); 00093 return; 00094 } 00095 00096 int version = 100*vmaj+vmin; 00097 if(version == 101) 00098 { 00099 while(!ts.atEnd()) 00100 { 00101 ++line_nb; 00102 QString line = ts.readLine().trimmed(); 00103 if(line.startsWith("name:")) 00104 { 00105 // Do nothing of the name 00106 } 00107 else if(line.startsWith("points:")) 00108 { 00109 QStringList nbpts = line.mid(7).trimmed().split(" "); 00110 if(nbpts.size() != 2) 00111 { 00112 REPORT_ERROR(fn, line_nb, "Error, there should be two values for the points number, not " << nbpts.size()); 00113 return; 00114 } 00115 bool ok; 00116 int nb_pts = nbpts[1].toInt(&ok); 00117 if(!ok) 00118 { 00119 REPORT_ERROR(fn, line_nb, "Error, number of control points is not a number"); 00120 return; 00121 } 00122 pts.resize(nb_pts); 00123 } 00124 else if(line.startsWith("type:")) 00125 { 00126 QString type = line.mid(5).trimmed().toLower(); 00127 if(type == "closed") 00128 closed = true; 00129 else if(type == "open") 00130 closed = false; 00131 else 00132 { 00133 REPORT_ERROR(fn, line_nb, "Unknown contour type: " << type); 00134 return; 00135 } 00136 } 00137 else 00138 { 00139 if(ptid >= (int)pts.size()) 00140 { 00141 REPORT_ERROR(fn, line_nb, "There are more control points defined than declared"); 00142 return; 00143 } 00144 QStringList pt = line.split(" "); 00145 if(pt.size() != 4) 00146 { 00147 REPORT_ERROR(fn, line_nb, "A points should be described with four values"); 00148 return; 00149 } 00150 bool ok; 00151 double x,y,z,m; 00152 x = pt[0].toDouble(&ok); 00153 if(!ok) 00154 { 00155 REPORT_ERROR(fn, line_nb, "Error, x coordinate is not a valid floating point value"); 00156 return; 00157 } 00158 y = pt[1].toDouble(&ok); 00159 if(!ok) 00160 { 00161 REPORT_ERROR(fn, line_nb, "Error, y coordinate is not a valid floating point value"); 00162 return; 00163 } 00164 z = pt[2].toDouble(&ok); 00165 if(!ok) 00166 { 00167 REPORT_ERROR(fn, line_nb, "Error, z coordinate is not a valid floating point value"); 00168 return; 00169 } 00170 m = pt[3].toDouble(&ok); 00171 if(!ok) 00172 { 00173 REPORT_ERROR(fn, line_nb, "Error, m coordinate is not a valid floating point value"); 00174 return; 00175 } 00176 Point3d v(x,y,z); 00177 pts[ptid++] = v; 00178 } 00179 } 00180 } 00181 else if(version == 102) 00182 { 00183 while(!ts.atEnd()) 00184 { 00185 ++line_nb; 00186 QString line = ts.readLine().trimmed(); 00187 if(line.startsWith("name:")) 00188 { 00189 // Do nothing of the name 00190 } 00191 else if(line.startsWith("points:")) 00192 { 00193 QStringList nbpts = line.mid(7).trimmed().split(" "); 00194 if(nbpts.size() != 2) 00195 { 00196 REPORT_ERROR(fn, line_nb, "Error, there should be two values for the points number, not " << nbpts.size()); 00197 return; 00198 } 00199 bool ok; 00200 int nb_pts = nbpts[1].toInt(&ok); 00201 if(!ok) 00202 { 00203 REPORT_ERROR(fn, line_nb, "Error, number of control points is not a number"); 00204 return; 00205 } 00206 pts.resize(nb_pts); 00207 } 00208 else if(line.startsWith("type:")) 00209 { 00210 QString type = line.mid(5).trimmed().toLower(); 00211 if(type.size() != 2) 00212 { 00213 REPORT_ERROR(fn, line_nb, "Error reading contour type: '" << type << "'"); 00214 return; 00215 } 00216 if(type[0] == 'c') 00217 closed = true; 00218 else if(type[0] == 'o') 00219 closed = false; 00220 else 00221 { 00222 REPORT_ERROR(fn, line_nb, "Unknown contour type: " << type); 00223 return; 00224 } 00225 if(type[1] == 'e') 00226 { 00227 regular = false; 00228 err << "Warning, this contour reader doesn't handle contours that are not regular" << endl; 00229 } 00230 else if(type[1] == 'r') 00231 { 00232 regular = true; 00233 } 00234 else 00235 { 00236 REPORT_ERROR(fn, line_nb, "Unknown contour type: " << type); 00237 return; 00238 } 00239 } 00240 else 00241 { 00242 if(ptid >= (int)pts.size()) 00243 { 00244 REPORT_ERROR(fn, line_nb, "There are more control points defined than declared"); 00245 return; 00246 } 00247 QStringList pt = line.split(" "); 00248 if(pt.size() != 4) 00249 { 00250 REPORT_ERROR(fn, line_nb, "A points should be described with four values"); 00251 return; 00252 } 00253 bool ok; 00254 double x,y,z,m; 00255 x = pt[0].toDouble(&ok); 00256 if(!ok) 00257 { 00258 REPORT_ERROR(fn, line_nb, "Error, x coordinate is not a valid floating point value"); 00259 return; 00260 } 00261 y = pt[1].toDouble(&ok); 00262 if(!ok) 00263 { 00264 REPORT_ERROR(fn, line_nb, "Error, y coordinate is not a valid floating point value"); 00265 return; 00266 } 00267 z = pt[2].toDouble(&ok); 00268 if(!ok) 00269 { 00270 REPORT_ERROR(fn, line_nb, "Error, z coordinate is not a valid floating point value"); 00271 return; 00272 } 00273 m = pt[3].toDouble(&ok); 00274 if(!ok) 00275 { 00276 REPORT_ERROR(fn, line_nb, "Error, m coordinate is not a valid floating point value"); 00277 return; 00278 } 00279 Point3d v(x,y,z); 00280 pts[ptid++] = v; 00281 } 00282 } 00283 } 00284 else if(version == 103) 00285 { 00286 while(!ts.atEnd()) 00287 { 00288 ++line_nb; 00289 QString line = ts.readLine().trimmed(); 00290 if(line.startsWith("name:")) 00291 { 00292 // Do nothing of the name 00293 } 00294 else if(line.startsWith("points:")) 00295 { 00296 QStringList nbpts = line.mid(7).trimmed().split(" "); 00297 if(nbpts.size() != 2) 00298 { 00299 REPORT_ERROR(fn, line_nb, "Error, there should be two values for the points number, not " << nbpts.size()); 00300 return; 00301 } 00302 bool ok; 00303 int nb_pts = nbpts[1].toInt(&ok); 00304 if(!ok) 00305 { 00306 REPORT_ERROR(fn, line_nb, "Error, number of control points is not a number"); 00307 return; 00308 } 00309 pts.resize(nb_pts); 00310 } 00311 else if(line.startsWith("type:")) 00312 { 00313 QString type = line.mid(5).trimmed().toLower(); 00314 if(type.size() != 2) 00315 { 00316 REPORT_ERROR(fn, line_nb, "Error reading contour type: '" << type << "'"); 00317 return; 00318 } 00319 if(type[0] == 'c') 00320 closed = true; 00321 else if(type[0] == 'o') 00322 closed = false; 00323 else 00324 { 00325 REPORT_ERROR(fn, line_nb, "Unknown contour type: " << type); 00326 return; 00327 } 00328 if(type[1] == 'e') 00329 { 00330 regular = false; 00331 err << "Warning, this contour reader doesn't handle contours that are not regular" << endl; 00332 } 00333 else if(type[1] == 'r') 00334 { 00335 regular = true; 00336 } 00337 else 00338 { 00339 REPORT_ERROR(fn, line_nb, "Unknown contour type: " << type); 00340 return; 00341 } 00342 } 00343 else if(line.startsWith("samples:")) 00344 { 00345 // ignore that 00346 } 00347 else 00348 { 00349 if(ptid >= (int)pts.size()) 00350 { 00351 REPORT_ERROR(fn, line_nb, "There are more control points defined than declared"); 00352 return; 00353 } 00354 QStringList pt = line.split(" "); 00355 if(pt.size() != 4) 00356 { 00357 REPORT_ERROR(fn, line_nb, "A points should be described with four values"); 00358 return; 00359 } 00360 bool ok; 00361 double x,y,z,m; 00362 x = pt[0].toDouble(&ok); 00363 if(!ok) 00364 { 00365 REPORT_ERROR(fn, line_nb, "Error, x coordinate is not a valid floating point value"); 00366 return; 00367 } 00368 y = pt[1].toDouble(&ok); 00369 if(!ok) 00370 { 00371 REPORT_ERROR(fn, line_nb, "Error, y coordinate is not a valid floating point value"); 00372 return; 00373 } 00374 z = pt[2].toDouble(&ok); 00375 if(!ok) 00376 { 00377 REPORT_ERROR(fn, line_nb, "Error, z coordinate is not a valid floating point value"); 00378 return; 00379 } 00380 m = pt[3].toDouble(&ok); 00381 if(!ok) 00382 { 00383 REPORT_ERROR(fn, line_nb, "Error, m coordinate is not a valid floating point value"); 00384 return; 00385 } 00386 Point3d v(x,y,z); 00387 pts[ptid++] = v; 00388 } 00389 } 00390 } 00391 else 00392 { 00393 REPORT_ERROR(fn, line_nb, "Cannot handle version " << vmaj << " " << vmin); 00394 return; 00395 } 00396 00397 if(ptid < (int)pts.size()) 00398 { 00399 REPORT_ERROR(fn, line_nb, "There are less control points defined than declared"); 00400 return; 00401 } 00402 00403 if (closed) { 00404 pts.push_back(pts[0]); 00405 pts.push_back(pts[1]); 00406 pts.push_back(pts[2]); 00407 } 00408 #if defined(__APPLE__) || defined(linux) 00409 flock(f.handle(), LOCK_UN); 00410 #endif 00411 f.close(); 00412 }
Vector< 3, double > util::Contour::tangent | ( | double | t, | |
double | dt = 0.01 | |||
) |
Finds the tangent vector at a given parameter value.
t | Parameter value for where to take the tangent. | |
dt | The interval size used for the numerical evaluation. |
Definition at line 509 of file contour.cpp.
References util::Vector< dim, T >::normalize().
Referenced by normal().
double util::Contour::travel | ( | double | t, | |
double | l, | |||
double | dt = 0.01 | |||
) |
Return the paramter after traveling a given arc length.
t | Parameter for the start of the interval. | |
l | The arc length to travel. | |
dt | The step used for forward differencing. |
It is expected that t is in the interval of [0, 1] and that l is positive.
Definition at line 489 of file contour.cpp.
References length().
00489 { 00490 if (t < 0.0) t = 0.0; 00491 if (l < 0.0) return 0.0; 00492 if (l < dt) return t; 00493 00494 Vector<3,double> start = (*this)(t); 00495 double t_length = 0.0; 00496 double u = t + dt; 00497 while (t_length < l && t < 1.0) { 00498 t_length += this->length(t, u, dt); 00499 t = u; 00500 u += dt; 00501 } 00502 return t; 00503 }