Main Page   Class Hierarchy   Compound List   File List   Compound Members  

nurbs.cpp

00001 /*=====================================================================
00002         File: nurbs.cpp
00003      Purpose:       
00004     Revision: $Id: nurbs.cpp,v 1.5 2003/01/27 11:37:36 philosophil Exp $
00005       Author: Philippe Lavoie          (3 Oct, 1996)
00006  Modified by: 
00007 
00008  Copyright notice:
00009           Copyright (C) 1996-1997 Philippe Lavoie
00010  
00011           This library is free software; you can redistribute it and/or
00012           modify it under the terms of the GNU Library General Public
00013           License as published by the Free Software Foundation; either
00014           version 2 of the License, or (at your option) any later version.
00015  
00016           This library is distributed in the hope that it will be useful,
00017           but WITHOUT ANY WARRANTY; without even the implied warranty of
00018           MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019           Library General Public License for more details.
00020  
00021           You should have received a copy of the GNU Library General Public
00022           License along with this library; if not, write to the Free
00023           Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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] ; // This makes the SGI compiler happy
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){ // the <= u_max doesn't work
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){ // the <= u_max doesn't work
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   // compute a coarse distance for the curve
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   // compute a coarse distance for the trajectory
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 // Setup the binomial coefficients into th matrix Bin
00660 // Bin(i,j) = (i  j)
00661 // The binomical coefficients are defined as follow
00662 //   (n)         n!
00663 //   (k)  =    k!(n-k)!       0<=k<=n
00664 // and the following relationship applies 
00665 // (n+1)     (n)   ( n )
00666 // ( k ) =   (k) + (k-1)
00685 template <class T>
00686 void binomialCoef(Matrix<T>& Bin){
00687   int n,k ;
00688   // Setup the first line
00689   Bin(0,0) = 1.0 ;
00690   for(k=Bin.cols()-1;k>0;--k)
00691     Bin(0,k) = 0.0 ;
00692   // Setup the other lines
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   // Compute the derivative at the parmeter u
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   // Compute the derivative at the parmeter u
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)) ; // Vector<T> N(p+1) ;
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 // it returns the matrix ders, where ders(n+1,deg+1) and the C'(u) = ders(1,span-deg+j) ;
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       // Lower triangle
00930       ndu(j,r) = right[r+1]+left[j-r] ;
00931       temp = ndu(r,j-1)/ndu(j,r) ;
00932       // Upper triangle
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   // Compute the derivatives
00944   Matrix<T> a(deg_+1,deg_+1) ;
00945   for(r=0;r<=deg_;r++){
00946     int s1,s2 ;
00947     s1 = 0 ; s2 = 1 ; // alternate rows in array a
00948     a(0,0) = 1.0 ;
00949     // Compute the kth derivative
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 ; // Switch rows
00986     }
00987   }
00988 
00989   // Multiply through by the correct factors
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 // Computes the non-zero basis functions into N of size deg+1
01000 // The following relationship applies   N[i] <= N[span-deg+i]  for i = 0..deg
01001 // A2.1 on p68 of the Nurbs Book
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   // Changing the method to generate a U compare to the one 
01281   // described by Piegl and Tiller in the NURBS book (eq 9.69)
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   // Changing the method to generate a U compare to the one 
01352   // described by Piegl and Tiller in the NURBS book (eq 9.69)
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   // Set up N 
01447   N(0,0) = 1.0 ;
01448   N(m-1,n-1) = 1.0 ;
01449 
01450   //  for(i=1;i<m-1;i++){
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){ // BOOO
01455        //if(span-deg_+j>0)
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   // Set up R
01463   //  for(i=1;i<n-1;i++){
01464   for(i=0;i<n;i++){
01465     R[i] = 0.0 ;
01466     //    for(j=1;j<m-1;j++)
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   // Solve      N^T*N*P = R
01476 
01477   // must check for the case where we want a curve of degree 1 having
01478   // only 2 points.
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   // Set up N 
01577   N(0,0) = 1.0 ;
01578   N(m-1,n-1) = 1.0 ;
01579 
01580   //  for(i=1;i<m-1;i++){
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        //if(span-deg_+j>0)
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   // Set up R
01593   //  for(i=1;i<n-1;i++){
01594   for(i=0;i<n;i++){
01595     R[i] = 0.0 ;
01596     //    for(j=1;j<m-1;j++)
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   // Solve      N^T*N*P = R
01606 
01607   // must check for the case where we want a curve of degree 1 having
01608   // only 2 points.
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 ; // Pj thru Pi will be overwritten
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++) {// Shift
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   // This might NOT be ok
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   // set up N
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     // Verify the Error for the affected range
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       // Using eqn 9.81, 9.83 and A2.4 to compute NewError[i]
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       // Remove the knot
01883       removeKnot(r,S[r],1) ;
01884 
01885       // update the error
01886       for(i=Rstart; i<=Rend ; i++)
01887         ek[i] = temp[i] ;
01888 
01889       // Break if there is no more interior knot
01890       if(P.n()<=deg_+1){
01891         break ;
01892       }
01893 
01894       // Update the new index range for some of the knots 
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) ; // Shrink Nl 
01913       Nr.resize(Nr.n()-1) ; // Shrink Nr
01914       // Update the new error bounds for some of the knots
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) ; // Shrink Br
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 ; // In case there is some addition round-off
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 ; // In case there is some addition round-off
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   // Initialize U
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   // Initialize P
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       // Find the degree elevated knot vector
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     // Project the points from curve to Q and update ek and ub
02150     //    for(i=0;i<Q.n();i++){
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   // Initialize U
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   // Initialize P
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     // Project the points from curve to Q and update ek and ub
02210     //    for(i=0;i<Q.n();i++){
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   //NurbsCurve<T,N> tCurve(1) ;
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   // Initialize U
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   // Initialize P
02261   for(i=0;i<P.n();i++)
02262     P[i] = Q[i] ;
02263   
02264   //removeKnotsBoundCurve(curve,ub,ek,E/10.0,curve) ;
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   // Initialize U
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   // Initialize P
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     //c2 *= c2 ;
02381     c2 /= norm(cd)*norm(c-p) ;
02382     //if(c2<e2*e2){
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) ; // coefficients for degree elevating the Bezier segment
02426   Vector< HPoint_nD<T,N> > bpts(p+1) ; // pth-degree Bezier control points of the current segment
02427   Vector< HPoint_nD<T,N> > ebpts(p+t+1) ; // (p+t)th-degree Bezier control points of the  current segment
02428   Vector< HPoint_nD<T,N> > Nextbpts(p-1) ; // leftmost control points of the next Bezier segment
02429   Vector<T> alphas(p-1) ; // knot instertion alphas.
02430 
02431   // Compute the binomial coefficients
02432   Matrix<T> Bin(ph+1,ph2+1) ;
02433   binomialCoef(Bin) ;
02434 
02435   // Compute Bezier degree elevation coefficients
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) ; // Allocate more control points than necessary
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   // Initialize the first Bezier segment
02475 
02476   for(i=0;i<=p ;i++) 
02477     bpts[i] = c.P[i] ;
02478 
02479   while(b<m){ // Big loop thru knot vector
02480     i=b ;
02481     while(b<m && c.U[b] >= c.U[b+1]) // for some odd reasons... == doesn't work
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){ // Insert knot to get Bezier segment
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++){ // Degree elevate Bezier,  only the points lbz,...,ph are used
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){ // Must remove knot u=c.U[a] oldr times
02518       // if(oldr>2) // Alphas on the right do not change
02519       //        alfj = (ua-U[kind-1])/(ub-U[kind-1]) ;
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++){ // Knot removal loop
02524         i = first ; j = last ;
02525         kj = j-kind+1 ;
02526         while(j-i>tr){ // Loop and compute the new control points for one removal step
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) // load the knot u=c.U[a]
02547       for(i=0;i<ph-oldr; i++){
02548         U[kind++] = ua ; 
02549       }
02550     for(j=lbz; j<=rbz ; j++) { // load control points onto the curve
02551       P[cind++] = ebpts[j] ; 
02552     }
02553 
02554     if(b<m){ // Set up for next pass thru loop
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) ; // Resize to the proper number of control points
02569 }
02570 
02589 template <class T, int N>
02590 int NurbsCurve<T,N>::knotInsertion(T u, int r,NurbsCurve<T,N>& nc){
02591   // Compute k and s      u = [ u_k , u_k+1)  with u_k having multiplicity s
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   // Load new knot vector
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   // Save unaltered control points
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   // Insert the knot r times
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   // Load remaining control points
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   // Initialize the basis matrix A
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   // Init matrix for LSE
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] ; // this makes the SGI compiler happy
02814     for(j=0; j<D;j++)
02815       qq(i,j) = (double)qp.data[j] ;
02816   }
02817 
02818   solve(A,qq,xx) ;
02819 
02820   // Store the data
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   // Setup up knot vector
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   // Initialize the basis matrix A
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   // Init matrix for LSE
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] ; // this makes the SGI compiler happy
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   // the following three assignment must be made to make the SGI compiler
02997   // a happy compiler
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   // Store the data
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   // Setup the Knot Vector for the curve
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   // Initialize the basis matrix A
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   // Init matrix for LSE
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   // Store the data
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   // Initialize the basis matrix A
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   // Init matrix for LSE
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   // Store the data
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   // Initialize the basis matrix A
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   // Init matrix for LSE
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   // Store the data
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   // a line is written like 
03257   // L(t) = Q + u*t
03258   // u is the parametric value P is a point in the line and T is the tangent
03259   // a plane is of the form
03260   // (X-P).v = 0 
03261   // where P is a point where the plane goes through and v is the normal to it
03262   // and X is (x,y,z)
03263   // solving for u
03264 
03265   Point_nD<T,N> v,px ;
03266 
03267   //px = crossProduct(t1,p1-p2) ;
03268   //v = crossProduct(px,t1) ;
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 ; // n control points ;
03350   double w1 = cos(dtheta/2.0) ; // dtheta/2.0 is base angle
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 ; // initialize start values
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 ; // load the knot vector
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) ;  // sqrt(2)/2
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   // Find the knots to insert
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     // Refine the curve
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) // Nothing to do... only 1 curve in the array
03563     return ;
03564 
03565   // Increase all the curves to the highest degree
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   // Find a common Knot vector
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   // Refine the knot vectors
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)){ // not of the same type size
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*)&deg_,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   //Vector<T> left(deg+1), right(deg+1) ;
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   //Vector<T> left(deg+1),right(deg+1) ;
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       // Lower triangle
03810       ndu(j,r) = right[r+1]+left[j-r] ;
03811       temp = ndu(r,j-1)/ndu(j,r) ;
03812       // Upper triangle
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   // Compute the derivatives
03824   Matrix<T> a(deg+1,deg+1) ;
03825   for(r=0;r<=deg;r++){
03826     int s1,s2 ;
03827     s1 = 0 ; s2 = 1 ; // alternate rows in array a
03828     a(0,0) = 1.0 ;
03829     // Compute the kth derivative
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 ; // Switch rows
03866     }
03867   }
03868 
03869   // Multiply through by the correct factors
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)) ; //Vector<T> alphas(deg+1) ;
03899 
03900   // all the curves will have the same vector
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] ; // th enumerator of the alphas
03927       for(j=deg_;j>mult;j--) // compute and store the alphas
03928         alphas[j-mult-1] = numer/(U[a+j]-U[a]) ;
03929       r = deg_-mult ; // insert knot r times
03930       for(j=1;j<=r;j++){
03931         save=r-j;
03932         s=mult+j; // this many new points
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) // control point of
03938           c[nb+1].P[save] = c[nb].P[deg_]; // next segment
03939       }
03940     }
03941     nb++ ;
03942     if(b<m){ // initialize for next segment
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   //if(p.z()==0.0){
03957     pnt.x() = p.x()/p.w() ;
03958     pnt.y() = p.y()/p.w() ;
03959     //}
03960     //else{
03961     //pnt.x() = (p.x()/p.w())/absolute(p.z()) ;
03962     //pnt.y() = (p.y()/p.w())/absolute(p.z()) ;
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   //p = p*magFact+Point_nD<T,N>(offX,offY,0)  ;
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   //p = p*magFact+Point_nD<T,N>(offX,offY,0)  ;
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   //p = p*magFact+Point_nD<T,N>(offX,offY,0)  ;
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   //p = p*magFact+Point_nD<double,N>(offX,offY,0)  ;
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   //HPoint_nD<T,N> tp ;
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   // find bounding box parameters
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     //magFact = minimum((T)500/(T)(Mx-mx),(T)700/(T)(My-my)) ;
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){ // draw the control points of the original curve
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   // extract the Bezier segments 
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   // find bounding box parameters
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){ // draw the control points of the original curve
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   // setup B
04659   Matrix_DOUBLE B ;
04660   
04661   int n,m ; // n is the number of rows, m the number of columns
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] ; // this makes the SGI compiler happy
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   // setup B
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   // optimize B
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] ; // this makes the SGI compiler happy
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   // get the multiplicity at u
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   // span is the begining of the upper curve
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   //AF
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     // get the number of steps 
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       // remove the last point from the list to elliminate
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){ // 4 knots at the same place from U[i] to U[i+3]
05281       u = U[i] ;
05282       return 1 ;
05283     }
05284     A = U[i+1]-U[i+3] ;
05285     if(A>=0){ // three knots are equal 
05286       u = U[i+1] ;
05287       return 1 ;
05288     }
05289     // there are 4 points of possible interest
05290     // the 'good' one lie between U[i+1] and U[i+3]
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       // X might be near U[i+2] but due to floating point error, it won't
05399       // be detected. It happens during tests, so it's possible...
05400       /*
05401       if(absolute(X-c)<0.0001*c){
05402         Error error("maxInfluence");
05403         error << "A numerical error in computing the point of maximal influence" ;
05404         error.warning() ;
05405         u = X ;
05406         return 1 ;
05407       }
05408       */
05409 
05410       if(X> b && X<=c + 1e-6 ){ // adding 1e-6 because of float->double conversions
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)) ; // Vector<T> N(p+1) ;
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 // the definitions are in f_nurbs.cpp and d_nurbs.cpp
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   // Load knot vector
06088   U = knots;
06089 
06090   // Form matrix N (Eq. 9.66) p. 411
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   // Form R (Eq. 9.67)
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] ; // this makes the SGI compiler happy
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   // The system to solve
06107   A = N.transpose() * N ;
06108   solve(A,R,Pi);
06109 
06110   // Update control points
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   // Load knot vector
06187   U = knots;
06188 
06189   // Form matrix N (Eq. 9.66) p. 411
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   // Form R (Eq. 9.67)
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] ; // this makes the SGI compiler happy
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   // The system to solve
06206   A = N.transpose() * N ;
06207   solve(A,R,Pi);
06208 
06209   // Update control points
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       //P[i].w()     = 1.0;
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     // Normalization
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     // Normalization
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   // Initialize the basis matrix A
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   // Init matrix for LSE
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   // AF: "solve" calls LU decomposition if A is square. I opted for
06527   // using the SVD routine which works better when the system of
06528   // equations is very large (more than 50 points). Probably since in
06529   // this cases the system matrix A is very sparse.
06530   SVDMatrix<double> svd(A) ;
06531   svd.solve(qq,xx) ;
06532 
06533   // Store the data
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   // Wrap around of control points
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   // Initialize the basis matrix A
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   // Init matrix for LSE
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   // AF: "solve" calls LU decomposition if A is square. I opted for
06605   // using the SVD routine which works better when the system of
06606   // equations is very large (more than 50 points). Probably since in
06607   // this cases the system matrix A is very sparse.
06608   SVDMatrix<double> svd(A) ;
06609   svd.solve(qq,xx) ;
06610 
06611   // Store the data
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   // Wrap around of control points
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   // Left side
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   // Copy
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   // Right side
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   // Now do the decomposition
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   // Construct the refinement vector
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   // The number of Bezier segments coincides with the number of
06705   // distinct control points in a closed curve
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   // Build temporary average sequence
06738   // Data stored in range U[deg+1 .. n]
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   // Now make the left and right periodic extensions
06748   // Left 
06749   for (j=0; j<deg; j++)    U[j] = U[j+iN+1] - 1;       
06750   // Right
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   // Initialize the internal knots
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   // Now make the left and right periodic extensions
06787   // Left 
06788   for (j=0; j<p; j++)       U[j] = U[j+iN+1] - 1;       
06789   // Right
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   // COnvert the curve to 3D if it is not
06865   NurbsCurve<T,3> curve3D;
06866   to3D(*this,curve3D);
06867   // Output it
06868   T fDu = 1/T(iNu);
06869   ofstream fout(filename) ;
06870   if(!fout)
06871     return 0 ;
06872   // Save the object type
06873   const char LINE = 'l'+ ('A' - 'a');
06874   fout << LINE << ' ';       ;
06875   T fThickness = T(1.);
06876   // Save surface properties
06877   fout << fThickness << ' ' 
06878        << iNu << endl;
06879   // Fill points 
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   // New line
06886   fout << endl ;
06887   // Elements
06888   fout << 1 << endl ;
06889   // New line
06890   fout << endl ;
06891   // Surface color RGBA (one color for the whole surface)
06892   T fR= T(color.r)/255;
06893   T fG= T(color.g)/255;
06894   T fB= T(color.b)/255;
06895   // Colour flag = ONE_COLOUR 
06896   fout << 0 << ' ' ;
06897   // The colour 
06898   fout << fR << ' '
06899        << fG << ' '
06900        << fB << ' '
06901        << fA << endl;
06902   // New line
06903   fout << endl ;
06904   fout << iNu << endl;
06905   // New line
06906   fout << endl ;
06907   // Save the dummy integers 
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   // Save the object type
06945   const char LINE = 'l'+ ('A' - 'a');
06946   fout << LINE << ' ';       ;
06947 
06948   float fThickness = 1;
06949   // Save surface properties
06950   fout << fThickness << ' ' 
06951        << iNu << endl;
06952 
06953   // Fill points 
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     // Requires sign inversion and swap of y-z
06960     p = -1.0*Curve.pointAt(u);
06961     fout << p.x() << ' ' << p.z() << ' ' << p.y() << endl;
06962   }
06963 
06964   // New line
06965   fout << endl ;
06966   // Elements
06967   fout << 1 << endl ;
06968   // New line
06969   fout << endl ;
06970   // Surface color RGBA (one color for the whole line)
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   /* Colour flag = ONE_COLOUR */
06976   fout << 0 << ' ' ;
06977   /* The colour */
06978   fout << fR << ' '
06979        << fG << ' '
06980        << fB << ' '
06981        << fA << endl;
06982   
06983   // New line
06984   fout << endl ;
06985 
06986   fout << iNu << endl;
06987 
06988   // New line
06989   fout << endl ;
06990 
06991   // Save the dummy integers 
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]) ; // set first knot
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]); // set last knot
07141 }
07142 
07143 } // end namespace
07144 
07145 
07146 #endif //  PLIB_NURBS_SOURCE

Generated on Tue Jun 24 13:26:57 2003 for NURBS++ by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002