#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 }
|
1.2.12 written by Dimitri van Heesch,
© 1997-2001