00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef PLIB_NURBS_NURBS_SOURCE
00026 #define PLIB_NURBS_NURBS_SOURCE
00027
00028 #include <nurbs.h>
00029 #include <fstream>
00030 #include <string.h>
00031 #include <nurbsS.h>
00032 #include "integrate.h"
00033
00034 #include <malloc.h>
00035
00038 namespace PLib {
00039
00045 template <class T, int N>
00046 NurbsCurve<T,N>::NurbsCurve(): P(1),U(1),deg_(0)
00047 {
00048 }
00049
00058 template <class T, int N>
00059 NurbsCurve<T,N>::NurbsCurve(const NurbsCurve<T,N>& nurb):
00060 ParaCurve<T,N>(), P(nurb.P),U(nurb.U),deg_(nurb.deg_)
00061 {
00062 }
00063
00075 template <class T, int N>
00076 void NurbsCurve<T,N>::reset(const Vector< HPoint_nD<T,N> >& P1, const Vector<T> &U1, int Degree) {
00077 int nSize = P1.n() ;
00078 int mSize = U1.n() ;
00079 deg_ = Degree ;
00080 if(nSize != mSize-deg_-1){
00081 #ifdef USE_EXCEPTION
00082 throw NurbsSizeError(P1.n(),U1.n(),Degree) ;
00083 #else
00084 Error err("reset");
00085 err << "Invalid input size for the control points and the knot vector when reseting a Nurbs Curve.\n";
00086 err << nSize << " control points and " << mSize << " knots\n" ;
00087 err.fatal() ;
00088 #endif
00089 }
00090 P.resize(P1.n()) ;
00091 U.resize(U1.n()) ;
00092 P = P1 ;
00093 U = U1 ;
00094 }
00095
00108 template <class T, int N>
00109 NurbsCurve<T,N>::NurbsCurve(const Vector< HPoint_nD<T,N> >& P1, const Vector<T> &U1, int Degree): P(P1), U(U1), deg_(Degree)
00110 {
00111
00112 if(P.n() != U.n()-deg_-1){
00113 #ifdef USE_EXCEPTION
00114 throw NurbsSizeError(P.n(),U.n(),deg_) ;
00115 #else
00116 Error err("NurbsCurve(P1,U1,Degree)");
00117 err << "Invalid input size for the control points and the knot vector.\n";
00118 err << P.n() << " control points and " << U.n() << " knots\n" ;
00119 err.fatal() ;
00120 #endif
00121 }
00122 }
00123
00137 template <class T, int N>
00138 NurbsCurve<T,N>::NurbsCurve(const Vector< Point_nD<T,N> >& P1, const Vector<T>& W, const Vector<T>& U1, int Degree): P(P1.n()), U(U1), deg_(Degree)
00139 {
00140 int nSize = P1.n() ;
00141 int mSize = U1.n() ;
00142
00143 if(nSize != mSize-deg_-1){
00144 #ifdef USE_EXCEPTION
00145 throw NurbsSizeError(P.n(),U.n(),deg_) ;
00146 #else
00147 Error err("NurbsCurve(P1,W,U1,Degree)") ;
00148 err << "Invalid input size for the control points and the knot vector.\n" ;
00149 err << nSize << " control points and " << mSize << " knots\n" ;
00150 err.fatal() ;
00151 #endif
00152 }
00153 if(nSize != W.n()){
00154 #ifdef USE_EXCEPTION
00155 throw NurbsInputError(nSize,W.n()) ;
00156 #else
00157 Error err("NurbsCurve(P1,W,U1,Degree)") ;
00158 err << "Size mismatched between the control points and the weights\n" ;
00159 err << "ControlPoints size = " << nSize << ", Weight size = " << W.n() << endl ;
00160 err.fatal() ;
00161 #endif
00162 }
00163
00164 for(int i = 0 ;i<nSize;i++){
00165 const Point_nD<T,N>& pt = P1[i] ;
00166 for(int j=0;j<N;j++)
00167 P[i].data[j] = pt.data[j] * W[i] ;
00168 P[i].w() = W[i] ;
00169 }
00170 }
00171
00183 template <class T, int N>
00184 NurbsCurve<T,N>& NurbsCurve<T,N>::operator=(const NurbsCurve<T,N>& curve) {
00185 if(curve.U.n() != curve.P.n()+curve.deg_+1){
00186 #ifdef USE_EXCEPTION
00187 throw NurbsSizeError(curve.P.n(),curve.U.n(),curve.deg_) ;
00188 #else
00189 Error err("operator=") ;
00190 err << "Invalid assignment... the curve being assigned to isn't valid\n" ;
00191 err.fatal() ;
00192 #endif
00193 }
00194 deg_ = curve.deg_ ;
00195 U = curve.U ;
00196 P = curve.P ;
00197 if(U.n()!=P.n()+deg_+1){
00198 #ifdef USE_EXCEPTION
00199 throw NurbsSizeError(P.n(),U.n(),deg_) ;
00200 #else
00201 Error err("operator=") ;
00202 err << "Error in assignment... couldn't assign properly the vectors\n" ;
00203 err.fatal() ;
00204 #endif
00205 }
00206 return *this ;
00207 }
00208
00209
00228 template <class T, int N>
00229 void NurbsCurve<T,N>::drawImg(Image_UBYTE& Img,unsigned char color,T step){
00230 Point_nD<T,N> a1,a2 ;
00231 T u_max = U[U.n()-1-deg_] ;
00232 if(step<=0)
00233 step = 0.01 ;
00234 a1 = this->pointAt(U[deg_]) ;
00235 T u ;
00236 int i1,j1,i2,j2 ;
00237 getCoordinates(a1,i1,j1,Img.rows(),Img.cols()) ;
00238 for(u=U[deg_]+step ; u < u_max+(step/2.0) ; u+=step){
00239 a2 = this->pointAt(u) ;
00240 if(!getCoordinates(a2,i2,j2,Img.rows(),Img.cols()))
00241 continue ;
00242 Img.drawLine(i1,j1,i2,j2,color) ;
00243 i1 = i2 ;
00244 j1 = j2 ;
00245 }
00246 a2 = this->pointAt(U[P.n()]) ;
00247 if(getCoordinates(a2,i2,j2,Img.rows(),Img.cols()))
00248 Img.drawLine(i1,j1,i2,j2,color) ;
00249 }
00250
00269 template <class T, int N>
00270 void NurbsCurve<T,N>::drawImg(Image_Color& Img,const Color& color,T step){
00271 Point_nD<T,N> a1,a2 ;
00272 T u_max = U[U.n()-1-deg_] ;
00273 if(step<=0)
00274 step = 0.01 ;
00275 a1 = this->pointAt(U[deg_]) ;
00276 int i1,j1,i2,j2 ;
00277 getCoordinates(a1,i1,j1,Img.rows(),Img.cols()) ;
00278 T u ;
00279 for(u=U[deg_]+step ; u < u_max+(step/2.0) ; u+=step){
00280 a2 = this->pointAt(u) ;
00281 if(!getCoordinates(a2,i2,j2,Img.rows(),Img.cols()))
00282 continue ;
00283 Img.drawLine(i1,j1,i2,j2,color) ;
00284 i1 = i2 ;
00285 j1 = j2 ;
00286 }
00287 a2 = this->pointAt(U[P.n()]) ;
00288 if(getCoordinates(a2,i2,j2,Img.rows(),Img.cols()))
00289 Img.drawLine(i1,j1,i2,j2,color) ;
00290 }
00291
00312 template <class T, int N>
00313 void NurbsCurve<T,N>::drawAaImg(Image_Color& Img, const Color& color, int precision, int alpha){
00314 NurbsCurve<T,3> profile ;
00315
00316 profile.makeCircle(Point_nD<T,3>(0,0,0),Point_nD<T,3>(1,0,0),Point_nD<T,3>(0,0,1),1.0,0,M_PI) ;
00317 drawAaImg(Img,color,profile,precision,alpha) ;
00318 }
00319
00341 template <class T, int N>
00342 void NurbsCurve<T,N>::drawAaImg(Image_Color& Img, const Color& color, const NurbsCurve<T,3>& profile, int precision, int alpha){
00343 Vector< HPoint_nD<T,3> > sPts(2) ;
00344 sPts[0] = sPts[1] = HPoint_nD<T,3>(1,1,1,1) ;
00345 Vector<T> sKnot(4) ;
00346 sKnot[0] = sKnot[1] = 0.0 ;
00347 sKnot[2] = sKnot[3] = 1.0 ;
00348
00349 NurbsCurve<T,3> scaling(sPts,sKnot,1) ;
00350
00351 drawAaImg(Img,color,profile,scaling,precision,alpha) ;
00352 }
00353
00384 template <class T, int N>
00385 NurbsSurface<T,3> NurbsCurve<T,N>::drawAaImg(Image_Color& Img, const Color& color, const NurbsCurve<T,3>& profile, const NurbsCurve<T,3>& scaling, int precision, int alpha){
00386 Matrix<T> addMatrix ;
00387 Matrix_INT nMatrix ;
00388
00389 addMatrix.resize(Img.rows(),Img.cols()) ;
00390 nMatrix.resize(Img.rows(),Img.cols()) ;
00391
00392 int i,j ;
00393
00394 T du,dv ;
00395
00396 Point_nD<T,N> a,b,c ;
00397 a = pointAt(0.0) ;
00398 b = pointAt(0.5) ;
00399 c = pointAt(1.0) ;
00400
00401 T distance = norm(b-a) + norm(c-b) ;
00402
00403 dv = distance*T(precision) ;
00404 dv = (U[U.n()-1]-U[0])/dv ;
00405
00406
00407 Point_nD<T,3> a2,b2,c2 ;
00408 a2 = profile.pointAt(0.0) ;
00409 b2 = profile.pointAt(0.5) ;
00410 c2 = profile.pointAt(1.0) ;
00411 distance = norm(b2-a2) + norm(c2-b2) ;
00412 du = distance*T(precision) ;
00413 du = (profile.knot()[profile.knot().n()-1]-profile.knot()[0])/du ;
00414
00415 NurbsSurface<T,3> drawCurve ;
00416 NurbsCurve<T,3> trajectory ;
00417
00418 to3D(*this,trajectory) ;
00419
00420 drawCurve.sweep(trajectory,profile,scaling,P.n()-1) ;
00421
00422 T u,v ;
00423
00424 for(u=U[0];u<U[U.n()-1];u+=du)
00425 for(v=profile.knot()[0];v<profile.knot()[profile.knot().n()-1];v+=dv){
00426 Point_nD<T,3> p ;
00427 p = drawCurve.pointAt(u,v) ;
00428 if(getCoordinates(p,i,j,Img.rows(),Img.cols())){
00429 addMatrix(i,j) += p.z() ;
00430 nMatrix(i,j) += 1 ;
00431 }
00432 }
00433
00434 T maxP = 1.0 ;
00435 for(i=0;i<Img.rows();++i)
00436 for(j=0;j<Img.cols();++j){
00437 addMatrix(i,j) /= T(nMatrix(i,j)) ;
00438 if(addMatrix(i,j)>maxP)
00439 maxP = addMatrix(i,j) ;
00440 }
00441
00442 for(i=0;i<Img.rows();++i)
00443 for(j=0;j<Img.cols();++j){
00444 if(nMatrix(i,j)){
00445 double mean = double(addMatrix(i,j))/double(maxP) ;
00446 if(alpha){
00447 Img(i,j).r = (unsigned char)(mean*double(color.r)+(1.0-mean)*double(Img(i,j).r)) ;
00448 Img(i,j).g = (unsigned char)(mean*double(color.g)+(1.0-mean)*double(Img(i,j).g)) ;
00449 Img(i,j).b = (unsigned char)(mean*double(color.b)+(1.0-mean)*double(Img(i,j).b)) ;
00450 }
00451 else{
00452 Img(i,j) = mean*color ;
00453 }
00454 }
00455 }
00456 return drawCurve ;
00457 }
00458
00470 template <class T, int N>
00471 void NurbsCurve<T,N>::transform(const MatrixRT<T>& A){
00472 for(int i=P.n()-1;i>=0;--i)
00473 P[i] = A*P[i] ;
00474 }
00475
00499 template <class T, int N>
00500 HPoint_nD<T,N> NurbsCurve<T,N>::operator()(T u) const{
00501 static Vector<T> Nb ;
00502 int span = findSpan(u) ;
00503
00504 basisFuns(u,span,Nb) ;
00505
00506 HPoint_nD<T,N> p(0) ;
00507 for(int i=deg_;i>=0;--i) {
00508 p += Nb[i] * P[span-deg_+i] ;
00509 }
00510 return p ;
00511 }
00512
00536 template <class T, int N>
00537 HPoint_nD<T,N> NurbsCurve<T,N>::hpointAt(T u, int span) const{
00538 static Vector<T> Nb ;
00539
00540 basisFuns(u,span,Nb) ;
00541
00542 HPoint_nD<T,N> p(0,0,0,0) ;
00543 for(int i=deg_;i>=0;--i) {
00544 p += Nb[i] * P[span-deg_+i] ;
00545 }
00546 return p ;
00547 }
00548
00565 template <class T, int N>
00566 Point_nD<T,N> NurbsCurve<T,N>::derive3D(T u, int d) const {
00567 Vector< Point_nD<T,N> > ders ;
00568 deriveAt(u,d,ders) ;
00569 return ders[d] ;
00570 }
00571
00588 template <class T, int N>
00589 HPoint_nD<T,N> NurbsCurve<T,N>::derive(T u, int d) const {
00590 Vector< HPoint_nD<T,N> > ders ;
00591 deriveAtH(u,d,ders) ;
00592 return ders[d] ;
00593 }
00594
00611 template <class T, int N>
00612 void NurbsCurve<T,N>::deriveAtH(T u,int d, Vector< HPoint_nD<T,N> >& ders) const{
00613 int du = minimum(d,deg_) ;
00614 int span ;
00615 Matrix<T> derF(du+1,deg_+1) ;
00616 ders.resize(d+1) ;
00617
00618 span = findSpan(u) ;
00619 dersBasisFuns(du,u,span,derF) ;
00620 for(int k=du;k>=0;--k){
00621 ders[k] = 0 ;
00622 for(int j=deg_;j>=0;--j){
00623 ders[k] += derF(k,j)*P[span-deg_+j] ;
00624 }
00625 }
00626 }
00627
00643 template <class T, int N>
00644 void NurbsCurve<T,N>::deriveAtH(T u, int d, int span, Vector< HPoint_nD<T,N> >& ders) const{
00645 int du = minimum(d,deg_) ;
00646 Matrix<T> derF(du+1,deg_+1) ;
00647 ders.resize(d+1) ;
00648
00649 dersBasisFuns(du,u,span,derF) ;
00650 for(int k=du;k>=0;--k){
00651 ders[k] = 0 ;
00652 for(int j=deg_;j>=0;--j){
00653 ders[k] += derF(k,j)*P[span-deg_+j] ;
00654 }
00655 }
00656 }
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00685 template <class T>
00686 void binomialCoef(Matrix<T>& Bin){
00687 int n,k ;
00688
00689 Bin(0,0) = 1.0 ;
00690 for(k=Bin.cols()-1;k>0;--k)
00691 Bin(0,k) = 0.0 ;
00692
00693 for(n=0;n<Bin.rows()-1;n++){
00694 Bin(n+1,0) = 1.0 ;
00695 for(k=1;k<Bin.cols();k++)
00696 if(n+1<k)
00697 Bin(n,k) = 0.0 ;
00698 else
00699 Bin(n+1,k) = Bin(n,k) + Bin(n,k-1) ;
00700 }
00701 }
00702
00714 template <class T, int N>
00715 void NurbsCurve<T,N>::deriveAt(T u, int d, Vector< Point_nD<T,N> >& ders) const{
00716 Vector< HPoint_nD<T,N> > dersW ;
00717 deriveAtH(u,d,dersW) ;
00718 Point_nD<T,N> v ;
00719 int k,i ;
00720 ders.resize(d+1) ;
00721
00722 static Matrix<T> Bin(1,1) ;
00723 if(Bin.rows() != d+1){
00724 Bin.resize(d+1,d+1) ;
00725 binomialCoef(Bin) ;
00726 }
00727
00728
00729
00730 for(k=0;k<=d;k++){
00731 v.x() = dersW[k].x() ;
00732 v.y() = dersW[k].y() ;
00733 v.z() = dersW[k].z() ;
00734 for(i=k ;i>0 ;--i){
00735 v -= (Bin(k,i)*dersW[i].w())*ders[k-i] ;
00736 }
00737 ders[k] = v ;
00738 ders[k] /= dersW[0].w() ;
00739 }
00740 }
00741
00754 template <class T, int N>
00755 void NurbsCurve<T,N>::deriveAt(T u, int d, int span, Vector< Point_nD<T,N> >& ders) const{
00756 Vector< HPoint_nD<T,N> > dersW ;
00757 deriveAtH(u,d,span,dersW) ;
00758 Point_nD<T,N> v ;
00759 int k,i ;
00760 ders.resize(d+1) ;
00761
00762 static Matrix<T> Bin(1,1) ;
00763 if(Bin.rows() != d+1){
00764 Bin.resize(d+1,d+1) ;
00765 binomialCoef(Bin) ;
00766 }
00767
00768
00769
00770 for(k=0;k<=d;k++){
00771 v.x() = dersW[k].x() ;
00772 v.y() = dersW[k].y() ;
00773 v.z() = dersW[k].z() ;
00774 for(i=k ;i>0 ;--i){
00775 v -= (Bin(k,i)*dersW[i].w())*ders[k-i];
00776 }
00777 ders[k] = v ;
00778 ders[k] /= dersW[0].w() ;
00779 }
00780 }
00781
00798 template <class T, int N>
00799 Point_nD<T,N> NurbsCurve<T,N>::normal(T u, const Point_nD<T,N>& v) const{
00800 return crossProduct(firstDn(u),v) ;
00801 }
00802
00839 template <class T, int D>
00840 T NurbsCurve<T,D>::basisFun(T u, int i, int p) const{
00841 T Nip ;
00842 T saved,Uleft,Uright,temp ;
00843
00844 if(p<1)
00845 p = deg_ ;
00846
00847 if((i==0 && u == U[0]) ||
00848 (i == U.n()-p-2 && u==U[U.n()-1])){
00849 Nip = 1.0 ;
00850 return Nip ;
00851 }
00852 if(u<U[i] || u>=U[i+p+1]){
00853 Nip = 0.0 ;
00854 return Nip;
00855 }
00856 T* N = (T*) alloca((p+1)*sizeof(T)) ;
00857
00858
00859 int j ;
00860 for(j=p;j>=0;--j){
00861 if(u>=U[i+j] && u<U[i+j+1])
00862 N[j] = 1.0 ;
00863 else
00864 N[j] = 0.0 ;
00865 }
00866 for(int k=1; k<=p ; k++){
00867 if(N[0] == 0.0)
00868 saved = 0.0 ;
00869 else
00870 saved = ( (u-U[i])*N[0])/(U[i+k]-U[i]) ;
00871 for(j=0;j<p-k+1;j++){
00872 Uleft = U[i+j+1] ;
00873 Uright = U[i+j+k+1] ;
00874 if(N[j+1]==0.0){
00875 N[j] = saved ;
00876 saved = 0.0 ;
00877 }
00878 else {
00879 temp = N[j+1]/(Uright-Uleft) ;
00880 N[j] = saved+(Uright-u)*temp ;
00881 saved = (u-Uleft)*temp ;
00882 }
00883 }
00884 }
00885 Nip = N[0] ;
00886
00887 return Nip ;
00888 }
00889
00890
00891
00911 template <class T, int N>
00912 void NurbsCurve<T,N>::dersBasisFuns(int n,T u, int span, Matrix<T>& ders) const {
00913 T* left = (T*) alloca(2*(deg_+1)*sizeof(T)) ;
00914 T* right = &left[deg_+1] ;
00915
00916 Matrix<T> ndu(deg_+1,deg_+1) ;
00917 T saved,temp ;
00918 int j,r ;
00919
00920 ders.resize(n+1,deg_+1) ;
00921
00922 ndu(0,0) = 1.0 ;
00923 for(j=1; j<= deg_ ;j++){
00924 left[j] = u-U[span+1-j] ;
00925 right[j] = U[span+j]-u ;
00926 saved = 0.0 ;
00927
00928 for(r=0;r<j ; r++){
00929
00930 ndu(j,r) = right[r+1]+left[j-r] ;
00931 temp = ndu(r,j-1)/ndu(j,r) ;
00932
00933 ndu(r,j) = saved+right[r+1] * temp ;
00934 saved = left[j-r] * temp ;
00935 }
00936
00937 ndu(j,j) = saved ;
00938 }
00939
00940 for(j=deg_;j>=0;--j)
00941 ders(0,j) = ndu(j,deg_) ;
00942
00943
00944 Matrix<T> a(deg_+1,deg_+1) ;
00945 for(r=0;r<=deg_;r++){
00946 int s1,s2 ;
00947 s1 = 0 ; s2 = 1 ;
00948 a(0,0) = 1.0 ;
00949
00950 for(int k=1;k<=n;k++){
00951 T d ;
00952 int rk,pk,j1,j2 ;
00953 d = 0.0 ;
00954 rk = r-k ; pk = deg_-k ;
00955
00956 if(r>=k){
00957 a(s2,0) = a(s1,0)/ndu(pk+1,rk) ;
00958 d = a(s2,0)*ndu(rk,pk) ;
00959 }
00960
00961 if(rk>=-1){
00962 j1 = 1 ;
00963 }
00964 else{
00965 j1 = -rk ;
00966 }
00967
00968 if(r-1 <= pk){
00969 j2 = k-1 ;
00970 }
00971 else{
00972 j2 = deg_-r ;
00973 }
00974
00975 for(j=j1;j<=j2;j++){
00976 a(s2,j) = (a(s1,j)-a(s1,j-1))/ndu(pk+1,rk+j) ;
00977 d += a(s2,j)*ndu(rk+j,pk) ;
00978 }
00979
00980 if(r<=pk){
00981 a(s2,k) = -a(s1,k-1)/ndu(pk+1,r) ;
00982 d += a(s2,k)*ndu(r,pk) ;
00983 }
00984 ders(k,r) = d ;
00985 j = s1 ; s1 = s2 ; s2 = j ;
00986 }
00987 }
00988
00989
00990 r = deg_ ;
00991 for(int k=1;k<=n;k++){
00992 for(j=deg_;j>=0;--j)
00993 ders(k,j) *= r ;
00994 r *= deg_-k ;
00995 }
00996
00997 }
00998
00999
01000
01001
01045 template <class T, int D>
01046 void NurbsCurve<T,D>::basisFuns(T u, int i, Vector<T>& N) const{
01047 T* left = (T*) alloca(2*(deg_+1)*sizeof(T)) ;
01048 T* right = &left[deg_+1] ;
01049
01050 T temp,saved ;
01051
01052 N.resize(deg_+1) ;
01053
01054 N[0] = 1.0 ;
01055 for(int j=1; j<= deg_ ; j++){
01056 left[j] = u-U[i+1-j] ;
01057 right[j] = U[i+j]-u ;
01058 saved = 0.0 ;
01059 for(int r=0 ; r<j; r++){
01060 temp = N[r]/(right[r+1]+left[j-r]) ;
01061 N[r] = saved+right[r+1] * temp ;
01062 saved = left[j-r] * temp ;
01063 }
01064 N[j] = saved ;
01065 }
01066
01067 }
01068
01083 template <class T, int N>
01084 int NurbsCurve<T,N>::findSpan(T u) const{
01085 if(u>=U[P.n()])
01086 return P.n()-1 ;
01087 if(u<=U[deg_])
01088 return deg_ ;
01089
01090 int low = 0 ;
01091 int high = P.n()+1 ;
01092 int mid = (low+high)/2 ;
01093
01094 while(u<U[mid] || u>= U[mid+1]){
01095 if(u<U[mid])
01096 high = mid ;
01097 else
01098 low = mid ;
01099 mid = (low+high)/2 ;
01100 }
01101 return mid ;
01102
01103 }
01104
01117 template <class T, int N>
01118 int NurbsCurve<T,N>::findKnot(T u) const{
01119 if(u==U[P.n()])
01120 return P.n() ;
01121 for(int i=deg_+1; i<P.n() ; i++)
01122 if(U[i]>u){
01123 return i-1 ;
01124 }
01125 return -1 ;
01126 }
01127
01128
01138 template <class T, int N>
01139 int NurbsCurve<T,N>::findMult(int r) const {
01140 int s=1 ;
01141 for(int i=r;i>deg_+1;--i)
01142 if(U[i]<=U[i-1])
01143 s++ ;
01144 else
01145 return s ;
01146 return s ;
01147 }
01148
01164 template <class T, int N>
01165 void NurbsCurve<T,N>::findMultSpan(T u, int& r, int& s) const {
01166 r = findKnot(u) ;
01167 if(u==U[r]){
01168 s = findMult(r) ;
01169 }
01170 else
01171 s = 0 ;
01172 }
01173
01186 template <class T, int N>
01187 void NurbsCurve<T,N>::resize(int n, int Deg){
01188 deg_ = Deg ;
01189 P.resize(n) ;
01190 U.resize(n+deg_+1) ;
01191 }
01192
01223 template <class T, int N>
01224 int NurbsCurve<T,N>::leastSquares(const Vector< Point_nD<T,N> >& Q, int degC, int n){
01225 Vector<T> ub(Q.n()) ;
01226
01227 chordLengthParam(Q,ub) ;
01228
01229 return leastSquares(Q,degC,n,ub) ;
01230 }
01231
01261 template <class T, int N>
01262 int NurbsCurve<T,N>::leastSquares(const Vector< Point_nD<T,N> >& Q, int degC, int n, const Vector<T>& ub){
01263 int i,j;
01264 T d,a ;
01265
01266 if(ub.n() != Q.n()){
01267 #ifdef USE_EXCEPTION
01268 throw NurbsInputError(ub.n(),Q.n()) ;
01269 #else
01270 Error err("leastSquares");
01271 err << "leastSquaresCurve\n" ;
01272 err << "ub size is different than Q's\n" ;
01273 err.fatal() ;
01274 #endif
01275 }
01276
01277 deg_ = degC ;
01278 U.resize(n+deg_+1) ;
01279
01280
01281
01282
01283 U.reset(1.0) ;
01284 d = (T)(Q.n())/(T)(n) ;
01285 for(j=0;j<=deg_;++j)
01286 U[j] = 0 ;
01287
01288 for(j=1;j<n-deg_;++j){
01289 U[deg_+j] = 0.0 ;
01290 for(int k=j;k<j+deg_;++k){
01291 i = (int)(k*d) ;
01292 a = T(k*d)-T(i) ;
01293 int i2 = (int)((k-1)*d) ;
01294 U[deg_+j] += a*ub[i2]+(1-a)*ub[i] ;
01295 }
01296 U[deg_+j] /= deg_ ;
01297 }
01298
01299 return leastSquares(Q, degC, n, ub, U) ;
01300 }
01301
01332 template <class T, int N>
01333 int NurbsCurve<T,N>::leastSquaresH(const Vector< HPoint_nD<T,N> >& Q, int degC, int n, const Vector<T>& ub){
01334 int i,j;
01335 T d,a ;
01336
01337 if(ub.n() != Q.n()){
01338 #ifdef USE_EXCEPTION
01339 throw NurbsInputError(ub.n(),Q.n()) ;
01340 #else
01341 Error err("leastSquares");
01342 err << "leastSquaresCurve\n" ;
01343 err << "ub size is different than Q's\n" ;
01344 err.fatal() ;
01345 #endif
01346 }
01347
01348 deg_ = degC ;
01349 U.resize(n+deg_+1) ;
01350
01351
01352
01353
01354 U.reset(1.0) ;
01355 d = (T)(Q.n())/(T)(n) ;
01356 for(j=0;j<=deg_;++j)
01357 U[j] = 0 ;
01358
01359 for(j=1;j<n-deg_;++j){
01360 U[deg_+j] = 0.0 ;
01361 for(int k=j;k<j+deg_;++k){
01362 i = (int)(k*d) ;
01363 a = T(k*d)-T(i) ;
01364 int i2 = (int)((k-1)*d) ;
01365 U[deg_+j] += a*ub[i2]+(1-a)*ub[i] ;
01366 }
01367 U[deg_+j] /= deg_ ;
01368 }
01369
01370 return leastSquaresH(Q, degC, n, ub, U) ;
01371 }
01372
01405 template <class T, int D>
01406 int NurbsCurve<T,D>::leastSquares(const Vector< Point_nD<T,D> >& Q, int degC, int n, const Vector<T>& ub, const Vector<T>& knot){
01407 int i,j,span;
01408 const int& m=Q.n() ;
01409
01410 if(ub.n() != Q.n()){
01411 #ifdef USE_EXCEPTION
01412 throw NurbsInputError(ub.n(),Q.n()) ;
01413 #else
01414 Error err("leastSquares");
01415 err << "leastSquaresCurve\n" ;
01416 err << "ub size is different than Q's\n" ;
01417 err.fatal();
01418 #endif
01419 }
01420
01421 if(knot.n() != n+degC+1){
01422 #ifdef USE_EXCEPTION
01423 throw NurbsSizeError(n,knot.n(),degC) ;
01424 #else
01425 Error err("leastSquares");
01426 err << "The knot vector supplied doesn't have the proper size.\n" ;
01427 err << "It should be n+degC+1 = " << n+degC+1 << " and it is " << knot.n() << endl ;
01428 err.fatal() ;
01429 #endif
01430 }
01431
01432 deg_ = degC ;
01433
01434 U = knot ;
01435
01436 P.resize(n) ;
01437
01438 Vector< Point_nD<T,D> > R(n),rk(m) ;
01439 Vector<T> funs(deg_+1) ;
01440 Matrix_DOUBLE N(m,n) ;
01441 R[0] = Q[0] ;
01442 R[n-1] = Q[m-1] ;
01443 N(0,0) = 1.0 ;
01444 N(m-1,n-1) = 1.0 ;
01445
01446
01447 N(0,0) = 1.0 ;
01448 N(m-1,n-1) = 1.0 ;
01449
01450
01451 for(i=0;i<m;i++){
01452 span = findSpan(ub[i]) ;
01453 basisFuns(ub[i],span,funs);
01454 for(j=0;j<=deg_;++j){
01455
01456 N(i,span-deg_+j) = (double)funs[j] ;
01457 }
01458 rk[i] = Q[i]-N(i,0)*Q[0]-N(i,n-1)*Q[m-1] ;
01459
01460 }
01461
01462
01463
01464 for(i=0;i<n;i++){
01465 R[i] = 0.0 ;
01466
01467 for(j=0;j<m;j++)
01468 R[i] += N(j,i)*rk[j] ;
01469 if(R[i].x()*R[i].x()<1e-10 &&
01470 R[i].y()*R[i].y()<1e-10 &&
01471 R[i].z()*R[i].z()<1e-10)
01472 return 0 ;
01473 }
01474
01475
01476
01477
01478
01479 if(n-2>0){
01480 Matrix_DOUBLE X(n-2,D),B(n-2,D),Ns(m-2,n-2) ;
01481 for(i=0;i<B.rows();i++){
01482 for(j=0;j<D;j++)
01483 B(i,j) = (double)R[i+1].data[j] ;
01484 }
01485 Ns = N.get(1,1,m-2,n-2) ;
01486
01487 solve(transpose(Ns)*Ns,B,X) ;
01488
01489 for(i=0;i<X.rows();i++){
01490 for(j=0;j<X.cols();j++)
01491 P[i+1].data[j] = (T)X(i,j) ;
01492 P[i+1].w() = 1.0 ;
01493 }
01494 }
01495 P[0] = Q[0] ;
01496 P[n-1] = Q[m-1] ;
01497 return 1 ;
01498 }
01499
01534 template <class T, int D>
01535 int NurbsCurve<T,D>::leastSquaresH(const Vector< HPoint_nD<T,D> >& Q, int degC, int n, const Vector<T>& ub, const Vector<T>& knot){
01536 int i,j,span,m ;
01537
01538 m = Q.n() ;
01539
01540 if(ub.n() != Q.n()){
01541 #ifdef USE_EXCEPTION
01542 throw NurbsInputError(ub.n(),Q.n()) ;
01543 #else
01544 Error err("leastSquares");
01545 err << "leastSquaresCurve\n" ;
01546 err << "ub size is different than Q's\n" ;
01547 err.fatal();
01548 #endif
01549 }
01550
01551 if(knot.n() != n+degC+1){
01552 #ifdef USE_EXCEPTION
01553 throw NurbsSizeError(n,knot.n(),degC) ;
01554 #else
01555 Error err("leastSquares");
01556 err << "The knot vector supplied doesn't have the proper size.\n" ;
01557 err << "It should be n+degC+1 = " << n+degC+1 << " and it is " << knot.n() << endl ;
01558 err.fatal() ;
01559 #endif
01560 }
01561
01562 deg_ = degC ;
01563
01564 U = knot ;
01565
01566 P.resize(n) ;
01567
01568 Vector< HPoint_nD<T,D> > R(n),rk(m) ;
01569 Vector<T> funs(deg_+1) ;
01570 Matrix_DOUBLE N(m,n) ;
01571 R[0] = Q[0] ;
01572 R[n-1] = Q[m-1] ;
01573 N(0,0) = 1.0 ;
01574 N(m-1,n-1) = 1.0 ;
01575
01576
01577 N(0,0) = 1.0 ;
01578 N(m-1,n-1) = 1.0 ;
01579
01580
01581 for(i=0;i<m;i++){
01582 span = findSpan(ub[i]) ;
01583 basisFuns(ub[i],span,funs);
01584 for(j=0;j<=deg_;j++){
01585
01586 N(i,span-deg_+j) = (double)funs[j] ;
01587 }
01588 rk[i] = Q[i]-N(i,0)*Q[0]-N(i,n-1)*Q[m-1] ;
01589
01590 }
01591
01592
01593
01594 for(i=0;i<n;i++){
01595 R[i] = 0.0 ;
01596
01597 for(j=0;j<m;j++)
01598 R[i] += N(j,i)*rk[j] ;
01599 if(R[i].x()*R[i].x()<1e-10 &&
01600 R[i].y()*R[i].y()<1e-10 &&
01601 R[i].z()*R[i].z()<1e-10)
01602 return 0 ;
01603 }
01604
01605
01606
01607
01608
01609 if(n-2>0){
01610 Matrix_DOUBLE X(n-2,D+1),B(n-2,D+1),Ns(m-2,n-2) ;
01611 for(i=0;i<B.rows();i++){
01612 for(j=0;j<D+1;j++)
01613 B(i,j) = (double)R[i+1].data[j] ;
01614 }
01615 Ns = N.get(1,1,m-2,n-2) ;
01616
01617 solve(transpose(Ns)*Ns,B,X) ;
01618
01619 for(i=0;i<X.rows();i++){
01620 for(j=0;j<X.cols();j++)
01621 P[i+1].data[j] = (T)X(i,j) ;
01622 P[i+1].w() = 1.0 ;
01623 }
01624 }
01625 P[0] = Q[0] ;
01626 P[n-1] = Q[m-1] ;
01627 return 1 ;
01628 }
01629
01647 template <class T, int N>
01648 T NurbsCurve<T,N>::getRemovalBnd(int r, int s ) const{
01649 Vector< HPoint_nD<T,N> > temp(U.rows()) ;
01650 int ord = deg_+1 ;
01651 int last = r-s ;
01652 int first = r-deg_ ;
01653 int off ;
01654 int i,j,ii,jj ;
01655 T alfi,alfj ;
01656 T u ;
01657
01658 u = U[r] ;
01659
01660 off = first-1;
01661 temp[0] = P[off] ;
01662 temp[last+1-off] = P[last+1] ;
01663
01664 i=first ; j=last ;
01665 ii=1 ; jj=last-off ;
01666
01667 while(j-i>0){
01668 alfi = (u-U[i])/(U[i+ord]-U[i]) ;
01669 alfj = (u-U[j])/(U[j+ord]-U[j]) ;
01670 temp[ii] = (P[i]-(1.0-alfi)*temp[ii-1])/alfi ;
01671 temp[jj] = (P[j]-alfj*temp[jj+1])/(1.0-alfj) ;
01672 ++i ; ++ii ;
01673 --j ; --jj ;
01674 }
01675 if(j-i<0){
01676 return distance3D(temp[ii-1],temp[jj+1]) ;
01677 }
01678 else{
01679 alfi=(u-U[i])/(U[i+ord]-U[i]) ;
01680 return distance3D(P[i],alfi*temp[ii+1]+(1.0-alfi)*temp[ii-1]) ;
01681 }
01682
01683 }
01684
01699 template <class T, int N>
01700 void NurbsCurve<T,N>::removeKnot(int r, int s, int num)
01701 {
01702 int m = U.n() ;
01703 int ord = deg_+1 ;
01704 int fout = (2*r-s-deg_)/2 ;
01705 int last = r-s ;
01706 int first = r-deg_ ;
01707 T alfi, alfj ;
01708 int i,j,k,ii,jj,off ;
01709 T u ;
01710
01711 Vector< HPoint_nD<T,N> > temp( 2*deg_+1 ) ;
01712
01713 u = U[r] ;
01714
01715 if(num<1){
01716 #ifdef USE_EXCEPTION
01717 throw NurbsInputError() ;
01718 #else
01719 Error err("removeKnot");
01720 err << "A knot can only be removed a positive number of times!\n" ;
01721 err << "num = " << num << endl ;
01722 err.fatal() ;
01723 #endif
01724 }
01725
01726 int t;
01727 for(t=0;t<num;++t){
01728 off = first-1 ;
01729 temp[0] = P[off] ;
01730 temp[last+1-off] = P[last+1] ;
01731 i = first; j = last ;
01732 ii = 1 ; jj = last-off ;
01733 while(j-i > t){
01734 alfi = (u-U[i])/(U[i+ord+t]-U[i]) ;
01735 alfj = (u-U[j-t])/(U[j+ord]-U[j-t]) ;
01736 temp[ii] = (P[i]-(1.0-alfi)*temp[ii-1])/alfi ;
01737 temp[jj] = (P[j]-alfj*temp[jj+1])/(1.0-alfj) ;
01738 ++i ; ++ii ;
01739 --j ; --jj ;
01740 }
01741 i = first ; j = last ;
01742 while(j-i>t){
01743 P[i] = temp[i-off] ;
01744 P[j] = temp[j-off] ;
01745 ++i; --j ;
01746 }
01747 --first ; ++last ;
01748 }
01749 if(t==0) {
01750 #ifdef USE_EXCEPTION
01751 throw NurbsError();
01752 #endif
01753 cerr << "Major error happening... t==0\n" ;
01754 return ;
01755 }
01756
01757 for(k=r+1; k<m ; ++k)
01758 U[k-t] = U[k] ;
01759 j = fout ; i=j ;
01760 for(k=1; k<t; k++)
01761 if( (k%2) == 1)
01762 ++i ;
01763 else
01764 --j ;
01765 for(k=i+1; k<P.n() ; k++) {
01766 P[j++] = P[k] ;
01767 }
01768
01769 resize(P.n()-t,deg_) ;
01770
01771 return ;
01772 }
01773
01774
01786 template <class T, int N>
01787 void NurbsCurve<T,N>::removeKnotsBound(const Vector<T>& ub,
01788 Vector<T>& ek, T E){
01789 Vector<T> Br(U.n()) ;
01790 Vector_INT S(U.n()) ;
01791 Vector_INT Nl(U.n());
01792 Vector_INT Nr(U.n());
01793 Vector<T> NewError(ub.n()) ;
01794 Vector<T> temp(ub.n()) ;
01795 int i,BrMinI ;
01796 int r,s,Rstart,Rend,k ;
01797 T BrMin,u,Infinity=1e20 ;
01798
01799 if(ek.n() != ub.n()){
01800 #ifdef USE_EXCEPTION
01801 throw NurbsInputError(ek.n(),ub.n());
01802 #else
01803 Error err("removeKnotsBound");
01804 err << "Error in removeKnotsBoundCurve\n" ;
01805 err << "The size of ub and ek mismatch\n" ;
01806 err.fatal() ;
01807 #endif
01808 }
01809
01810 Br.reset(Infinity) ;
01811 S.reset(0) ;
01812 s = 1 ;
01813 for(i=deg_+1;i<P.n();i++){
01814 if(U[i]<U[i+1]){
01815 Br[i] = getRemovalBnd(i,s) ;
01816 S[i] = s ;
01817 s = 1 ;
01818 }
01819 else {
01820 Br[i] = Infinity ;
01821 S[i] = 1 ;
01822 s++ ;
01823 }
01824 }
01825
01826
01827
01828 Nl[0] = 0 ;
01829 Nr.reset(ub.n()-1) ;
01830 for(i=0;i<ub.n();i++){
01831 int span = findSpan(ub[i]);
01832 if(!Nl[span]){
01833 Nl[span] = i ;
01834 }
01835 if(i+1<ub.n())
01836 Nr[span] = i+1 ;
01837 }
01838
01839
01840 while(1) {
01841 BrMinI = Br.minIndex() ;
01842 BrMin = Br[BrMinI] ;
01843
01844 if(BrMin == Infinity)
01845 break ;
01846
01847 s = S[BrMinI] ;
01848 r = BrMinI ;
01849
01850
01851 Rstart = maximum(r-deg_,deg_+1) ;
01852 Rend = minimum(r+deg_-S[r+deg_]+1,P.n()-1) ;
01853 Rstart = Nl[Rstart] ;
01854 Rend = Nr[Rend] ;
01855
01856 int removable ;
01857 removable = 1 ;
01858 for(i=Rstart;i<=Rend ; i++){
01859
01860 T a ;
01861 s = S[r] ;
01862 if((deg_+s)%2){
01863 u = ub[i] ;
01864 k = (deg_+s+1)/2 ;
01865 a = U[r]-U[r-k+1] ;
01866 a /= U[r-k+deg_+2]-U[r-k+1] ;
01867 NewError[i] = (1.0-a)*Br[r] * basisFun(u,r-k+1);
01868 }
01869 else{
01870 u = ub[i] ;
01871 k = (deg_+s)/2 ;
01872 NewError[i] = Br[r] * basisFun(u,r-k);
01873 }
01874 temp[i] = NewError[i] + ek[i];
01875 if(temp[i]>E){
01876 removable = 0 ;
01877 Br[r] = Infinity ;
01878 break ;
01879 }
01880 }
01881 if(removable){
01882
01883 removeKnot(r,S[r],1) ;
01884
01885
01886 for(i=Rstart; i<=Rend ; i++)
01887 ek[i] = temp[i] ;
01888
01889
01890 if(P.n()<=deg_+1){
01891 break ;
01892 }
01893
01894
01895 Rstart = Nl[r-deg_-1] ;
01896 Rend = Nr[r-S[r]] ;
01897 int span, oldspan ;
01898 oldspan = -1 ;
01899 for(k=Rstart;k<=Rend;k++){
01900 span = findSpan(ub[k]);
01901 if(span != oldspan){
01902 Nl[span] = k ;
01903 }
01904 if(k+1<ub.n())
01905 Nr[span] = k+1 ;
01906 oldspan = span ;
01907 }
01908 for(k=r-S[r]+1;k<Nl.n()-1;k++){
01909 Nl[k] = Nl[k+1] ;
01910 Nr[k] = Nr[k+1] ;
01911 }
01912 Nl.resize(Nl.n()-1) ;
01913 Nr.resize(Nr.n()-1) ;
01914
01915 Rstart = maximum(r-deg_,deg_+1) ;
01916 Rend = minimum(r+deg_-S[r]+1,P.n()) ;
01917 s = S[Rstart] ;
01918 for(i=Rstart;i<=Rend;i++){
01919 if(U[i]<U[i+1]){
01920 Br[i] = getRemovalBnd(i,s) ;
01921 S[i] = s ;
01922 s = 1;
01923 }
01924 else {
01925 Br[i] = Infinity ;
01926 S[i] = 1 ;
01927 s++ ;
01928 }
01929 }
01930 for(i=Rend+1;i<Br.n()-1;i++){
01931 Br[i] = Br[i+1] ;
01932 S[i] = S[i+1] ;
01933 }
01934 Br.resize(Br.n()-1) ;
01935 }
01936 else{
01937 Br[r] = Infinity ;
01938 }
01939
01940 }
01941
01942 }
01943
01970 template <class T, int N>
01971 T chordLengthParam(const Vector< Point_nD<T,N> >& Q, Vector<T> &ub){
01972 int i ;
01973 T d = T(0);
01974
01975 ub.resize(Q.n()) ;
01976 ub[0] = 0 ;
01977 for(i=1;i<ub.n();i++){
01978 d += norm(Q[i]-Q[i-1]) ;
01979 }
01980 if(d>0){
01981 for(i=1;i<ub.n()-1;++i){
01982 ub[i] = ub[i-1] + norm(Q[i]-Q[i-1])/d ;
01983 }
01984 ub[ub.n()-1] = 1.0 ;
01985 }
01986 else{
01987 for(i=1;i<ub.n()-1;++i)
01988 ub[i] = T(i)/T(ub.n()-1) ;
01989 ub[ub.n()-1] = 1.0 ;
01990 }
01991 return d ;
01992 }
01993
02020 template <class T, int N>
02021 T chordLengthParamH(const Vector< HPoint_nD<T,N> >& Q, Vector<T> &ub){
02022 int i ;
02023 T d = 0.0 ;
02024
02025 ub.resize(Q.n()) ;
02026 ub[0] = 0 ;
02027 for(i=1;i<ub.n();i++){
02028 d += norm(Q[i]-Q[i-1]) ;
02029 }
02030 for(i=1;i<ub.n()-1;i++){
02031 ub[i] = ub[i-1] + norm(Q[i]-Q[i-1])/d ;
02032 }
02033 ub[ub.n()-1] = 1.0 ;
02034 return d ;
02035 }
02036
02055 template <class T, int N>
02056 void NurbsCurve<T,N>::globalApproxErrBnd(Vector< Point_nD<T,N> >& Q, int degC, T E){
02057 Vector<T> ub(Q.n()) ;
02058 chordLengthParam(Q,ub) ;
02059
02060 globalApproxErrBnd(Q,ub,degC,E) ;
02061 }
02062
02084 template <class T, int N>
02085 void NurbsCurve<T,N>::globalApproxErrBnd(Vector< Point_nD<T,N> >& Q, Vector<T>& ub, int degC, T E){
02086 Vector<T> ek(Q.n()) ;
02087 Vector<T> Uh(Q.n()) ;
02088 NurbsCurve<T,N> tcurve ;
02089 int i,j,degL ;
02090
02091 if(ub.n() != Q.n()){
02092 #ifdef USE_EXCEPTION
02093 throw NurbsInputError(ub.n(),Q.n()) ;
02094 #else
02095 Error err("globalApproxErrBnd");
02096 err << "The data vector and the parameter vectors are not of the same size!\n" ;
02097 err << "Q.n() = " << Q.n() << ", ub.n() = " << ub.n() << endl ;
02098 err.fatal() ;
02099 #endif
02100 }
02101
02102 resize(Q.n(),1) ;
02103
02104
02105 deg_ = 1 ;
02106 for(i=0;i<ub.n();i++){
02107 U[i+deg_] = ub[i] ;
02108 }
02109 U[0] = 0 ;
02110 U[U.n()-1] = 1.0 ;
02111
02112 for(i=0;i<P.n();i++)
02113 P[i] = Q[i] ;
02114
02115 for(degL=1; degL<=degC+1 ; degL++){
02116 removeKnotsBound(ub,ek,E) ;
02117
02118 if(degL==degC)
02119 break ;
02120
02121 if(degL<degC){
02122
02123
02124 Uh.resize(U.n()*2) ;
02125
02126 Uh[0] = U[0] ;
02127 j = 1 ;
02128 for(i=1;i<U.n();++i){
02129 if(U[i]>U[i-1])
02130 Uh[j++] = U[i-1] ;
02131 Uh[j++] = U[i] ;
02132 }
02133 Uh[j++] = U[U.n()-1] ;
02134 Uh.resize(j) ;
02135 tcurve = *this ;
02136 if(!leastSquares(Q,degL+1,Uh.n()-degL-1-1,ub,Uh)){
02137 *this = tcurve ;
02138 degreeElevate(1);
02139 }
02140 }
02141 else{
02142 tcurve = *this ;
02143 if(!leastSquares(Q,degL,P.n(),ub,U)){
02144 *this = tcurve ;
02145 }
02146 }
02147
02148
02149
02150
02151 for(i=0;i<Q.n();i++){
02152 T u_i ;
02153 Point_nD<T,N> r_i ;
02154 projectTo(Q[i],ub[i],u_i,r_i) ;
02155 ek[i] = norm(r_i-Q[i]) ;
02156 ub[i] = u_i ;
02157 }
02158 }
02159 }
02160
02181 template <class T, int N>
02182 void NurbsCurve<T,N>::globalApproxErrBnd2(Vector< Point_nD<T,N> >& Q,
02183 int degC,
02184 T E){
02185 Vector<T> ub(Q.n()) ;
02186 Vector<T> ek(Q.n()) ;
02187 Vector<T> Uh(Q.n()) ;
02188 NurbsCurve<T,N> tcurve ;
02189 int i,degL ;
02190
02191 resize(Q.n(),1) ;
02192
02193 chordLengthParam(Q,ub) ;
02194
02195
02196 deg_ = 1 ;
02197 for(i=0;i<ub.n();i++){
02198 U[i+deg_] = ub[i] ;
02199 }
02200 U[0] = 0 ;
02201 U[U.n()-1] = 1.0 ;
02202
02203 for(i=0;i<P.n();i++)
02204 P[i] = Q[i] ;
02205
02206 for(degL=1; degL<degC ; degL++){
02207 degreeElevate(1);
02208
02209
02210
02211 for(i=0;i<Q.n();i++){
02212 T u_i ;
02213 Point_nD<T,N> r_i ;
02214 projectTo(Q[i],ub[i],u_i,r_i) ;
02215 ek[i] = norm(r_i-Q[i]) ;
02216 ub[i] = u_i ;
02217 }
02218 removeKnotsBound(ub,ek,E) ;
02219 }
02220 }
02221
02241 template <class T, int N>
02242 void NurbsCurve<T,N>::globalApproxErrBnd3(Vector< Point_nD<T,N> >& Q,int degC,T E){
02243
02244 Vector<T> ub(Q.n()) ;
02245 Vector<T> ek(Q.n()) ;
02246 int i ;
02247
02248 resize(Q.n(),1) ;
02249
02250 chordLengthParam(Q,ub) ;
02251
02252
02253 deg_ = 1 ;
02254 for(i=0;i<ub.n();i++){
02255 U[i+deg_] = ub[i] ;
02256 }
02257 U[0] = 0 ;
02258 U[U.n()-1] = 1.0 ;
02259
02260
02261 for(i=0;i<P.n();i++)
02262 P[i] = Q[i] ;
02263
02264
02265 degreeElevate(degC-1) ;
02266 removeKnotsBound(ub,ek,E) ;
02267 }
02268
02269
02290 template <class T, int N>
02291 void NurbsCurve<T,N>::globalApproxErrBnd3(Vector< Point_nD<T,N> >& Q,
02292 const Vector<T> &ub,
02293 int degC,
02294 T E){
02295 Vector<T> ek(Q.n()) ;
02296 int i ;
02297
02298 resize(Q.n(),1) ;
02299
02300
02301 deg_ = 1 ;
02302 for(i=0;i<ub.n();i++){
02303 U[i+deg_] = ub[i] ;
02304 }
02305 U[0] = 0 ;
02306 U[U.n()-1] = 1.0 ;
02307
02308
02309 for(i=0;i<P.n();i++)
02310 P[i] = Q[i] ;
02311
02312 degreeElevate(degC-1) ;
02313 removeKnotsBound(ub,ek,E) ;
02314 }
02315
02316
02337 template <class T, int N>
02338 void NurbsCurve<T,N>::projectTo(const Point_nD<T,N>& p, T guess, T& u, Point_nD<T,N>& r, T e1, T e2,int maxTry) const{
02339 T un ;
02340 T c1, c2;
02341 Vector< Point_nD<T,N> > Cd ;
02342 Point_nD<T,N> c, cd,cdd,best ;
02343 T best_e ;
02344 int t = 0 ;
02345 u = guess ;
02346
02347 if(u<U[0]) u = U[0] ;
02348 if(u>U[U.n()-1]) u = U[U.n()-1] ;
02349
02350 best = pointAt(u);
02351
02352 while(1) {
02353 ++t ;
02354 if(t>maxTry){
02355 r = best ;
02356 return ;
02357 }
02358 c = pointAt(u) ;
02359 deriveAt(u,2,Cd) ;
02360 cd = Cd[1] ;
02361 cdd = Cd[2] ;
02362 c1 = norm2(c-p) ;
02363
02364 if(t==0){
02365 best_e = c1+1;
02366 }
02367
02368 if(c1<e1*e1){
02369 r = c ;
02370 return ;
02371 }
02372 else{
02373 if(c1<best_e){
02374 best = c;
02375 best_e = c1;
02376 }
02377 }
02378
02379 c2 = norm((Point_nD<T,N>)(cd*(c-p))) ;
02380
02381 c2 /= norm(cd)*norm(c-p) ;
02382
02383 if(c2<e2){
02384 r =c ;
02385 return ;
02386 }
02387
02388 un = u- cd*(c-p)/(cdd*(c-p)+norm2(cd)) ;
02389
02390 if(un<U[0]) un = U[0] ;
02391 if(un>U[U.n()-1]) un = U[U.n()-1] ;
02392
02393 if(norm2((un-u)*cd)<e1*e1){
02394 r = c ;
02395 return ;
02396 }
02397 u = un ;
02398 }
02399 }
02400
02411 template <class T, int N>
02412 void NurbsCurve<T,N>::degreeElevate(int t){
02413 if(t<=0){
02414 return ;
02415 }
02416
02417 NurbsCurve<T,N> c(*this) ;
02418
02419 int i,j,k ;
02420 int n = c.ctrlPnts().n()-1;
02421 int p = c.deg_ ;
02422 int m = n+p+1;
02423 int ph = p+t ;
02424 int ph2 = ph/2 ;
02425 Matrix<T> bezalfs(p+t+1,p+1) ;
02426 Vector< HPoint_nD<T,N> > bpts(p+1) ;
02427 Vector< HPoint_nD<T,N> > ebpts(p+t+1) ;
02428 Vector< HPoint_nD<T,N> > Nextbpts(p-1) ;
02429 Vector<T> alphas(p-1) ;
02430
02431
02432 Matrix<T> Bin(ph+1,ph2+1) ;
02433 binomialCoef(Bin) ;
02434
02435
02436 T inv,mpi ;
02437 bezalfs(0,0) = bezalfs(ph,p) = 1.0 ;
02438 for(i=1;i<=ph2;i++){
02439 inv= 1.0/Bin(ph,i) ;
02440 mpi = minimum(p,i) ;
02441 for(j=maximum(0,i-t); j<=mpi; j++){
02442 bezalfs(i,j) = inv*Bin(p,j)*Bin(t,i-j) ;
02443 }
02444 }
02445
02446 for(i=ph2+1;i<ph ; i++){
02447 mpi = minimum(p,i) ;
02448 for(j=maximum(0,i-t); j<=mpi ; j++)
02449 bezalfs(i,j) = bezalfs(ph-i,p-j) ;
02450 }
02451
02452 resize(c.P.n()+c.P.n()*t,ph) ;
02453
02454 int mh = ph ;
02455 int kind = ph+1 ;
02456 T ua = c.U[0] ;
02457 T ub = 0.0 ;
02458 int r=-1 ;
02459 int oldr ;
02460 int a = p ;
02461 int b = p+1 ;
02462 int cind = 1 ;
02463 int rbz,lbz = 1 ;
02464 int mul,save,s;
02465 T alf;
02466 int first, last, kj ;
02467 T den,bet,gam,numer ;
02468
02469 P[0] = c.P[0] ;
02470 for(i=0; i <= ph ; i++){
02471 U[i] = ua ;
02472 }
02473
02474
02475
02476 for(i=0;i<=p ;i++)
02477 bpts[i] = c.P[i] ;
02478
02479 while(b<m){
02480 i=b ;
02481 while(b<m && c.U[b] >= c.U[b+1])
02482 b++ ;
02483 mul = b-i+1 ;
02484 mh += mul+t ;
02485 ub = c.U[b] ;
02486 oldr = r ;
02487 r = p-mul ;
02488 if(oldr>0)
02489 lbz = (oldr+2)/2 ;
02490 else
02491 lbz = 1 ;
02492 if(r>0)
02493 rbz = ph-(r+1)/2 ;
02494 else
02495 rbz = ph ;
02496 if(r>0){
02497 numer = ub-ua ;
02498 for(k=p;k>mul;k--){
02499 alphas[k-mul-1] = numer/(c.U[a+k]-ua) ;
02500 }
02501 for(j=1;j<=r;j++){
02502 save = r-j ; s = mul+j ;
02503 for(k=p;k>=s;k--){
02504 bpts[k] = alphas[k-s] * bpts[k]+(1.0-alphas[k-s])*bpts[k-1] ;
02505 }
02506 Nextbpts[save] = bpts[p] ;
02507 }
02508 }
02509
02510 for(i=lbz;i<=ph;i++){
02511 ebpts[i] = 0.0 ;
02512 mpi = minimum(p,i) ;
02513 for(j=maximum(0,i-t); j<=mpi ; j++)
02514 ebpts[i] += bezalfs(i,j)*bpts[j] ;
02515 }
02516
02517 if(oldr>1){
02518
02519
02520 first = kind-2 ; last = kind ;
02521 den = ub-ua ;
02522 bet = (ub-U[kind-1])/den ;
02523 for(int tr=1; tr<oldr; tr++){
02524 i = first ; j = last ;
02525 kj = j-kind+1 ;
02526 while(j-i>tr){
02527 if(i<cind){
02528 alf=(ub-U[i])/(ua-U[i]) ;
02529 P[i] = alf*P[i] + (1.0-alf)*P[i-1] ;
02530 }
02531 if( j>= lbz){
02532 if(j-tr <= kind-ph+oldr){
02533 gam = (ub-U[j-tr])/den ;
02534 ebpts[kj] = gam*ebpts[kj] + (1.0-gam)*ebpts[kj+1] ;
02535 }
02536 else{
02537 ebpts[kj] = bet*ebpts[kj]+(1.0-bet)*ebpts[kj+1] ;
02538 }
02539 }
02540 ++i ; --j; --kj ;
02541 }
02542 --first ; ++last ;
02543 }
02544 }
02545
02546 if(a!=p)
02547 for(i=0;i<ph-oldr; i++){
02548 U[kind++] = ua ;
02549 }
02550 for(j=lbz; j<=rbz ; j++) {
02551 P[cind++] = ebpts[j] ;
02552 }
02553
02554 if(b<m){
02555 for(j=0;j<r;j++)
02556 bpts[j] = Nextbpts[j] ;
02557 for(j=r;j<=p;j++)
02558 bpts[j] = c.P[b-p+j] ;
02559 a=b ;
02560 b++ ;
02561 ua = ub ;
02562 }
02563 else{
02564 for(i=0;i<=ph;i++)
02565 U[kind+i] = ub ;
02566 }
02567 }
02568 resize(mh-ph,ph) ;
02569 }
02570
02589 template <class T, int N>
02590 int NurbsCurve<T,N>::knotInsertion(T u, int r,NurbsCurve<T,N>& nc){
02591
02592 int k=0,s=0 ;
02593 int i,j ;
02594 int p = deg_ ;
02595
02596 if(u<U[deg_] || u>U[P.n()]){
02597 #ifdef USE_EXCEPTION
02598 throw NurbsError();
02599 #else
02600 Error err("knotInsertion");
02601 err << "The parametric value isn't inside a valid range." ;
02602 err << "The valid range is between " << U[deg_] << " and " << U[P.n()] << endl ;
02603 err.fatal();
02604 #endif
02605 }
02606
02607 for(i=0;i<U.n();i++){
02608 if(U[i]>u) {
02609 k = i-1 ;
02610 break ;
02611 }
02612 }
02613
02614 if(u<=U[k]){
02615 s = 1 ;
02616 for(i=k;i>deg_;i--){
02617 if(U[i]<=U[i-1])
02618 s++ ;
02619 else
02620 break ;
02621 }
02622 }
02623 else{
02624 s=0 ;
02625 }
02626
02627 if((r+s)>p+1)
02628 r = p+1-s ;
02629
02630 if(r<=0)
02631 return 0 ;
02632
02633 nc.resize(P.n()+r,deg_) ;
02634
02635
02636 for(i=0;i<=k;i++)
02637 nc.U[i] = U[i] ;
02638 for(i=1;i<=r;i++)
02639 nc.U[k+i] = u ;
02640 for(i=k+1;i<U.n(); i++)
02641 nc.U[i+r] = U[i] ;
02642
02643
02644 Vector< HPoint_nD<T,N> > R(p+1) ;
02645
02646 for(i=0; i<=k-p ; i++)
02647 nc.P[i] = P[i] ;
02648 for(i=k-s ; i< P.n() ; i++)
02649 nc.P[i+r] = P[i] ;
02650 for(i=0; i<=p-s; i++)
02651 R[i] = P[k-p+i] ;
02652
02653
02654 int L=0 ;
02655 T alpha ;
02656 for(j=1; j<=r ; j++){
02657 L = k-p+j ;
02658 for(i=0;i<=p-j-s;i++){
02659 alpha = (u-U[L+i])/(U[i+k+1]-U[L+i]) ;
02660 R[i] = alpha*R[i+1] + (1.0-alpha)*R[i] ;
02661 }
02662 nc.P[L] = R[0] ;
02663 if(p-j-s > 0)
02664 nc.P[k+r-j-s] = R[p-j-s] ;
02665 }
02666
02667
02668 for(i=L+1; i<k-s ; i++){
02669 nc.P[i] = R[i-L] ;
02670 }
02671 return r ;
02672 }
02673
02684 template <class T, int N>
02685 void NurbsCurve<T,N>::refineKnotVector(const Vector<T>& X){
02686 int n = P.n()-1 ;
02687 int p = deg_ ;
02688 int m = n+p+1 ;
02689 int a,b ;
02690 int r = X.n()-1 ;
02691
02692 NurbsCurve<T,N> c(*this) ;
02693
02694 resize(r+1+n+1,p) ;
02695
02696 a = c.findSpan(X[0]) ;
02697 b = c.findSpan(X[r]) ;
02698 ++b ;
02699 int j ;
02700 for(j=0; j<=a-p ; j++)
02701 P[j] = c.P[j] ;
02702 for(j = b-1 ; j<=n ; j++)
02703 P[j+r+1] = c.P[j] ;
02704 for(j=0; j<=a ; j++)
02705 U[j] = c.U[j] ;
02706 for(j=b+p ; j<=m ; j++)
02707 U[j+r+1] = c.U[j] ;
02708 int i = b+p-1 ;
02709 int k = b+p+r ;
02710 for(j=r; j>=0 ; j--){
02711 while(X[j] <= c.U[i] && i>a){
02712 P[k-p-1] = c.P[i-p-1] ;
02713 U[k] = c.U[i] ;
02714 --k ;
02715 --i ;
02716 }
02717 P[k-p-1] = P[k-p] ;
02718 for(int l=1; l<=p ; l++){
02719 int ind = k-p+l ;
02720 T alpha = U[k+l] - X[j] ;
02721 if(alpha==0.0)
02722 P[ind-1] = P[ind] ;
02723 else
02724 alpha /= U[k+l]-c.U[i-p+l] ;
02725 P[ind-1] = alpha*P[ind-1] + (1.0-alpha)*P[ind] ;
02726 }
02727 U[k] = X[j] ;
02728 --k ;
02729 }
02730 }
02731
02743 template <class T, int N>
02744 void NurbsCurve<T,N>::globalInterp(const Vector< Point_nD<T,N> >& Q, int d){
02745 Vector<T> ub ;
02746 chordLengthParam(Q,ub) ;
02747 globalInterp(Q,ub,d) ;
02748 }
02749
02765 template <class T, int D>
02766 void NurbsCurve<T,D>::globalInterp(const Vector< Point_nD<T,D> >& Q, const Vector<T>& ub, int d){
02767 int i,j ;
02768
02769 if(d<=0){
02770 #ifdef USE_EXCEPTION
02771 throw NurbsInputError() ;
02772 #else
02773 Error err("globalInterp");
02774 err << "The degree specified is equal or smaller than 0\n" ;
02775 err << "deg = " << deg_ << endl ;
02776 err.fatal() ;
02777 #endif
02778 }
02779 if(d>=Q.n()){
02780 #ifdef USE_EXCEPTION
02781 throw NurbsInputError() ;
02782 #else
02783 Error err("globalInterp");
02784 err << "The degree specified is greater then Q.n()+1\n" ;
02785 err << "Q.n() = " << Q.n() << ", and deg = " << deg_ << endl ;
02786 err.warning() ;
02787 d = Q.n()-1 ;
02788 #endif
02789 }
02790
02791
02792 resize(Q.n(),d) ;
02793 Matrix_DOUBLE A(Q.n(),Q.n()) ;
02794
02795 knotAveraging(ub,d,U) ;
02796
02797
02798 Vector<T> N(deg_+1) ;
02799
02800 for(i=1;i<Q.n()-1;i++){
02801 int span = findSpan(ub[i]);
02802 basisFuns(ub[i],span,N) ;
02803 for(j=0;j<=deg_;j++)
02804 A(i,span-deg_+j) = (double)N[j] ;
02805 }
02806 A(0,0) = 1.0 ;
02807 A(Q.n()-1,Q.n()-1) = 1.0 ;
02808
02809
02810 Matrix_DOUBLE qq(Q.n(),D) ;
02811 Matrix_DOUBLE xx(Q.n(),D) ;
02812 for(i=0;i<Q.n();i++){
02813 const Point_nD<T,D>& qp = Q[i] ;
02814 for(j=0; j<D;j++)
02815 qq(i,j) = (double)qp.data[j] ;
02816 }
02817
02818 solve(A,qq,xx) ;
02819
02820
02821 for(i=0;i<xx.rows();i++){
02822 for(j=0;j<D;j++)
02823 P[i].data[j] = (T)xx(i,j) ;
02824 P[i].w() = 1.0 ;
02825 }
02826
02827 }
02828
02858 template <class T, int nD>
02859 void NurbsCurve<T,nD>::globalInterpD(const Vector< Point_nD<T,nD> >& Q, const Vector< Point_nD<T,nD> >& D, int d, int unitD, T a){
02860 int i,j,n ;
02861
02862 if(d<=1){
02863 #ifdef USE_EXCEPTION
02864 throw NurbsInputError() ;
02865 #else
02866 Error err("globalInterpD");
02867 err << "The degree specified is equal or smaller than 1\n" ;
02868 err << "deg = " << deg_ << endl ;
02869 err.fatal() ;
02870 #endif
02871 }
02872 if(d>=Q.n()){
02873 #ifdef USE_EXCEPTION
02874 throw NurbsInputError() ;
02875 #else
02876 Error err("globalInterpD");
02877 err << "The degree specified is greater then Q.n()+1\n" ;
02878 err << "Q.n() = " << Q.n() << ", and deg = " << deg_ << endl ;
02879 err.warning() ;
02880 d = Q.n()-1 ;
02881 #endif
02882 }
02883 if(a<=0){
02884 #ifdef USE_EXCEPTION
02885 throw NurbsInputError() ;
02886 #else
02887 Error err("globalInterpD");
02888 err << "The a value must be greater than 0\n" ;
02889 err << "It is presently " << a << endl ;
02890 err.fatal() ;
02891 #endif
02892 }
02893 if(Q.n() != D.n()){
02894 #ifdef USE_EXCEPTION
02895 throw NurbsInputError(Q.n(),D.n()) ;
02896 #else
02897 Error err("globalInterpD") ;
02898 err << "The number of points to interpolate is different than\n the number of derivative points.\n" ;
02899 err << "Q.n() = " << Q.n() << ", D.n() = " << D.n() << endl ;
02900 err.fatal() ;
02901 #endif
02902 }
02903
02904 deg_ = d ;
02905 n = 2*Q.n() ;
02906
02907 resize(n,deg_) ;
02908
02909 Vector<T> ub(Q.n()) ;
02910
02911 T chordLength ;
02912
02913 chordLength = chordLengthParam(Q,ub) ;
02914
02915 if(unitD)
02916 chordLength *= a ;
02917
02918
02919 switch(deg_){
02920 case 2:
02921 {
02922 for(i=0;i<=deg_;++i){
02923 U[i] = T(0) ;
02924 U[U.n()-1-i] = T(1) ;
02925 }
02926 for(i=0;i<ub.n()-1;++i){
02927 U[2*i+deg_] = ub[i] ;
02928 U[2*i+deg_+1] = (ub[i]+ub[i+1])/T(2) ;
02929 }
02930 break ;
02931 }
02932 case 3:
02933 {
02934 for(i=0;i<=deg_;++i){
02935 U[i] = T(0) ;
02936 U[U.n()-1-i] = T(1) ;
02937 }
02938 for(i=1;i<ub.n()-1;++i){
02939 U[deg_+2*i] = (2*ub[i]+ub[i+1])/T(3) ;
02940 U[deg_+2*i+1] = (ub[i]+2*ub[i+1])/T(3) ;
02941 }
02942 U[4] = ub[1]/T(2);
02943 U[U.n()-deg_-2] = (ub[ub.n()-1]+T(1))/T(2) ;
02944 }
02945 default:
02946 {
02947 Vector<T> ub2(2*Q.n()) ;
02948 for(i=0;i<ub.n()-1;++i){
02949 ub2[2*i] = ub[i] ;
02950 ub2[2*i+1] = (ub[i]+ub[i+1])/2.0 ;
02951 }
02952
02953 ub2[ub2.n()-2] = (ub2[ub2.n()-1]+ub2[ub2.n()-3])/2.0 ;
02954 knotAveraging(ub2,deg_,U) ;
02955 }
02956 }
02957
02958
02959 Matrix_DOUBLE A(n,n) ;
02960 Vector<T> N(deg_+1) ;
02961 Matrix<T> Nd(1,1) ;
02962
02963 for(i=1;i<Q.n()-1;i++){
02964 int span = findSpan(ub[i]);
02965 basisFuns(ub[i],span,N) ;
02966 dersBasisFuns(1,ub[i],span,Nd) ;
02967 for(j=0;j<=deg_;j++) {
02968 A(2*i,span-deg_+j) = (double)N[j] ;
02969 A(2*i+1,span-deg_+j) = (double)Nd(1,j) ;
02970 }
02971 }
02972 A(0,0) = 1.0 ;
02973 A(1,0) = -1.0 ;
02974 A(1,1) = 1.0 ;
02975 A(A.rows()-2,A.cols()-2) = -1.0 ;
02976 A(A.rows()-2,A.cols()-1) = 1.0 ;
02977 A(A.rows()-1,A.cols()-1) = 1.0 ;
02978
02979
02980 Matrix_DOUBLE qq(n,nD) ;
02981 Matrix_DOUBLE xx(n,nD) ;
02982 for(i=0;i<Q.n();i++){
02983 const Point_nD<T,nD>& qp = Q[i] ;
02984 const Point_nD<T,nD>& dp = D[i] ;
02985 for(j=0; j<nD;j++){
02986 qq(2*i,j) = (double)qp.data[j] ;
02987 qq(2*i+1,j) = (double)dp.data[j] ;
02988 if(unitD)
02989 qq(2*i+1,j) *= chordLength ;
02990 }
02991 }
02992
02993 T d0Factor = U[deg_+1]/deg_ ;
02994 T dnFactor = (1-U[U.n()-deg_-2])/deg_ ;
02995
02996
02997
02998 const Point_nD<T,nD>& dp0 = D[0] ;
02999 const Point_nD<T,nD>& dpn = D[D.n()-1] ;
03000 const Point_nD<T,nD>& qpn = Q[Q.n()-1] ;
03001 for(j=0;j<nD;++j){
03002 qq(1,j) = d0Factor*double(dp0.data[j]) ;
03003 qq(A.cols()-2,j) = dnFactor*double(dpn.data[j]) ;
03004 if(unitD){
03005 qq(1,j) *= chordLength ;
03006 qq(A.cols()-2,j) *= chordLength ;
03007 }
03008 qq(A.cols()-1,j) = double(qpn.data[j]) ;
03009 }
03010
03011 if(!solve(A,qq,xx)){
03012 #ifdef USE_EXCEPTION
03013 throw NurbsError();
03014 #else
03015 Error err("globablInterpD");
03016 err << "The matrix couldn't not be solved properly. There is no valid"
03017 " solutions for the input parameters you gave OR there is a "
03018 " computational error (using double float might solve the problem).";
03019 err.warning();
03020 #endif
03021 }
03022
03023
03024 for(i=0;i<xx.rows();i++){
03025 for(j=0;j<nD;j++)
03026 P[i].data[j] = (T)xx(i,j) ;
03027 P[i].w() = 1.0 ;
03028 }
03029
03030 P[0] = Q[0] ;
03031 P[P.n()-1] = Q[Q.n()-1] ;
03032 }
03033
03047 template <class T, int D>
03048 void NurbsCurve<T,D>::globalInterpH(const Vector< HPoint_nD<T,D> >& Q, int d){
03049 int i,j ;
03050
03051 resize(Q.n(),d) ;
03052 Matrix_DOUBLE A(Q.n(),Q.n()) ;
03053 Vector<T> ub(Q.n()) ;
03054
03055 chordLengthParamH(Q,ub) ;
03056
03057
03058 for(i=0;i<=deg_;i++)
03059 U[i] = 0 ;
03060 for(i=P.n(); i<U.n(); i++)
03061 U[i] = 1.0 ;
03062 for(j=1; j<Q.n()-deg_ ; j++){
03063 T t=0 ;
03064 for(i=j; i< j+deg_ ; i++)
03065 t += ub[i] ;
03066 U[j+deg_] = t/(T)deg_ ;
03067 }
03068
03069
03070 Vector<T> N(deg_+1) ;
03071
03072 for(i=1;i<Q.n()-1;i++){
03073 int span = findSpan(ub[i]);
03074 basisFuns(ub[i],span,N) ;
03075 for(j=0;j<=deg_;j++)
03076 A(i,span-deg_+j) = (double)N[j] ;
03077 }
03078 A(0,0) = 1.0 ;
03079 A(Q.n()-1,Q.n()-1) = 1.0 ;
03080
03081
03082 Matrix_DOUBLE qq(Q.n(),D+1) ;
03083 Matrix_DOUBLE xx(Q.n(),D+1) ;
03084 for(i=0;i<Q.n();i++)
03085 for(j=0; j<D+1;j++)
03086 qq(i,j) = (double)Q[i].data[j] ;
03087
03088 solve(A,qq,xx) ;
03089
03090
03091 for(i=0;i<xx.rows();i++){
03092 for(j=0;j<D+1;j++)
03093 P[i].data[j] = (T)xx(i,j) ;
03094 }
03095
03096 }
03097
03113 template <class T, int D>
03114 void NurbsCurve<T,D>::globalInterpH(const Vector< HPoint_nD<T,D> >& Q, const Vector<T>& Uc, int d){
03115 int i,j ;
03116
03117 resize(Q.n(),d) ;
03118 Matrix_DOUBLE A(Q.n(),Q.n()) ;
03119 Vector<T> ub(Q.n()) ;
03120
03121 if(Uc.n() != U.n()){
03122 #ifdef USE_EXCEPTION
03123 throw NurbsInputError(Uc.n(),U.n()) ;
03124 #else
03125 Error err("globalInterp");
03126 err << "Invalid dimension for the given Knot vector.\n" ;
03127 err << "U required = " << U.n() << ", U given = " << Uc.n() << endl ;
03128 err.fatal() ;
03129 #endif
03130 }
03131 U = Uc ;
03132 chordLengthParamH(Q,ub) ;
03133
03134
03135 Vector<T> N(deg_+1) ;
03136
03137 for(i=1;i<Q.n()-1;i++){
03138 int span = findSpan(ub[i]);
03139 basisFuns(ub[i],span,N) ;
03140 for(j=0;j<=deg_;j++)
03141 A(i,span-deg_+j) = (double)N[j] ;
03142 }
03143 A(0,0) = 1.0 ;
03144 A(Q.n()-1,Q.n()-1) = 1.0 ;
03145
03146
03147 Matrix_DOUBLE qq(Q.n(),D+1) ;
03148 Matrix_DOUBLE xx(Q.n(),D+1) ;
03149 for(i=0;i<Q.n();i++)
03150 for(j=0; j<D+1;j++)
03151 qq(i,j) = (double)Q[i].data[j] ;
03152
03153 solve(A,qq,xx) ;
03154
03155
03156 for(i=0;i<xx.rows();i++){
03157 for(j=0;j<D+1;j++)
03158 P[i].data[j] = (T)xx(i,j) ;
03159 }
03160
03161 }
03162
03182 template <class T, int D>
03183 void NurbsCurve<T,D>::globalInterpH(const Vector< HPoint_nD<T,D> >& Q, const Vector<T>& ub, const Vector<T>& Uc, int d){
03184 int i,j ;
03185
03186 resize(Q.n(),d) ;
03187 Matrix_DOUBLE A(Q.n(),Q.n()) ;
03188
03189 if(Uc.n() != U.n()){
03190 #ifdef USE_EXCEPTION
03191 throw NurbsInputError(Uc.n(),U.n()) ;
03192 #else
03193 Error err("globalInterp");
03194 err << "Invalid dimension for the given Knot vector.\n" ;
03195 err << "U required = " << U.n() << ", U given = " << Uc.n() << endl ;
03196 err.fatal() ;
03197 #endif
03198 }
03199 U = Uc ;
03200
03201
03202 Vector<T> N(deg_+1) ;
03203
03204 for(i=1;i<Q.n()-1;i++){
03205 int span = findSpan(ub[i]);
03206 basisFuns(ub[i],span,N) ;
03207 for(j=0;j<=deg_;j++)
03208 A(i,span-deg_+j) = (double)N[j] ;
03209 }
03210 A(0,0) = 1.0 ;
03211 A(Q.n()-1,Q.n()-1) = 1.0 ;
03212
03213
03214 Matrix_DOUBLE qq(Q.n(),D+1) ;
03215 Matrix_DOUBLE xx(Q.n(),D+1) ;
03216 for(i=0;i<Q.n();i++)
03217 for(j=0; j<D+1;j++)
03218 qq(i,j) = (double)Q[i].data[j] ;
03219
03220 solve(A,qq,xx) ;
03221
03222
03223 for(i=0;i<xx.rows();i++){
03224 for(j=0;j<D+1;j++)
03225 P[i].data[j] = (T)xx(i,j) ;
03226 }
03227
03228 }
03229
03230 template <class T, int N>
03231 inline T pow2(T a){
03232 return a*a ;
03233 }
03234
03254 template <class T, int N>
03255 int intersectLine(const Point_nD<T,N>& p1, const Point_nD<T,N>& t1, const Point_nD<T,N>& p2, const Point_nD<T,N>& t2, Point_nD<T,N>& p){
03256
03257
03258
03259
03260
03261
03262
03263
03264
03265 Point_nD<T,N> v,px ;
03266
03267
03268
03269 px = crossProduct(t1,t2) ;
03270 v = crossProduct(px,t1) ;
03271
03272 T t = (p1-p2)*v ;
03273 T vw = v*t2 ;
03274 if(to2power(vw)<1e-7)
03275 return 0 ;
03276 t /= vw ;
03277 p = p2+(((p1-p2)*v)/vw)*t2 ;
03278 return 1 ;
03279 }
03280
03281 #ifdef HAVE_TEMPLATE_OF_TEMPLATE
03282 template <class T>
03283 int intersectLine(const Point_nD<T,2>& p1, const Point_nD<T,2>& t1, const Point_nD<T,2>& p2, const Point_nD<T,2>& t2, Point_nD<T,2>& p){
03284 cout << "PLEASE, DEFINE THIS FUNCTION\n" ;
03285
03286 return 1 ;
03287 }
03288 #else
03289
03290 #ifdef TEMPLATE_SPECIALIZATION
03291
03292 template <>
03293 int intersectLine(const Point_nD<float,2>& p1, const Point_nD<float,2>& t1, const Point_nD<float,2>& p2, const Point_nD<float,2>& t2, Point_nD<float,2>& p){
03294 cout << "PLEASE, DEFINE THIS FUNCTION\n" ;
03295
03296 return 1 ;
03297 }
03298
03299 template <>
03300 int intersectLine(const Point_nD<double,2>& p1, const Point_nD<double,2>& t1, const Point_nD<double,2>& p2, const Point_nD<double,2>& t2, Point_nD<double,2>& p){
03301 cout << "PLEASE, DEFINE THIS FUNCTION\n" ;
03302
03303 return 1 ;
03304 }
03305 #endif //TEMPLATE_SPECIALIZATION
03306
03307 #endif
03308
03329 template <class T, int N>
03330 void NurbsCurve<T,N>::makeCircle(const Point_nD<T,N>& O, const Point_nD<T,N>& X, const Point_nD<T,N>& Y, T r, double as, double ae){
03331 double theta,angle,dtheta ;
03332 int narcs ;
03333 while(ae<as)
03334 ae += 2*M_PI ;
03335 theta = ae-as ;
03336 if(theta<=M_PI/2.0)
03337 narcs = 1 ;
03338 else{
03339 if(theta<=M_PI)
03340 narcs = 2 ;
03341 else{
03342 if(theta<=1.5*M_PI)
03343 narcs = 3 ;
03344 else
03345 narcs = 4 ;
03346 }
03347 }
03348 dtheta = theta/(double)narcs ;
03349 int n = 2*narcs+1 ;
03350 double w1 = cos(dtheta/2.0) ;
03351
03352 Point_nD<T,N> P0,T0,P2,T2,P1 ;
03353 P0 = O + r*cos(as)*X + r*sin(as)*Y ;
03354 T0 = -sin(as)*X + cos(as)*Y ;
03355 resize(n,2) ;
03356
03357 P[0] = P0 ;
03358 int i ;
03359 int index = 0 ;
03360 angle = as ;
03361 for(i=1;i<=narcs;++i){
03362 angle += dtheta ;
03363 P2 = O+ r*cos(angle)*X + r*sin(angle)*Y ;
03364 P[index+2] = P2 ;
03365 T2 = -sin(angle)*X + cos(angle)*Y ;
03366 intersectLine(P0,T0,P2,T2,P1) ;
03367 P[index+1] = P1 ;
03368 P[index+1] *= w1 ;
03369 index += 2 ;
03370 if(i<narcs){
03371 P0 = P2 ;
03372 T0 = T2 ;
03373 }
03374 }
03375 int j = 2*narcs+1 ;
03376 for(i=0;i<3;++i){
03377 U[i] = 0.0 ;
03378 U[i+j] = 1.0 ;
03379 }
03380 switch(narcs){
03381 case 1: break ;
03382 case 2:
03383 U[3] = U[4] = 0.5 ;
03384 break ;
03385 case 3:
03386 U[3] = U[4] = 1.0/3.0 ;
03387 U[5] = U[6] = 2.0/3.0 ;
03388 break ;
03389 case 4:
03390 U[3] = U[4] = 0.25 ;
03391 U[5] = U[6] = 0.50 ;
03392 U[7] = U[8] = 0.75 ;
03393 break ;
03394 }
03395 }
03396
03411 template <class T, int N>
03412 void NurbsCurve<T,N>::makeCircle(const Point_nD<T,N>& O, T r, double as, double ae){
03413 makeCircle(O,Point_nD<T,N>(1,0,0),Point_nD<T,N>(0,1,0),r,as,ae) ;
03414 }
03415
03428 template <class T, int N>
03429 void NurbsCurve<T,N>::makeCircle(const Point_nD<T,N>& O, T r){
03430 resize(9,2);
03431 U[0] = U[1] = U[2] = 0 ;
03432 U[3] = U[4] = 0.25 ;
03433 U[5] = U[6] = 0.50 ;
03434 U[7] = U[8] = 0.75 ;
03435 U[9] = U[10] = U[11] = 1 ;
03436
03437
03438 const T wm = T(0.707106781185) ;
03439
03440 P[0] = HPoint_nD<T,N>(r,0,0,1) ;
03441 P[1] = HPoint_nD<T,N>(r*wm,r*wm,0,wm) ;
03442 P[2] = HPoint_nD<T,N>(0,r,0,1) ;
03443 P[3] = HPoint_nD<T,N>(-r*wm,r*wm,0,wm) ;
03444 P[4] = HPoint_nD<T,N>(-r,0,0,1) ;
03445 P[5] = HPoint_nD<T,N>(-r*wm,-r*wm,0,wm) ;
03446 P[6] = HPoint_nD<T,N>(0,-r,0,1) ;
03447 P[7] = HPoint_nD<T,N>(r*wm,-r*wm,0,wm) ;
03448 P[8] = HPoint_nD<T,N>(r,0,0,1) ;
03449
03450 for(int i=8;i>=0;--i){
03451 P[i].x() += O.x() ;
03452 P[i].y() += O.y() ;
03453 P[i].z() += O.z() ;
03454 }
03455
03456
03457
03458 }
03459
03476 template <class T>
03477 Vector<T> knotUnion(const Vector<T>& Ua, const Vector<T>& Ub) {
03478 Vector<T> U(Ua.n()+Ub.n()) ;
03479 int done = 0 ;
03480 int i,ia,ib ;
03481 T t ;
03482
03483 i = ia = ib = 0 ;
03484 while(!done){
03485 if(Ua[ia] == Ub[ib]){
03486 t = Ua[ia] ;
03487 ++ia ; ++ib ;
03488 }
03489 else{
03490 if(Ua[ia]<Ub[ib]){
03491 t = Ua[ia] ;
03492 ++ia ;
03493 }
03494 else{
03495 t = Ub[ib] ;
03496 ++ib ;
03497 }
03498 }
03499 U[i++] = t ;
03500 done = (ia>=Ua.n() || ib>=Ub.n()) ;
03501 }
03502 U.resize(i) ;
03503 return U ;
03504 }
03505
03518 template <class T, int N>
03519 void NurbsCurve<T,N>::mergeKnotVector(const Vector<T> &Um){
03520 int i,ia,ib ;
03521
03522 Vector<T> I(Um.n()) ;
03523 int done = 0 ;
03524 i = ia = ib = 0 ;
03525 while(!done) {
03526 if(Um[ib] == U[ia]){
03527 ++ib ; ++ia ;
03528 }
03529 else{
03530 I[i++] = Um[ib] ;
03531 ib++ ;
03532 }
03533 done = (ia>=U.n() || ib >= Um.n()) ;
03534 }
03535 I.resize(i) ;
03536
03537 if(I.n()>0){
03538
03539 refineKnotVector(I) ;
03540 }
03541 }
03542
03543
03557 template <class T, int N>
03558 void generateCompatibleCurves(NurbsCurveArray<T,N> &ca){
03559 int i;
03560 NurbsCurve<T,N> tc ;
03561
03562 if(ca.n()<=1)
03563 return ;
03564
03565
03566 int p = 1 ;
03567 for(i=0;i<ca.n();i++)
03568 if(p<ca[i].deg_)
03569 p = ca[i].deg_ ;
03570 for(i=0;i<ca.n();i++){
03571 ca[i].degreeElevate(p-ca[i].deg_);
03572 }
03573
03574
03575 Vector<T> Uc(ca[0].U) ;
03576 for(i=1;i<ca.n();i++){
03577 Uc = knotUnion(Uc,ca[i].U) ;
03578 }
03579
03580
03581 for(i=0;i<ca.n();i++)
03582 ca[i].mergeKnotVector(Uc) ;
03583 }
03584
03595 template <class T, int N>
03596 int NurbsCurve<T,N>::read(ifstream &fin){
03597 if(!fin) {
03598 return 0 ;
03599 }
03600 int np,d;
03601 char *type ;
03602 type = new char[3] ;
03603 if(!fin.read(type,sizeof(char)*3)) { delete []type ; return 0 ;}
03604 int r1 = strncmp(type,"nc3",3) ;
03605 int r2 = strncmp(type,"nc4",3) ;
03606 if(!(r1==0 || r2==0)) {
03607 delete []type ;
03608 return 0 ;
03609 }
03610 int st ;
03611 char stc ;
03612 if(!fin.read((char*)&stc,sizeof(char))) { delete []type ; return 0 ;}
03613 if(!fin.read((char*)&np,sizeof(int))) { delete []type ; return 0 ;}
03614 if(!fin.read((char*)&d,sizeof(int))) { delete []type ; return 0 ;}
03615
03616 st = stc - '0' ;
03617 if(st != sizeof(T)){
03618 delete []type ;
03619 return 0 ;
03620 }
03621
03622 resize(np,d) ;
03623
03624 if(!fin.read((char*)U.memory(),sizeof(T)*U.n())) { delete []type ; return 0 ;}
03625
03626
03627 T *p,*p2 ;
03628 if(!r1){
03629 p = new T[3*np] ;
03630 if(!fin.read((char*)p,sizeof(T)*3*np)) { delete []type ; return 0 ;}
03631 p2 = p ;
03632 for(int i=0;i<np;i++){
03633 P[i].x() = *(p++) ;
03634 P[i].y() = *(p++) ;
03635 P[i].z() = *(p++) ;
03636 P[i].w() = 1.0 ;
03637 }
03638 delete []p2 ;
03639 }
03640 else{
03641 p = new T[4*np] ;
03642 if(!fin.read((char*)p,sizeof(T)*4*np)) { delete []type ; return 0 ;}
03643 p2 = p ;
03644 for(int i=0;i<np;i++){
03645 P[i].x() = *(p++) ;
03646 P[i].y() = *(p++) ;
03647 P[i].z() = *(p++) ;
03648 P[i].w() = *(p++) ;
03649 }
03650 delete []p2 ;
03651 }
03652
03653 delete []type ;
03654 return 1 ;
03655 }
03656
03666 template <class T, int N>
03667 int NurbsCurve<T,N>::read(const char* filename){
03668 ifstream fin(filename) ;
03669 if(!fin) {
03670 return 0 ;
03671 }
03672 return read(fin) ;
03673 }
03674
03684 template <class T, int N>
03685 int NurbsCurve<T,N>::write(const char* filename) const {
03686 ofstream fout(filename) ;
03687
03688 if(!fout)
03689 return 0 ;
03690 return write(fout) ;
03691 }
03692
03702 template <class T, int N>
03703 int NurbsCurve<T,N>::write(ofstream &fout) const {
03704 if(!fout)
03705 return 0 ;
03706 int pn = P.n() ;
03707 char st = '0' + sizeof(T) ;
03708 if(!fout.write((char*)&"nc4",sizeof(char)*3)) return 0 ;
03709 if(!fout.write((char*)&st,sizeof(char))) return 0 ;
03710 if(!fout.write((char*)&pn,sizeof(int))) return 0 ;
03711 if(!fout.write((char*)°_,sizeof(int))) return 0 ;
03712 if(!fout.write((char*)U.memory(),sizeof(T)*U.n())) return 0 ;
03713
03714 T *p,*p2 ;
03715 p = new T[P.n()*4] ;
03716 p2 = p ;
03717 for(int i=0;i<P.n();i++) {
03718 *p = P[i].x() ; p++ ;
03719 *p = P[i].y() ; p++ ;
03720 *p = P[i].z() ; p++ ;
03721 *p = P[i].w() ; p++ ;
03722 }
03723 if(!fout.write((char*)p2,sizeof(T)*P.n()*4)) return 0 ;
03724 delete []p2 ;
03725 return 1 ;
03726 }
03727
03745 template <class T>
03746 void nurbsBasisFuns(T u, int span, int deg, const Vector<T>& U, Vector<T>& N) {
03747
03748 T* left = (T*) alloca(2*(deg+1)*sizeof(T)) ;
03749 T* right = &left[deg+1] ;
03750
03751 T temp,saved ;
03752
03753 N.resize(deg+1) ;
03754
03755 N[0] = 1.0 ;
03756 for(int j=1; j<= deg ; j++){
03757 left[j] = u-U[span+1-j] ;
03758 right[j] = U[span+j]-u ;
03759 saved = 0.0 ;
03760 for(int r=0 ; r<j; r++){
03761 temp = N[r]/(right[r+1]+left[j-r]) ;
03762 N[r] = saved+right[r+1] * temp ;
03763 saved = left[j-r] * temp ;
03764 }
03765 N[j] = saved ;
03766 }
03767
03768 }
03769
03790 template <class T>
03791 void nurbsDersBasisFuns(int n,T u, int span, int deg, const Vector<T>& U, Matrix<T>& ders) {
03792
03793 T* left = (T*) alloca(2*(deg+1)*sizeof(T)) ;
03794 T* right = &left[deg+1] ;
03795
03796 Matrix<T> ndu(deg+1,deg+1) ;
03797 T saved,temp ;
03798 int j,r ;
03799
03800 ders.resize(n+1,deg+1) ;
03801
03802 ndu(0,0) = 1.0 ;
03803 for(j=1; j<= deg ;j++){
03804 left[j] = u-U[span+1-j] ;
03805 right[j] = U[span+j]-u ;
03806 saved = 0.0 ;
03807
03808 for(r=0;r<j ; r++){
03809
03810 ndu(j,r) = right[r+1]+left[j-r] ;
03811 temp = ndu(r,j-1)/ndu(j,r) ;
03812
03813 ndu(r,j) = saved+right[r+1] * temp ;
03814 saved = left[j-r] * temp ;
03815 }
03816
03817 ndu(j,j) = saved ;
03818 }
03819
03820 for(j=0;j<=deg;j++)
03821 ders(0,j) = ndu(j,deg) ;
03822
03823
03824 Matrix<T> a(deg+1,deg+1) ;
03825 for(r=0;r<=deg;r++){
03826 int s1,s2 ;
03827 s1 = 0 ; s2 = 1 ;
03828 a(0,0) = 1.0 ;
03829
03830 for(int k=1;k<=n;k++){
03831 T d ;
03832 int rk,pk,j1,j2 ;
03833 d = 0.0 ;
03834 rk = r-k ; pk = deg-k ;
03835
03836 if(r>=k){
03837 a(s2,0) = a(s1,0)/ndu(pk+1,rk) ;
03838 d = a(s2,0)*ndu(rk,pk) ;
03839 }
03840
03841 if(rk>=-1){
03842 j1 = 1 ;
03843 }
03844 else{
03845 j1 = -rk ;
03846 }
03847
03848 if(r-1 <= pk){
03849 j2 = k-1 ;
03850 }
03851 else{
03852 j2 = deg-r ;
03853 }
03854
03855 for(j=j1;j<=j2;j++){
03856 a(s2,j) = (a(s1,j)-a(s1,j-1))/ndu(pk+1,rk+j) ;
03857 d += a(s2,j)*ndu(rk+j,pk) ;
03858 }
03859
03860 if(r<=pk){
03861 a(s2,k) = -a(s1,k-1)/ndu(pk+1,r) ;
03862 d += a(s2,k)*ndu(r,pk) ;
03863 }
03864 ders(k,r) = d ;
03865 j = s1 ; s1 = s2 ; s2 = j ;
03866 }
03867 }
03868
03869
03870 r = deg ;
03871 for(int k=1;k<=n;k++){
03872 for(j=0;j<=deg;j++)
03873 ders(k,j) *= r ;
03874 r *= deg-k ;
03875 }
03876
03877 }
03878
03879
03894 template <class T, int N>
03895 void NurbsCurve<T,N>::decompose(NurbsCurveArray<T,N>& c) const {
03896 int i,m,a,b,nb,mult,j,r,save,s,k ;
03897 T numer,alpha ;
03898 T* alphas = (T*) alloca((deg_+1)*sizeof(T)) ;
03899
03900
03901 Vector<T> nU ;
03902 nU.resize(2*(deg_+1)) ;
03903 for(i=0;i<nU.n()/2;i++)
03904 nU[i] = 0 ;
03905 for(i=nU.n()/2;i<nU.n();i++)
03906 nU[i] = 1 ;
03907
03908 c.resize(P.n()-deg_) ;
03909 for(i=0;i<c.n();i++){
03910 c[i].resize(deg_+1,deg_) ;
03911 c[i].U = nU ;
03912 }
03913
03914 m = P.n()+deg_ ;
03915 a = deg_ ;
03916 b = deg_+1 ;
03917 nb = 0 ;
03918
03919 for(i=0;i<=deg_;i++)
03920 c[nb].P[i] = P[i] ;
03921 while(b<m){
03922 i = b ;
03923 while(b<m && U[b+1] <= U[b]) b++ ;
03924 mult = b-i+1 ;
03925 if(mult<deg_){
03926 numer = U[b]-U[a] ;
03927 for(j=deg_;j>mult;j--)
03928 alphas[j-mult-1] = numer/(U[a+j]-U[a]) ;
03929 r = deg_-mult ;
03930 for(j=1;j<=r;j++){
03931 save=r-j;
03932 s=mult+j;
03933 for(k=deg_;k>=s;k--){
03934 alpha = alphas[k-s] ;
03935 c[nb].P[k] = alpha*c[nb].P[k] + (1.0-alpha)*c[nb].P[k-1] ;
03936 }
03937 if(b<m)
03938 c[nb+1].P[save] = c[nb].P[deg_];
03939 }
03940 }
03941 nb++ ;
03942 if(b<m){
03943 for(i=deg_-mult; i<= deg_ ; i++)
03944 c[nb].P[i] = P[b-deg_+i];
03945 a=b ;
03946 b++ ;
03947 }
03948 }
03949 c.resize(nb) ;
03950
03951 }
03952
03953 template <class T, int N>
03954 inline Point_nD<T,N> project2D(const HPoint_nD<T,N>& p){
03955 Point_nD<T,N> pnt ;
03956
03957 pnt.x() = p.x()/p.w() ;
03958 pnt.y() = p.y()/p.w() ;
03959
03960
03961
03962
03963
03964 return pnt ;
03965 }
03966
03967 const float offX = 50 ;
03968 const float offY = 70 ;
03969
03970 template <class T, int N>
03971 inline void movePsP(Point_nD<T,N> &p, T magFact){
03972 p *= magFact ;
03973 p += Point_nD<T,N>(offX,offY,0) ;
03974
03975 }
03976
03977 #ifdef HAVE_TEMPLATE_OF_TEMPLATE
03978 template <class T>
03979 inline void movePsP(Point_nD<T,2> &p, T magFact){
03980 p *= magFact ;
03981 p += Point_nD<T,2>(offX,offY) ;
03982
03983 }
03984 #else
03985
03986 template <>
03987 inline void movePsP(Point_nD<float,2> &p, float magFact){
03988 p *= magFact ;
03989 p += Point_nD<float,2>(offX,offY) ;
03990
03991 }
03992
03993 template <>
03994 inline void movePsP(Point_nD<double,2> &p, double magFact){
03995 p *= magFact ;
03996 p += Point_nD<double,2>(offX,offY) ;
03997
03998 }
03999
04000 #endif
04001
04026 template <class T, int N>
04027 int NurbsCurve<T,N>::writePS(const char* filename,int cp,T magFact, T dash, bool bOpen) const {
04028
04029 ofstream fout(filename) ;
04030
04031 if(!fout)
04032 return 0 ;
04033
04034 if(deg_<3){
04035 NurbsCurve<T,N> c3(*this) ;
04036 c3.degreeElevate(3-deg_) ;
04037 return c3.writePS(filename,cp,magFact,dash,bOpen) ;
04038 }
04039
04040 NurbsCurveArray<T,N> Ca ;
04041 if (bOpen)
04042 decompose(Ca) ;
04043 else
04044 decomposeClosed(Ca) ;
04045
04046 int guess =0 ;
04047 if(magFact<= T() ){
04048 magFact = T(1) ;
04049 guess = 1 ;
04050 }
04051
04052 Matrix< Point_nD<T,N> > pnts(Ca.n(),deg_+1) ;
04053 int i,j ;
04054
04055
04056
04057 for(i=0;i<Ca.n();i++){
04058 for(j=0;j<deg_+1;j++){
04059 pnts(i,j) = project2D(Ca[i].P[j]) ;
04060 }
04061 }
04062
04063
04064 T mx,my,Mx,My ;
04065 mx = Mx = pnts(0,0).x() ;
04066 my = My = pnts(0,0).y() ;
04067
04068 for(i=0;i<Ca.n();i++){
04069 Point_nD<T,N> p ;
04070 int step ;
04071 step = 8 ;
04072 for(j=0;j<=step;j++){
04073 T u ;
04074 u = (T)j/(T)step ;
04075 p = project2D(Ca[i](u)) ;
04076 if(p.x() < mx)
04077 mx = p.x() ;
04078 if(p.x() > Mx)
04079 Mx = p.x() ;
04080 if(p.y() < my)
04081 my = p.y() ;
04082 if(p.y() > My)
04083 My = p.y() ;
04084 }
04085 }
04086
04087 if(guess){
04088
04089 }
04090
04091 mx = mx*magFact+offX;
04092 my = my*magFact+offY;
04093 Mx = Mx*magFact+offX;
04094 My = My*magFact+offY;
04095 for(i=0;i<Ca.n();i++)
04096 for(j=0;j<deg_+1;j++)
04097 movePsP(pnts(i,j),magFact) ;
04098
04099 fout << "%!PS-Adobe-2.1\n%%Title: " << filename << endl ;
04100 fout << "%%Creator: NurbsCurve<T,N>::writePS\n" ;
04101 fout << "%%BoundingBox: " << mx << ' ' << my << ' ' << Mx << ' ' << My << endl ;
04102 fout << "%%Pages: 0" << endl ;
04103 fout << "%%EndComments" << endl ;
04104 fout << "0 setlinewidth\n" ;
04105 fout << "0 setgray\n" ;
04106 fout << endl ;
04107
04108 fout << "newpath\n" ;
04109 fout << pnts(0,0).x() << ' ' << pnts(0,0).y() << " moveto\n" ;
04110 for(i=0;i<Ca.n();i++){
04111 for(j=1;j<deg_+1;j++){
04112 fout << pnts(i,j).x() << ' ' << pnts(i,j).y() << ' ' ;
04113 }
04114 fout << "curveto\n" ;
04115 }
04116 fout << "stroke\n" ;
04117
04118 if(cp>0){
04119 Vector< Point_nD<T,N> > pts(P.n()) ;
04120 for(i=0;i<P.n();i++){
04121 pts[i] = project2D(P[i]) ;
04122 movePsP(pts[i],magFact) ;
04123 fout << "newpath\n" ;
04124 fout << pts[i].x() << ' ' << pts[i].y() << " 3 0 360 arc\nfill\n" ;
04125 }
04126 if(dash>0)
04127 fout << "[" << dash << "] " << dash << " setdash\n" ;
04128 fout << "newpath\n" ;
04129
04130 fout << pts[0].x() << ' ' << pts[0].y() << " moveto\n" ;
04131 for(i=1;i<P.n();i++)
04132 fout << pts[i].x() << ' ' << pts[i].y() << " lineto\n" ;
04133 fout << "stroke\n" ;
04134 }
04135 else{
04136 if(cp<0){
04137 Vector< Point_nD<T,N> > pts(P.n()*Ca.n()) ;
04138 int k=0 ;
04139 for(i=0;i<Ca.n();i++)
04140 for(j=0;j<deg_+1;j++){
04141 pts[k] = project2D(Ca[i].P[j]) ;
04142 movePsP(pts[k],magFact) ;
04143 fout << "newpath\n" ;
04144 fout << pts[k].x() << ' ' << pts[k].y() << " 3 0 360 arc\nfill\n" ;
04145 k++ ;
04146 }
04147 if(dash>0)
04148 fout << "[" << dash << "] " << dash << " setdash\n" ;
04149 fout << "newpath\n" ;
04150
04151 fout << pts[0].x() << ' ' << pts[0].y() << " moveto\n" ;
04152 for(i=1;i<k;i++)
04153 fout << pts[i].x() << ' ' << pts[i].y() << " lineto\n" ;
04154 fout << "stroke\n" ;
04155 }
04156 }
04157
04158 fout << "showpage\n%%EOF\n" ;
04159 return 1 ;
04160 }
04161
04195 template <class T, int N>
04196 int NurbsCurve<T,N>::writePSp(const char* filename,const Vector< Point_nD<T,N> >& points, const Vector< Point_nD<T,N> >& vectors, int cp, T magFact, T dash, bool bOpen) const {
04197 ofstream fout(filename) ;
04198
04199 if(!fout)
04200 return 0 ;
04201
04202 if(deg_<3){
04203 NurbsCurve<T,N> c3(*this) ;
04204 c3.degreeElevate(3-deg_) ;
04205 return c3.writePSp(filename,points,vectors,cp,magFact,dash,bOpen) ;
04206 }
04207
04208
04209 NurbsCurveArray<T,N> Ca ;
04210 if (bOpen)
04211 decompose(Ca) ;
04212 else
04213 decomposeClosed(Ca) ;
04214
04215 int guess =0 ;
04216 if(magFact<=0){
04217 magFact = 1.0 ;
04218 guess = 1 ;
04219 }
04220
04221 Matrix< Point_nD<T,N> > pnts(Ca.n(),deg_+1) ;
04222 int i,j ;
04223 for(i=0;i<Ca.n();i++){
04224 for(j=0;j<deg_+1;j++){
04225 pnts(i,j) = project2D(Ca[i].P[j]) ;
04226 }
04227 }
04228
04229
04230
04231 T mx,my,Mx,My ;
04232 mx = Mx = pnts(0,0).x() ;
04233 my = My = pnts(0,0).y() ;
04234
04235 for(i=0;i<Ca.n();i++){
04236 Point_nD<T,N> p ;
04237 int step ;
04238 step = 8 ;
04239 for(j=0;j<=step;j++){
04240 T u ;
04241 u = (T)j/(T)step ;
04242 p = project2D(Ca[i](u)) ;
04243 if(p.x() < mx)
04244 mx = p.x() ;
04245 if(p.x() > Mx)
04246 Mx = p.x() ;
04247 if(p.y() < my)
04248 my = p.y() ;
04249 if(p.y() > My)
04250 My = p.y() ;
04251 }
04252 }
04253
04254 if(guess){
04255 magFact = minimum((T)500/(T)(Mx-mx),(T)700/(T)(My-my)) ;
04256 }
04257
04258 mx = mx*magFact+offX;
04259 my = my*magFact+offY;
04260 Mx = Mx*magFact+offX;
04261 My = My*magFact+offY;
04262 for(i=0;i<Ca.n();i++)
04263 for(j=0;j<deg_+1;j++)
04264 movePsP(pnts(i,j),magFact) ;
04265
04266 fout << "%!PS-Adobe-2.1\n%%Title: " << filename << endl ;
04267 fout << "%%Creator: NurbsCurve<T,N>::writePS\n" ;
04268 fout << "%%BoundingBox: " << mx << ' ' << my << ' ' << Mx << ' ' << My << endl ;
04269 fout << "%%Pages: 0" << endl ;
04270 fout << "%%EndComments" << endl ;
04271 fout << "0 setlinewidth\n" ;
04272 fout << "0 setgray\n" ;
04273 fout << endl ;
04274
04275 fout << "newpath\n" ;
04276 fout << pnts(0,0).x() << ' ' << pnts(0,0).y() << " moveto\n" ;
04277 for(i=0;i<Ca.n();i++){
04278 for(j=1;j<deg_+1;j++){
04279 fout << pnts(i,j).x() << ' ' << pnts(i,j).y() << ' ' ;
04280 }
04281 fout << "curveto\n" ;
04282 }
04283 fout << "stroke\n" ;
04284
04285 if(cp>0){
04286 Vector< Point_nD<T,N> > pts(P.n()) ;
04287 for(i=0;i<P.n();i++){
04288 pts[i] = project2D(P[i]) ;
04289 movePsP(pts[i],magFact) ;
04290 fout << "newpath\n" ;
04291 fout << pts[i].x() << ' ' << pts[i].y() << " 3 0 360 arc\nfill\n" ;
04292 }
04293 if(dash>0)
04294 fout << "[" << dash << "] " << dash << " setdash\n" ;
04295 fout << "newpath\n" ;
04296
04297 fout << pts[0].x() << ' ' << pts[0].y() << " moveto\n" ;
04298 for(i=1;i<P.n();i++)
04299 fout << pts[i].x() << ' ' << pts[i].y() << " lineto\n" ;
04300 fout << "stroke\n" ;
04301 }
04302 else{
04303 if(cp<0){
04304 Vector< Point_nD<T,N> > pts(P.n()*Ca.n()) ;
04305 int k=0 ;
04306 for(i=0;i<Ca.n();i++)
04307 for(j=0;j<deg_+1;j++){
04308 pts[k] = project2D(Ca[i].P[j]) ;
04309 movePsP(pts[k],magFact) ;
04310 fout << "newpath\n" ;
04311 fout << pts[k].x() << ' ' << pts[k].y() << " 3 0 360 arc\nfill\n" ;
04312 k++ ;
04313 }
04314 if(dash>0)
04315 fout << "[" << dash << "] " << dash << " setdash\n" ;
04316 fout << "newpath\n" ;
04317
04318 fout << pts[0].x() << ' ' << pts[0].y() << " moveto\n" ;
04319 for(i=1;i<k;i++)
04320 fout << pts[i].x() << ' ' << pts[i].y() << " lineto\n" ;
04321 fout << "stroke\n" ;
04322 }
04323 }
04324
04325 for(i=0;i<points.n();++i){
04326 Point_nD<T,N> p ;
04327 p = points[i] ;
04328 movePsP(p,magFact) ;
04329 fout << "newpath\n" ;
04330 fout << p.x() << ' ' << p.y() << " 3 0 360 arc\nfill\n" ;
04331 }
04332
04333 if(vectors.n()==points.n()){
04334 for(i=0;i<points.n();++i){
04335 Point_nD<T,N> p,p2 ;
04336 p = points[i] ;
04337 p2 = points[i] + vectors[i] ;
04338 movePsP(p,magFact) ;
04339 movePsP(p2,magFact) ;
04340 fout << "newpath\n" ;
04341 fout << p.x() << ' ' << p.y() << " moveto\n" ;
04342 if(dash>0)
04343 fout << "[" << dash/2.0 << "] " << dash/2.0 << " setdash\n" ;
04344 fout << p2.x() << ' ' << p2.y() << " lineto\n" ;
04345 fout << "stroke\n" ;
04346 }
04347 }
04348
04349 fout << "showpage\n%%EOF\n" ;
04350 return 1 ;
04351 }
04352
04373 template <class T, int N>
04374 int NurbsCurve<T,N>::writeVRML(const char* filename,T radius,int K, const Color& color,int Nu,int Nv, T u_s, T u_e) const{
04375 NurbsSurface<T,N> S ;
04376 NurbsCurve<T,N> C ;
04377
04378 C.makeCircle(Point_nD<T,N>(0,0,0),Point_nD<T,N>(1,0,0),Point_nD<T,N>(0,0,1),radius,0,2*M_PI);
04379 S.sweep(*this,C,K) ;
04380 return S.writeVRML(filename,color,Nu,Nv,0,1,u_s,u_e) ;
04381 }
04382
04403 template <class T, int N>
04404 int NurbsCurve<T,N>::writeVRML97(const char* filename,T radius,int K, const Color& color,int Nu,int Nv, T u_s, T u_e) const{
04405 NurbsSurface<T,N> S ;
04406 NurbsCurve<T,N> C ;
04407
04408 C.makeCircle(Point_nD<T,N>(0,0,0),Point_nD<T,N>(1,0,0),Point_nD<T,N>(0,0,1),radius,0,2*M_PI);
04409 S.sweep(*this,C,K) ;
04410 return S.writeVRML97(filename,color,Nu,Nv,0,1,u_s,u_e) ;
04411 }
04412
04433 template <class T, int N>
04434 int NurbsCurve<T,N>::writeVRML(ostream &fout,T radius,int K, const Color& color,int Nu,int Nv, T u_s, T u_e) const{
04435 NurbsSurface<T,N> S ;
04436 NurbsCurve<T,N> C ;
04437
04438 C.makeCircle(Point_nD<T,N>(0,0,0),Point_nD<T,N>(1,0,0),Point_nD<T,N>(0,0,1),radius,0,2*M_PI);
04439 S.sweep(*this,C,K) ;
04440 return S.writeVRML(fout,color,Nu,Nv,0,1,u_s,u_e) ;
04441 }
04442
04463 template <class T, int N>
04464 int NurbsCurve<T,N>::writeVRML97(ostream &fout,T radius,int K, const Color& color,int Nu,int Nv, T u_s, T u_e) const{
04465 NurbsSurface<T,N> S ;
04466 NurbsCurve<T,N> C ;
04467
04468 C.makeCircle(Point_nD<T,N>(0,0,0),Point_nD<T,N>(1,0,0),Point_nD<T,N>(0,0,1),radius,0,2*M_PI);
04469 S.sweep(*this,C,K) ;
04470 return S.writeVRML97(fout,color,Nu,Nv,0,1,u_s,u_e) ;
04471 }
04472
04485 template <class T>
04486 void to3D(const NurbsCurve<T,2>& c2d, NurbsCurve<T,3>& c3d){
04487 c3d.resize(c2d.ctrlPnts().n(),c2d.degree()) ;
04488
04489 c3d.modKnot(c2d.knot()) ;
04490 HPoint_nD<T,3> p(0) ;
04491 for(int i=c2d.ctrlPnts().n()-1;i>=0;--i){
04492 p.x() = c2d.ctrlPnts()[i].x() ;
04493 p.y() = c2d.ctrlPnts()[i].y() ;
04494 p.w() = c2d.ctrlPnts()[i].w() ;
04495 c3d.modCP(i,p) ;
04496 }
04497 }
04498
04499 template <class T>
04500 void to3D(const NurbsCurve<T,3>& c2d, NurbsCurve<T,3>& c3d){
04501 c3d = c2d ;
04502 }
04503
04521 template <class T>
04522 void to2D(const NurbsCurve<T,3>& c3d, NurbsCurve<T,2>& c2d){
04523 c2d.resize(c3d.ctrlPnts().n(),c3d.degree()) ;
04524
04525 c2d.modKnot(c3d.knot()) ;
04526 HPoint_nD<T,2> p(0) ;
04527 for(int i=c3d.ctrlPnts().n()-1;i>=0;--i){
04528 p.x() = c3d.ctrlPnts()[i].x() ;
04529 p.y() = c3d.ctrlPnts()[i].y() ;
04530 p.w() = c3d.ctrlPnts()[i].w() ;
04531 c2d.modCP(i,p) ;
04532 }
04533 }
04534
04562 template <class T>
04563 void knotAveraging(const Vector<T>& uk, int deg, Vector<T>& U){
04564 U.resize(uk.n()+deg+1) ;
04565
04566 int j ;
04567 for(j=1;j<uk.n()-deg;++j){
04568 U[j+deg] = 0.0 ;
04569 for(int i=j;i<j+deg;++i)
04570 U[j+deg] += uk[i] ;
04571 U[j+deg] /= (T)deg ;
04572 }
04573 for(j=0;j<=deg;++j)
04574 U[j] = 0.0 ;
04575 for(j=U.n()-deg-1;j<U.n();++j)
04576 U[j] = 1.0 ;
04577 }
04578
04579
04580
04595 template <class T>
04596 void averagingKnots(const Vector<T>& U, int deg, Vector<T>& uk){
04597 uk.resize(U.n()-deg-1) ;
04598
04599 int i,k ;
04600
04601 uk[0] = U[0] ;
04602 uk[uk.n()-1] = U[U.n()-1] ;
04603
04604 for(k=1;k<uk.n()-1;++k){
04605 uk[k] = 0.0 ;
04606 for(i=k+1;i<k+deg+1;++i)
04607 uk[k] += U[i] ;
04608 uk[k] /= deg ;
04609 }
04610 }
04611
04627 template <class T, int N>
04628 int NurbsCurve<T,N>::movePoint(T u, const Point_nD<T,N>& delta) {
04629 BasicArray< Point_nD<T,N> > d(1) ;
04630 d[0] = delta ;
04631 return movePoint(u,d) ;
04632 }
04633
04654 template <class T, int N>
04655 int NurbsCurve<T,N>::movePoint(T u, const BasicArray< Point_nD<T,N> >& delta) {
04656 int i,j ;
04657
04658
04659 Matrix_DOUBLE B ;
04660
04661 int n,m ;
04662
04663 m = deg_ + 1 ;
04664 n = delta.n() ;
04665
04666 B.resize(n,m) ;
04667
04668 int span = findSpan(u) ;
04669
04670 n = 0 ;
04671
04672 Matrix<T> R ;
04673
04674 dersBasisFuns(delta.n()-1,u,span,R) ;
04675
04676
04677 for(i=0;i<delta.n();++i){
04678 if(delta[i].x()==0.0 && delta[i].y()==0.0 && delta[i].z()==0.0)
04679 continue ;
04680 for(j=0;j<m;++j){
04681 B(n,j) = (double)R(i,j) ;
04682 }
04683 ++n ;
04684 }
04685
04686 Matrix_DOUBLE A ;
04687 Matrix_DOUBLE Bt(transpose(B)) ;
04688 Matrix_DOUBLE BBt ;
04689
04690 BBt = inverse(B*Bt) ;
04691 A = Bt*BBt ;
04692
04693 Matrix_DOUBLE dD ;
04694
04695 dD.resize(delta.n(),N) ;
04696 for(i=0;i<delta.n();++i){
04697 const Point_nD<T,N>& d = delta[i] ;
04698 for(j=0;j<N;++j)
04699 dD(i,j) = (double)d.data[j] ;
04700 }
04701
04702 Matrix_DOUBLE dP ;
04703
04704 dP = A*dD ;
04705
04706 for(i=0;i<m;++i){
04707 P[span-deg_+i].x() += dP(i,0)*P[span-deg_+i].w() ;
04708 P[span-deg_+i].y() += dP(i,1)*P[span-deg_+i].w() ;
04709 P[span-deg_+i].z() += dP(i,2)*P[span-deg_+i].w() ;
04710 }
04711
04712 return 1 ;
04713 }
04714
04747 template <class T, int N>
04748 int NurbsCurve<T,N>::movePoint(const BasicArray<T>& ur, const BasicArray< Point_nD<T,N> >& D) {
04749 BasicArray<int> fixCP(0) ;
04750 BasicArray<int> Dr(D.n()) ;
04751 BasicArray<int> Dk(D.n()) ;
04752
04753 if(ur.n() != D.n()){
04754 #ifdef USE_EXCEPTION
04755 throw NurbsInputError(ur.n(),D.n()) ;
04756 #else
04757 Error err("movePoint(ur,D)");
04758 err << "The two input vectors are not of the same size\n" ;
04759 err << "ur.n()= " << ur.n() << ", D.n() = " << D.n() << endl ;
04760 err.fatal() ;
04761 #endif
04762 }
04763
04764 for(int i=0;i<Dr.n();++i){
04765 Dr[i] = i ;
04766 }
04767 Dk.reset(0) ;
04768 return movePoint(ur,D,Dr,Dk,fixCP) ;
04769 }
04770
04811 template <class T, int N>
04812 int NurbsCurve<T,N>::movePoint(const BasicArray<T>& ur, const BasicArray< Point_nD<T,N> >& D, const BasicArray_INT& Dr, const BasicArray_INT& Dk) {
04813 BasicArray_INT fixCP(0) ;
04814
04815 if(D.n() != Dr.n() ){
04816 #ifdef USE_EXCEPTION
04817 throw NurbsInputError(D.n(),Dr.n()) ;
04818 #else
04819 Error err("movePoint(ur,D,Dr,Dk)");
04820 err << "The D,Dr,Dk vectors are not of the same size\n" ;
04821 err << "D.n()= " << D.n() << ", Dr.n() = " << Dr.n()
04822 << ", Dk.n() = " << Dk.n() << endl ;
04823 err.fatal() ;
04824 #endif
04825 }
04826
04827 if( D.n() !=Dk.n()){
04828 #ifdef USE_EXCEPTION
04829 throw NurbsInputError(D.n(),Dk.n()) ;
04830 #else
04831 Error err("movePoint(ur,D,Dr,Dk)");
04832 err << "The D,Dr,Dk vectors are not of the same size\n" ;
04833 err << "D.n()= " << D.n() << ", Dr.n() = " << Dr.n()
04834 << ", Dk.n() = " << Dk.n() << endl ;
04835 err.fatal() ;
04836 #endif
04837 }
04838
04839 return movePoint(ur,D,Dr,Dk,fixCP) ;
04840 }
04841
04887 template <class T, int N>
04888 int NurbsCurve<T,N>::movePoint(const BasicArray<T>& ur, const BasicArray< Point_nD<T,N> >& D, const BasicArray_INT& Dr, const BasicArray_INT& Dk, const BasicArray_INT& fixCP) {
04889 int i,j,n ;
04890
04891 if(D.n() != Dr.n() ){
04892 #ifdef USE_EXCEPTION
04893 throw NurbsInputError(D.n(),Dr.n()) ;
04894 #else
04895 Error err("movePoint(ur,D,Dr,Dk)");
04896 err << "The D,Dr,Dk vectors are not of the same size\n" ;
04897 err << "D.n()= " << D.n() << ", Dr.n() = " << Dr.n()
04898 << ", Dk.n() = " << Dk.n() << endl ;
04899 err.fatal() ;
04900 #endif
04901 }
04902
04903 if( D.n() !=Dk.n()){
04904 #ifdef USE_EXCEPTION
04905 throw NurbsInputError(D.n(),Dk.n()) ;
04906 #else
04907 Error err("movePoint(ur,D,Dr,Dk)");
04908 err << "The D,Dr,Dk vectors are not of the same size\n" ;
04909 err << "D.n()= " << D.n() << ", Dr.n() = " << Dr.n()
04910 << ", Dk.n() = " << Dk.n() << endl ;
04911 err.fatal() ;
04912 #endif
04913 }
04914
04915
04916 Matrix_DOUBLE B ;
04917
04918 B.resize(D.n(),P.n()) ;
04919
04920 int span ;
04921
04922 Matrix<T> R ;
04923
04924 B.reset(0.0) ;
04925
04926 for(i=0;i<D.n();++i){
04927 span = findSpan(ur[Dr[i]]) ;
04928 dersBasisFuns(Dk[i],ur[Dr[i]],span,R) ;
04929 for(j=0;j<=deg_;++j){
04930 B(i,span-deg_+j) = (double)R(Dk[i],j) ;
04931 }
04932 }
04933
04934
04935 BasicArray_INT remove(B.cols()) ;
04936 BasicArray_INT map(B.cols()) ;
04937 remove.reset((int)1.0) ;
04938
04939 for(j=0;j<B.cols();++j){
04940 for(i=0;i<B.rows();++i)
04941 if((B(i,j)*B(i,j))>1e-10){
04942 remove[j] = 0 ;
04943 break ;
04944 }
04945 }
04946
04947 for(i=0;i<fixCP.n();++i){
04948 remove[fixCP[i]] = 1 ;
04949 }
04950
04951 n = 0 ;
04952 for(i=0;i<B.cols();++i){
04953 if(!remove[i]){
04954 map[n] = i ;
04955 ++n ;
04956 }
04957 }
04958
04959 map.resize(n) ;
04960
04961 Matrix_DOUBLE Bopt(B.rows(),n) ;
04962 for(j=0;j<n;++j){
04963 for(i=0;i<B.rows();++i)
04964 Bopt(i,j) = B(i,map[j]) ;
04965 }
04966
04967 Matrix_DOUBLE A ;
04968 Matrix_DOUBLE Bt(transpose(Bopt)) ;
04969 Matrix_DOUBLE BBt ;
04970
04971 BBt = inverse(Bopt*Bt) ;
04972
04973 A = Bt*BBt ;
04974
04975 Matrix_DOUBLE dD ;
04976
04977 dD.resize(D.n(),N) ;
04978 for(i=0;i<D.n();++i){
04979 const Point_nD<T,N>& d = D[i] ;
04980 for(j=0;j<N;++j)
04981 dD(i,j) = (double)d.data[j] ;
04982 }
04983
04984 Matrix_DOUBLE dP ;
04985
04986 dP = A*dD ;
04987
04988 for(i=0;i<map.n();++i){
04989 P[map[i]].x() += dP(i,0)*P[map[i]].w() ;
04990 P[map[i]].y() += dP(i,1)*P[map[i]].w() ;
04991 P[map[i]].z() += dP(i,2)*P[map[i]].w() ;
04992 }
04993
04994 return 1 ;
04995 }
04996
05011 template <class T, int N>
05012 int NurbsCurve<T,N>::splitAt(T u, NurbsCurve<T,N>& cl, NurbsCurve<T,N>& cu) const {
05013 if(u<= U[deg_])
05014 return 0 ;
05015 if(u>= U[U.n()-deg_-1])
05016 return 0 ;
05017
05018
05019 int s,j,i ;
05020 int span = findSpan(u) ;
05021
05022 if(absolute(u-U[span])<1e-6)
05023 s = findMult(span) ;
05024 else
05025 s = 0 ;
05026
05027 BasicArray<T> X(deg_+1-s) ;
05028 X.reset(u) ;
05029
05030 cl = *this ;
05031 if(X.n()>0)
05032 cl.refineKnotVector(X) ;
05033
05034 span = cl.findSpan(u)-deg_ ;
05035
05036 cu.resize(cl.P.n()-span,deg_) ;
05037 for(i=cl.P.n()-1,j=cu.P.n()-1;j>=0;--j,--i){
05038 cu.P[j] = cl.P[i] ;
05039 }
05040
05041 for(i=cl.U.n()-1,j=cu.U.n()-1;j>=0;--j,--i){
05042 cu.U[j] = cl.U[i] ;
05043 }
05044 cl.resize(span,deg_) ;
05045
05046 return 1 ;
05047 }
05048
05064 template <class T, int N>
05065 int NurbsCurve<T,N>::mergeOf(const NurbsCurve<T,N>& cl, const NurbsCurve<T,N> &cu){
05066 if(cl.deg_ != cu.deg_){
05067 #ifdef USE_EXCEPTION
05068 throw NurbsInputError();
05069 #else
05070 Error err("NurbsCurve<T,N>::mergeOf");
05071 err << " The two curves are not of the same degree\n" ;
05072 err.warning() ;
05073 return 0 ;
05074 #endif
05075 }
05076 if((cl.U[cl.U.n()-1]-cu.U[0])*(cl.U[cl.U.n()-1]-cu.U[0])>1e-8){
05077 #ifdef USE_EXCEPTION
05078 throw NurbsInputError();
05079 #else
05080 Error err("NurbsCurve<T,N>::mergeOf");
05081 err << " The two knot vectors are not compatible.\n" ;
05082 err << "The first one is " << cl.U << endl ;
05083 err << "The second is " << cu.U << endl ;
05084 err.warning() ;
05085 return 0 ;
05086 #endif
05087 }
05088 if(norm2(cl.P[cl.P.n()-1]-cu.P[0])>1e-8){
05089 #ifdef USE_EXCEPTION
05090 throw NurbsInputError();
05091 #else
05092 Error err("NurbsCurve<T,N>::mergeOf");
05093 err << " The end control points are NOT the same.\n" ;
05094 err << " cl.P[n-1] = " << cl.P[cl.P.n()-1] << endl ;
05095 err << " cu.P[0] = " << cu.P[0] << endl ;
05096 err.warning() ;
05097 return 0 ;
05098 #endif
05099 }
05100 resize(cl.P.n()+cu.P.n(),cl.deg_) ;
05101
05102 int i ;
05103 for(i=0;i<cl.P.n();++i)
05104 P[i] = cl.P[i] ;
05105 for(;i<P.n();++i)
05106 P[i] = cu.P[i-cl.P.n()] ;
05107
05108 for(i=0;i<cl.U.n();++i)
05109 U[i] = cl.U[i] ;
05110 for(;i<U.n();++i)
05111 U[i] = cu.U[i-cl.U.n()+deg_+1] ;
05112
05113 return 1 ;
05114 }
05115
05136 template <class T>
05137 int findSpan(T u, const Vector<T>& U, int deg) {
05138 if(u>=U[U.n()-deg-1])
05139 return U.n()-deg-1 ;
05140 if(u<=U[deg])
05141 return deg ;
05142
05143 int low = 0 ;
05144 int high = U.n()-deg ;
05145 int mid = (low+high)/2 ;
05146
05147 while(u<U[mid] || u>= U[mid+1]){
05148 if(u<U[mid])
05149 high = mid ;
05150 else
05151 low = mid ;
05152 mid = (low+high)/2 ;
05153 }
05154 return mid ;
05155
05156 }
05157
05158
05174 template <class T, int N>
05175 BasicList<Point_nD<T,N> > NurbsCurve<T,N>::tesselate(T tolerance,BasicList<T> *uk) const {
05176 BasicList<Point_nD<T,N> > list,list2 ;
05177
05178 NurbsCurveArray<T,N> ca ;
05179 decompose(ca) ;
05180
05181 if(ca.n()==1){
05182
05183 T u = U[0] ;
05184 Point_nD<T,N> maxD(0) ;
05185 Point_nD<T,N> prev ;
05186
05187 Vector< Point_nD<T,N> > ders(2) ;
05188
05189 deriveAt(u,1,ders) ;
05190
05191 prev = ders[1] ;
05192
05193 int i ;
05194 for(i=1;i<11;++i){
05195 u = T(i)/T(10)*(U[U.n()-1]-U[0]) + U[0] ;
05196 deriveAt(u,1,ders) ;
05197 Point_nD<T,N> delta = ders[1]-prev ;
05198 delta.x() = absolute(delta.x()) ;
05199 delta.y() = absolute(delta.y()) ;
05200 delta.z() = absolute(delta.z()) ;
05201 maxD = maximumRef(maxD,delta) ;
05202 prev = ders[1] ;
05203 }
05204
05205 const T sqr2 = T(1.414241527) ;
05206
05207 int n = (int)rint(sqr2*norm(maxD)/tolerance) ;
05208
05209 n+=2 ;
05210 if(n<3) n = 3 ;
05211
05212 for(i=0;i<n;++i){
05213 u = (U[U.n()-deg_-1]-U[deg_])*T(i)/T(n-1) + U[deg_] ;
05214 list.add(pointAt(u)) ;
05215 if(uk)
05216 uk->add(u) ;
05217 }
05218
05219 return list ;
05220 }
05221 else{
05222 for(int i=0;i<ca.n();++i){
05223 list2 = ca[i].tesselate(tolerance,uk) ;
05224
05225
05226 list.erase((BasicNode<Point_nD<T,N> >*)list.last()) ;
05227 list.addElements(list2) ;
05228 }
05229 }
05230 return list ;
05231 }
05232
05261 template <class T>
05262 int maxInfluence(int i, const Vector<T>& U, int p, T &u){
05263 if(i>U.n()-p-2)
05264 return 0 ;
05265 switch(p){
05266 case 1: u = U[i+1] ; return 1 ;
05267 case 2: {
05268 T A = U[i] + U[i+1] - U[i+2] - U[i+3] ;
05269 if(A>=0){
05270 u = U[i] ;
05271 return 1 ;
05272 }
05273 else{
05274 u = (U[i]*U[i+1] - U[i+2]*U[i+3])/A ;
05275 return 1 ;
05276 }
05277 }
05278 case 3:{
05279 double A = U[i]-U[i+3] ;
05280 if(A>=0){
05281 u = U[i] ;
05282 return 1 ;
05283 }
05284 A = U[i+1]-U[i+3] ;
05285 if(A>=0){
05286 u = U[i+1] ;
05287 return 1 ;
05288 }
05289
05290
05291 double a,b,c,d,e,X ;
05292 a = U[i] ;
05293 b = U[i+1] ;
05294 c = U[i+2] ;
05295 d = U[i+3] ;
05296 e = U[i+4] ;
05297
05298 double t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t15,t16,t18;
05299 double t21,t22,t24,t25,t27,t28,t31,t32,t34,t35,t45,t46 ,t49 ,t52 ,t56;
05300 double t63 ,t66 ,t69 ,t88 ,t107,t110 ;
05301 double t115,t116,t117,t118,t119,t120,t121,t122,t124,t125,t127;
05302 double t133,t135,t136,t143,t151,t154 ;
05303 double t14,t17,t19,t20,t26,t29,t30,t33,t36,t37,t38,t39,t47,t55,t57 ;
05304 double t59,t62,t64,t65,t67,t70,t72,t73,t75,t76,t77,t78,t79,t80 ;
05305 double t81,t82,t83,t84,t85,t86,t87,t90,t91,t92,t93,t95,t96 ;
05306 double t97,t99,t101 ;
05307
05308 t1 = b*e;
05309 t2 = b*b;
05310 t3 = b*a;
05311 t4 = b*d;
05312 t5 = b*c;
05313 t6 = d*e;
05314 t7 = c*d;
05315 t8 = c*e;
05316 t9 = c*a;
05317 t10 = a*e;
05318 t11 = d*a;
05319 t12 = a*a;
05320 t13 = -t1+t2+t3-t4-t5+t6+t7+t8-t9-t10-t11+t12;
05321 t14 = 1/t13;
05322 t15 = t2*a;
05323 t16 = t3*e;
05324 t17 = t3*c;
05325 t18 = t7*e;
05326 t19 = t3*d;
05327 t20 = t12*b;
05328 t21 = t2*t12;
05329 t22 = e*e;
05330 t24 = c*c;
05331 t25 = t24*t22;
05332 t26 = t25*t11;
05333 t27 = t12*t22;
05334 t28 = t27*t5;
05335 t29 = t24*t12;
05336 t30 = t29*t6;
05337 t31 = t27*t7;
05338 t32 = d*d;
05339 t33 = t32*t12;
05340 t34 = t33*t5;
05341 t35 = t33*t8;
05342 t36 = t29*t4;
05343 t37 = t33*t1;
05344 t38 = t12*a;
05345 t39 = t38*b;
05346 t45 = t21*t22-t26-t28+t30+t31-t34+t35-t36-t37+t39*t7+
05347 t39*t8-t38*c*t6+t39*t6;
05348 t46 = t2*b;
05349 t47 = t46*a;
05350 t49 = t15*t18;
05351 t52 = t3*t22*c*d;
05352 t55 = t24*d*e*t3;
05353 t56 = t2*t22;
05354 t57 = t56*t7;
05355 t59 = c*t32*t16;
05356 t62 = t7*e*t12*b;
05357 t63 = t56*t9;
05358 t64 = t56*t11;
05359 t65 = t24*t32;
05360 t66 = t65*t3;
05361 t67 = t46*c;
05362 t69 = t2*t32;
05363 t70 = t69*t9;
05364 t72 = t69*t8;
05365 t73 = t47*t8-3.0*t49+2.0*t52+2.0*t55+t57+2.0*t59-3.0*t62-t63-t64+t66+
05366 t67*t11-t70+t47*t6+t72;
05367 t75 = t2*t24;
05368 t76 = t75*t10;
05369 t77 = t69*t10;
05370 t78 = t75*t11;
05371 t79 = t32*t22;
05372 t80 = t79*t9;
05373 t81 = t79*t3;
05374 t82 = t75*t6;
05375 t83 = t25*t3;
05376 t84 = t65*t10;
05377 t85 = t65*t1;
05378 t86 = t79*t5;
05379 t87 = t25*t4;
05380 t88 = t27*t4;
05381 t90 = -t76-t77-t78-t80+t81+t82+t83-t84-t85-t86-t87-t88-t67*t6;
05382 t91 = t29*t1;
05383 t92 = t21*t8;
05384 t93 = t21*t6;
05385 t95 = t21*t7;
05386 t96 = t21*t24;
05387 t97 = t46*t12;
05388 t99 = t2*t38;
05389 t101 = t65*t22;
05390 t107 = -t91+2.0*t92+2.0*t93+t46*t38+2.0*t95+t96-t97*c-t99*c+t101+t21*t32-
05391 t99*d-t99*e-t97*e-t97*d;
05392 t110 = sqrt(t45+t73+t90+t107);
05393
05394 X = t14*(2.0*t15-2.0*t16-2.0*t17+2.0*t18-2.0*t19+2.0*t20+2.0*t110)/2;
05395
05396 if(c-b > 0){
05397
05398
05399
05400
05401
05402
05403
05404
05405
05406
05407
05408
05409
05410 if(X> b && X<=c + 1e-6 ){
05411 u = (T)X ;
05412 return 1 ;
05413 }
05414
05415 X = t14*(2.0*t15-2.0*t16-2.0*t17+2.0*t18-2.0*t19+2.0*t20-2.0*t110)/2;
05416 if(X>b && X<=c){
05417 u = (T)X ;
05418 return 1 ;
05419 }
05420 }
05421
05422 t115 = -t9-t32-t6+t1-t3+t4+t10+t11+t8-t5-t22+t7;
05423 t116 = 1/t115;
05424 t117 = t6*a;
05425 t118 = t4*e;
05426 t119 = d*t22;
05427 t120 = t32*e;
05428 t121 = -t26+t28+t30-t31+t34-t35-t36-t37+2.0*t49-3.0*t52+2.0*t55-t57-3.0*
05429 t59;
05430 t122 = 2.0*t62+t63-t64+t66+t70-t72-t76-t77-t78+2.0*t80+2.0*t81+t82+t83-
05431 t84;
05432 t124 = t32*d;
05433 t125 = t124*b;
05434 t127 = t124*t22;
05435 t133 = t22*e;
05436 t135 = -t85+2.0*t86-t87-t88-t91-t125*t9-t127*c+t125*t8+t125*t10+t124*a*t8
05437 +t124*t133-t92+t93;
05438 t136 = t133*b;
05439 t143 = t32*t133;
05440 t151 = -t95+t136*t7-t136*t9+t133*c*t11+t136*t11+t69*t22+t96+t101-t143*c-b
05441 *t32*t133-t125*t22-t143*a-t127*a+t79*t12;
05442 t154 = sqrt(t121+t122+t135+t151);
05443
05444
05445
05446 X=t116*(2.0*t117+2.0*t118-2.0*t17-2.0*t119-2.0*t120+2.0*t18+2.0*t154)/2.0;
05447
05448 if(X>=c - 1e-6 && X<d){
05449 u = (T)X ;
05450 return 1 ;
05451 }
05452
05453 X=t116*(2.0*t117+2.0*t118-2.0*t17-2.0*t119-2.0*t120+2.0*t18-2.0*t154)/2.0;
05454
05455 if(X>=c && X<d){
05456 u = (T)X ;
05457 return 1 ;
05458 }
05459
05460 #ifdef USE_EXCEPTION
05461 throw NurbsComputationError();
05462 #else
05463 Error error("maxInfluence") ;
05464 error << "It seems the program couldn't find a proper maxInfluence point\n." ;
05465 error << "so far u is set to " << u << endl ;
05466 error << "and the input arguments were \n" ;
05467 error << "i = " << i << endl ;
05468 error << "U = " << U << endl ;
05469 error << "p = " << p << endl ;
05470 error.warning() ;
05471 return 0 ;
05472 #endif
05473 }
05474 default:{
05475 #ifdef USE_EXCEPTION
05476 throw NurbsInputError();
05477 #else
05478 Error error("maxInfluence");
05479 error << "The point of maximal influence is only computed for a degree of 3 or lower." ;
05480 error << "The degree given was " << p << endl ;
05481 error.warning() ;
05482 return 0 ;
05483 #endif
05484 }
05485 }
05486 return 0;
05487 }
05488
05527 template <class T>
05528 T nurbsBasisFun(T u, int i, int p, const Vector<T>& U) {
05529 T Nip ;
05530 T saved,Uleft,Uright,temp ;
05531
05532 if(p<1){
05533 #ifdef USE_EXCEPTION
05534 throw NurbsInputError();
05535 #else
05536 Error error("nurbsBasisFun") ;
05537 error << "You need to specify a valid degree for the basis function!\n" ;
05538 error << "p = " << p << " but it requires a value >0.\n" ;
05539 error.fatal() ;
05540 #endif
05541 }
05542
05543 if((i==0 && u == U[p]) ||
05544 (i == U.n()-p-2 && u==U[U.n()-p-1])){
05545 Nip = 1.0 ;
05546 return Nip ;
05547 }
05548 if(u<U[i] || u>=U[i+p+1]){
05549 Nip = 0.0 ;
05550 return Nip;
05551 }
05552
05553 T* N = (T*) alloca((p+1)*sizeof(T)) ;
05554
05555 int j ;
05556 for(j=0;j<=p;j++){
05557 if(u>=U[i+j] && u<U[i+j+1])
05558 N[j] = 1.0 ;
05559 else
05560 N[j] = 0.0 ;
05561 }
05562 for(int k=1; k<=p ; k++){
05563 if(N[0] == 0.0)
05564 saved = 0.0 ;
05565 else
05566 saved = ( (u-U[i])*N[0])/(U[i+k]-U[i]) ;
05567 for(j=0;j<p-k+1;j++){
05568 Uleft = U[i+j+1] ;
05569 Uright = U[i+j+k+1] ;
05570 if(N[j+1]==0.0){
05571 N[j] = saved ;
05572 saved = 0.0 ;
05573 }
05574 else {
05575 temp = N[j+1]/(Uright-Uleft) ;
05576 N[j] = saved+(Uright-u)*temp ;
05577 saved = (u-Uleft)*temp ;
05578 }
05579 }
05580 }
05581 Nip = N[0] ;
05582
05583 return Nip ;
05584 }
05585
05586 template <class T, int N>
05587 struct LengthData {
05588 int span ;
05589 const NurbsCurve<T,N>* c ;
05590 LengthData(const NurbsCurve<T,N>* curve): c(curve) { }
05591 };
05592
05593 template <class T, int N>
05594 struct OpLengthFcn : public ClassPOvoid<T> {
05595 T operator()(T a, void* pnt){
05596 LengthData<T,N>* p = (LengthData<T,N>*)pnt ;
05597 return (p->c)->lengthF(a,p->span) ;
05598 }
05599 };
05600
05601
05626 template <class T, int N>
05627 T NurbsCurve<T,N>::length(T eps,int n) const {
05628 T l = T() ;
05629 T err ;
05630
05631 static Vector<T> bufFcn ;
05632
05633 if(bufFcn.n() != n){
05634 bufFcn.resize(n) ;
05635 intccini(bufFcn) ;
05636 }
05637
05638 LengthData<T,N> data(this) ;
05639 OpLengthFcn<T,N> op;
05640
05641 for(int i=deg_;i<P.n();++i){
05642 if(U[i] >= U[i+1])
05643 continue ;
05644 data.span = i ;
05645 l += intcc((ClassPOvoid<T>*)&op,(void*)&data,U[i],U[i+1],eps,bufFcn,err) ;
05646 }
05647 return l ;
05648 }
05649
05677 template <class T, int N>
05678 T NurbsCurve<T,N>::lengthIn(T us, T ue,T eps, int n) const {
05679 T l = T() ;
05680 T err ;
05681
05682 static Vector<T> bufFcn ;
05683
05684 if(bufFcn.n() != n){
05685 bufFcn.resize(n) ;
05686 intccini(bufFcn) ;
05687 }
05688
05689 LengthData<T,N> data(this) ;
05690 OpLengthFcn<T,N> op;
05691
05692 for(int i=deg_;i<P.n();++i){
05693 if(U[i] >= U[i+1])
05694 continue ;
05695 data.span = i ;
05696 if(i<findSpan(us))
05697 continue ;
05698 if(us>=U[i] && ue<=U[i+findMult(i)]){
05699 l = intcc((ClassPOvoid<T>*)&op,(void*)&data,us,ue,eps,bufFcn,err) ;
05700 break ;
05701 }
05702 if(us>=U[i]){
05703 l += intcc((ClassPOvoid<T>*)&op,(void*)&data,us,U[i+findMult(i)],eps,bufFcn,err) ;
05704 continue ;
05705 }
05706 if(ue<=U[i+findMult(i)]){
05707 l += intcc((ClassPOvoid<T>*)&op,(void*)&data,U[i],ue,eps,bufFcn,err) ;
05708 break ;
05709 }
05710 l += intcc((ClassPOvoid<T>*)&op,(void*)&data,U[i],U[i+findMult(i)],eps,bufFcn,err) ;
05711 }
05712 return l ;
05713 }
05714
05715
05716
05717
05731 template <class T, int N>
05732 T NurbsCurve<T,N>::lengthF(T u) const {
05733 Point_nD<T,N> dd = firstDn(u) ;
05734 T tmp = sqrt(dd.x()*dd.x()+dd.y()*dd.y()+dd.z()*dd.z()) ;
05735 return tmp ;
05736 }
05737
05752 template <class T, int N>
05753 T NurbsCurve<T,N>::lengthF(T u, int span) const {
05754 Point_nD<T,N> dd = firstDn(u,span) ;
05755 T tmp = sqrt(dd.x()*dd.x()+dd.y()*dd.y()+dd.z()*dd.z()) ;
05756 return tmp ;
05757 }
05758
05759
05774 template <class T, int N>
05775 void NurbsCurve<T,N>::makeLine(const Point_nD<T,N>& P0, const Point_nD<T,N>& P1, int d) {
05776 if(d<2)
05777 d = 2 ;
05778 resize(2,1) ;
05779 P[0] = HPoint_nD<T,N>(P0) ;
05780 P[1] = HPoint_nD<T,N>(P1) ;
05781 U[0] = U[1] = 0 ;
05782 U[2] = U[3] = 1 ;
05783 degreeElevate(d-1) ;
05784 }
05785
05799 template <class T, int D>
05800 HPoint_nD<T,D> NurbsCurve<T,D>::firstD(T u) const {
05801 int span = findSpan(u) ;
05802 int i ;
05803
05804 static Vector<T> N ;
05805
05806 nurbsBasisFuns(u,span,deg_-1,U,N) ;
05807
05808 HPoint_nD<T,D> Cd(0,0,0,0) ;
05809 HPoint_nD<T,D> Qi ;
05810
05811 for(i=deg_-1;i>=0;--i){
05812 int j = span-deg_+i ;
05813 Qi = (P[j+1]-P[j]);
05814 Qi *= T(deg_)/(U[j+deg_+1]-U[j+1]) ;
05815 Cd += N[i]*Qi ;
05816 }
05817
05818 return Cd ;
05819 }
05820
05836 template <class T, int D>
05837 HPoint_nD<T,D> NurbsCurve<T,D>::firstD(T u, int span) const {
05838 int i ;
05839
05840 static Vector<T> N ;
05841
05842 nurbsBasisFuns(u,span,deg_-1,U,N) ;
05843
05844 HPoint_nD<T,D> Cd(0,0,0,0) ;
05845 HPoint_nD<T,D> Qi ;
05846
05847 for(i=deg_-1;i>=0;--i){
05848 int j = span-deg_+i ;
05849 Qi = (P[j+1]-P[j]);
05850 Qi *= T(deg_)/(U[j+deg_+1]-U[j+1]) ;
05851 Cd += N[i]*Qi ;
05852 }
05853
05854 return Cd ;
05855 }
05856
05857
05872 template <class T, int N>
05873 Point_nD<T,N> NurbsCurve<T,N>::firstDn(T u) const {
05874 int span = findSpan(u) ;
05875 Point_nD<T,N> Cp ;
05876 HPoint_nD<T,N> Cd ;
05877 Cd = firstD(u,span) ;
05878
05879 Point_nD<T,N> pd(Cd.projectW()) ;
05880 T w = Cd.w() ;
05881 Cd = hpointAt(u,span) ;
05882 pd -= w*project(Cd) ;
05883 pd /= Cd.w() ;
05884
05885 return pd ;
05886 }
05887
05901 template <class T, int N>
05902 Point_nD<T,N> NurbsCurve<T,N>::firstDn(T u, int span) const {
05903 int i ;
05904 Point_nD<T,N> Cp ;
05905 HPoint_nD<T,N> Cd ;
05906 Cd = firstD(u,span) ;
05907
05908 Point_nD<T,N> pd(Cd.projectW()) ;
05909 T w = Cd.w() ;
05910 Cd = hpointAt(u,span) ;
05911 pd -= w*project(Cd) ;
05912 pd /= Cd.w() ;
05913
05914 return pd ;
05915 }
05916
05943 template <class T, int N>
05944 int NurbsCurve<T,N>::leastSquaresClosed(const Vector< Point_nD<T,N> >& Qw, int degC, int nCP){
05945
05946 Vector<T> ub;
05947 Vector<T> Uk;
05948 chordLengthParamClosed(Qw,ub,degC) ;
05949 return leastSquaresClosed(Qw,degC,nCP,ub);
05950 }
05951
05980 template <class T, int N>
05981 int NurbsCurve<T,N>::leastSquaresClosed(const Vector< Point_nD<T,N> >& Qw, int degC, int nCP, const Vector<T>& ub){
05982 Vector<T> Uk;
05983 knotApproximationClosed(Uk,ub,nCP+degC-1,degC);
05984 return leastSquaresClosed(Qw,degC,nCP,ub,Uk);
05985 }
05986
06014 template <class T, int N>
06015 int NurbsCurve<T,N>::leastSquaresClosedH(const Vector< HPoint_nD<T,N> >& Qw, int degC, int nCP, const Vector<T>& ub){
06016
06017 Vector<T> Uk;
06018 knotApproximationClosed(Uk,ub,nCP+degC-1,degC);
06019
06020 return leastSquaresClosedH(Qw,degC,nCP,ub,Uk);
06021 }
06022
06051 template <class T, int D>
06052 int NurbsCurve<T,D>::leastSquaresClosed(const Vector< Point_nD<T,D> >& Qw, int degC, int nCP, const Vector<T>& ub, const Vector<T>& knots){
06053 resize(nCP+degC,degC) ;
06054
06055 int n = P.n()-1;
06056 int iN = nCP-1;
06057 int iM = Qw.n()-degC-1;
06058 int p = degC ;
06059
06060 if(ub.n() != Qw.n()){
06061 #ifdef USE_EXCEPTION
06062 throw NurbsInputError(ub.n(),Qw.n());
06063 #else
06064 Error err("leastSquaresClosed");
06065 err << "leastSquaresCurveC\n" ;
06066 err << "ub size is different than Qw's\n" ;
06067 err.fatal();
06068 #endif
06069 }
06070
06071 if( knots.n() != U.n()){
06072 #ifdef USE_EXCEPTION
06073 throw NurbsInputError(knots.n(),U.n());
06074 #else
06075 Error err("leastSquaresClosed");
06076 err << "The knot vector supplied doesn't have the proper size.\n" ;
06077 err << "It should be n+degC+1 = " << U.n() << " and it is " << knots.n() << endl ;
06078 err.fatal() ;
06079 #endif
06080 }
06081
06082 Matrix_DOUBLE N(iM+1,iN+1);
06083 Matrix_DOUBLE A(iN+1,iN+1);
06084 Matrix_DOUBLE R(iN+1,D);
06085 Matrix_DOUBLE Pi(iN+1,D);
06086
06087
06088 U = knots;
06089
06090
06091 N = 0;
06092 for (int i=0; i<=n; i++)
06093 for (int k=0; k<=iM; k++)
06094 N(k,i%(iN+1)) += basisFun(ub[k],i,p) ;
06095
06096
06097 R.reset(0.0);
06098 for (int i=0; i<=iN; i++)
06099 for (int k=0; k<=iM; k++){
06100 const Point_nD<T,D>& qp = Qw[k] ;
06101 const double& Nki = N(k,i);
06102 for (int j=0; j<D; j++)
06103 R(i,j) += Nki * qp.data[j] ;
06104 }
06105
06106
06107 A = N.transpose() * N ;
06108 solve(A,R,Pi);
06109
06110
06111 for (int i=0; i<= n; i++)
06112 for (int k=0; k<D; k++){
06113 P[i].data[k] = Pi(i%(iN+1),k) ;
06114 P[i].w() = 1.0;
06115 }
06116 return 1;
06117 }
06118
06119
06148 template <class T, int D>
06149 int NurbsCurve<T,D>::leastSquaresClosedH(const Vector< HPoint_nD<T,D> >& Qw, int degC, int nCP, const Vector<T>& ub, const Vector<T>& knots){
06150
06151 resize(nCP+degC,degC) ;
06152
06153 int n = P.n()-1;
06154 int iN = nCP-1;
06155 int iM = Qw.n()-degC-1;
06156 int p = degC ;
06157
06158
06159 if(ub.n() != Qw.n()){
06160 #ifdef USE_EXCEPTION
06161 throw NurbsInputError(ub.n(),Qw.n());
06162 #else
06163 Error err("leastSquaresClosedH");
06164 err << "leastSquaresCurveC\n" ;
06165 err << "ub size is different than Qw's\n" ;
06166 err.fatal();
06167 #endif
06168 }
06169
06170 if( knots.n() != U.n()){
06171 #ifdef USE_EXCEPTION
06172 throw NurbsInputError(knots.n(),U.n());
06173 #else
06174 Error err("leastSquaresClosed");
06175 err << "The knot vector supplied doesn't have the proper size.\n" ;
06176 err << "It should be n+degC+1 = " << U.n() << " and it is " << knots.n() << endl ;
06177 err.fatal() ;
06178 #endif
06179 }
06180
06181 Matrix_DOUBLE N(iM+1,iN+1);
06182 Matrix_DOUBLE A(iN+1,iN+1);
06183 Matrix_DOUBLE R(iN+1,D+1);
06184 Matrix_DOUBLE Pi(iN+1,D+1);
06185
06186
06187 U = knots;
06188
06189
06190 N = 0;
06191 for (int i=0; i<=n; i++)
06192 for (int k=0; k<=iM; k++)
06193 N(k,i%(iN+1)) += basisFun(ub[k],i,p) ;
06194
06195
06196 R.reset(0.0);
06197 for (int i=0; i<=iN; i++)
06198 for (int k=0; k<=iM; k++){
06199 const HPoint_nD<T,D>& qp = Qw[k] ;
06200 const double& Nki = N(k,i);
06201 for (int j=0; j<D+1; j++)
06202 R(i,j) += Nki * qp.data[j] ;
06203 }
06204
06205
06206 A = N.transpose() * N ;
06207 solve(A,R,Pi);
06208
06209
06210 for (int i=0; i<= n; i++)
06211 for (int k=0; k<D+1; k++){
06212 P[i].data[k] = Pi(i%(iN+1),k) ;
06213
06214 }
06215 return 1;
06216 }
06217
06218
06233 template <class T, int N>
06234 T chordLengthParamClosed(const Vector< Point_nD<T,N> >& Qw, Vector<T> &ub,int deg){
06235
06236 int i ;
06237 T d = 0.0 ;
06238
06239 ub.resize(Qw.n()) ;
06240 ub[0] = 0 ;
06241 for(i=1;i<=ub.n()-deg;i++){
06242 d += norm(Qw[i]-Qw[i-1]) ;
06243 }
06244 if(d>0){
06245 for(i=1;i<ub.n();++i)
06246 ub[i] = ub[i-1] + norm(Qw[i]-Qw[i-1]);
06247
06248 for(i=0;i<ub.n();++i)
06249 ub[i]/= d;
06250 }
06251 else
06252 for(i=1;i<ub.n();++i)
06253 ub[i] = (T)(i)/(T)(ub.n()-2) ;
06254
06255 return d ;
06256 }
06257
06272 template <class T, int N>
06273 T chordLengthParamClosedH(const Vector< HPoint_nD<T,N> >& Qw, Vector<T> &ub,int deg){
06274
06275 int i ;
06276 T d = 0.0 ;
06277
06278 ub.resize(Qw.n()) ;
06279 ub[0] = 0 ;
06280 for(i=1;i<ub.n()-deg+1;i++){
06281 d += norm(Qw[i]-Qw[i-1]) ;
06282 }
06283 if(d>0){
06284 for(i=1;i<ub.n();++i)
06285 ub[i] = ub[i-1] + norm(Qw[i]-Qw[i-1]);
06286
06287 for(i=0;i<ub.n();++i)
06288 ub[i]/=ub[ub.n()-deg] ;
06289 }
06290 else
06291 for(i=1;i<ub.n();++i)
06292 ub[i] = (T)(i)/(T)(ub.n()-deg) ;
06293
06294 return d ;
06295 }
06296
06297
06308 template <class T, int N>
06309 void NurbsCurve<T,N>::refineKnotVectorClosed(const Vector<T>& X){
06310
06311 int n = P.n()-1 ;
06312 int p = deg_ ;
06313 int m = n+p+1 ;
06314 int a,b ;
06315 int r = X.n()-1 ;
06316
06317
06318 NurbsCurve<T,N> c(*this) ;
06319 resize(r+1+n+1,p) ;
06320 a = c.findSpan(X[0]) ;
06321 b = c.findSpan(X[r]) ;
06322 ++b ;
06323 int j ;
06324
06325 for(j=0; j<=a-p ; j++)
06326 P[j] = c.P[j] ;
06327 for(j = b-1 ; j<=n ; j++)
06328 P[j+r+1] = c.P[j] ;
06329 for(j=0; j<=a ; j++)
06330 U[j] = c.U[j] ;
06331 for(j=b+p ; j<=m ; j++)
06332 U[j+r+1] = c.U[j] ;
06333
06334 int i = b+p-1 ;
06335 int k = b+p+r ;
06336 for(j=r; j>=0 ; j--){
06337 while(X[j] <= c.U[i] && i>a){
06338 int ind = i-p-1;
06339 if (ind<0)
06340 ind += n + 1 ;
06341 P[k-p-1] = c.P[ind] ;
06342 U[k] = c.U[i] ;
06343 --k ;
06344 --i ;
06345 }
06346 P[k-p-1] = P[k-p] ;
06347 for(int l=1; l<=p ; l++){
06348 int ind = k-p+l ;
06349 T alpha = U[k+l] - X[j] ;
06350 if(alpha==0.0)
06351 P[ind-1] = P[ind] ;
06352 else {
06353 alpha /= U[k+l]-c.U[i-p+l] ;
06354 P[ind-1] = alpha*P[ind-1] + (1.0-alpha)*P[ind] ;
06355 }
06356 }
06357 U[k] = X[j] ;
06358 --k ;
06359 }
06360 }
06361
06362
06378 template <class T, int N>
06379 void NurbsCurve<T,N>::globalInterpClosed(const Vector< Point_nD<T,N> >& Qw, int d){
06380 Vector<T> ub ;
06381 Vector<T> Uc;
06382
06383 chordLengthParamClosed(Qw,ub,d) ;
06384 knotAveragingClosed(ub,d,Uc);
06385
06386 globalInterpClosed(Qw,ub,Uc,d) ;
06387 }
06388
06407 template <class T, int D>
06408 void NurbsCurve<T,D>::globalInterpClosedH(const Vector< HPoint_nD<T,D> >& Qw, int d){
06409
06410 Vector<T> ub ;
06411 Vector<T> Uc;
06412
06413 chordLengthParamClosedH(Qw,ub,d) ;
06414 knotAveragingClosed(ub,d,Uc);
06415 globalInterpClosedH(Qw,ub,Uc,d);
06416
06417 }
06418
06436 template <class T, int D>
06437 void NurbsCurve<T,D>::globalInterpClosed(const Vector< Point_nD<T,D> >& Qw, const Vector<T>& ub, int d){
06438
06439 Vector<T> Uc;
06440 knotAveragingClosed(ub,d,Uc);
06441 globalInterpClosed(Qw,ub,Uc,d);
06442 }
06443
06461 template <class T, int D>
06462 void NurbsCurve<T,D>::globalInterpClosedH(const Vector< HPoint_nD<T,D> >& Qw, const Vector<T>& ub, int d){
06463
06464 Vector<T> Uc;
06465 knotAveragingClosed(ub,d,Uc);
06466 globalInterpClosedH(Qw,ub,Uc,d);
06467 }
06468
06487 template <class T, int D>
06488 void NurbsCurve<T,D>::globalInterpClosed(const Vector< Point_nD<T,D> >& Qw,
06489 const Vector<T>& ub, const Vector<T>& Uc, int d){
06490 int i,j ;
06491
06492 resize(Qw.n(),d) ;
06493
06494 int iN = Qw.n() - d - 1;
06495 Matrix_DOUBLE A(iN+1,iN+1) ;
06496
06497 if(Uc.n() != U.n()){
06498 #ifdef USE_EXCEPTION
06499 throw NurbsInputError(Uc.n(),U.n());
06500 #else
06501 Error err("globalInterpClosedH");
06502 err << "Invalid dimension for the given Knot vector.\n" ;
06503 err << "U required = " << U.n() << ", U given = " << Uc.n() << endl ;
06504 err.fatal() ;
06505 #endif
06506 }
06507 U = Uc ;
06508
06509
06510 Vector<T> N(d+1) ;
06511
06512 for(i=0;i<=iN;i++){
06513 int span = findSpan(ub[i]);
06514 basisFuns(ub[i],span,N) ;
06515 for(j=span-d;j<=span;j++)
06516 A(i,j%(iN+1)) = (double)N[j-span+d] ;
06517 }
06518
06519
06520 Matrix_DOUBLE qq(iN+1,D) ;
06521 Matrix_DOUBLE xx(iN+1,D) ;
06522 for(i=0;i<=iN ;i++)
06523 for(j=0; j<D;j++)
06524 qq(i,j) = (double)Qw[i].data[j] ;
06525
06526
06527
06528
06529
06530 SVDMatrix<double> svd(A) ;
06531 svd.solve(qq,xx) ;
06532
06533
06534 for(i=0;i<xx.rows();i++){
06535 for(j=0;j<D;j++)
06536 P[i].data[j] = (T)xx(i,j) ;
06537 P[i].w() = 1.0 ;
06538 }
06539
06540
06541 for(i=0;i<d;i++){
06542 for(j=0;j<D;j++)
06543 P[xx.rows()+i].data[j] = (T)xx(i,j) ;
06544 }
06545 }
06546
06565 template <class T, int D>
06566 void NurbsCurve<T,D>::globalInterpClosedH(const Vector< HPoint_nD<T,D> >& Qw,
06567 const Vector<T>& ub, const Vector<T>& Uc, int d){
06568 int i,j ;
06569
06570 resize(Qw.n(),d) ;
06571
06572 int iN = Qw.n() - d - 1;
06573 Matrix_DOUBLE A(iN+1,iN+1) ;
06574
06575 if(Uc.n() != U.n()){
06576 #ifdef USE_EXCEPTION
06577 throw NurbsInputError(Uc.n(),U.n());
06578 #else
06579 Error err("globalInterpClosedH");
06580 err << "Invalid dimension for the given Knot vector.\n" ;
06581 err << "U required = " << U.n() << ", U given = " << Uc.n() << endl ;
06582 err.fatal() ;
06583 #endif
06584 }
06585 U = Uc ;
06586
06587
06588 Vector<T> N(d+1) ;
06589
06590 for(i=0;i<=iN;i++){
06591 int span = findSpan(ub[i]);
06592 basisFuns(ub[i],span,N) ;
06593 for(j=span-d;j<=span;j++)
06594 A(i,j%(iN+1)) = (double)N[j-span+d] ;
06595 }
06596
06597
06598 Matrix_DOUBLE qq(iN+1,D+1) ;
06599 Matrix_DOUBLE xx(iN+1,D+1) ;
06600 for(i=0;i<=iN ;i++)
06601 for(j=0; j<D+1;j++)
06602 qq(i,j) = (double)Qw[i].data[j] ;
06603
06604
06605
06606
06607
06608 SVDMatrix<double> svd(A) ;
06609 svd.solve(qq,xx) ;
06610
06611
06612 for(i=0;i<xx.rows();i++){
06613 for(j=0;j<D+1;j++)
06614 P[i].data[j] = (T)xx(i,j) ;
06615 }
06616
06617
06618 for(i=0;i<d;i++){
06619 for(j=0;j<D+1;j++)
06620 P[xx.rows()+i].data[j] = (T)xx(i,j) ;
06621 }
06622 }
06623
06635 template <class T, int D>
06636 void NurbsCurve<T,D>::decomposeClosed(NurbsCurveArray<T,D>& c) const {
06637
06638 int ix,b,nb,mult,j ;
06639 Vector<T> alphas(deg_+1) ;
06640 Vector<T> Uexpanded(U.n()+2*deg_) ;
06641 Vector< HPoint_nD<T,D> > Pexpanded(P.n()+2*deg_) ;
06642
06643 int N = P.n() - deg_ - 1;
06644 int i ;
06645
06646
06647 for (i=0; i<deg_; i++){
06648 Pexpanded[i] = P[P.n()-2*deg_+i] ;
06649 Uexpanded[i] = U[N+1-deg_+i] - 1 ;
06650 }
06651
06652
06653 for (i=0; i<P.n(); i++)
06654 Pexpanded[i+deg_] = P[i] ;
06655 for (i=0; i<U.n(); i++)
06656 Uexpanded[i+deg_] = U[i] ;
06657
06658
06659 for (i=0; i<deg_; i++){
06660 Pexpanded[i+deg_+P.n()] = P[deg_+i] ;
06661 Uexpanded[i+deg_+U.n()] = 1 + U[2*deg_+1+i] ;
06662 }
06663
06664 Vector<T> nU ;
06665 nU.resize(2*(deg_+1)) ;
06666 for(i=0;i<nU.n()/2;i++)
06667 nU[i] = 0 ;
06668 for(i=nU.n()/2;i<nU.n();i++)
06669 nU[i] = 1 ;
06670
06671 c.resize(P.n()) ;
06672
06673 for(i=0;i<c.n();i++){
06674 c[i].resize(deg_+1,deg_) ;
06675 c[i].U = nU ;
06676 }
06677
06678 Vector<T> X(Uexpanded.n()*deg_) ;
06679
06680
06681 ix= 0;
06682 i = 0;
06683 b = 2*deg_;
06684
06685 while ( b < U.n() ) {
06686 i = b;
06687 while( b < Uexpanded.n()-1 && Uexpanded[b+1] <= Uexpanded[b] ) b++ ;
06688 mult = b-i+1 ;
06689
06690 if(mult<deg_){
06691 for(j=deg_;j>=mult;j--) {
06692 X[ix] = Uexpanded[b] ;
06693 ix++ ;
06694 }
06695 }
06696 b++;
06697 }
06698
06699 X.resize(ix);
06700
06701 NurbsCurve<T,D> cl = NurbsCurve(Pexpanded,Uexpanded,deg_);
06702 cl.refineKnotVectorClosed(X) ;
06703
06704
06705
06706 nb = P.n()-deg_;
06707
06708 c.resize(nb);
06709 for (i=0; i<c.n(); i++)
06710 for (int k=0; k<=deg_; k++)
06711 c[i].P[k] = cl.P[i*(deg_+1)+k+2*deg_];
06712 }
06713
06726 template <class T>
06727 void knotAveragingClosed(const Vector<T>& uk, int deg, Vector<T>& U){
06728
06729 U.resize(uk.n()+deg+1) ;
06730
06731 int i, j ;
06732 int index;
06733 int iN = uk.n() - deg - 1;
06734 int n = uk.n() - 1;
06735 int m = U.n() - 1;
06736
06737
06738
06739 for (j=0; j<=iN; j++) {
06740 index = j+deg+1;
06741 U[index] = 0.0;
06742 for (i=j; i<=j+deg-1; i++)
06743 U[index] += uk[i];
06744 U[index] /= deg;
06745 }
06746
06747
06748
06749 for (j=0; j<deg; j++) U[j] = U[j+iN+1] - 1;
06750
06751 for (j=n+1; j<=m; j++) U[j] = 1 + U[j-(iN+1)];
06752
06753 }
06754
06769 template <class T>
06770 void knotApproximationClosed( Vector<T>& U, const Vector<T>& ub, int n, int p){
06771
06772 int i, j;
06773 int iN = n - p ;
06774 U.resize(n+p+2) ;
06775 T d = ub.n()/(T)(n-p+1) ;
06776 T alpha;
06777
06778 U = 0 ;
06779
06780 for ( j=1; j<= n-p ; j++) {
06781 i = int(j*d);
06782 alpha = j*d - i;
06783 U[p+j] = (1-alpha)*ub[i-1] + alpha*ub[i] ;
06784 }
06785
06786
06787
06788 for (j=0; j<p; j++) U[j] = U[j+iN+1] - 1;
06789
06790 for (j=n+1; j<U.n(); j++) U[j] = 1 + U[j-(iN+1)];
06791 }
06792
06805 template <class T, int N>
06806 void wrapPointVector(const Vector<Point_nD<T,N> >& Q, int d, Vector<Point_nD<T,N> >& Qw){
06807 int i ;
06808
06809 Qw = Q;
06810 Qw.resize(Q.n()+d);
06811
06812 for (i=0; i<d; i++)
06813 Qw[i+Q.n()] = Q[i];
06814
06815 }
06816
06829 template <class T, int N>
06830 void wrapPointVectorH(const Vector<HPoint_nD<T,N> >& Q, int d, Vector<HPoint_nD<T,N> >& Qw){
06831 int i ;
06832
06833 Qw = Q;
06834 Qw.resize(Q.n()+d);
06835
06836 for (i=0; i<d; i++)
06837 Qw[i+Q.n()] = Q[i];
06838
06839 }
06840
06859 template <class T, int N>
06860 int NurbsCurve<T,N>::writeDisplayLINE(const char* filename, int iNu, const Color& color,T fA) const
06861 {
06862
06863 int i;
06864
06865 NurbsCurve<T,3> curve3D;
06866 to3D(*this,curve3D);
06867
06868 T fDu = 1/T(iNu);
06869 ofstream fout(filename) ;
06870 if(!fout)
06871 return 0 ;
06872
06873 const char LINE = 'l'+ ('A' - 'a');
06874 fout << LINE << ' '; ;
06875 T fThickness = T(1.);
06876
06877 fout << fThickness << ' '
06878 << iNu << endl;
06879
06880 Point_nD<T,3> p;
06881 for (T u = 0; u<1-fDu/2; u+=fDu, i++){
06882 p = T(-1)*curve3D.pointAt(u);
06883 fout << p.x() << ' ' << p.z() << ' ' << p.y() << endl;
06884 }
06885
06886 fout << endl ;
06887
06888 fout << 1 << endl ;
06889
06890 fout << endl ;
06891
06892 T fR= T(color.r)/255;
06893 T fG= T(color.g)/255;
06894 T fB= T(color.b)/255;
06895
06896 fout << 0 << ' ' ;
06897
06898 fout << fR << ' '
06899 << fG << ' '
06900 << fB << ' '
06901 << fA << endl;
06902
06903 fout << endl ;
06904 fout << iNu << endl;
06905
06906 fout << endl ;
06907
06908 for (i=0; i<iNu; i++)
06909 fout << i << ' ';
06910 fout << endl ;
06911 return 1;
06912 }
06913
06934 template <class T, int N>
06935 int NurbsCurve<T,N>::writeDisplayLINE(const char* filename,const Color& color, int iNu,T u_s, T u_e) const
06936 {
06937
06938 int i;
06939 T fDu = (u_e-u_s)/iNu;
06940 ofstream fout(filename) ;
06941 if(!fout)
06942 return 0 ;
06943
06944
06945 const char LINE = 'l'+ ('A' - 'a');
06946 fout << LINE << ' '; ;
06947
06948 float fThickness = 1;
06949
06950 fout << fThickness << ' '
06951 << iNu << endl;
06952
06953
06954 NurbsCurve<T,3> Curve;
06955 to3D(*this,Curve);
06956 Point_nD<T,3> p;
06957 T u ;
06958 for ( u = u_s; u<u_e-fDu/2; u+=fDu, i++){
06959
06960 p = -1.0*Curve.pointAt(u);
06961 fout << p.x() << ' ' << p.z() << ' ' << p.y() << endl;
06962 }
06963
06964
06965 fout << endl ;
06966
06967 fout << 1 << endl ;
06968
06969 fout << endl ;
06970
06971 float fR=color.r/255.0;
06972 float fG=color.g/255.0;
06973 float fB=color.b/255.0;
06974 float fA=1;
06975
06976 fout << 0 << ' ' ;
06977
06978 fout << fR << ' '
06979 << fG << ' '
06980 << fB << ' '
06981 << fA << endl;
06982
06983
06984 fout << endl ;
06985
06986 fout << iNu << endl;
06987
06988
06989 fout << endl ;
06990
06991
06992 for (i=0; i<iNu; i++)
06993 fout << i << ' ';
06994 fout << endl ;
06995
06996 return 1;
06997 }
06998
07011 template <class T, int N>
07012 void NurbsCurve<T,N>::setTangent(T u, const Point_nD<T,N>& T0) {
07013 Point_nD<T,N> ders = derive3D(u,1) ;
07014
07015 BasicArray<Point_nD<T,N> > D(2) ;
07016 BasicArray<int> dr(2) ;
07017 BasicArray<int> dk(2) ;
07018 BasicArray<T> ur(1) ;
07019
07020 ur[0] = u ;
07021 dr[0] = 0 ;
07022 dr[1] = 0 ;
07023 dk[0] = 0 ;
07024 dk[1] = 1 ;
07025 D[0] = Point_nD<T,N>(0) ;
07026
07027 T length = ders.norm() ;
07028
07029 D[1] = T0 - ders/length ;
07030 D[1] *= length ;
07031
07032 movePoint(ur,D,dr,dk) ;
07033
07034 }
07035
07048 template <class T, int N>
07049 void NurbsCurve<T,N>::setTangentAtEnd(const Point_nD<T,N>& T0, const Point_nD<T,N>& T1) {
07050 Point_nD<T,N> ders0 = derive3D(U[deg_],1) ;
07051 Point_nD<T,N> ders1 = derive3D(U[P.n()],1) ;
07052
07053 BasicArray<Point_nD<T,N> > D(4) ;
07054 BasicArray<int> dr(4) ;
07055 BasicArray<int> dk(4) ;
07056 BasicArray<T> ur(2) ;
07057
07058 ur[0] = U[deg_] ;
07059 ur[1] = U[P.n()] ;
07060 D[0] = D[1] = Point_nD<T,N>(0) ;
07061 dr[0] = 0 ;
07062 dr[1] = 1 ;
07063 dr[2] = 0 ;
07064 dr[3] = 1 ;
07065 dk[0] = dk[1] = 0 ;
07066 dk[2] = dk[3] = 1 ;
07067
07068 T length = ders0.norm() ;
07069
07070 D[2] = T0 - ders0/length ;
07071 D[2] *= length ;
07072
07073 length = ders1.norm();
07074 D[3] = T1 - ders1/length ;
07075 D[3] *= length ;
07076
07077 movePoint(ur,D,dr,dk) ;
07078
07079 }
07080
07081
07091 template <class T, int N>
07092 void NurbsCurve<T,N>::clamp(){
07093 NurbsCurve<T,N> nc(*this) ;
07094
07095 int n1 = nc.knotInsertion(U[deg_],deg_,*this);
07096 int n2 = knotInsertion(U[P.n()],deg_,nc);
07097
07098 if(n1 || n2 ){
07099 U.resize(nc.U.n()-n1-n2) ;
07100 P.resize(U.n()-deg_-1) ;
07101 for(int i=U.n()-1;i>=0;--i){
07102 U[i] = nc.U[i+deg_] ;
07103 if(i<P.n())
07104 P[i] = nc.P[i+deg_] ;
07105 }
07106 }
07107
07108 }
07109
07119 template <class T, int N>
07120 void NurbsCurve<T,N>::unclamp(){
07121 int n = P.n()-1 ;
07122 int i,j ;
07123 for(i=0;i<=deg_-2;++i){
07124 U[deg_-i-1] = U[deg_-i] - (U[n-i+1]-U[n-i]) ;
07125 int k=deg_-1 ;
07126 for(j=i;j>=0;--j){
07127 T alpha = (U[deg_]-U[k])/(U[deg_+j+1]-U[k]);
07128 P[j] = (P[j]-alpha*P[j+1])/(T(1)-alpha);
07129 --k ;
07130 }
07131 }
07132 U[0] = U[1] - (U[n-deg_+2]-U[n-deg_+1]) ;
07133 for(i=0;i<=deg_-2;++i){
07134 U[n+i+2] = U[n+i+1] + (U[deg_+i+1]-U[deg_+i]);
07135 for(j=i;j>=0;--j){
07136 T alpha = (U[n+1]-U[n-j])/(U[n-j+i+2]-U[n-j]);
07137 P[n-j] = (P[n-j]-(1.0-alpha)*P[n-j-1])/alpha ;
07138 }
07139 }
07140 U[n+deg_+1] = U[n+deg_] + (U[2*deg_]-U[2*deg_-1]);
07141 }
07142
07143 }
07144
07145
07146 #endif // PLIB_NURBS_SOURCE