#include <HxBSplineCurve.h>
Public Methods | |
HxBSplineCurve () | |
Construct default curve. More... | |
HxBSplineCurve (const HxBSplineBasis &basis, const HxPointSetR2 &cp) | |
Construct a curve with given basis and control points. More... | |
~HxBSplineCurve () | |
Destructor. More... | |
int | ident () const |
Get the identifier. More... | |
HxBSplineBasis | basis () const |
Get the basis. More... | |
HxBSplineType | curveType () const |
Get the curve type. More... | |
int | degree () const |
Get the degree of the curve. More... | |
double | minT () const |
Get the minimum value of T. More... | |
double | maxT () const |
Get the maximum value of T. More... | |
HxBSplineInterval | getInterval (double t1, double t2) const |
Get the curve interval determined by t1, t2. More... | |
int | numP () const |
Get the number of control points. More... | |
HxPointR2 | P (int i) const |
Get the coordinates of control point i. More... | |
HxPointSetR2 | allP () const |
Get the coordinates of all control points. More... | |
HxPolyline2d | controlP () const |
Get the control polygon. More... | |
double | B (int i, double t) const |
Get the value of basis i at path position t. More... | |
double | dB (int order, int i, double t) const |
Get derivative of basis i at path position t. More... | |
HxBSplineInterval | pathAffectedBy (int index) const |
Get the curve interval affected by given control point. More... | |
vector< int > | PThatAffectCAt (double t) const |
Get the indices of control points that affect the curve at path position t. More... | |
vector< int > | PThatAffectCAt (const HxBSplineInterval &interval) const |
Get the indices of control points that affect the curve inside given interval. More... | |
HxPointR2 | C (double t) const |
Get the curve point at path position t. More... | |
HxVectorR2 | dC (int order, double t) const |
Get the curve derivative at path position t. More... | |
double | kAtC (double t) const |
Get curvature at path position t. More... | |
double | dTurnAngleAtC (double t) const |
Get derivative of turning angle at path position t. More... | |
double | length (int n=50) const |
Get the total curve length based on distance between the given number of samples (n). More... | |
double | length (const HxBSplineInterval &interval, int n=50) const |
Get the length of the given curve interval. More... | |
HxPointR2 | center () const |
Get the center of control polygon. More... | |
HxPolyline2d | sampleC (int n=50) const |
Sample the curve at n points. More... | |
HxBSplineCurve | changeAllP (const HxPointSetR2 &p) const |
Replace the coordinates of all control points. More... | |
HxBSplineCurve | translateAllP (const HxVectorR2 &v) const |
Translate all control points. More... | |
HxBSplineCurve | scaleAllP (double s) const |
Scale control polygon using center as origin. More... | |
HxBSplineCurve | translateCurve (const HxVectorR2 &v, double t) const |
Translate the given point in the curve in the given direction modifying only one control point (NURBS book p.511-513). More... | |
HxBSplineCurve | translateCurve (const HxPointR2 &pDest, double t) const |
Translate the given point in the curve to the given position modifying only one control point (NURBS book p.511-513). More... | |
HxBSplineCurve | translateCurve2 (const HxVectorR2 &v, double t) const |
Translate the given point in the curve to the given position modifying two control points (NURBS book p.511-513). More... | |
HxBSplineCurve | insertKnot (double t, int n=1) const |
Insert a given number of knots in the curve with corresponding control point without changing parametrization and geometry. More... | |
STD_OSTREAM & | dump (STD_OSTREAM &) const |
Dump the curve on the given stream. More... | |
Static Public Methods | |
HxBSplineCurve | makeUniform (HxPolyline2d cp, int degree) |
Make a curve with uniform knots. More... | |
HxBSplineCurve | makeInterpolating (HxPolyline2d cp) |
Make an interpolating curve (uniform knots). More... |
Based on "Curve and Surface Fitting with Splines", by "Dierckx,P.", "Oxford", "1993", chapter "Univariate Splines", and "The NURBS book", "Piegl, L. and Tiller, W.", Springer, 1997.
|
Construct default curve.
00021 { 00022 _ident = _nr++; 00023 makeDefault(); 00024 } |
|
Construct a curve with given basis and control points.
00027 : _basis(basis) 00028 { 00029 _ident = _nr++; 00030 if ( vectorOfCP.size() != numP() ) { 00031 message("(constructor) invalid number of control points - making default"); 00032 makeDefault(); 00033 } 00034 else 00035 _PVec = vectorOfCP; 00036 } |
|
Destructor.
00064 { 00065 } |
|
Make a curve with uniform knots.
00040 { 00041 HxBSplineType type = (cp.getClosed())? closed : openRepeatEndPoints; 00042 HxPointSetR2 p = cp.getPoints(); 00043 00044 int nInt; 00045 if (cp.getClosed()) 00046 nInt = p.size(); 00047 else 00048 nInt = p.size() - degree; 00049 00050 HxBSplineBasis base(type, degree, nInt, uniformKnots, 0, 1); 00051 return HxBSplineCurve(base, p); 00052 } |
|
Make an interpolating curve (uniform knots).
00056 { 00057 HxLocalInterpol interpol(3, cp.getPoints(), cp.getClosed()); 00058 HxBSplineType type = (cp.getClosed())? closed : open; 00059 HxBSplineBasis base(type, 3, interpol.allKnots()); 00060 return HxBSplineCurve(base, interpol.allP()); 00061 } |
|
Get the identifier.
00200 { 00201 return _ident; 00202 } |
|
Get the basis.
00206 { 00207 return _basis; 00208 } |
|
Get the curve type.
00212 { 00213 return _basis.curveType(); 00214 } |
|
Get the degree of the curve.
00218 { 00219 return _basis.degree(); 00220 } |
|
Get the minimum value of T.
00224 { 00225 return _basis.minT(); 00226 } |
|
Get the maximum value of T.
00230 { 00231 return _basis.maxT(); 00232 } |
|
Get the curve interval determined by t1, t2.
00236 { 00237 return HxBSplineInterval(t1, t2, 00238 _basis.minT(), _basis.maxT(), _basis.curveType()); 00239 } |
|
Get the number of control points.
00261 { 00262 return _basis.numB(); 00263 } |
|
Get the coordinates of control point i.
00267 { 00268 if ( i < 0 || i >= numP() ) { 00269 message("(P) invalid index - setting to 0"); 00270 i = 0; 00271 } 00272 return _PVec[i]; 00273 } |
|
Get the coordinates of all control points.
00277 { 00278 return _PVec; 00279 } |
|
Get the control polygon.
00283 { 00284 return HxPolyline2d(_PVec, (curveType() == closed)); 00285 } |
|
Get the value of basis i at path position t.
00243 { 00244 return _basis.B(i, t); 00245 } |
|
Get derivative of basis i at path position t.
00249 { 00250 return _basis.dB(order, i, t); 00251 } |
|
Get the curve interval affected by given control point.
00255 { 00256 return _basis.pathAffectedBy(index); 00257 } |
|
Get the indices of control points that affect the curve at path position t.
00073 { 00074 if ( t < minT() ) { 00075 message("(PThatAffectCAt) invalid t - setting to minT()"); 00076 t = minT(); 00077 } 00078 if ( t >= maxT() ) { 00079 message("(PThatAffectCAt) invalid t - setting near to maxT()"); 00080 t = maxT() - EPS; 00081 } 00082 00083 vector<int> b; 00084 int index = _basis.whichInterval(t); 00085 for ( int i=index; i <= index + degree(); i++) 00086 b.push_back(indexPVec(i)); 00087 00088 return b; 00089 } |
|
Get the indices of control points that affect the curve inside given interval.
00097 { 00098 int i = indexPVec(_basis.whichInterval(interval.begin())); 00099 int f = indexPVec(_basis.whichInterval(interval.end()) + degree()); 00100 00101 vector<int> b; 00102 while (i != f) { 00103 b.push_back(indexPVec(i)); 00104 if ( ++i >= numP() ) 00105 i = 0; // wrap closed curve 00106 }; 00107 b.push_back(indexPVec(f)); 00108 return b; 00109 } |
|
Get the curve point at path position t.
00295 { 00296 HxVectorR2 tmp = dC( 0, t); 00297 return HxPointR2(tmp.x(), tmp.y()); 00298 } |
|
Get the curve derivative at path position t.
00121 { 00122 if ( t < minT() ) { 00123 message("(dC) invalid t - setting to minT()"); 00124 t = minT(); 00125 } 00126 if ( t >= maxT() ) { 00127 message("(dC) invalid t - setting near to maxT()"); 00128 t = maxT() - EPS; 00129 } 00130 if ( ! inRange(order, 0, degree()-1) ) { 00131 message("(dC) derivative not defined - fixing to 1st"); 00132 order = 1; 00133 } 00134 00135 double multterm = 1; 00136 int i; 00137 for (i = 1 ; i <= order ; i++) 00138 multterm *= (degree()+1-i); 00139 00140 int index = _basis.whichInterval(t); 00141 double sumtermx = 0, sumtermy = 0; 00142 for (i = index+order ; i <= index + degree(); i++) { 00143 double nterm = _basis.nim(t,i,degree()+1-order); 00144 HxPointR2 cterm = civ(i,order); 00145 sumtermx += cterm.x() * nterm; 00146 sumtermy += cterm.y() * nterm; 00147 } 00148 00149 return HxVectorR2(multterm*sumtermx, multterm*sumtermy); 00150 } |
|
Get curvature at path position t.
00158 { 00159 if ( degree() <= 2 ) { 00160 message("(kAtC) can't compute curvature - returning 0"); 00161 return 0; 00162 } 00163 00164 HxVectorR2 d1 = dC(1,t); 00165 HxVectorR2 d2 = dC(2,t); 00166 double l2 = d1.squaredMagnitude(); 00167 double l = sqrt(l2); 00168 return (d1.x() * d2.y() - d2.x() * d1.y()) / (l * l2); 00169 } |
|
Get derivative of turning angle at path position t.
00177 { 00178 if ( degree() <= 2 ) { 00179 message("(dTurnAngleAtC) can't compute curvature - returning 0"); 00180 return 0; 00181 } 00182 00183 HxVectorR2 d1 = dC(1,t); 00184 HxVectorR2 d2 = dC(2,t); 00185 double l2 = d1.squaredMagnitude(); 00186 return (d1.x() * d2.y() - d2.x() * d1.y()) / l2; 00187 } |
|
Get the total curve length based on distance between the given number of samples (n).
00231 { 00232 double length = 0.0; 00233 double d = (maxT()-EPS - minT() ) / np; 00234 00235 if ( degree() > 1 ) { 00236 for ( double t = minT(); t < maxT(); t+= d) 00237 length += dC(1,t).magnitude(); 00238 return length*d; 00239 } else { 00240 HxPointR2 p1 = C(minT()); 00241 for ( double t = minT(); t < maxT(); t+= d) { 00242 HxPointR2 p2 = C(t); 00243 HxVectorR2 v(p2,p1); 00244 length += v.magnitude(); 00245 p1 = p2; 00246 } 00247 if ( curveType() == closed ) { 00248 HxVectorR2 v(C(minT()), p1); 00249 length += v.magnitude(); 00250 } 00251 return length; 00252 } 00253 } |
|
Get the length of the given curve interval.
00197 { 00198 double length = 0.0; 00199 double d = part.length()/ np; 00200 00201 if ( degree() > 1 ) { 00202 double t=part.begin(); 00203 for ( int i=0; i < np; i++) { 00204 length += dC(1,t).magnitude(); 00205 t=part.next(t, d); 00206 } 00207 return length*d; 00208 } else { 00209 HxPointR2 p1 = C(part.begin()); 00210 HxPointR2 p2; 00211 double t= part.next(part.begin(),d); 00212 for ( int i=0; i < np; i++) { 00213 p2 = C(t); 00214 HxVectorR2 v(p2,p1); 00215 length += v.magnitude(); 00216 p1 = p2; 00217 t=part.next(t, d); 00218 } 00219 return length; 00220 } 00221 } |
|
Get the center of control polygon.
00278 { 00279 double sumX=0, sumY=0; 00280 for (int i=0; i < _PVec.size(); i++) { 00281 sumX += _PVec[i].x(); 00282 sumY += _PVec[i].y(); 00283 } 00284 return HxPointR2( sumX/_PVec.size(), sumY/_PVec.size()); 00285 } |
|
Sample the curve at n points.
|
|
Replace the coordinates of all control points.
00289 { 00290 return HxBSplineCurve(_basis, p); 00291 } |
|
Translate all control points.
00293 { 00294 HxPointSetR2 tmp(_PVec.size()); 00295 for (int i=0; i < tmp.size(); i++) { 00296 tmp[i] = _PVec[i].add(v); 00297 } 00298 return HxBSplineCurve( _basis, tmp); 00299 } |
|
Scale control polygon using center as origin.
00309 { 00310 HxPointSetR2 tmp(_PVec.size()); 00311 HxPointR2 origin(center()); 00312 for (int i=0; i < tmp.size(); i++) { 00313 HxVectorR2 v(_PVec[i],origin); 00314 tmp[i] = origin.add(v.mul(s)); 00315 } 00316 return HxBSplineCurve( _basis, tmp); 00317 } |
|
Translate the given point in the curve in the given direction modifying only one control point (NURBS book p.511-513).
00329 { 00330 HxBSplineCurve tmp(*this); 00331 if ( absolute(basis().nearestKnot(t)-t) > EPS ) 00332 tmp= insertKnot(t); 00333 00334 // determine CP to move and vector 00335 int i = tmp._basis.maxBasis(t); 00336 double d = vec.magnitude(); 00337 double alpha = d / tmp._basis.B(i, t); 00338 HxVectorR2 V = vec.div(d).mul(alpha); 00339 00340 // update control point 00341 int index = tmp.indexPVec(i); 00342 tmp._PVec[index] = tmp._PVec[index].add(V); 00343 00344 return tmp; 00345 } |
|
Translate the given point in the curve to the given position modifying only one control point (NURBS book p.511-513).
00302 { 00303 return translateCurve( HxVectorR2(pDest, C(t)), t); 00304 } |
|
Translate the given point in the curve to the given position modifying two control points (NURBS book p.511-513).
00357 { 00358 HxBSplineCurve tmp(*this); 00359 HxBSplineBasis tmpBasis(tmp._basis); 00360 00361 // determine two CP to move 00362 int k = tmpBasis.maxBasis(t); 00363 double kNode = tmpBasis.node(k); 00364 while ( kNode >= t ) { 00365 k--; 00366 if ( k < 0 ) 00367 k = tmpBasis.nIntervals()-1; 00368 kNode = tmpBasis.node(k); 00369 } 00370 00371 int k1; 00372 if ( k >= tmpBasis.nIntervals() ) 00373 k1 = 0; 00374 else k1 = k+1; 00375 double k1Node = tmpBasis.node(k1); 00376 00377 // determine proportion of each CP 00378 HxBSplineInterval intA( kNode, t, minT(), maxT(), curveType()); 00379 HxBSplineInterval intB( kNode, k1Node, minT(), maxT(), curveType()); 00380 double l = intA.length() / intB.length(); 00381 00382 // determine motion vector 00383 double d = vec.magnitude(); 00384 double alpha = d / ( (1-l)*tmpBasis.B(k, t) + l*tmpBasis.B(k1, t) ); 00385 HxVectorR2 V = vec.div(d).mul(alpha); 00386 00387 // update control points 00388 int index = tmp.indexPVec(k); 00389 tmp._PVec[index] = tmp._PVec[index].add(V.mul(1-l)); 00390 index = tmp.indexPVec(k1); 00391 tmp._PVec[index] = tmp._PVec[index].add(V.mul(l)); 00392 00393 return tmp; 00394 } |
|
Insert a given number of knots in the curve with corresponding control point without changing parametrization and geometry.
00404 { 00405 if ( t < minT() ) { 00406 message("(insertKnot) invalid knot - setting to minT()"); 00407 t = minT(); 00408 } 00409 if ( t >= maxT() ) { 00410 message("(insertKnot) invalid knot - setting near to maxT()"); 00411 t = maxT() - EPS; 00412 } 00413 if ( n != 1 ) { 00414 message("(insertKnot) multiple knot insertion not supported - inserting 1 knot"); 00415 n=1; 00416 } 00417 00418 HxBSplineBasis newB = _basis.insertKnot(t,n); 00419 HxPointSetR2 newP = _PVec; 00420 00421 vector<HxVectorR2> aux(degree()+1); 00422 int ii1 = _basis.whichInterval(t); 00423 int ii2 = _basis.internalBasisIndex(ii1,t); 00424 int k = ii2 + degree(); 00425 int j =1; 00426 int s =0; // multiplicity 00427 00428 int i; 00429 for (i=0; i <= degree()-s; i++) { 00430 HxPointR2 p = newP[indexPVec(k-degree()+i)]; 00431 aux[i] = HxVectorR2(p.x(), p.y()); 00432 } 00433 00434 int L = k - degree() + j; 00435 // newP.insert(newP.begin()+indexPVec(L), n, HxPointR2(0,0)); 00436 newP.insert(newP.begin()+L, n, HxPointR2(0,0)); 00437 for ( i=0; i <= degree() -j-s; i++) { 00438 double a = (t - _basis._knotsVec[L+i]) / 00439 (_basis._knotsVec[i+k+1] - _basis._knotsVec[L+i]); 00440 aux[i] = aux[i+1].mul(a).add(aux[i].mul(1.0-a)); 00441 } 00442 00443 HxBSplineCurve tmp(newB, newP); 00444 for ( i=L; i <= k-s; i++ ) { 00445 HxVectorR2 v(aux[i-L]); 00446 tmp._PVec[tmp.indexPVec(i)] = HxPointR2(v.x(), v.y()); 00447 } 00448 00449 return tmp; 00450 } |
|
Dump the curve on the given stream.
00458 { 00459 _basis.dump(os); 00460 00461 if ( _PVec.empty() ) { 00462 os << "\nNo Control Points"; 00463 } else { 00464 os << "P Vector: " << _PVec.size() << " points\n"; 00465 for ( int i = 0; i < _PVec.size(); i++ ) { 00466 os <<"("<< _PVec[i].x() << ","<<_PVec[i].y()<<") "; 00467 } 00468 } 00469 00470 os << STD_ENDL; 00471 return os; 00472 } |