00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef PLIB_NURBS_NURBSS_SOURCE
00027 #define PLIB_NURBS_NURBSS_SOURCE
00028
00029
00030 #include <nurbs.h>
00031 #include <string.h>
00032 #include <matrixRT.h>
00033 #include <math.h>
00034 #include <nurbsS.h>
00035 #include "integrate.h"
00036
00037 #ifdef USING_VCC
00038 #include <malloc.h>
00039 #endif
00040
00043 namespace PLib {
00044
00053 template <class T, int N>
00054 NurbsSurface<T,N>::NurbsSurface():
00055 ParaSurface<T,N>(), U(1),V(1),P(1,1),degU(0),degV(0)
00056 {
00057 }
00058
00067 template <class T, int N>
00068 NurbsSurface<T,N>::NurbsSurface(const NurbsSurface<T,N>& s):
00069 ParaSurface<T,N>(), U(s.U), V(s.V), P(s.P), degU(s.degU), degV(s.degV)
00070 {
00071 }
00072
00073
00086 template <class T, int N>
00087 NurbsSurface<T,N>::NurbsSurface(int DegU, int DegV, const Vector<T>& Uk, const Vector<T>& Vk, const Matrix< HPoint_nD<T,N> >& Cp) :
00088 ParaSurface<T,N>(), U(Uk),V(Vk),P(Cp),degU(DegU),degV(DegV)
00089 {
00090 int bad = 0 ;
00091
00092 if(U.n() != P.rows()+degU+1){
00093 #ifdef USE_EXCEPTION
00094 throw NurbsSizeError(P.rows(),U.n(),degU) ;
00095 #else
00096 Error err("NurbsSurface<T,N> constructor") ;
00097 err << "The U knot vector and the number of rows of the control points are incompatible\n" ;
00098 err << "P.rows() = " << P.rows() << ", U.n() = " << U.n() << endl ;
00099 bad = 1 ;
00100 err.fatal() ;
00101 #endif
00102 }
00103 if(V.n() != P.cols()+degV+1){
00104 #ifdef USE_EXCEPTION
00105 throw NurbsSizeError(P.cols(),V.n(),degV);
00106 #else
00107 Error err("NurbsSurface<T,N> constructor") ;
00108 err << "The V knot vector and the number of columns of the control points are incompatible\n" ;
00109 err << "P.cols() = " << P.cols() << ", V.n() = " << V.n() << endl ;
00110 bad = 1 ;
00111 err.fatal() ;
00112 #endif
00113 }
00114 if(bad)
00115 exit(-1) ;
00116 }
00117
00131 template <class T, int N>
00132 NurbsSurface<T,N>::NurbsSurface(int DegU, int DegV, Vector<T>& Uk, Vector<T>& Vk, Matrix< Point_nD<T,N> >& Cp, Matrix<T>& W) :
00133 ParaSurface<T,N>(), U(Uk),V(Vk),P(Cp.rows(),Cp.cols()),degU(DegU),degV(DegV)
00134 {
00135 int bad = 0 ;
00136
00137 if(U.n() != Cp.rows()+degU+1){
00138 #ifdef USE_EXCEPTION
00139 throw NurbsSizeError(P.rows(),U.n(),degU);
00140 #else
00141 Error err("NurbsSurface<T,N> constructor") ;
00142 err << "The U knot vector and the number of rows of the control points are incompatible\n" ;
00143 err << "P.rows() = " << P.rows() << ", U.n() = " << U.n() << endl ;
00144 bad = 1 ;
00145 err.fatal() ;
00146 #endif
00147 }
00148 if(V.n() != Cp.cols()+degV+1){
00149 #ifdef USE_EXCEPTION
00150 throw NurbsSizeError(P.cols(),V.n(),degV);
00151 #else
00152 Error err("NurbsSurface<T,N> constructor") ;
00153 err << "The V knot vector and the number of columns of the control points are incompatible\n" ;
00154 err << "P.cols() = " << P.cols() << ", V.n() = " << V.n() << endl ;
00155 bad = 1 ;
00156 err.fatal() ;
00157 #endif
00158 }
00159 if(W.rows() != Cp.rows()){
00160 #ifdef USE_EXCEPTION
00161 throw NurbsInputError(W.rows(),Cp.rows()) ;
00162 #else
00163 Error err("NurbsSurface<T,N> constructor") ;
00164 err << "The dimension of the weights are incompatible with the dimension of the control points\n" ;
00165 err << "W( " << W.rows() << ", " << W.cols() << ") and P( " << P.rows() << ", " << P.cols() << ") \n" ;
00166 bad = 1 ;
00167 err.fatal() ;
00168 #endif
00169 }
00170 if(W.cols() != Cp.cols()){
00171 #ifdef USE_EXCEPTION
00172 throw NurbsInputError(W.cols(),Cp.cols()) ;
00173 #else
00174 Error err("NurbsSurface<T,N> constructor") ;
00175 err << "The dimension of the weights are incompatible with the dimension of the control poitns\n" ;
00176 err << "W( " << W.rows() << ", " << W.cols() << ") and P( " << P.rows() << ", " << P.cols() << ") \n" ;
00177 bad = 1 ;
00178 err.fatal() ;
00179 #endif
00180 }
00181
00182 for(int i=0;i<Cp.rows();i++)
00183 if(bad)
00184 break ;
00185 else{
00186 for(int j=0;j<Cp.cols();j++)
00187 if(W(i,j)==0.0){
00188 #ifdef USE_EXCEPTION
00189 throw NurbsInputError();
00190 #else
00191 Error err("NurbsSurface<T,N> constructor") ;
00192 err << "Error initializing a NurbsSurface.\n" ;
00193 err << "The weight W(" << i << ", " << j << ") is equal to 0.\n" ;
00194 bad = 1 ;
00195 err.fatal() ;
00196 break ;
00197 #endif
00198 }
00199 else {
00200 P(i,j) = Cp(i,j) ;
00201 P(i,j) *= W(i,j) ;
00202 }
00203 }
00204
00205 if(bad)
00206 exit(-1) ;
00207 }
00208
00216 template <class T, int N>
00217 NurbsSurface<T,N>& NurbsSurface<T,N>::operator=(const NurbsSurface<T,N>& nS){
00218 P = nS.P ;
00219 U = nS.U ;
00220 V = nS.V ;
00221 degU = nS.degU ;
00222 degV = nS.degV ;
00223 return *this ;
00224 }
00225
00226 template <class T, int N>
00227 struct AreaData {
00228 T v;
00229 T eps;
00230 T knotUi;
00231 T knotUii;
00232 T knotVj;
00233 T knotVjj;
00234 const NurbsSurface<T,N>& s ;
00235 const BasicArray<T> w ;
00236 AreaData(const NurbsSurface<T,N>& surf,T e,
00237 const BasicArray<T>& ww):
00238 s(surf),v(T(0)),eps(e),w(ww),
00239 knotUi(T(0)), knotUii(T(1)) {}
00240 };
00241
00242 template <class T, int N>
00243 struct OpAreaAuxFcn : public ClassPOvoid<T> {
00244 T operator()(T u, void* data){
00245 AreaData<T,N>* p = (AreaData<T,N>*)data ;
00246 return (p->s).areaF(u,p->v) ;
00247 }
00248 };
00249
00250 template <class T, int N>
00251 struct OpAreaFcn : public ClassPOvoid<T> {
00252 T operator()(T v, void* data){
00253 static Vector<T> w;
00254 T err;
00255 OpAreaAuxFcn<T,N> f;
00256 AreaData<T,N>* Data = (AreaData<T,N>*)data ;
00257 Data->v = v ;
00258 return intcc2((ClassPOvoid<T>*)&f,Data,
00259 Data->knotUi,Data->knotUii,
00260 Data->eps,Data->w,err);
00261 }
00262 };
00263
00288 template <class T, int N>
00289 T NurbsSurface<T,N>::area(T eps,int n) const {
00290 T a = T(0.0) ;
00291 T err ;
00292 static Vector<T> bufFcn(0) ;
00293
00294 if(bufFcn.n() != n){
00295 bufFcn.resize(n) ;
00296 intccini(bufFcn) ;
00297 }
00298
00299 AreaData<T,N> data(*this,eps,bufFcn) ;
00300 OpAreaFcn<T,N> op;
00301
00302
00303 for(int i=degU;i<P.rows();++i){
00304 if(U[i] >= U[i+1] || U[i]>=T(1.0))
00305 continue ;
00306 data.knotUi = U[i] ;
00307 data.knotUii = U[i+1] ;
00308 for(int j=degV;j<P.cols();++j){
00309 if(V[j] >= V[j+1] || V[j]>=T(1.0))
00310 continue ;
00311 data.knotVj = V[j] ;
00312 data.knotVjj = V[j+1] ;
00313 a += intcc2((ClassPOvoid<T>*)&op,(void*)&data,
00314 data.knotVj,data.knotVjj,
00315 eps,bufFcn,err) ;
00316 }
00317 }
00318 return a ;
00319 }
00320
00350 template <class T, int N>
00351 T NurbsSurface<T,N>::areaIn(T us, T ue, T vs, T ve, T eps, int n) const {
00352 T l = T() ;
00353 T err ;
00354 T a ;
00355 bool bLastU = false;
00356 bool bLastV = false;
00357 static Vector<T> bufFcn ;
00358
00359 if(bufFcn.n() != n){
00360 bufFcn.resize(n) ;
00361 intccini(bufFcn) ;
00362 }
00363
00364 AreaData<T,N> data(*this,eps,bufFcn) ;
00365 OpAreaFcn<T,N> op;
00366 for(int i=degU;i<P.rows();++i){
00367 if(U[i] >= U[i+1] || U[i] >= T(1))
00368 continue;
00369 if(i<findSpanU(us))
00370 continue ;
00371 if(us>=U[i] && ue<=U[i+findMultU(i)]){
00372 data.knotUi = us;
00373 data.knotUii = ue;
00374 bLastU = true;
00375 goto Integrate_I;
00376 }
00377 if(us>=U[i]){
00378 data.knotUi = us;
00379 data.knotUii = U[i+findMultU(i)];
00380 bLastU = false;
00381 goto Integrate_I;
00382 }
00383 if(ue<=U[i+1]){
00384 data.knotUi = U[i];
00385 data.knotUii = ue;
00386 bLastU = true;
00387 goto Integrate_I;
00388 }
00389 data.knotUi = U[i] ;
00390 data.knotUii = U[i+findMultU(i)] ;
00391 Integrate_I:
00392 for(int j=degV;j<P.cols();++j){
00393 if(V[j] >= V[j+1] || V[j]>=T(1))
00394 continue ;
00395 if(j<findSpanV(vs))
00396 continue ;
00397 if(vs>=V[j] && ve<=V[j+findMultV(j)]){
00398 data.knotVj = vs;
00399 data.knotVjj = ve;
00400 bLastV = true;
00401 goto Integrate_II;
00402 }
00403 if(vs>=V[j]){
00404 data.knotVj = vs;
00405 data.knotVjj = V[j+findMultV(j)];
00406 bLastV = false;
00407 goto Integrate_II;
00408 }
00409 if(ve<=V[j+1]){
00410 data.knotVj = V[j];
00411 data.knotVjj = ve;
00412 bLastV = true;
00413 goto Integrate_II;
00414 }
00415 data.knotVj = V[j] ;
00416 data.knotVjj = V[j+findMultV(j)] ;
00417 Integrate_II:
00418 a += intcc2((ClassPOvoid<T>*)&op,(void*)&data,data.knotVj,data.knotVjj,eps,bufFcn,err) ;
00419 if (bLastU && bLastV)
00420 return a;
00421 if (bLastV)
00422 break;
00423 }
00424 }
00425 return a ;
00426 }
00427
00428
00429
00430
00445 template <class T, int N>
00446 T NurbsSurface<T,N>::areaF(T u, T v) const {
00447
00448 Matrix<Point_nD<T,N> > Skl(2,2) ;
00449 deriveAt(u,v,1,Skl);
00450 T tmp = norm(crossProduct(Skl(1,0),Skl(0,1)));
00451 return tmp ;
00452 }
00453
00466 template <class T, int N>
00467 int NurbsSurface<T,N>::ok() {
00468 if(P.rows() <= degU)
00469 return 0 ;
00470 if(P.cols() <= degV)
00471 return 0 ;
00472 if(P.rows() != U.n()+degU+1)
00473 return 0 ;
00474 if(P.cols() != V.n()+degV+1)
00475 return 0 ;
00476 return 1 ;
00477 }
00498 template <class T, int N>
00499 void NurbsSurface<T,N>::reset(const Matrix< HPoint_nD<T,N> >& Pts, const Vector<T> &U1, const Vector<T> &V1){
00500 P = Pts;
00501 U = U1;
00502 V = V1;
00503 degU = U.size()-P.rows()-1;
00504 degV = V.size()-P.cols()-1;
00505 }
00506
00522 template <class T, int N>
00523 void NurbsSurface<T,N>::resize(int Pu, int Pv, int DegU, int DegV){
00524 P.resize(Pu,Pv) ;
00525 degU = DegU ;
00526 degV = DegV ;
00527 U.resize(Pu+DegU+1) ;
00528 V.resize(Pv+DegV+1) ;
00529 }
00530
00542 template <class T, int N>
00543 void NurbsSurface<T,N>::resizeKeep(int Pu, int Pv, int DegU, int DegV){
00544 P.resizeKeep(Pu,Pv) ;
00545 degU = DegU ;
00546 degV = DegV ;
00547 U.resize(Pu+DegU+1) ;
00548 V.resize(Pv+DegV+1) ;
00549 }
00550
00568 template <class T, int D>
00569 int NurbsSurface<T,D>::skinV(NurbsCurveArray<T,D>& ca, int dV) {
00570 Vector<T> vk(ca.n()) ;
00571
00572 T* d ;
00573 int i,k,N,K ;
00574
00575 if(ca.n()<dV){
00576 #ifdef USE_EXCEPTION
00577 throw NurbsInputError();
00578 #else
00579 Error err("NurbsSurface<T,D> skinV") ;
00580 err << "The number of curves are insufficient for the degree of interpolation specified.\n" ;
00581 err << "n of curves = " << ca.n() << ", degree of interpolation = " << dV << endl ;
00582 err.warning() ;
00583 return 0 ;
00584 #endif
00585 }
00586
00587 generateCompatibleCurves(ca) ;
00588
00589 K = ca.n() ;
00590 N = ca[0].ctrlPnts().n() ;
00591
00592 resize(N,K,ca[0].degree(),dV) ;
00593
00594
00595 d = new T[ca[0].ctrlPnts().n()] ;
00596 for(i=0;i<N;i++){
00597 d[i] = 0 ;
00598 for(k=1;k<K;k++){
00599 d[i] += norm(ca[k].ctrlPnts(i)-ca[k-1].ctrlPnts(i)) ;
00600 }
00601 }
00602
00603 vk[0] = 0 ;
00604 for(k=1;k<K;k++){
00605 vk[k] = 0 ;
00606 for(i=0;i<N;i++)
00607 vk[k] += norm(ca[k].ctrlPnts(i)-ca[k-1].ctrlPnts(i))/d[i] ;
00608 vk[k] /= (T)N ;
00609 vk[k] += vk[k-1] ;
00610 }
00611 vk[vk.n()-1] = 1.0 ;
00612
00613 for(i=1;i<K-degV;i++){
00614 V[i+degV] = 0 ;
00615 for(k=i;k<i+degV;k++)
00616 V[i+degV] += vk[k] ;
00617 V[i+degV] /= (T)degV ;
00618 }
00619 for(i=0;i<=degV;i++) V[i] = 0.0 ;
00620 for(i=V.n()-degV-1;i<V.n();i++) V[i] = 1.0 ;
00621
00622
00623 Vector< HPoint_nD<T,D> > Q(K) ;
00624 NurbsCurve<T,D> i_curve ;
00625
00626
00627 for(i=0;i<N;i++){
00628 for(k=0;k<K;k++)
00629 Q[k] = ca[k].ctrlPnts(i) ;
00630 i_curve.globalInterpH(Q,vk,V,degV);
00631 for(k=0;k<K;k++)
00632 P(i,k) = i_curve.ctrlPnts(k) ;
00633 }
00634
00635 U = ca[0].knot() ;
00636
00637 delete []d ;
00638 return 1 ;
00639 }
00640
00657 template <class T, int nD>
00658 int NurbsSurface<T,nD>::skinU(NurbsCurveArray<T,nD>& ca, int dU) {
00659 Vector<T> uk(ca.n());
00660
00661 T* d;
00662 int i,k,N,K ;
00663
00664 if(ca.n()<dU){
00665 #ifdef USE_EXCEPTION
00666 throw NurbsInputError();
00667 #else
00668 Error err("NurbsSurface<T,N> skinU") ;
00669 err << "The number of curves are insufficient for the degree of interpolation specified.\n" ;
00670 err << "n of curves = " << ca.n() << ", degree of interpolation = " << dU << endl ;
00671 err.warning() ;
00672 return 0 ;
00673 #endif
00674 }
00675
00676 generateCompatibleCurves(ca) ;
00677
00678 K = ca.n() ;
00679 N = ca[0].ctrlPnts().n() ;
00680
00681 resize(K,N,dU,ca[0].degree()) ;
00682
00683
00684 d = new T[ca[0].ctrlPnts().n()] ;
00685 for(i=0;i<N;i++){
00686 d[i] = 0 ;
00687 for(k=1;k<K;k++){
00688 d[i] += norm(ca[k].ctrlPnts(i)-ca[k-1].ctrlPnts(i)) ;
00689 }
00690 }
00691
00692 uk[0] = 0 ;
00693 for(k=1;k<K;k++){
00694 uk[k] = 0 ;
00695 for(i=0;i<N;i++)
00696 uk[k] += norm(ca[k].ctrlPnts(i)-ca[k-1].ctrlPnts(i))/d[i] ;
00697 uk[k] /= (T)N ;
00698 uk[k] += uk[k-1] ;
00699 }
00700 uk[uk.n()-1] = 1.0 ;
00701
00702 for(i=1;i<K-degU;i++){
00703 U[i+degU] = 0 ;
00704 for(k=i;k<i+degU;k++)
00705 U[i+degU] += uk[k] ;
00706 U[i+degU] /= (T)degU ;
00707 }
00708 for(i=0;i<=degU;i++) U[i] = 0.0 ;
00709 for(i=U.n()-degU-1;i<U.n();i++) U[i] = 1.0 ;
00710
00711
00712 Vector< HPoint_nD<T,nD> > Q(K) ;
00713 NurbsCurve<T,nD> i_curve ;
00714
00715
00716 for(i=0;i<N;i++){
00717 for(k=0;k<K;k++)
00718 Q[k] = ca[k].ctrlPnts(i) ;
00719 i_curve.globalInterpH(Q,uk,U,degU) ;
00720 for(k=0;k<K;k++)
00721 P(k,i) = i_curve.ctrlPnts(k) ;
00722 }
00723
00724 V = ca[0].knot() ;
00725
00726 delete []d ;
00727
00728 return 1 ;
00729 }
00730
00749 template <class T, int N>
00750 int surfMeshParams(const Matrix< Point_nD<T,N> >& Q, Vector<T>& uk, Vector<T>& vl){
00751 int n,m,k,l,num ;
00752 double d,total ;
00753
00754 T* cds = new T[maximum(Q.rows(),Q.cols())] ;
00755
00756 n = Q.rows() ;
00757 m = Q.cols() ;
00758 uk.resize(n) ;
00759 vl.resize(m) ;
00760 num = m ;
00761
00762
00763
00764 uk.reset(0) ;
00765
00766 for(l=0;l<m;l++){
00767 total = 0.0 ;
00768 for(k=1;k<n;k++){
00769 cds[k] = norm(Q(k,l)-Q(k-1,l)) ;
00770 total += cds[k] ;
00771 }
00772 if(total==0.0)
00773 num-- ;
00774 else {
00775 d = 0.0 ;
00776 for(k=1;k<n;k++){
00777 d += cds[k] ;
00778 uk[k] += d/total ;
00779 }
00780 }
00781 }
00782
00783 if(num==0) {
00784 delete []cds ;
00785 return 0 ;
00786 }
00787 for(k=1;k<n-1;k++)
00788 uk[k] /= num ;
00789 uk[n-1] = 1.0 ;
00790
00791
00792 vl.reset(0) ;
00793
00794
00795
00796 num = n ;
00797
00798 for(k=0;k<n;k++){
00799 total = 0.0 ;
00800 for(l=1;l<m;l++){
00801 cds[l] = norm(Q(k,l)-Q(k,l-1)) ;
00802 total += cds[l] ;
00803 }
00804 if(total==0.0)
00805 num-- ;
00806 else {
00807 d = 0.0 ;
00808 for(l=1;l<m;l++){
00809 d += cds[l] ;
00810 vl[l] += d/total ;
00811 }
00812 }
00813 }
00814
00815 delete []cds ;
00816
00817 if(num==0)
00818 return 0 ;
00819 for(l=1;l<m-1;l++)
00820 vl[l] /= num ;
00821 vl[m-1] = 1.0 ;
00822
00823
00824 return 1 ;
00825 }
00826
00843 template <class T, int N>
00844 int surfMeshParamsH(const Matrix< HPoint_nD<T,N> >& Q, Vector<T>& uk, Vector<T>& vl){
00845 int n,m,k,l,num ;
00846 double d,total ;
00847
00848 T* cds = new T[maximum(Q.rows(),Q.cols())] ;
00849
00850 n = Q.rows() ;
00851 m = Q.cols() ;
00852 uk.resize(n) ;
00853 vl.resize(m) ;
00854 num = m ;
00855
00856
00857
00858 uk.reset(0) ;
00859
00860 for(l=0;l<m;l++){
00861 total = 0.0 ;
00862 for(k=1;k<n;k++){
00863 cds[k] = norm(Q(k,l)-Q(k-1,l)) ;
00864 total += cds[k] ;
00865 }
00866 if(total==0.0)
00867 num-- ;
00868 else {
00869 d = 0.0 ;
00870 for(k=1;k<n;k++){
00871 d += cds[k] ;
00872 uk[k] += d/total ;
00873 }
00874 }
00875 }
00876
00877 if(num==0) {
00878 delete []cds ;
00879 return 0 ;
00880 }
00881 for(k=1;k<n-1;k++)
00882 uk[k] /= num ;
00883 uk[n-1] = 1.0 ;
00884
00885
00886 vl.reset(0) ;
00887
00888
00889 num = n ;
00890
00891 for(k=0;k<n;k++){
00892 total = 0.0 ;
00893 for(l=1;l<m;l++){
00894 cds[l] = norm(Q(k,l)-Q(k,l-1)) ;
00895 total += cds[l] ;
00896 }
00897 if(total==0.0)
00898 num-- ;
00899 else {
00900 d = 0.0 ;
00901 for(l=1;l<m;l++){
00902 d += cds[l] ;
00903 vl[l] += d/total ;
00904 }
00905 }
00906 }
00907
00908 delete []cds ;
00909
00910 if(num==0)
00911 return 0 ;
00912 for(l=1;l<m-1;l++)
00913 vl[l] /= num ;
00914 vl[m-1] = 1.0 ;
00915 return 1 ;
00916 }
00917
00928 template <class T, int N>
00929 void NurbsSurface<T,N>::globalInterp(const Matrix< Point_nD<T,N> >& Q, int pU, int pV){
00930 Vector<T> vk,uk ;
00931
00932 resize(Q.rows(),Q.cols(),pU,pV) ;
00933
00934 surfMeshParams(Q,uk,vk) ;
00935 knotAveraging(uk,pU,U) ;
00936 knotAveraging(vk,pV,V) ;
00937
00938
00939 Vector< HPoint_nD<T,N> > Pts(Q.rows()) ;
00940 NurbsCurve<T,N> R ;
00941
00942 int i,j ;
00943
00944 for(j=0;j<Q.cols();j++){
00945 for(i=0;i<Q.rows();i++)
00946 Pts[i] = Q(i,j) ;
00947 R.globalInterpH(Pts,uk,U,pU);
00948 for(i=0;i<Q.rows();i++)
00949 P(i,j) = R.ctrlPnts(i) ;
00950 }
00951
00952 Pts.resize(Q.cols()) ;
00953 for(i=0;i<Q.rows();i++){
00954 for(j=0;j<Q.cols();j++)
00955 Pts[j] = P(i,j) ;
00956 R.globalInterpH(Pts,vk,V,pV) ;
00957 for(j=0;j<Q.cols();j++)
00958 P(i,j) = R.ctrlPnts(j) ;
00959 }
00960 }
00961
00972 template <class T, int N>
00973 void NurbsSurface<T,N>::globalInterpH(const Matrix< HPoint_nD<T,N> >& Q, int pU, int pV){
00974 Vector<T> vk,uk ;
00975
00976 resize(Q.rows(),Q.cols(),pU,pV) ;
00977
00978 surfMeshParamsH(Q,uk,vk) ;
00979 knotAveraging(uk,pU,U) ;
00980 knotAveraging(vk,pV,V) ;
00981
00982
00983 Vector< HPoint_nD<T,N> > Pts(Q.rows()) ;
00984 NurbsCurve<T,N> R ;
00985
00986 int i,j ;
00987
00988 for(j=0;j<Q.cols();j++){
00989 for(i=0;i<Q.rows();i++)
00990 Pts[i] = Q(i,j) ;
00991 R.globalInterpH(Pts,uk,U,pU);
00992 for(i=0;i<Q.rows();i++)
00993 P(i,j) = R.ctrlPnts(i) ;
00994 }
00995
00996 Pts.resize(Q.cols()) ;
00997 for(i=0;i<Q.rows();i++){
00998 for(j=0;j<Q.cols();j++)
00999 Pts[j] = P(i,j) ;
01000 R.globalInterpH(Pts,vk,V,pV) ;
01001 for(j=0;j<Q.cols();j++)
01002 P(i,j) = R.ctrlPnts(j) ;
01003 }
01004 }
01005
01018 template <class T, int N>
01019 void NurbsSurface<T,N>::leastSquares(const Matrix< Point_nD<T,N> >& Q, int pU, int pV, int nU, int nV){
01020 Vector<T> vk,uk ;
01021
01022 resize(nU,nV,pU,pV) ;
01023
01024 surfMeshParams(Q,uk,vk) ;
01025
01026 Vector< HPoint_nD<T,N> > Pts(Q.rows()) ;
01027 NurbsCurve<T,N> R ;
01028
01029 int i,j ;
01030
01031 Matrix< HPoint_nD<T,N> > P2 ;
01032
01033 P2.resize(nU,Q.cols()) ;
01034
01035 for(j=0;j<Q.cols();j++){
01036 for(i=0;i<Q.rows();i++)
01037 Pts[i] = Q(i,j) ;
01038 R.leastSquaresH(Pts,pU,nU,uk);
01039 for(i=0;i<P.rows();i++)
01040 P2(i,j) = R.ctrlPnts(i) ;
01041 if(j==0)
01042 U = R.knot() ;
01043 }
01044
01045 Pts.resize(Q.cols()) ;
01046 for(i=0;i<P.rows();i++){
01047 for(j=0;j<Q.cols();j++)
01048 Pts[j] = P2(i,j) ;
01049 R.leastSquaresH(Pts,pV,nV,vk) ;
01050 for(j=0;j<P.cols();j++)
01051 P(i,j) = R.ctrlPnts(j) ;
01052 if(i==0)
01053 V = R.knot() ;
01054 }
01055 }
01056
01079 template <class T, int N>
01080 void globalSurfInterpXY(const Matrix< Point_nD<T,N> >& Q, int pU, int pV, NurbsSurface<T,N>& S) {
01081 Vector<T> uk,vk ;
01082 T um,uM ;
01083 T vm,vM ;
01084
01085 um = Q(0,0).y() ;
01086 vm = Q(0,0).x() ;
01087 uM = Q(Q.rows()-1,0).y() ;
01088 vM = Q(0,Q.cols()-1).x() ;
01089
01090 uk.resize(Q.rows()) ;
01091 vk.resize(Q.cols()) ;
01092
01093 uk[0] = 0.0 ;
01094 vk[0] = 0.0 ;
01095 uk[uk.n()-1] = 1.0 ;
01096 vk[vk.n()-1] = 1.0 ;
01097
01098 T dU = uM-um ;
01099 T dV = vM-vm ;
01100
01101 int i ;
01102 for(i=1;i<uk.n()-1;++i){
01103 uk[i] = Q(i,0).y()/dU ;
01104 }
01105
01106 for(i=1;i<vk.n()-1;++i){
01107 vk[i] = Q(0,i).x()/dV ;
01108 }
01109
01110 globalSurfInterpXY(Q,pU,pV,S,uk,vk) ;
01111 }
01112
01134 template <class T, int N>
01135 void globalSurfInterpXY(const Matrix< Point_nD<T,N> >& Q, int pU, int pV, NurbsSurface<T,N>& S, const Vector<T>& uk, const Vector<T>& vk){
01136 Vector<T> V,U ;
01137 int i,j ;
01138
01139
01140 knotAveraging(uk,pU,U) ;
01141 knotAveraging(vk,pV,V) ;
01142
01143 Vector< HPoint_nD<T,N> > P(Q.rows()) ;
01144 NurbsCurve<T,N> R ;
01145
01146 S.resize(Q.rows(),Q.cols(),pU,pV) ;
01147 S.U = U ;
01148 S.V = V ;
01149
01150 for(j=0;j<Q.cols();j++){
01151 for(i=0;i<Q.rows();i++)
01152 P[i] = Q(i,j) ;
01153 R.globalInterpH(P,uk,U,pU) ;
01154 for(i=0;i<Q.rows();i++)
01155 S.P(i,j) = R.ctrlPnts(i) ;
01156 }
01157
01158 P.resize(Q.cols()) ;
01159 for(i=0;i<Q.rows();i++){
01160 for(j=0;j<Q.cols();j++)
01161 P[j] = S.P(i,j) ;
01162 R.globalInterpH(P,vk,V,pV) ;
01163 for(j=0;j<Q.cols();j++)
01164 S.P(i,j) = R.ctrlPnts(j) ;
01165 }
01166 }
01167
01168
01183 template <class T, int N>
01184 void globalSurfApprox(const Matrix< Point_nD<T,N> >& Q, int pU, int pV, NurbsSurface<T,N>& S, double error){
01185
01186 NurbsCurveArray<T,N> R ;
01187 Vector< Point_nD<T,N> > P ;
01188
01189 Matrix< HPoint_nD<T,N> > St ;
01190 Vector<T> Ut,Vt ;
01191
01192 Vector<T> vk,uk ;
01193
01194 surfMeshParams(Q,uk,vk) ;
01195
01196 R.resize(Q.cols()) ;
01197 P.resize(Q.rows()) ;
01198
01199 int i,j ;
01200
01201 for(j=0;j<Q.cols();j++){
01202 for(i=0;i<Q.rows();i++)
01203 P[i] = Q(i,j) ;
01204 R[j].globalApproxErrBnd(P,uk,pU,error) ;
01205 }
01206
01207
01208 generateCompatibleCurves(R) ;
01209
01210 Ut.resize(R[0].knot().n()) ;
01211 Ut = R[0].knot() ;
01212
01213 St.resize(R[0].ctrlPnts().n(),R.n()) ;
01214
01215 for(i=0;i<R[0].ctrlPnts().n();i++){
01216 for(j=0;j<R.n();j++)
01217 St(i,j) = R[j].ctrlPnts(i) ;
01218 }
01219
01220 P.resize(St.cols()) ;
01221 R.resize(St.rows()) ;
01222 for(i=0;i<St.rows();i++){
01223 for(j=0;j<St.cols();j++)
01224 P[j] = project(St(i,j)) ;
01225 R[i].globalApproxErrBnd(P,vk,pV,error) ;
01226 }
01227
01228 generateCompatibleCurves(R) ;
01229
01230 Vt.resize(R[0].knot().n()) ;
01231 Vt = R[0].knot() ;
01232
01233 S.resize(St.rows(),R[0].ctrlPnts().n(),pU,pV) ;
01234 for(i=0;i<S.ctrlPnts().rows();i++)
01235 for(j=0;j<S.ctrlPnts().cols();j++){
01236 S.P(i,j) = R[i].ctrlPnts(j) ;
01237 }
01238 S.U = Ut ;
01239 S.V = Vt ;
01240 }
01241
01242
01254 template <class T, int N>
01255 void NurbsSurface<T,N>::degreeElevate(int tU, int tV) {
01256 degreeElevateU(tU) ;
01257 degreeElevateV(tV) ;
01258 }
01259
01268 template <class T, int N>
01269 void NurbsSurface<T,N>::degreeElevateU(int t) {
01270 if(t<=0){
01271 return ;
01272 }
01273
01274 NurbsSurface<T,N> S(*this) ;
01275
01276 int i,j,k ;
01277 int n = S.ctrlPnts().rows()-1;
01278 int p = S.degU ;
01279 int m = n+p+1;
01280 int ph = p+t ;
01281 int ph2 = ph/2 ;
01282 Matrix<T> bezalfs(p+t+1,p+1) ;
01283 Matrix< HPoint_nD<T,N> > bpts(p+1,S.P.cols()) ;
01284 Matrix< HPoint_nD<T,N> > ebpts(p+t+1,S.P.cols()) ;
01285 Matrix< HPoint_nD<T,N> > Nextbpts(p-1,S.P.cols()) ;
01286 Vector<T> alphas(p-1) ;
01287
01288
01289 Matrix<T> Bin(ph+1,ph2+1) ;
01290 binomialCoef(Bin) ;
01291
01292
01293 T inv,mpi ;
01294 bezalfs(0,0) = bezalfs(ph,p) = 1.0 ;
01295 for(i=1;i<=ph2;i++){
01296 inv= 1.0/Bin(ph,i) ;
01297 mpi = minimum(p,i) ;
01298 for(j=maximum(0,i-t); j<=mpi; j++){
01299 bezalfs(i,j) = inv*Bin(p,j)*Bin(t,i-j) ;
01300 }
01301 }
01302
01303 for(i=ph2+1;i<ph ; i++){
01304 mpi = minimum(p,i) ;
01305 for(j=maximum(0,i-t); j<=mpi ; j++)
01306 bezalfs(i,j) = bezalfs(ph-i,p-j) ;
01307 }
01308
01309
01310 resize(S.P.rows()+S.P.rows()*t,S.P.cols(),ph,S.degV) ;
01311
01312 int colJ ;
01313 int mh = ph ;
01314 int kind = ph+1 ;
01315 T ua = S.U[0] ;
01316 T ub = 0.0 ;
01317 int r=-1 ;
01318 int oldr ;
01319 int a = p ;
01320 int b = p+1 ;
01321 int cind = 1 ;
01322 int rbz,lbz = 1 ;
01323 int mul,save,s;
01324 T alf ;
01325 int first, last, kj ;
01326 T den,bet,gam,numer ;
01327
01328 for(i=0;i<S.P.cols();i++)
01329 P(0,i) = S.P(0,i) ;
01330 for(i=0; i <= ph ; i++){
01331 U[i] = ua ;
01332 }
01333
01334
01335
01336 for(i=0;i<=p ;i++)
01337 for(j=0;j<S.P.cols();j++)
01338 bpts(i,j) = S.P(i,j);
01339
01340 while(b<m){
01341 i=b ;
01342 while(b<m && S.U[b] >= S.U[b+1])
01343 b++ ;
01344 mul = b-i+1 ;
01345 mh += mul+t ;
01346 ub = S.U[b] ;
01347 oldr = r ;
01348 r = p-mul ;
01349 if(oldr>0)
01350 lbz = (oldr+2)/2 ;
01351 else
01352 lbz = 1 ;
01353 if(r>0)
01354 rbz = ph-(r+1)/2 ;
01355 else
01356 rbz = ph ;
01357 if(r>0){
01358 numer = ub-ua ;
01359 for(k=p;k>mul;k--){
01360 alphas[k-mul-1] = numer/(S.U[a+k]-ua) ;
01361 }
01362 for(j=1;j<=r;j++){
01363 save = r-j ; s = mul+j ;
01364 for(k=p;k>=s;k--){
01365 for(colJ=0;colJ<S.P.cols();colJ++){
01366 bpts(k,colJ) = alphas[k-s]*bpts(k,colJ)+(1.0-alphas[k-s])*bpts(k-1,colJ) ;}
01367 }
01368 if(Nextbpts.rows()>0)
01369 for(colJ=0;colJ<S.P.cols();colJ++){
01370 Nextbpts(save,colJ) = bpts(p,colJ) ;}
01371 }
01372 }
01373
01374 for(i=lbz;i<=ph;i++){
01375 for(colJ=0;colJ<S.P.cols();colJ++){
01376 ebpts(i,colJ) = 0.0 ;}
01377 mpi = minimum(p,i) ;
01378 for(j=maximum(0,i-t); j<=mpi ; j++)
01379 for(colJ=0;colJ<S.P.cols();colJ++){
01380 ebpts(i,colJ) += bezalfs(i,j)*bpts(j,colJ) ;}
01381 }
01382
01383 if(oldr>1){
01384
01385
01386 first = kind-2 ; last = kind ;
01387 den = ub-ua ;
01388 bet = (ub-U[kind-1])/den ;
01389 for(int tr=1; tr<oldr; tr++){
01390 i = first ; j = last ;
01391 kj = j-kind+1 ;
01392 while(j-i>tr){
01393 if(i<cind){
01394 alf=(ub-U[i])/(ua-U[i]) ;
01395 for(colJ=0;colJ<S.P.cols();colJ++){
01396 P(i,colJ) = alf*P(i,colJ) + (1.0-alf)*P(i-1,colJ) ;}
01397 }
01398 if( j>= lbz){
01399 if(j-tr <= kind-ph+oldr){
01400 gam = (ub-U[j-tr])/den ;
01401 for(colJ=0;colJ<S.P.cols();colJ++){
01402 ebpts(kj,colJ) = gam*ebpts(kj,colJ) + (1.0-gam)*ebpts(kj+1,colJ) ;}
01403 }
01404 else{
01405 for(colJ=0;colJ<S.P.cols();colJ++){
01406 ebpts(kj,colJ) = bet*ebpts(kj,colJ)+(1.0-bet)*ebpts(kj+1,colJ) ;}
01407 }
01408 }
01409 ++i ; --j; --kj ;
01410 }
01411 --first ; ++last ;
01412 }
01413 }
01414
01415 if(a!=p)
01416 for(i=0;i<ph-oldr; i++){
01417 U[kind++] = ua ;
01418 }
01419
01420 for(j=lbz; j<=rbz ; j++) {
01421 for(colJ=0;colJ<S.P.cols();colJ++)
01422 P(cind,colJ) = ebpts(j,colJ) ;
01423 ++cind ;
01424 }
01425
01426 if(b<m){
01427 for(colJ=0;colJ<S.P.cols();colJ++){
01428 for(j=0;j<r;j++)
01429 bpts(j,colJ) = Nextbpts(j,colJ) ;
01430 for(j=r;j<=p;j++)
01431 bpts(j,colJ) = S.P(b-p+j,colJ) ;
01432 }
01433 a=b ;
01434 b++ ;
01435 ua = ub ;
01436 }
01437 else{
01438 for(i=0;i<=ph;i++)
01439 U[kind+i] = ub ;
01440 }
01441 }
01442
01443 resizeKeep(mh-ph,S.P.cols(),ph,S.degV) ;
01444 }
01445
01454 template <class T, int N>
01455 void NurbsSurface<T,N>::degreeElevateV(int t) {
01456 if(t<=0){
01457 return ;
01458 }
01459
01460 NurbsSurface<T,N> S(*this) ;
01461
01462 int i,j,k ;
01463 int n = S.ctrlPnts().cols()-1;
01464 int p = S.degV ;
01465 int m = n+p+1;
01466 int ph = p+t ;
01467 int ph2 = ph/2 ;
01468 Matrix<T> bezalfs(p+t+1,p+1) ;
01469 Matrix< HPoint_nD<T,N> > bpts(p+1,S.P.rows()) ;
01470 Matrix< HPoint_nD<T,N> > ebpts(p+t+1,S.P.rows()) ;
01471 Matrix< HPoint_nD<T,N> > Nextbpts(p-1,S.P.rows()) ;
01472
01473 T* alphas = (T*) alloca((p-1)*sizeof(T)) ;
01474
01475
01476 Matrix<T> Bin(ph+1,ph2+1) ;
01477 binomialCoef(Bin) ;
01478
01479
01480 T inv,mpi ;
01481 bezalfs(0,0) = bezalfs(ph,p) = 1.0 ;
01482 for(i=1;i<=ph2;i++){
01483 inv= 1.0/Bin(ph,i) ;
01484 mpi = minimum(p,i) ;
01485 for(j=maximum(0,i-t); j<=mpi; j++){
01486 bezalfs(i,j) = inv*Bin(p,j)*Bin(t,i-j) ;
01487 }
01488 }
01489
01490 for(i=ph2+1;i<ph ; i++){
01491 mpi = minimum(p,i) ;
01492 for(j=maximum(0,i-t); j<=mpi ; j++)
01493 bezalfs(i,j) = bezalfs(ph-i,p-j) ;
01494 }
01495
01496 resize(S.P.rows(),S.P.cols()+S.P.cols()*t,S.degU,ph) ;
01497
01498 int rowJ ;
01499 int mh = ph ;
01500 int kind = ph+1 ;
01501 T va = S.V[0] ;
01502 T vb = 0.0 ;
01503 int r=-1 ;
01504 int oldr ;
01505 int a = p ;
01506 int b = p+1 ;
01507 int cind = 1 ;
01508 int rbz,lbz = 1 ;
01509 int mul,save,s;
01510 T alf ;
01511 int first, last, kj ;
01512 T den,bet,gam,numer ;
01513
01514 for(i=0;i<S.P.rows();i++)
01515 P(i,0) = S.P(i,0) ;
01516 for(i=0; i <= ph ; i++){
01517 V[i] = va ;
01518 }
01519
01520
01521
01522 for(i=0;i<=p ;i++)
01523 for(j=0;j<S.P.rows();j++)
01524 bpts(i,j) = S.P(j,i);
01525
01526 while(b<m){
01527 i=b ;
01528 while(b<m && S.V[b] >= S.V[b+1])
01529 b++ ;
01530 mul = b-i+1 ;
01531 mh += mul+t ;
01532 vb = S.V[b] ;
01533 oldr = r ;
01534 r = p-mul ;
01535 if(oldr>0)
01536 lbz = (oldr+2)/2 ;
01537 else
01538 lbz = 1 ;
01539 if(r>0)
01540 rbz = ph-(r+1)/2 ;
01541 else
01542 rbz = ph ;
01543 if(r>0){
01544 numer = vb-va ;
01545 for(k=p;k>mul;k--){
01546 alphas[k-mul-1] = numer/(S.V[a+k]-va) ;
01547 }
01548 for(j=1;j<=r;j++){
01549 save = r-j ; s = mul+j ;
01550 for(k=p;k>=s;k--){
01551 for(rowJ=0;rowJ<S.P.rows();rowJ++){
01552 bpts(k,rowJ) = alphas[k-s]*bpts(k,rowJ)+(1.0-alphas[k-s])*bpts(k-1,rowJ) ;}
01553 }
01554 if(Nextbpts.rows()>0)
01555 for(rowJ=0;rowJ<S.P.rows();rowJ++){
01556 Nextbpts(save,rowJ) = bpts(p,rowJ) ;}
01557 }
01558 }
01559
01560 for(i=lbz;i<=ph;i++){
01561 for(rowJ=0;rowJ<S.P.rows();rowJ++){
01562 ebpts(i,rowJ) = 0.0 ;}
01563 mpi = minimum(p,i) ;
01564 for(j=maximum(0,i-t); j<=mpi ; j++)
01565 for(rowJ=0;rowJ<S.P.rows();rowJ++){
01566 ebpts(i,rowJ) += bezalfs(i,j)*bpts(j,rowJ) ;}
01567 }
01568
01569 if(oldr>1){
01570
01571
01572 first = kind-2 ; last = kind ;
01573 den = vb-va ;
01574 bet = (vb-V[kind-1])/den ;
01575 for(int tr=1; tr<oldr; tr++){
01576 i = first ; j = last ;
01577 kj = j-kind+1 ;
01578 while(j-i>tr){
01579 if(i<cind){
01580 alf=(vb-V[i])/(va-V[i]) ;
01581 for(rowJ=0;rowJ<S.P.rows();rowJ++){
01582 P(rowJ,i) = alf*P(rowJ,i) + (1.0-alf)*P(rowJ,i-1) ;}
01583 }
01584 if( j>= lbz){
01585 if(j-tr <= kind-ph+oldr){
01586 gam = (vb-V[j-tr])/den ;
01587 for(rowJ=0;rowJ<S.P.rows();rowJ++){
01588 ebpts(kj,rowJ) = gam*ebpts(kj,rowJ) + (1.0-gam)*ebpts(kj+1,rowJ) ;}
01589 }
01590 else{
01591 for(rowJ=0;rowJ<S.P.rows();rowJ++){
01592 ebpts(kj,rowJ) = bet*ebpts(kj,rowJ)+(1.0-bet)*ebpts(kj+1,rowJ) ;}
01593 }
01594 }
01595 ++i ; --j; --kj ;
01596 }
01597 --first ; ++last ;
01598 }
01599 }
01600
01601 if(a!=p)
01602 for(i=0;i<ph-oldr; i++){
01603 V[kind++] = va ;
01604 }
01605
01606 for(j=lbz; j<=rbz ; j++) {
01607 for(rowJ=0;rowJ<S.P.rows();rowJ++)
01608 P(rowJ,cind) = ebpts(j,rowJ) ;
01609 ++cind ;
01610 }
01611
01612 if(b<m){
01613 for(rowJ=0;rowJ<S.P.rows();rowJ++){
01614 for(j=0;j<r;j++)
01615 bpts(j,rowJ) = Nextbpts(j,rowJ) ;
01616 for(j=r;j<=p;j++)
01617 bpts(j,rowJ) = S.P(rowJ,b-p+j) ;
01618 }
01619 a=b ;
01620 b++ ;
01621 va = vb ;
01622 }
01623 else{
01624 for(i=0;i<=ph;i++)
01625 V[kind+i] = vb ;
01626 }
01627 }
01628
01629 resizeKeep(S.P.rows(),mh-ph,S.degU,ph) ;
01630 }
01642 template <class T, int N>
01643 int NurbsSurface<T,N>::findMultU(int r) const {
01644 int s=1 ;
01645 for(int i=r;i>degU+1;i--)
01646 if(U[i]<=U[i-1])
01647 s++ ;
01648 else
01649 return s ;
01650 return s ;
01651 }
01652
01665 template <class T, int N>
01666 int NurbsSurface<T,N>::findMultV(int r) const {
01667 int s=1 ;
01668 for(int i=r;i>degV+1;i--)
01669 if(V[i]<=V[i-1])
01670 s++ ;
01671 else
01672 return s ;
01673 return s ;
01674 }
01675
01676
01677
01678
01695 template <class T, int N>
01696 void NurbsSurface<T,N>::findSpan(T u, T v, int& spanU, int& spanV) const{
01697 spanU = findSpanU(u) ;
01698 spanV = findSpanV(v) ;
01699 }
01700
01717 template <class T, int N>
01718 int NurbsSurface<T,N>::findSpanU(T u) const{
01719 if(u>=U[P.rows()])
01720 return P.rows()-1 ;
01721 if(u<=U[degU])
01722 return degU ;
01723
01724
01725 int low = 0 ;
01726 int high = P.rows()+1 ;
01727 int mid = (low+high)/2 ;
01728
01729 while(u<U[mid] || u>= U[mid+1]){
01730 if(u<U[mid])
01731 high = mid ;
01732 else
01733 low = mid ;
01734 mid = (low+high)/2 ;
01735 }
01736 return mid ;
01737 }
01738
01755 template <class T, int N>
01756 int NurbsSurface<T,N>::findSpanV(T v) const{
01757 if(v>=V[P.cols()])
01758 return P.cols()-1 ;
01759 if(v<=V[degV])
01760 return degV ;
01761
01762
01763 int low = 0 ;
01764 int high = P.cols()+1 ;
01765 int mid = (low+high)/2 ;
01766
01767 while(v<V[mid] || v>= V[mid+1]){
01768 if(v<V[mid])
01769 high = mid ;
01770 else
01771 low = mid ;
01772 mid = (low+high)/2 ;
01773 }
01774 return mid ;
01775 }
01776
01790 template <class T, int N>
01791 void NurbsSurface<T,N>::basisFuns(T u, T v, int spanU, int spanV, Vector<T>& Nu, Vector<T> &Nv) const{
01792 basisFunsU(u,spanU,Nu) ;
01793 basisFunsV(v,spanV,Nv) ;
01794 }
01795
01806 template <class T, int nD>
01807 void NurbsSurface<T,nD>::basisFunsU(T u, int span, Vector<T>& N) const {
01808
01809 T* left = (T*) alloca((degU+1)*sizeof(T)) ;
01810 T* right = (T*) alloca((degU+1)*sizeof(T)) ;
01811 T temp,saved ;
01812
01813
01814 N.resize(degU+1) ;
01815
01816 N[0] = 1.0 ;
01817 for(int j=1; j<= degU ; j++){
01818 left[j] = u-U[span+1-j] ;
01819 right[j] = U[span+j]-u ;
01820 saved = 0.0 ;
01821 for(int r=0 ; r<j; r++){
01822 temp = N[r]/(right[r+1]+left[j-r]) ;
01823 N[r] = saved+right[r+1]*temp ;
01824 saved = left[j-r]*temp ;
01825 }
01826 N[j] = saved ;
01827 }
01828
01829 }
01830
01841 template <class T, int nD>
01842 void NurbsSurface<T,nD>::basisFunsV(T v, int span, Vector<T>& N) const {
01843
01844 T* left = (T*) alloca((degV+1)*sizeof(T)) ;
01845 T* right = (T*) alloca((degV+1)*sizeof(T)) ;
01846 T temp,saved ;
01847
01848
01849 N.resize(degV+1) ;
01850
01851 N[0] = 1.0 ;
01852 for(int j=1; j<= degV ; j++){
01853 left[j] = v-V[span+1-j] ;
01854 right[j] = V[span+j]-v ;
01855 saved = 0.0 ;
01856 for(int r=0 ; r<j; r++){
01857 temp = N[r]/(right[r+1]+left[j-r]) ;
01858 N[r] = saved+right[r+1]*temp ;
01859 saved = left[j-r]*temp ;
01860 }
01861 N[j] = saved ;
01862 }
01863
01864 }
01865
01883 template <class T, int nD>
01884 void NurbsSurface<T,nD>::deriveAtH(T u, T v, int d, Matrix< HPoint_nD<T,nD> > &skl) const {
01885 int k,l,du,dv;
01886 skl.resize(d+1,d+1) ;
01887
01888 du = minimum(d,degU) ;
01889 for(k=degU+1;k<=d;++k)
01890 for(l=0;l<=d-k;++l)
01891 skl(k,l) = 0.0 ;
01892 dv=minimum(d,degV) ;
01893 for(l=degV+1;l<=d;++l)
01894 for(k=0;k<=d-l;++k)
01895 skl(k,l) = 0.0 ;
01896 int uspan = findSpanU(u) ;
01897 int vspan = findSpanV(v) ;
01898 Matrix<T> Nu,Nv ;
01899 nurbsDersBasisFuns(du,u,uspan,degU,U,Nu) ;
01900 nurbsDersBasisFuns(dv,v,vspan,degV,V,Nv) ;
01901
01902 Vector< HPoint_nD<T,nD> > temp(degV+1) ;
01903 int dd,r,s ;
01904 for(k=0;k<=du;++k){
01905 for(s=0;s<=degV;++s){
01906 temp[s] = 0.0 ;
01907 for(r=0;r<=degU;++r)
01908 temp[s] += Nu(k,r)*P(uspan-degU+r,vspan-degV+s) ;
01909 }
01910 dd = minimum(d-k,dv) ;
01911 for(l=0;l<=dd;++l){
01912 skl(k,l) = 0.0 ;
01913 for(s=0;s<=degV;++s)
01914 skl(k,l) += Nv(l,s)*temp[s] ;
01915 }
01916 }
01917 }
01918
01936 template <class T, int N>
01937 void NurbsSurface<T,N>::deriveAt(T u, T v, int d, Matrix< Point_nD<T,N> > &skl) const {
01938 int k,l ;
01939 Matrix< HPoint_nD<T,N> > ders ;
01940 Point_nD<T,N> pv,pv2 ;
01941
01942 skl.resize(d+1,d+1) ;
01943
01944 deriveAtH(u,v,d,ders) ;
01945
01946 Matrix<T> Bin(d+1,d+1) ;
01947 binomialCoef(Bin) ;
01948 int i,j ;
01949
01950 for(k=0;k<=d;++k){
01951 for(l=0;l<=d-k;++l){
01952 pv.x() = ders(k,l).x() ;
01953 pv.y() = ders(k,l).y() ;
01954 pv.z() = ders(k,l).z() ;
01955 for(j=1;j<=l;j++)
01956 pv -= Bin(l,j)*ders(0,j).w()*skl(k,l-j) ;
01957 for(i=1;i<=k;i++){
01958 pv -= Bin(k,i)*ders(i,0).w()*skl(k-i,l) ;
01959 pv2 = 0.0 ;
01960 for(j=1;j<=l;j++)
01961 pv2 += Bin(l,j)*ders(i,j).w()*skl(k-i,l-j) ;
01962 pv -= Bin(k,i)*pv2 ;
01963 }
01964 skl(k,l) = pv/ders(0,0).w() ;
01965 }
01966 }
01967 }
01968
01980 template <class T, int N>
01981 Point_nD<T,N> NurbsSurface<T,N>::normal(T u, T v) const {
01982 Matrix< Point_nD<T,N> > ders ;
01983
01984 deriveAt(u,v,1,ders) ;
01985
01986 return crossProduct(ders(1,0),ders(0,1)) ;
01987 }
01988
02002 template <class T, int N>
02003 HPoint_nD<T,N> NurbsSurface<T,N>::operator()(T u, T v) const{
02004 int uspan = findSpanU(u) ;
02005 int vspan = findSpanV(v) ;
02006 Vector<T> Nu,Nv ;
02007 Vector< HPoint_nD<T,N> > temp(degV+1) ;
02008
02009 basisFuns(u,v,uspan,vspan,Nu,Nv) ;
02010
02011 int l;
02012 for(l=0;l<=degV;l++){
02013 temp[l] =0.0 ;
02014 for(int k=0;k<=degU;k++){
02015 temp[l] += Nu[k]*P(uspan-degU+k,vspan-degV+l) ;
02016 }
02017 }
02018 HPoint_nD<T,N> sp(0,0,0,0) ;
02019 for(l=0;l<=degV;l++){
02020 sp += Nv[l]*temp[l] ;
02021 }
02022 return sp ;
02023 }
02024
02025 inline
02026 int max3(int a,int b, int c){
02027 int m = a ;
02028 if(m <b)
02029 m = b ;
02030 if(m <c)
02031 m = c ;
02032 return m ;
02033 }
02034
02052 template <class T, int N>
02053 void gordonSurface(NurbsCurveArray<T,N>& lU, NurbsCurveArray<T,N>& lV, const Matrix< Point_nD<T,N> >& intersections, NurbsSurface<T,N>& gS){
02054 NurbsSurface<T,N> sU,sV,sI ;
02055 sU.skinU(lU,3) ;
02056 sV.skinV(lV,3) ;
02057 sI.globalInterp(intersections,3,3) ;
02058
02059 int du = max3(sU.degU,sV.degU,sI.degU) ;
02060 int dv = max3(sU.degV,sV.degV,sI.degV) ;
02061
02062
02063 NurbsSurface<T,N> SU,SV,SI ;
02064 degreeElevate(sU,du-sU.degU,dv-sU.degV,SU) ;
02065 degreeElevate(sV,du-sV.degU,dv-sV.degV,SV) ;
02066 degreeElevate(sI,du-sI.degU,dv-sI.degV,SI) ;
02067
02068
02069 Vector<T> U,V ;
02070 U = knotUnion(SU.knotU(),SV.knotU()) ;
02071 U = knotUnion(U,SI.knotU()) ;
02072 V = knotUnion(SU.knotV(),SV.knotV()) ;
02073 V = knotUnion(V,SI.knotV()) ;
02074
02075 SU.mergeKnots(U,V) ;
02076 SV.mergeKnots(U,V) ;
02077 SI.mergeKnots(U,V) ;
02078
02079 gS = SU ;
02080
02081 for(int i=0;i<gS.P.rows();i++)
02082 for(int j=0;j<gS.P.cols();j++){
02083 gS.P(i,j) += SV.P(i,j) ;
02084 gS.P(i,j) -= SI.P(i,j) ;
02085 }
02086 }
02087
02088 template <class T>
02089 inline void insert(T u, Vector<T>& v){
02090 int i ;
02091 if(u<v[0] || u>v[v.n()-1])
02092 return ;
02093 v.resize(v.n()+1) ;
02094 i = v.n()-1 ;
02095 while(v[i-1]>u){
02096 v[i] = v[i-1] ;
02097 --i ;
02098 }
02099 v[i] = u ;
02100 }
02101
02102
02144 template <class T, int N>
02145 void NurbsSurface<T,N>::sweep(const NurbsCurve<T,N>& Trj, const NurbsCurve<T,N>& C, const NurbsCurve<T,N>& Sv, int K, int useAy, int invAz) {
02146 int i,j,k,m,q,ktv,nsect ;
02147 q = Trj.degree() ;
02148 ktv = Trj.knot().n() ;
02149 nsect = K ;
02150
02151 V.resize(Trj.knot().n()) ;
02152 V = Trj.knot() ;
02153
02154 if(ktv <= nsect+q){
02155 m = nsect+q-ktv+1 ;
02156
02157
02158
02159 for(i=0;i<m;++i){
02160 T md,mt ;
02161 T mu = -1;
02162 md = 0 ;
02163 for(j=1;j<V.n();++j){
02164 mt = V[j]-V[j-1] ;
02165 if(mt>md){
02166 md = mt ;
02167 mu = (V[j]+V[j-1])/2.0 ;
02168 }
02169 }
02170 insert(mu,V) ;
02171 }
02172 }
02173 else{
02174 if(ktv>nsect){
02175 nsect = ktv-q-1 ;
02176 }
02177 }
02178
02179 Vector<T> v;
02180
02181
02182 v.resize(nsect) ;
02183 v[0] = Trj.knot(Trj.degree()) ;
02184 v[nsect-1] = Trj.knot(Trj.knot().n()-Trj.degree()-1) ;
02185 for(k=1;k<nsect-1;++k){
02186 v[k] = 0.0 ;
02187 for(i=k+1;i<k+q+1;++i)
02188 v[k] += V[i] ;
02189 v[k] /= q ;
02190 }
02191
02192 resize(C.ctrlPnts().n(),nsect,C.degree(),Trj.degree()) ;
02193
02194 U = C.knot() ;
02195
02196
02197 Vector< Point_nD<T,N> > B ;
02198 NurbsCurve<T,N> Bv ;
02199 Vector< Point_nD<T,N> > Td ;
02200
02201 B.resize(v.n()) ;
02202 Trj.deriveAt(v[0],1,Td) ;
02203
02204 B[0] = Td[1] ;
02205 if(Td[1].y() ==0)
02206 B[0] = crossProduct(Point_nD<T,N>(0,1,0),B[0]) ;
02207 else
02208 B[0] = crossProduct(Point_nD<T,N>(1,0,0),B[0]) ;
02209 B[0] /= norm(B[0]) ;
02210
02211
02212 for(i=1;i<v.n();++i){
02213 Trj.deriveAt(v[i],1,Td);
02214 Point_nD<T,N> Ti(Td[1]) ;
02215 Ti = Ti/norm(Ti) ;
02216 Point_nD<T,N> bi ;
02217 bi = B[i-1]-(B[i-1]*Ti)*Ti ;
02218 B[i] = bi/norm(bi) ;
02219 }
02220
02221 Bv.globalInterp(B,v,minimum(3,B.n()-1)) ;
02222
02223 Vector< HPoint_nD<T,N> > Q(C.ctrlPnts().n()) ;
02224 for(k=0;k<nsect;++k){
02225
02226 for(i=0;i<Q.n();++i){
02227 HPoint_nD<T,N> sk(Sv(v[k])) ;
02228 Q[i].x() = sk.x()*C.ctrlPnts(i).x() ;
02229 Q[i].y() = sk.y()*C.ctrlPnts(i).y() ;
02230 Q[i].z() = sk.z()*C.ctrlPnts(i).z() ;
02231 Q[i].w() = sk.w()*C.ctrlPnts(i).w() ;
02232 }
02233
02234 Point_nD<T,N> o = Trj.pointAt(v[k]) ;
02235
02236
02237
02238 Trj.deriveAt(v[k],1,Td) ;
02239
02240 Point_nD<T,N> x = Td[1]/norm(Td[1]) ;
02241
02242
02243 Point_nD<T,N> z = Bv.pointAt(v[k]) ;
02244 z /= norm(z) ;
02245
02246
02247 Point_nD<T,N> y = crossProduct(z,x) ;
02248
02249
02250
02251
02252
02253
02254
02255
02256
02257
02258
02259
02260
02261
02262
02263 MatrixRT_DOUBLE R ;
02264 R(0,0) = y.x();
02265 R(1,0) = y.y();
02266 R(2,0) = y.z();
02267 R(0,1) = x.x();
02268 R(1,1) = x.y();
02269 R(2,1) = x.z();
02270 R(0,2) = z.x();
02271 R(1,2) = z.y();
02272 R(2,2) = z.z();
02273
02274
02275 MatrixRT_DOUBLE Tx ;
02276 Tx.translate(o.x(),o.y(),o.z());
02277
02278 MatrixRT_DOUBLE A ;
02279 A = Tx * R ;
02280
02281 for(i=0;i<Q.n();++i){
02282 P(i,k) = A*(Q[i]) ;
02283 }
02284 }
02285
02286
02287 Q.resize(P.cols()) ;
02288 NurbsCurve<T,N> R;
02289 for(i=0;i<P.rows();++i){
02290 for(k=0;k<P.cols();++k)
02291 Q[k] = P(i,k) ;
02292 R.globalInterpH(Q,v,V,degV) ;
02293 for(k=0;k<P.cols();++k)
02294 P(i,k) = R.ctrlPnts(k) ;
02295 }
02296
02297 }
02298
02331 template <class T, int N>
02332 void NurbsSurface<T,N>::sweep(const NurbsCurve<T,N>& Trj, const NurbsCurve<T,N>& C, int K, int useAy,int invAz) {
02333
02334 Vector< HPoint_nD<T,N> > p(2) ;
02335 p[0] = HPoint_nD<T,N>(1,1,1,1) ;
02336 p[1] = HPoint_nD<T,N>(1,1,1,1) ;
02337 Vector<T> u(4) ;
02338 u[0] = u[1] = 0.0 ; u[2] = u[3] = 1.0 ;
02339
02340 NurbsCurve<T,N> Sv(p,u,1) ;
02341
02342 sweep(Trj,C,Sv,K,useAy,invAz) ;
02343 }
02344
02356 template <class T, int N>
02357 void NurbsSurface<T,N>::transform(const MatrixRT<T>& A){
02358 for(int i=0;i<P.rows();++i)
02359 for(int j=0;j<P.cols();++j)
02360 P(i,j) = A*P(i,j) ;
02361 }
02362
02372 template <class T, int N>
02373 void NurbsSurface<T,N>::refineKnots(const Vector<T>& nU, const Vector<T>& nV){
02374 refineKnotU(nU) ;
02375 refineKnotV(nV) ;
02376 }
02377
02386 template <class T, int N>
02387 void NurbsSurface<T,N>::refineKnotU(const Vector<T>& X) {
02388 if(X.n()<=0)
02389 return ;
02390 int n = P.rows()-1 ;
02391 int p = degU;
02392 int m = n+p+1 ;
02393 int a,b ;
02394 int r = X.n()-1 ;
02395 NurbsSurface<T,N> nS ;
02396
02397 nS = *this ;
02398 nS.resize(r+1+n+1,P.cols(),degU,degV) ;
02399
02400 a = findSpanU(X[0]) ;
02401 b = findSpanU(X[r]) ;
02402 ++b ;
02403
02404 int j,col ;
02405 for(col=0;col<P.cols();col++){
02406 for(j=0; j<=a-p ; j++)
02407 nS.P(j,col) = P(j,col);
02408 for(j = b-1 ; j<=n ; j++)
02409 nS.P(j+r+1,col) = P(j,col) ;
02410 }
02411 for(j=0; j<=a ; j++)
02412 nS.U[j] = U[j] ;
02413 for(j=b+p ; j<=m ; j++)
02414 nS.U[j+r+1] = U[j] ;
02415 int i = b+p-1 ;
02416 int k = b+p+r ;
02417 for(j=r; j>=0 ; j--){
02418 while(X[j] <= U[i] && i>a){
02419 for(col=0;col<P.cols();col++)
02420 nS.P(k-p-1,col) = P(i-p-1,col) ;
02421 nS.U[k] = U[i] ;
02422 --k ;
02423 --i ;
02424 }
02425 for(col=0;col<P.cols();col++)
02426 nS.P(k-p-1,col) = nS.P(k-p,col) ;
02427 for(int l=1; l<=p ; l++){
02428 int ind = k-p+l ;
02429 T alpha = nS.U[k+l] - X[j] ;
02430 if(alpha==0.0)
02431 for(col=0;col<P.cols();col++)
02432 nS.P(ind-1,col) = nS.P(ind,col) ;
02433 else
02434 alpha /= nS.U[k+l]-U[i-p+l] ;
02435 for(col=0;col<P.cols();col++)
02436 nS.P(ind-1,col) = alpha*nS.P(ind-1,col) + (1.0-alpha)*nS.P(ind,col) ;
02437 }
02438 nS.U[k] = X[j] ;
02439 --k ;
02440 }
02441 *this = nS ;
02442 }
02443
02452 template <class T, int N>
02453 void NurbsSurface<T,N>::refineKnotV(const Vector<T>& X) {
02454 if(X.n()<=0)
02455 return ;
02456 int n = P.cols()-1 ;
02457 int p = degV;
02458 int m = n+p+1 ;
02459 int a,b ;
02460 int r = X.n()-1 ;
02461 NurbsSurface<T,N> nS ;
02462
02463 try {
02464 nS = *this ;
02465 nS.resize(P.rows(),r+1+n+1,degU,degV) ;
02466 }
02467 catch(...){
02468 cerr << "Out of memory\n" ;
02469 }
02470
02471 a = findSpanV(X[0]) ;
02472 b = findSpanV(X[r]) ;
02473 ++b ;
02474
02475 int j,row ;
02476 for(row=0;row<P.rows();row++){
02477 for(j=0; j<=a-p ; j++)
02478 nS.P(row,j) = P(row,j);
02479 for(j = b-1 ; j<=n ; j++)
02480 nS.P(row,j+r+1) = P(row,j) ;
02481 }
02482 for(j=0; j<=a ; j++)
02483 nS.V[j] = V[j] ;
02484 for(j=b+p ; j<=m ; j++)
02485 nS.V[j+r+1] = V[j] ;
02486 int i = b+p-1 ;
02487 int k = b+p+r ;
02488 for(j=r; j>=0 ; j--){
02489 while(X[j] <= V[i] && i>a){
02490 for(row=0;row<P.rows();row++)
02491 nS.P(row,k-p-1) = P(row,i-p-1) ;
02492 nS.V[k] = V[i] ;
02493 --k ;
02494 --i ;
02495 }
02496 for(row=0;row<P.rows();row++)
02497 nS.P(row,k-p-1) = nS.P(row,k-p) ;
02498 for(int l=1; l<=p ; l++){
02499 int ind = k-p+l ;
02500 T alpha = nS.V[k+l] - X[j] ;
02501 if(alpha==0.0)
02502 for(row=0;row<P.rows();row++)
02503 nS.P(row,ind-1) = nS.P(row,ind) ;
02504 else
02505 alpha /= nS.V[k+l]-V[i-p+l] ;
02506 for(row=0;row<P.rows();row++)
02507 nS.P(row,ind-1) = alpha*nS.P(row,ind-1) + (1.0-alpha)*nS.P(row,ind) ;
02508 }
02509 nS.V[k] = X[j] ;
02510 --k ;
02511 }
02512 *this = nS ;
02513 }
02514
02515
02528 template <class T, int N>
02529 void NurbsSurface<T,N>::mergeKnots(const Vector<T>& nU, const Vector<T>& nV) {
02530 mergeKnotU(nU) ;
02531 mergeKnotV(nV) ;
02532 }
02533
02544 template <class T, int N>
02545 void NurbsSurface<T,N>::mergeKnotU(const Vector<T>& X){
02546 int i,ia,ib ;
02547
02548 Vector<T> I(U.n()) ;
02549 int done = 0 ;
02550 i = ia = ib = 0 ;
02551 while(!done) {
02552 if(X[ib] == U[ia]){
02553 ++ib ; ++ia ;
02554 }
02555 else{
02556 I[i++] = X[ib] ;
02557 ib++ ;
02558 }
02559 done = (ia>=U.n() || ib >= X.n()) ;
02560 }
02561 I.resize(i) ;
02562
02563 if(I.n()>0)
02564 refineKnotU(I) ;
02565 }
02566
02577 template <class T, int N>
02578 void NurbsSurface<T,N>::mergeKnotV(const Vector<T>& X){
02579 int i,ia,ib ;
02580
02581 Vector<T> I(V.n()) ;
02582 int done = 0 ;
02583 i = ia = ib = 0 ;
02584 while(!done) {
02585 if(X[ib] == V[ia]){
02586 ++ib ; ++ia ;
02587 }
02588 else{
02589 I[i++] = X[ib] ;
02590 ib++ ;
02591 }
02592 done = (ia>=V.n() || ib >= X.n()) ;
02593 }
02594 I.resize(i) ;
02595
02596 if(I.n()>0)
02597 refineKnotV(I) ;
02598 }
02599
02610 template <class T, int N>
02611 int NurbsSurface<T,N>::read(ifstream &fin){
02612 if(!fin) {
02613 return 0 ;
02614 }
02615 int nu,nv,du,dv;
02616 char *type ;
02617 type = new char[3] ;
02618 if(!fin.read(type,sizeof(char)*3)) { delete []type ; return 0 ;}
02619 int r1 = strncmp(type,"ns3",3) ;
02620 int r2 = strncmp(type,"ns4",3) ;
02621 if(!(r1 || r2))
02622 return 0 ;
02623 int st ;
02624 char stc ;
02625 if(!fin.read((char*)&stc,sizeof(char))) { delete []type ; return 0 ;}
02626 if(!fin.read((char*)&nu,sizeof(int))) { delete []type ; return 0 ;}
02627 if(!fin.read((char*)&nv,sizeof(int))) { delete []type ; return 0 ;}
02628 if(!fin.read((char*)&du,sizeof(int))) { delete []type ; return 0 ;}
02629 if(!fin.read((char*)&dv,sizeof(int))) { delete []type ; return 0 ;}
02630
02631 st = stc - '0' ;
02632 if(st != sizeof(T)){
02633 delete []type ;
02634 return 0 ;
02635 }
02636
02637 resize(nu,nv,du,dv) ;
02638
02639 if(!fin.read((char*)U.memory(),sizeof(T)*U.n())) { delete []type ; return 0 ;}
02640 if(!fin.read((char*)V.memory(),sizeof(T)*V.n())) { delete []type ; return 0 ;}
02641
02642
02643 T *p,*p2 ;
02644 if(!r1){
02645 p = new T[3*nu*nv] ;
02646 if(!fin.read((char*)p,sizeof(T)*3*nu*nv)) { delete []type ; return 0 ;}
02647 p2 = p ;
02648 for(int i=0;i<nu;i++)
02649 for(int j=0;j<nv;j++){
02650 P(i,j).x() = *(p++) ;
02651 P(i,j).y() = *(p++) ;
02652 P(i,j).z() = *(p++) ;
02653 P(i,j).w() = 1.0 ;
02654 }
02655 delete []p2 ;
02656 }
02657 else{
02658 p = new T[4*nu*nv] ;
02659 if(!fin.read((char*)p,sizeof(T)*4*nu*nv)) { delete []type ; return 0 ;}
02660 p2 = p ;
02661 for(int i=0;i<nu;i++)
02662 for(int j=0;j<nv;j++){
02663 P(i,j).x() = *(p++) ;
02664 P(i,j).y() = *(p++) ;
02665 P(i,j).z() = *(p++) ;
02666 P(i,j).w() = *(p++) ;
02667 }
02668 delete []p2 ;
02669 }
02670
02671 delete []type ;
02672 return 1 ;
02673 }
02674
02685 template <class T, int N>
02686 int NurbsSurface<T,N>::read(const char* filename){
02687 ifstream fin(filename) ;
02688 if(!fin) {
02689 return 0 ;
02690 }
02691
02692 return read(fin) ;
02693 }
02694
02705 template <class T, int N>
02706 int NurbsSurface<T,N>::write(ofstream &fout) const {
02707 if(!fout)
02708 return 0 ;
02709 int prows = P.rows();
02710 int pcols = P.cols();
02711 char st = '0' + sizeof(T) ;
02712 if(!fout.write((char*)&"ns4",sizeof(char)*3)) return 0 ;
02713 if(!fout.write((char*)&st,sizeof(char))) return 0 ;
02714 if(!fout.write((char*)&prows,sizeof(int))) return 0 ;
02715 if(!fout.write((char*)&pcols,sizeof(int))) return 0 ;
02716 if(!fout.write((char*)°U,sizeof(int))) return 0 ;
02717 if(!fout.write((char*)°V,sizeof(int))) return 0 ;
02718 if(!fout.write((char*)U.memory(),sizeof(T)*U.n())) return 0 ;
02719 if(!fout.write((char*)V.memory(),sizeof(T)*V.n())) return 0 ;
02720
02721 T *p,*p2 ;
02722 p = new T[P.rows()*P.cols()*4] ;
02723 p2 = p ;
02724 for(int i=0;i<P.rows();i++)
02725 for(int j=0;j<P.cols();j++){
02726 *p = P(i,j).x() ; p++ ;
02727 *p = P(i,j).y() ; p++ ;
02728 *p = P(i,j).z() ; p++ ;
02729 *p = P(i,j).w() ; p++ ;
02730 }
02731 if(!fout.write((char*)p2,sizeof(T)*P.rows()*P.cols()*4)) return 0 ;
02732 delete []p2 ;
02733 return 1 ;
02734 }
02735
02746 template <class T, int N>
02747 int NurbsSurface<T,N>::write(const char* filename) const {
02748 ofstream fout(filename) ;
02749 if(!fout)
02750 return 0 ;
02751 return write(fout);
02752 }
02753
02766 template <class T, int N>
02767 NurbsSurface<T,N>& NurbsSurface<T,N>::transpose(void){
02768 Vector<T> t(U) ;
02769 int d ;
02770 U = V ;
02771 V = t ;
02772 d = degU ;
02773 degU = degV ;
02774 degV = d ;
02775 P = ::transpose(P) ;
02776 return *this ;
02777 }
02778
02796 template <class T, int N>
02797 int NurbsSurface<T,N>::movePoint(T u, T v, const Point_nD<T,N>& delta){
02798
02799 Matrix_DOUBLE B(1,(degU+1)*(degV+1)) ;
02800 int i,j,k ;
02801
02802 int spanU,spanV ;
02803
02804 Vector<T> Ru,Rv ;
02805
02806 B.reset(0.0) ;
02807
02808 findSpan(u,v,spanU,spanV) ;
02809 nurbsBasisFuns(u,spanU,degU,U,Ru) ;
02810 nurbsBasisFuns(v,spanV,degV,V,Rv) ;
02811 for(j=0;j<=degU;++j){
02812 for(k=0;k<=degV;++k){
02813 B(0,j*(degV+1)+k)
02814 = (double)Ru[j]*(double)Rv[k] ;
02815 }
02816 }
02817
02818 Matrix_DOUBLE A ;
02819 Matrix_DOUBLE Bt(::transpose(B)) ;
02820 Matrix_DOUBLE BBt ;
02821
02822 BBt = inverse(B*Bt) ;
02823 A = Bt*BBt ;
02824
02825 Matrix_DOUBLE dD(1,3) ;
02826
02827 for(j=0;j<3;++j)
02828 dD(0,j) = (double)delta.data[j] ;
02829
02830 Matrix_DOUBLE dP ;
02831
02832 dP = A*dD ;
02833
02834 i= 0 ;
02835
02836 for(j=0;j<=degU;++j){
02837 for(k=0;k<=degV;++k){
02838 T w = P(spanU-degU+j,spanV-degV+k).w() ;
02839 P(spanU-degU+j,spanV-degV+k).x() += dP(i,0)*w ;
02840 P(spanU-degU+j,spanV-degV+k).y() += dP(i,1)*w ;
02841 P(spanU-degU+j,spanV-degV+k).z() += dP(i,2)*w ;
02842 ++i ;
02843 }
02844 }
02845
02846 return 1 ;
02847 }
02848
02879 template <class T, int N>
02880 int NurbsSurface<T,N>::movePoint(const Vector<T>& ur, const Vector<T>& vr, const Vector< Point_nD<T,N> >& D, const Vector_INT& Du, const Vector_INT& Dv) {
02881 Vector_INT Dk(Du.n()),Dl(Dv.n()) ;
02882 BasicArray<Coordinate> fixCP(0) ;
02883 Dk.reset(0) ;
02884 Dl.reset(0) ;
02885 return movePoint(ur,vr,D,Du,Dv,Dk,Dl,fixCP) ;
02886 }
02887
02922 template <class T, int N>
02923 int NurbsSurface<T,N>::movePoint(const Vector<T>& ur, const Vector<T>& vr, const Vector< Point_nD<T,N> >& D, const Vector_INT& Du, const Vector_INT& Dv, const Vector_INT& Dk, const Vector_INT& Dl) {
02924 BasicArray<Coordinate> fixCP(0) ;
02925 return movePoint(ur,vr,D,Du,Dv,Dk,Dl,fixCP) ;
02926 }
02927
02928
02929
02969 template <class T, int N>
02970 int NurbsSurface<T,N>::movePoint(const Vector<T>& ur, const Vector<T>& vr, const Vector< Point_nD<T,N> >& D, const Vector_INT& Du, const Vector_INT& Dv, const Vector_INT& Dk, const Vector_INT& Dl, const BasicArray<Coordinate>& fixCP) {
02971 int i,j,k,n ;
02972
02973 if(D.n() != Du.n() || D.n() !=Du.n() || D.n() != Dv.n() || D.n() != Dv.n()){
02974 #ifdef USE_EXCEPTION
02975 throw NurbsInputError();
02976 #else
02977 Error err("movePoint(ur,D,Dr,Dk,fixCP)");
02978 err << "The D,Dr,Dk vectors are not of the same size\n" ;
02979 err << "D.n()= " << D.n() << ", Du.n() = " << Du.n()
02980 << ", Dk.n() = " << Dk.n() << ", Dv.n() = " << Dv.n()
02981 << ", Dl.n() = " << Dl.n() << endl ;
02982 err.fatal() ;
02983 #endif
02984 }
02985
02986
02987 Matrix_DOUBLE B ;
02988
02989 B.resize(D.n(),P.rows()*P.cols()) ;
02990
02991 int spanU,spanV ;
02992
02993 Matrix<T> Ru,Rv ;
02994
02995 B.reset(0.0) ;
02996
02997 for(i=0;i<D.rows();++i){
02998 findSpan(ur[Du[i]],vr[Dv[i]],spanU,spanV) ;
02999 nurbsDersBasisFuns(Dk[i],ur[Du[i]],spanU,degU,U,Ru) ;
03000 nurbsDersBasisFuns(Dl[i],vr[Dv[i]],spanV,degV,V,Rv) ;
03001 for(j=0;j<=degU;++j){
03002 for(k=0;k<=degV;++k){
03003 B(i,(spanU-degU+j)*P.cols()+spanV-degV+k)
03004 = (double)Ru(Dk[i],j)*(double)Rv(Dl[i],k) ;
03005 }
03006 }
03007 }
03008
03009
03010 Vector_INT remove(B.cols()) ;
03011 BasicArray<Coordinate> map(B.cols()) ;
03012 remove.reset((int)1.0) ;
03013
03014 for(j=0;j<B.cols();++j){
03015 for(i=0;i<B.rows();++i)
03016 if((B(i,j)*B(i,j))>1e-10){
03017 remove[j] = 0 ;
03018 break ;
03019 }
03020 }
03021
03022 for(i=0;i<fixCP.n();++i){
03023 remove[fixCP[i].i*P.cols()+fixCP[i].j] = 1 ;
03024 }
03025
03026 n = 0 ;
03027 for(i=0;i<B.cols();++i){
03028 if(!remove[i]){
03029 map[n].i = i/P.cols() ;
03030 map[n].j = i%P.cols() ;
03031 ++n ;
03032 }
03033 }
03034
03035 map.resize(n) ;
03036
03037 Matrix_DOUBLE Bopt(B.rows(),n) ;
03038 for(j=0;j<n;++j){
03039 for(i=0;i<B.rows();++i)
03040 Bopt(i,j) = B(i,map[j].i*P.cols()+map[j].j) ;
03041 }
03042
03043 Matrix_DOUBLE A ;
03044 Matrix_DOUBLE Bt(::transpose(Bopt)) ;
03045 Matrix_DOUBLE BBt ;
03046
03047 BBt = inverse(Bopt*Bt) ;
03048
03049 A = Bt*BBt ;
03050
03051 Matrix_DOUBLE dD(D.rows(),3) ;
03052
03053 for(i=0;i<D.rows();++i){
03054 const Point_nD<T,N>& d = D[i] ;
03055 for(j=0;j<3;++j)
03056 dD(i,j) = (double)d.data[j] ;
03057 }
03058
03059 Matrix_DOUBLE dP ;
03060
03061 dP = A*dD ;
03062
03063 for(i=0;i<map.n();++i){
03064 P(map[i].i,map[i].j).x() += dP(i,0)*P(map[i].i,map[i].j).w() ;
03065 P(map[i].i,map[i].j).y() += dP(i,1)*P(map[i].i,map[i].j).w() ;
03066 P(map[i].i,map[i].j).z() += dP(i,2)*P(map[i].i,map[i].j).w() ;
03067 }
03068
03069 return 1 ;
03070 }
03071
03072
03084 template <class T, int N>
03085 void projectToLine(const Point_nD<T,N>& S, const Point_nD<T,N>& Trj, const Point_nD<T,N>& pnt, Point_nD<T,N>& p) {
03086
03087 Point_nD<T,N> a = pnt-S ;
03088
03089 T fraction, denom ;
03090 denom = norm2(Trj) ;
03091 fraction = (denom == 0.0) ? 0.0 : (Trj*a) / denom ;
03092 p = fraction * Trj ;
03093 p += S ;
03094 }
03095
03117 template <class T, int N>
03118 void NurbsSurface<T,N>::makeFromRevolution(const NurbsCurve<T,N>& profile, const Point_nD<T,N>& S, const Point_nD<T,N>& Tvec, double theta){
03119 double angle,dtheta ;
03120 int narcs ;
03121 int i,j ;
03122
03123
03124
03125
03126 if(theta>2.0*M_PI)
03127 theta = 2.0*M_PI ;
03128
03129 if(theta <= 0)
03130 theta = 0 ;
03131
03132 if(theta<M_PI/2.0)
03133 narcs = 1 ;
03134 else{
03135 if(theta<M_PI)
03136 narcs = 2 ;
03137 else{
03138 if(theta<1.5*M_PI)
03139 narcs = 3 ;
03140 else
03141 narcs = 4 ;
03142 }
03143 }
03144 dtheta = theta/(double)narcs ;
03145
03146 int n = 2*narcs+1 ;
03147 resize(n,profile.ctrlPnts().n(),2,profile.degree()) ;
03148
03149 switch(narcs){
03150 case 1: break ;
03151 case 2:
03152 U[3] = U[4] = 0.5 ;
03153 break ;
03154 case 3:
03155 U[3] = U[4] = 1.0/3.0 ;
03156 U[5] = U[6] = 2.0/3.0 ;
03157 break ;
03158 case 4:
03159 U[3] = U[4] = 0.25 ;
03160 U[5] = U[6] = 0.50 ;
03161 U[7] = U[8] = 0.75 ;
03162 break ;
03163 }
03164
03165 j = 3 + 2*(narcs-1) ;
03166 for(i=0;i<3;++j,++i){
03167 U[i] = 0.0 ;
03168 U[j] = 1.0 ;
03169 }
03170
03171 V = profile.knot() ;
03172
03173 double wm = cos(dtheta/2.0) ;
03174
03175 Vector_DOUBLE cosines(narcs+1),sines(narcs+1) ;
03176 angle = 0 ;
03177 for(i=1;i<=narcs;++i){
03178 angle = dtheta*(double)i ;
03179 cosines[i] = cos(angle) ;
03180 sines[i] = sin(angle) ;
03181 }
03182
03183 Point_nD<T,N> P0,T0,P2,T2,P1 ;
03184
03185 for(j=0;j<P.cols();++j){
03186 Point_nD<T,N> O ;
03187 T wj = profile.ctrlPnts(j).w() ;
03188
03189 projectToLine(S,Tvec,project(profile.ctrlPnts(j)),O) ;
03190
03191 Point_nD<T,N> X,Y ;
03192 X = project(profile.ctrlPnts(j))-O ;
03193
03194
03195 double r = norm(X) ;
03196
03197 if(r < 1e-7){
03198 for(i=0;i<P.rows();++i){
03199 P(i,j) = O ;
03200 P(i,j) *= wj ;
03201 }
03202 continue ;
03203 }
03204
03205 T b1 = X.norm2() ;
03206 T b2 = X.norm() ;
03207 T b3 = sqrt(b1) ;
03208 T b4 = norm(X) ;
03209
03210 X = X.unitLength() ;
03211 Y = crossProduct(Tvec,X) ;
03212 Y = Y.unitLength() ;
03213
03214 P0 = project(profile.ctrlPnts(j)) ;
03215
03216 P(0,j) = profile.ctrlPnts(j) ;
03217
03218 T0 = Y ;
03219 int index = 0 ;
03220
03221 for(i=1;i<=narcs;++i){
03222 angle = dtheta*(double)i ;
03223 P2 = O+ r*cosines[i]*X + r*sines[i]*Y ;
03224
03225 P(index+2,j) = P2 ;
03226 P(index+2,j) *= wj ;
03227 T2 = -sines[i]*X + cosines[i]*Y ;
03228
03229 intersectLine(P0,T0,P2,T2,P1) ;
03230 P(index+1,j) = P1 ;
03231 P(index+1,j) *= wm*wj ;
03232 index += 2 ;
03233 P0 = P2 ;
03234 T0 = T2 ;
03235 }
03236 }
03237 }
03238
03256 template <class T, int N>
03257 void NurbsSurface<T,N>::makeFromRevolution(const NurbsCurve<T,N>& profile, const Point_nD<T,N>& S, const Point_nD<T,N>& Tvec){
03258 double angle,dtheta ;
03259 int narcs ;
03260 int i,j ;
03261
03262 int n = 9 ;
03263 resize(n,profile.ctrlPnts().n(),2,profile.degree()) ;
03264
03265 U[0] = U[1] = U[2] = 0 ;
03266 U[3] = U[4] = 0.25 ;
03267 U[5] = U[6] = 0.50 ;
03268 U[7] = U[8] = 0.75 ;
03269 U[9] = U[10] = U[11] = 1 ;
03270
03271 V = profile.knot() ;
03272
03273
03274 const T wm = T(0.707106781185) ;
03275
03276 for(j=0;j<P.cols();++j){
03277 Point_nD<T,N> O ;
03278 T wj = profile.ctrlPnts(j).w() ;
03279
03280 projectToLine(S,Tvec,project(profile.ctrlPnts(j)),O) ;
03281
03282 Point_nD<T,N> X,Y ;
03283 X = project(profile.ctrlPnts(j))-O ;
03284
03285
03286 double r = norm(X) ;
03287
03288 if(r < 1e-7){
03289 for(i=0;i<P.rows();++i){
03290 P(i,j) = O ;
03291 P(i,j) *= wj ;
03292 }
03293 continue ;
03294 }
03295
03296 X = X.unitLength() ;
03297 Y = crossProduct(Tvec,X) ;
03298 Y = Y.unitLength() ;
03299
03300 P(0,j) = O + r*X ;
03301 P(1,j) = O + r*X + r*Y ;
03302 P(2,j) = O + r*Y ;
03303 P(3,j) = O - r*X + r*Y ;
03304 P(4,j) = O - r*X ;
03305 P(5,j) = O - r*X - r*Y ;
03306 P(6,j) = O - r*Y ;
03307 P(7,j) = O + r*X - r*Y ;
03308 P(8,j) = P(0,j) ;
03309 P(0,j) *= wj ;
03310 P(1,j) *= wj*wm ;
03311 P(2,j) *= wj ;
03312 P(3,j) *= wj*wm ;
03313 P(4,j) *= wj ;
03314 P(5,j) *= wj*wm ;
03315 P(6,j) *= wj ;
03316 P(7,j) *= wj*wm ;
03317 P(8,j) *= wj ;
03318 }
03319 }
03320
03331 template <class T, int N>
03332 void NurbsSurface<T,N>::makeFromRevolution(const NurbsCurve<T,N>& profile){
03333 int j ;
03334 int n = 9 ;
03335 resize(n,profile.ctrlPnts().n(),2,profile.degree()) ;
03336
03337 U[0] = U[1] = U[2] = 0 ;
03338 U[3] = U[4] = 0.25 ;
03339 U[5] = U[6] = 0.50 ;
03340 U[7] = U[8] = 0.75 ;
03341 U[9] = U[10] = U[11] = 1 ;
03342
03343 V = profile.knot() ;
03344
03345
03346 const T wm = T(0.707106781185) ;
03347
03348 for(j=0;j<P.cols();++j){
03349 T wj = profile.ctrlPnts(j).w() ;
03350
03351 Point_nD<T,N> p = project(profile.ctrlPnts(j)) ;
03352 T r = T(sqrt(p.x()*p.x()+p.y()*p.y()));
03353
03354 T wjm = wj*wm ;
03355 T rwjm = r*wj*wm ;
03356 T rwj = r*wj ;
03357 p.z() *= wj ;
03358
03359 P(0,j) = HPoint_nD<T,N>(rwj,0,p.z(),wj) ;
03360 P(1,j) = HPoint_nD<T,N>(rwjm,rwjm,p.z()*wm,wjm) ;
03361 P(2,j) = HPoint_nD<T,N>(0,rwj,p.z(),wj) ;
03362 P(3,j) = HPoint_nD<T,N>(-rwjm,rwjm,p.z()*wm,wjm) ;
03363 P(4,j) = HPoint_nD<T,N>(-rwj,0,p.z(),wj) ;
03364 P(5,j) = HPoint_nD<T,N>(-rwjm,-rwjm,p.z()*wm,wjm) ;
03365 P(6,j) = HPoint_nD<T,N>(0,-rwj,p.z(),wj) ;
03366 P(7,j) = HPoint_nD<T,N>(rwjm,-rwjm,p.z()*wm,wjm) ;
03367 P(8,j) = HPoint_nD<T,N>(rwj,0,p.z(),wj) ;
03368 }
03369 }
03370
03385 template <class T, int D>
03386 void NurbsSurface<T,D>::isoCurveU(T u, NurbsCurve<T,D>& c) const {
03387 c.resize(P.cols(),degV) ;
03388
03389 c.modKnot(V) ;
03390
03391 if(u>U[U.n()-1])
03392 u = U[U.n()-1] ;
03393 if(u<U[0])
03394 u = U[0] ;
03395
03396
03397
03398 int span = findSpanU(u) ;
03399
03400 Vector<T> N ;
03401 basisFunsU(u,span,N) ;
03402
03403 HPoint_nD<T,D> p ;
03404 for(int i=0;i<P.cols();++i){
03405 p = 0 ;
03406 for(int j=0;j<=degU;++j)
03407 p += N[j]*P(span-degU+j,i) ;
03408 c.modCP(i,p) ;
03409 }
03410
03411 }
03412
03427 template <class T, int D>
03428 void NurbsSurface<T,D>::isoCurveV(T v, NurbsCurve<T,D>& c) const {
03429 c.resize(P.rows(),degU) ;
03430
03431 c.modKnot(U) ;
03432
03433 if(v>V[V.n()-1])
03434 v = V[V.n()-1] ;
03435 if(v<V[0])
03436 v = V[0] ;
03437
03438 int span = findSpanV(v) ;
03439
03440 Vector<T> N ;
03441 basisFunsV(v,span,N) ;
03442
03443 HPoint_nD<T,D> p ;
03444 for(int i=0;i<P.rows();++i){
03445 p = 0 ;
03446 for(int j=0;j<=degV;++j)
03447 p += N[j]*P(i,span-degV+j) ;
03448 c.modCP(i,p) ;
03449 }
03450 }
03451
03464 template <class T, int N>
03465 int NurbsSurface<T,N>::decompose(NurbsSurfaceArray<T,N>& S) const {
03466 int i,m,a,b,nb,mult,j,r,save,s,k,row,col ;
03467 T numer,alpha ;
03468
03469
03470
03471 T* alphas = (T*) alloca((maximum(degU,degV)+1)*sizeof(T)) ;
03472
03473
03474 Vector<T> nU ;
03475 nU.resize(2*(degU+1)) ;
03476 for(i=0;i<nU.n()/2;++i)
03477 nU[i] = 0 ;
03478 for(i=nU.n()/2;i<nU.n();++i)
03479 nU[i] = 1 ;
03480
03481 Vector<T> nV ;
03482 nV.resize(2*(degV+1)) ;
03483 for(i=0;i<nV.n()/2;++i)
03484 nV[i] = 0 ;
03485 for(i=nV.n()/2;i<nV.n();++i)
03486 nV[i] = 1 ;
03487
03488 NurbsSurfaceArray<T,N> Su ;
03489 Su.resize(P.rows()-degU) ;
03490 for(i=0;i<Su.n();i++){
03491 Su[i].resize(degU+1,P.cols(),degU,degV) ;
03492 Su[i].U = nU ;
03493 Su[i].V = V ;
03494 }
03495
03496 m = P.rows()+degU ;
03497 a = degU ;
03498 b = degU+1 ;
03499 nb = 0 ;
03500
03501 for(i=0;i<=degU;i++)
03502 for(col=0;col<P.cols();col++)
03503 Su[nb].P(i,col) = P(i,col) ;
03504 while(b<m){
03505 i = b ;
03506 while(b<m && U[b+1] <= U[b]) b++ ;
03507 mult = b-i+1 ;
03508 if(mult<degU){
03509 numer = U[b]-U[a] ;
03510 for(j=degU;j>mult;j--)
03511 alphas[j-mult-1] = numer/(U[a+j]-U[a]) ;
03512 r = degU-mult ;
03513 for(j=1;j<=r;j++){
03514 save=r-j;
03515 s=mult+j;
03516 for(k=degU;k>=s;k--){
03517 alpha = alphas[k-s] ;
03518 for(col=0;col<P.cols();++col)
03519 Su[nb].P(k,col) = alpha*Su[nb].P(k,col)+(1.0-alpha)*Su[nb].P(k-1,col);
03520 }
03521 if(b<m)
03522 for(col=0;col<P.cols();++col)
03523 Su[nb+1].P(save,col) = Su[nb].P(degU,col) ;
03524 }
03525 }
03526 ++nb ;
03527 if(b<m){
03528 for(i=degU-mult; i<= degU ; ++i)
03529 for(col=0;col<P.cols();++col)
03530 Su[nb].P(i,col) = P(b-degU+i,col) ;
03531 a=b ;
03532 ++b ;
03533 }
03534 }
03535 Su.resize(nb) ;
03536
03537 S.resize(Su.n()*(P.cols()-degV)) ;
03538
03539 for(i=0;i<S.n();i++){
03540 S[i].resize(degU+1,degV+1,degU,degV) ;
03541 S[i].U = nU ;
03542 S[i].V = nV ;
03543 }
03544
03545 nb = 0 ;
03546
03547 for(int np=0;np<Su.n();++np){
03548 for(i=0;i<=degU;i++)
03549 for(j=0;j<=degV;++j)
03550 S[nb].P(i,j) = Su[np].P(i,j) ;
03551 m = P.cols()+degV ;
03552 a = degV ;
03553 b = degV+1 ;
03554 while(b<m){
03555 i = b ;
03556 while(b<m && V[b+1] <= V[b]) b++ ;
03557 mult = b-i+1 ;
03558 if(mult<degV){
03559 numer = V[b]-V[a] ;
03560 for(j=degV;j>mult;j--)
03561 alphas[j-mult-1] = numer/(V[a+j]-V[a]) ;
03562 r = degV-mult ;
03563 for(j=1;j<=r;j++){
03564 save=r-j;
03565 s=mult+j;
03566 for(k=degV;k>=s;k--){
03567 alpha = alphas[k-s] ;
03568 for(row=0;row<=degU;++row)
03569 S[nb].P(row,k) = alpha*S[nb].P(row,k)+(1.0-alpha)*S[nb].P(row,k-1);
03570 }
03571 if(b<m)
03572 for(row=0;row<=degU;++row)
03573 S[nb+1].P(row,save) = S[nb].P(row,degV) ;
03574 }
03575 }
03576 ++nb ;
03577 if(b<m){
03578 for(i=degV-mult; i<= degV ; ++i)
03579 for(row=0;row<=degU;++row)
03580 S[nb].P(row,i) = Su[np].P(row,b-degV+i) ;
03581 a=b ;
03582 ++b ;
03583 }
03584 }
03585 }
03586
03587 S.resize(nb) ;
03588
03589 return Su.n() ;
03590 }
03591
03617 template <class T, int N>
03618 int NurbsSurface<T,N>::writePOVRAY(ostream& povray, int patch_type, double flatness, int num_u_steps, int num_v_steps) const {
03619 if(degU>3 || degV>3){
03620 #ifdef USE_EXCEPTION
03621 throw NurbsInputError();
03622 #else
03623 Error err("NurbsSurface<T,N> writePOVRAY") ;
03624 err << "The degree of the surface is higher than 3!\n"
03625 << "A povrary file can not be generated.\n" ;
03626 err.warning() ;
03627 return 0;
03628 #endif
03629 }
03630
03631 NurbsSurface<T,N> S(*this) ;
03632
03633 S.degreeElevate(3-degU,3-degV) ;
03634
03635 NurbsSurfaceArray<T,N> Sa ;
03636 S.decompose(Sa) ;
03637 int bad = 0 ;
03638
03639 povray << "//\n//Generated for POV-Ray(tm) 3.0 by Phil's NURBS library\n" ;
03640 povray << "// http://yukon.genie.uottawa.ca/info/soft/nurbs\n//\n" ;
03641
03642 for(int i=0;i<Sa.n();++i){
03643 povray << "bicubic_patch {\n\ttype " << patch_type << endl ;
03644 povray << "\tflatness " << flatness << endl ;
03645 povray << "\tu_steps " << num_u_steps << endl ;
03646 povray << "\tv_steps " << num_v_steps << endl ;
03647 for(int j=0;j<4;++j){
03648 for(int k=0;k<4;++k){
03649 Point_nD<T,N> p = project(Sa[i].ctrlPnts(j,k)) ;
03650 if(Sa[i].ctrlPnts(j,k).w()>1.0001 || Sa[i].ctrlPnts(j,k).w()<0.9999)
03651 bad = 1 ;
03652 povray << "\t<" << p.x() << ", " << p.y() << ", " << p.z() << ">" ;
03653 if(j==3 && k==3)
03654 povray << "\n}\n\n" ;
03655 else
03656 povray << ",\n " ;
03657 }
03658 povray << endl ;
03659 }
03660 }
03661 if(bad){
03662 #ifdef USE_EXCEPTION
03663 throw NurbsWarning();
03664 #else
03665 Error err("NurbsSurface<T,N> writePOVRAY") ;
03666 err << "Warning: at least one of the control point was not rational\n" ;
03667 err << "The resulting surface will NOT be the same as the one which\n" ;
03668 err << "generated it.\n" ;
03669 err.warning() ;
03670 #endif
03671 }
03672 return bad ;
03673 }
03674
03675
03697 template <class T, int N>
03698 int NurbsSurface<T,N>::writePOVRAY(T tolerance, ostream& povray,const Color& color, int smooth, T ambient, T diffuse) const {
03699 BasicList<Point_nD<T,N> > points ;
03700 BasicList<int> connect ;
03701 BasicList<Point_nD<T,N> > norm ;
03702
03703 if(smooth)
03704 tesselate(tolerance,points,connect,&norm) ;
03705 else
03706 tesselate(tolerance,points,connect) ;
03707
03708 povray << "mesh {\n" ;
03709
03710 BasicNode<int> *node ;
03711
03712 BasicNode<Point_nD<T,N> > *nodeP ;
03713 BasicNode<Point_nD<T,N> > *nodeN ;
03714 nodeP = points.goToFirst() ;
03715 nodeN = 0 ;
03716
03717 if(smooth)
03718 nodeN = norm.goToFirst() ;
03719
03720 Vector< Point_nD<T,N> > Pts(points.size()) ;
03721 Vector< Point_nD<T,N> > Norm(norm.size()) ;
03722 for(int i=0;i<Pts.n();++i){
03723 Pts[i] = *nodeP->data ;
03724 nodeP = points.goToNext() ;
03725 if(smooth){
03726 Norm[i] = *nodeN->data ;
03727 nodeN = norm.goToNext() ;
03728 }
03729 }
03730
03731 node = connect.goToFirst() ;
03732 while(node){
03733 if(smooth)
03734 povray << "\tsmooth_triangle { " ;
03735 else
03736 povray << "\ttriangle { " ;
03737 povray << "< " << Pts[*node->data].x() << ", " << Pts[*node->data].y() << ", " << Pts[*node->data].z() << "> , " ;
03738 if(smooth)
03739 povray << "< " << Norm[*node->data].x() << ", " << Norm[*node->data].y() << ", " << Norm[*node->data].z() << "> , " ;
03740 node = connect.goToNext() ;
03741 povray << "< " << Pts[*node->data].x() << ", " << Pts[*node->data].y() << ", " << Pts[*node->data].z() << "> , " ;
03742 if(smooth)
03743 povray << "< " << Norm[*node->data].x() << ", " << Norm[*node->data].y() << ", " << Norm[*node->data].z() << "> , " ;
03744 node = connect.goToNext() ;
03745 povray << "< " << Pts[*node->data].x() << ", " << Pts[*node->data].y() << ", " << Pts[*node->data].z() << "> " ;
03746 if(smooth)
03747 povray << ", < " << Norm[*node->data].x() << ", " << Norm[*node->data].y() << ", " << Norm[*node->data].z() << "> " ;
03748 node = connect.goToNext() ;
03749 node = connect.goToNext() ;
03750 povray << "}\n" ;
03751 }
03752
03753 povray << "\ttexture{ pigment { rgb < " << (double)color.r/255.0 << ", " << (double)color.g/255.0 << ", " << (double)color.b/255.0 << " >}\n" ;
03754 povray << "\t\tfinish { ambient " << ambient << " diffuse " << diffuse << " }\n\t}\n" ;
03755
03756 povray << "}\n\n" ;
03757 return povray.good() ;
03758 }
03759
03782 template <class T, int N>
03783 int NurbsSurface<T,N>::writePOVRAY(const char *filename, const Color& col, const Point_nD<T,N>& cView, const Point_nD<T,N>& up, int patch_type, double flatness, int num_u_steps, int num_v_steps) const {
03784 ofstream fout(filename) ;
03785 if(!fout)
03786 return 0 ;
03787
03788 Point_nD<T,N> view(T(-1.0)*cView) ;
03789
03790 fout << "//\n//Generated for POV-Ray(tm) 3.0 by Phil's NURBS library\n//\n" ;
03791 fout << "\n#include \"colors.inc\"\n" ;
03792
03793
03794
03795
03796
03797 Point_nD<T,N> minP, maxP ;
03798 minP.x() = extremum(1,coordX) ;
03799 minP.y() = extremum(1,coordY) ;
03800 minP.z() = extremum(1,coordZ) ;
03801 maxP.x() = extremum(0,coordX) ;
03802 maxP.y() = extremum(0,coordY) ;
03803 maxP.z() = extremum(0,coordZ) ;
03804
03805 Point_nD<T,N> lookAt ;
03806 lookAt.x() = (minP.x()+maxP.x())/2.0 ;
03807 lookAt.y() = (minP.y()+maxP.y())/2.0 ;
03808 lookAt.z() = (minP.z()+maxP.z())/2.0 ;
03809
03810 Point_nD<T,N> camera1, camera2 ;
03811
03812 Point_nD<T,N> q1 = minP-lookAt ;
03813 Point_nD<T,N> q2 = maxP-lookAt ;
03814 T D1 = absolute(dot(q1,view))/norm(view) ;
03815 T D2 = absolute(dot(q2,view))/norm(view) ;
03816
03817 T a1 = norm(q1)*cos(angle(view,q1)) ;
03818 T a2 = norm(q2)*cos(angle(view,q2)) ;
03819
03820 T b1 = D1/tan(18.0*M_PI/180.0) ;
03821 T b2 = D2/tan(18.0*M_PI/180.0) ;
03822
03823 camera1 = lookAt+(a1+b1)*view.unitLength() ;
03824 camera2 = lookAt+(a2+b2)*view.unitLength() ;
03825
03826 Point_nD<T,N> right ;
03827
03828 right = crossProduct(view,up) ;
03829
03830 fout << "camera {\n\tlocation <" ;
03831 if(norm2(camera1-lookAt)>norm2(camera2-lookAt))
03832 fout << camera1.x() << ", " << camera1.y() << ", " << camera1.z() << ">\n" ;
03833 else
03834 fout << camera2.x() << ", " << camera2.y() << ", " << camera2.z() << ">\n" ;
03835 fout << "\tup < " << up.x() << ", " << up.y() << ", " << up.z() << ">\n" ;
03836 fout << "\tright < " << right.x() << ", " << right.y() << ", " << right.z() << ">\n" ;
03837 fout << "\tlook_at < " << lookAt.x() << ", " << lookAt.y() << ", " << lookAt.z() << ">\n\tangle 36\n}\n\n" ;
03838
03839 fout << "union {\n" ;
03840 writePOVRAY(fout,patch_type,flatness,num_u_steps,num_v_steps) ;
03841 fout << " texture {\n\tpigment {\n\t\tcolor rgb < " << (double)col.r/255.0 <<
03842 ", " << (double)col.g/255.0 << ", " << (double)col.b/255.0 << "> \n" <<
03843 "\t}\n\tfinish { \n\t\tambient .2\n\t\tdiffuse .6\n\t}\n }\n" ;
03844 fout << "\n}\n" ;
03845
03846 fout << "light_source { < " ;
03847 if(norm2(camera1-lookAt)>norm2(camera2-lookAt))
03848 fout << camera1.x()+view.x() << ", " << camera1.y()+view.y() << ", " << camera1.z()+view.z() << "> color White}\n\n" ;
03849 else
03850 fout << camera2.x()+view.x() << ", " << camera2.y()+view.y() << ", " << camera2.z()+view.z() << "> color White}\n\n" ;
03851
03852 return fout.good() ;
03853 }
03854
03855
03880 template <class T, int N>
03881 int NurbsSurface<T,N>::writePOVRAY(T tolerance, const char *filename, const Color& col, const Point_nD<T,N>& cView, const Point_nD<T,N>& up, int smooth, T ambient, T diffuse) const {
03882 ofstream fout(filename) ;
03883 if(!fout)
03884 return 0 ;
03885
03886 Point_nD<T,N> view(T(-1)*cView) ;
03887
03888 fout << "//\n//Generated for POV-Ray(tm) 3.0 by Phil's NURBS library\n//\n" ;
03889 fout << "\n#include \"colors.inc\"\n" ;
03890
03891
03892
03893
03894
03895 Point_nD<T,N> minP, maxP ;
03896 minP.x() = extremum(1,coordX) ;
03897 minP.y() = extremum(1,coordY) ;
03898 minP.z() = extremum(1,coordZ) ;
03899 maxP.x() = extremum(0,coordX) ;
03900 maxP.y() = extremum(0,coordY) ;
03901 maxP.z() = extremum(0,coordZ) ;
03902
03903 Point_nD<T,N> lookAt ;
03904 lookAt.x() = (minP.x()+maxP.x())/2.0 ;
03905 lookAt.y() = (minP.y()+maxP.y())/2.0 ;
03906 lookAt.z() = (minP.z()+maxP.z())/2.0 ;
03907
03908 Point_nD<T,N> camera1, camera2 ;
03909
03910 Point_nD<T,N> q1 = minP-lookAt ;
03911 Point_nD<T,N> q2 = maxP-lookAt ;
03912 T D1 = absolute(dot(q1,view))/norm(view) ;
03913 T D2 = absolute(dot(q2,view))/norm(view) ;
03914
03915 T a1 = norm(q1)*cos(angle(view,q1)) ;
03916 T a2 = norm(q2)*cos(angle(view,q2)) ;
03917
03918 T b1 = D1/tan(18.0*M_PI/180.0) ;
03919 T b2 = D2/tan(18.0*M_PI/180.0) ;
03920
03921 camera1 = lookAt+(a1+b1)*view.unitLength() ;
03922 camera2 = lookAt+(a2+b2)*view.unitLength() ;
03923
03924 Point_nD<T,N> right ;
03925
03926 right = crossProduct(view,up) ;
03927
03928 fout << "camera {\n\tlocation <" ;
03929 if(norm2(camera1-lookAt)>norm2(camera2-lookAt))
03930 fout << camera1.x() << ", " << camera1.y() << ", " << camera1.z() << ">\n" ;
03931 else
03932 fout << camera2.x() << ", " << camera2.y() << ", " << camera2.z() << ">\n" ;
03933 fout << "\tup < " << up.x() << ", " << up.y() << ", " << up.z() << ">\n" ;
03934 fout << "\tright < " << right.x() << ", " << right.y() << ", " << right.z() << ">\n" ;
03935 fout << "\tlook_at < " << lookAt.x() << ", " << lookAt.y() << ", " << lookAt.z() << ">\n\tangle 36\n}\n\n" ;
03936
03937 writePOVRAY(tolerance,fout,col,smooth,ambient,diffuse) ;
03938
03939
03940 fout << "light_source { < " ;
03941 if(norm2(camera1-lookAt)>norm2(camera2-lookAt))
03942 fout << camera1.x()+view.x() << ", " << camera1.y()+view.y() << ", " << camera1.z()+view.z() << "> color White}\n\n" ;
03943 else
03944 fout << camera2.x()+view.x() << ", " << camera2.y()+view.y() << ", " << camera2.z()+view.z() << "> color White}\n\n" ;
03945
03946 return fout.good() ;
03947 }
03948
03949
03950
03951
03971 template <class T, int N>
03972 int NurbsSurface<T,N>::writeRIB(ostream& rib) const {
03973 rib << "NuPatch " << P.rows() << ' ' << degU+1 << " [ " ;
03974 int k;
03975
03976
03977 for(k=0;k<U.n();++k)
03978 rib << U[k] << ' ' ;
03979 rib << " ] " << U[0] << ' ' << U[U.n()-1] << ' ' << P.cols() << ' ' << degV+1 << " [ " ;
03980 for(k=0;k<V.n();++k)
03981 rib << V[k] << ' ' ;
03982 rib << " ] " << V[0] << ' ' << V[V.n()-1] << " \"Pw\" [ " ;
03983 for(int j=0;j<P.cols();++j)
03984 for(int i=0;i<P.rows();++i)
03985 rib << P(i,j) ;
03986 rib << " ]\n" ;
03987 return rib.good() ;
03988 }
03989
04012 template <class T, int N>
04013 int NurbsSurface<T,N>::writeRIB(const char* filename, const Color& col, const Point_nD<T,N>& view) const {
04014 ofstream fout(filename) ;
04015 if(!fout)
04016 return 0;
04017
04018
04019
04020 int i,j ;
04021
04022
04023 MatrixRT<double> Rx ;
04024 double xzlen, yzlen, yrot, xrot;
04025
04026
04027
04028
04029
04030 xzlen = sqrt(view.x()*view.x()+view.z()*view.z()) ;
04031 if(xzlen == 0)
04032 yrot = (view.y() < 0) ? M_PI : 0;
04033 else
04034 yrot = acos(view.y()/xzlen);
04035
04036
04037
04038
04039
04040
04041 yzlen = sqrt(view.y()*view.y()+xzlen*xzlen);
04042 xrot = acos(xzlen/yzlen);
04043
04044
04045 if (view.y() > 0){
04046 if(view.x()>0)
04047 Rx.rotate(xrot,yrot,0.0) ;
04048 else
04049 Rx.rotate(xrot,-yrot,0.0) ;
04050 }
04051 else{
04052 if(view.x()>0)
04053 Rx.rotate(-xrot,yrot,0.0) ;
04054 else
04055 Rx.rotate(-xrot,-yrot,0.0) ;
04056 }
04057
04058 Point_nD<T,N> minP, maxP ;
04059 minP.x() = extremum(1,coordX) ;
04060 minP.y() = extremum(1,coordY) ;
04061 minP.z() = extremum(1,coordZ) ;
04062 maxP.x() = extremum(0,coordX) ;
04063 maxP.y() = extremum(0,coordY) ;
04064 maxP.z() = extremum(0,coordZ) ;
04065
04066 Point_nD<T,N> lookAt ;
04067 lookAt.x() = (minP.x()+maxP.x())/2.0 ;
04068 lookAt.y() = (minP.y()+maxP.y())/2.0 ;
04069 lookAt.z() = (minP.z()+maxP.z())/2.0 ;
04070
04071 Point_nD<T,N> camera1, camera2 ;
04072
04073 Point_nD<T,N> q1 = minP-lookAt ;
04074 Point_nD<T,N> q2 = maxP-lookAt ;
04075 T D1 = absolute(dot(q1,view))/norm(view) ;
04076 T D2 = absolute(dot(q2,view))/norm(view) ;
04077
04078 T a1 = norm(q1)*cos(angle(view,q1)) ;
04079 T a2 = norm(q2)*cos(angle(view,q2)) ;
04080
04081 T b1 = D1/tan(18.0*M_PI/180.0) ;
04082 T b2 = D2/tan(18.0*M_PI/180.0) ;
04083
04084 camera1 = lookAt+(a1+b1)*view.unitLength() ;
04085 camera2 = lookAt+(a2+b2)*view.unitLength() ;
04086
04087 Point_nD<T,N> camera ;
04088
04089 if(norm(camera1-lookAt)>norm(camera2-lookAt))
04090 camera = camera1 ;
04091 else
04092 camera = camera2 ;
04093
04094 char front[1024] ;
04095
04096 char *ext ;
04097 ext = strstr(filename,".rib") ;
04098 if(ext){
04099 for(i=0;i<1024;++i){
04100 if(&filename[i] == ext)
04101 break ;
04102 else
04103 front[i] = filename[i] ;
04104 if(!front[i])
04105 break ;
04106 }
04107 }
04108 else{
04109 strcpy(front,filename) ;
04110 }
04111
04112
04113 fout << "##RenderMan RIB-Structure 1.0\n" ;
04114 fout << "#" << filename << endl;
04115 fout << "Format 400 400 1\n";
04116 fout << "Display \"" << front << ".tif\" \"file\" \"rgba\"\n" ;
04117 fout << "Projection \"perspective\" \"fov\" [36]\n" ;
04118 fout << "Translate 0 0 " << norm(camera-lookAt) << endl ;
04119 fout << "Option \"render\" \"prmanspecular\" [1]\n" ;
04120
04121 fout << "\nWorldBegin\n" ;
04122 fout << "LightSource \"ambientlight\" 0 \"intensity\" [0.3]\n" ;
04123 fout << "LightSource \"distantlight\" 1 \"to\" [ " << view.x() << ' ' << view.y() << ' ' << view.z() << "]\n" ;
04124
04125
04126 fout << "AttributeBegin\nSurface \"plastic\"\n" ;
04127 fout << "Color [ " << (double)col.r/255.0 << ' ' << (double)col.g/255.0 << ' ' << double(col.b)/255.0 << "]\n" ;
04128
04129 fout << "Transform [ " ;
04130
04131 for(j=0;j<4;++j)
04132 for(i=0;i<4;++i)
04133 fout << Rx(i,j) << ' ' ;
04134 fout << "]\n" ;
04135 fout << "Translate " << -lookAt.x() << ' ' << -lookAt.y() << ' ' << -lookAt.z() << endl ;
04136
04137
04138 writeRIB(fout) ;
04139
04140 fout << "AttributeEnd\nWorldEnd\n\n" ;
04141
04142 return fout.good() ;
04143 }
04144
04145
04159 template <class T, int N>
04160 void NurbsSurface<T,N>::tesselate(T tolerance, BasicList<Point_nD<T,N> > &points, BasicList<int> &connect, BasicList<Point_nD<T,N> > *Norm) const {
04161
04162 #ifdef USE_EXCEPTION
04163 throw NurbsError() ;
04164 #else
04165 Error err("NurbsSurface<T,N>::tesselate");
04166 err << "The tesselate member function is deprecated. Please use\n"
04167 "the NurbsSubSurface class member functions instead.\n" ;
04168 err.fatal();
04169 #endif
04170 }
04171
04172
04185 template <class T, int N>
04186 void NurbsSurface<T,N>::makeSphere(const Point_nD<T,N>& O, T r) {
04187 NurbsCurve<T,N> c ;
04188
04189 const T wm = T(0.707106781185) ;
04190
04191 c.resize(5,2) ;
04192
04193 c.modCP(0,HPoint_nD<T,N>(0,0,r,1)) ;
04194 c.modCP(1,HPoint_nD<T,N>(-r*wm,0,r*wm,wm)) ;
04195 c.modCP(2,HPoint_nD<T,N>(-r,0,0,1)) ;
04196 c.modCP(3,HPoint_nD<T,N>(-r*wm,0,-r*wm,wm)) ;
04197 c.modCP(4,HPoint_nD<T,N>(0,0,-r,1)) ;
04198
04199 Vector<T> k(5+2+1) ;
04200 k[0] = k[1] = k[2] = 0 ;
04201 k[3] = k[4] = 0.5 ;
04202 k[5] = k[6] = k[7] = 1 ;
04203
04204 c.modKnot(k) ;
04205
04206 makeFromRevolution(c) ;
04207 MatrixRT<T> Tx ;
04208 Tx.translate(O.x(),O.y(),O.z()) ;
04209 transform(Tx) ;
04210 }
04211
04242 template <class T, int N>
04243 int NurbsSurface<T,N>::writePS(const char* filename, int nu, int nv, const Point_nD<T,N>& camera, const Point_nD<T,N>& lookAt, int cp,T magFact,T dash) const {
04244 NurbsCurveArray<T,N> Ca ;
04245 if(nu<=0 || nv<=0)
04246 return 0 ;
04247
04248
04249
04250 Point_nD<T,N> np = lookAt-camera ;
04251 np = np.unitLength() ;
04252 np *= -1 ;
04253
04254 T rx = atan2(np.z(),np.y()) ;
04255 T ry = atan2(np.z(),np.x()) ;
04256
04257 MatrixRT<T> Tx(rx,ry,0,camera.x(),camera.y(),camera.z()) ;
04258
04259
04260
04261 Ca.resize(nu+nv+2) ;
04262 int i ;
04263 for(i=0;i<=nu;++i){
04264 T u = U[0]+T(i)*(U[U.n()-1]-U[0])/T(nu) ;
04265 isoCurveU(u , Ca[i]) ;
04266 Ca[i].transform(Tx) ;
04267 }
04268 for(;i<=nv+nu+1;++i){
04269 T v = V[0]+T(i-nu-1)*(V[V.n()-1]-V[0])/T(nv) ;
04270 isoCurveV(v , Ca[i]) ;
04271 Ca[i].transform(Tx) ;
04272 }
04273
04274
04275 return Ca.writePS(filename,cp,magFact,dash) ;
04276 }
04277
04317 template <class T, int N>
04318 int NurbsSurface<T,N>::writePSp(const char*, int nu, int nv, const Point_nD<T,N>& camera, const Point_nD<T,N>& lookAt, const Vector< Point_nD<T,N> >&,const Vector< Point_nD<T,N> >&, int cp,T magFact,T dash) const {
04319 cerr << "Not implemented. Not sure what is different between this and writePS\n";
04320 return 0;
04321 }
04322
04331 template <class T, int N>
04332 ostream& NurbsSurface<T,N>::print(ostream& o) const {
04333 o << "Degree: " << degU << ' ' << degV << endl;
04334 o << "U : " << U << endl;
04335 o << "V: " << V << endl ;
04336 o << "matrix size: " << P.rows() << ' ' << P.cols() << endl ;
04337 o << P << endl;
04338 return o;
04339 }
04340
04357 template <class T, int N>
04358 int surfMeshParamsClosedU(const Matrix< Point_nD<T,N> >& Q, Vector<T>& uk, Vector<T>& vl, int degU){
04359
04360 int n,m,k,l,num ;
04361 double d,total ;
04362 Vector<T> cds(Q.rows()) ;
04363
04364 n = Q.rows() ;
04365 m = Q.cols() ;
04366 uk.resize(n) ;
04367 vl.resize(m) ;
04368 num = m ;
04369
04370
04371 uk.reset(0) ;
04372
04373 for(l=0;l<m;l++){
04374 total = 0.0 ;
04375 for(k=1;k<=n-degU;k++){
04376 cds[k] = norm(Q(k,l)-Q(k-1,l)) ;
04377 total += cds[k] ;
04378 }
04379 for(k=n-degU+1; k<n ;k++)
04380 cds[k] = norm(Q(k,l)-Q(k-1,l)) ;
04381
04382 if(total==0.0)
04383 num-- ;
04384 else {
04385 d = 0.0 ;
04386 for(k=1;k<n;k++){
04387 d += cds[k] ;
04388 uk[k] += d/total ;
04389 }
04390 }
04391 }
04392 if(num==0)
04393 return 0 ;
04394 for(k=1;k<n;k++)
04395 uk[k] /= num ;
04396
04397
04398 vl.reset(0) ;
04399 cds.resize(m) ;
04400
04401 num = n ;
04402
04403 for(k=0;k<n;k++){
04404 total = 0.0 ;
04405 for(l=1;l<m;l++){
04406 cds[l] = norm(Q(k,l)-Q(k,l-1)) ;
04407 total += cds[l] ;
04408 }
04409 if(total==0.0)
04410 num-- ;
04411 else {
04412 d = 0.0 ;
04413 for(l=1;l<m;l++){
04414 d += cds[l] ;
04415 vl[l] += d/total ;
04416 }
04417 }
04418 }
04419 if(num==0)
04420 return 0 ;
04421 for(l=1;l<m-1;l++)
04422 vl[l] /= num ;
04423 vl[m-1] = 1.0 ;
04424
04425
04426 return 1 ;
04427 }
04428
04445 template <class T, int N>
04446 int surfMeshParamsClosedUH(const Matrix< HPoint_nD<T,N> >& Q, Vector<T>& uk, Vector<T>& vl, int degU){
04447
04448 int n,m,k,l,num ;
04449 double d,total ;
04450 Vector<T> cds(Q.rows()) ;
04451
04452 n = Q.rows() ;
04453 m = Q.cols() ;
04454 uk.resize(n) ;
04455 vl.resize(m) ;
04456 num = m ;
04457
04458
04459 uk.reset(0) ;
04460
04461 for(l=0;l<m;l++){
04462 total = 0.0 ;
04463
04464 for(k=1;k<=n-degU;k++){
04465 cds[k] = norm(Q(k,l)-Q(k-1,l)) ;
04466 total += cds[k] ;
04467 }
04468 for(k=n-degU+1; k<n ;k++)
04469 cds[k] = norm(Q(k,l)-Q(k-1,l)) ;
04470 if(total==0.0)
04471 num-- ;
04472 else {
04473 d = 0.0 ;
04474 for(k=1;k<n;k++){
04475 d += cds[k] ;
04476 uk[k] += d/total ;
04477 }
04478 }
04479 }
04480 if(num==0)
04481 return 0 ;
04482 for(k=1;k<n;k++)
04483 uk[k] /= num ;
04484
04485
04486 vl.reset(0) ;
04487 cds.resize(m) ;
04488
04489 num = n ;
04490
04491 for(k=0;k<n;k++){
04492 total = 0.0 ;
04493 for(l=1;l<m;l++){
04494 cds[l] = norm(Q(k,l)-Q(k,l-1)) ;
04495 total += cds[l] ;
04496 }
04497 if(total==0.0)
04498 num-- ;
04499 else {
04500 d = 0.0 ;
04501 for(l=1;l<m;l++){
04502 d += cds[l] ;
04503 vl[l] += d/total ;
04504 }
04505 }
04506 }
04507 if(num==0)
04508 return 0 ;
04509 for(l=1;l<m-1;l++)
04510 vl[l] /= num ;
04511 vl[m-1] = 1.0 ;
04512
04513 return 1 ;
04514 }
04515
04516
04533 template <class T, int N>
04534 void NurbsSurface<T,N>::globalInterpClosedU(const Matrix< Point_nD<T,N> >& Q, int pU, int pV){
04535 Vector<T> vk,uk ;
04536
04537 resize(Q.rows(),Q.cols(),pU,pV) ;
04538
04539 surfMeshParamsClosedU(Q,uk,vk,pU) ;
04540 knotAveragingClosed(uk,pU,U) ;
04541 knotAveraging(vk,pV,V) ;
04542
04543
04544 Vector< HPoint_nD<T,N> > Pts(Q.cols()) ;
04545 NurbsCurve<T,N> R ;
04546
04547 int i,j ;
04548 for(i=0;i<Q.rows();i++){
04549 for(j=0;j<Q.cols();j++)
04550 Pts[j] = Q(i,j) ;
04551 R.globalInterpH(Pts,vk,V,pV) ;
04552 for(j=0;j<Q.cols();j++)
04553 P(i,j) = R.ctrlPnts(j) ;
04554 }
04555
04556 Pts.resize(Q.rows()) ;
04557 for(j=0;j<Q.cols();j++){
04558 for(i=0;i<Q.rows();i++)
04559 Pts[i] = P(i,j) ;
04560
04561 R.globalInterpClosedH(Pts,uk,U,pU);
04562 for(i=0;i<Q.rows();i++)
04563 P(i,j) = R.ctrlPnts(i) ;
04564 }
04565
04566 }
04567
04583 template <class T, int N>
04584 void NurbsSurface<T,N>::globalInterpClosedUH(const Matrix< HPoint_nD<T,N> >& Q, int pU, int pV){
04585 Vector<T> vk,uk ;
04586
04587 resize(Q.rows(),Q.cols(),pU,pV) ;
04588
04589 surfMeshParamsClosedUH(Q,uk,vk,pU) ;
04590 knotAveragingClosed(uk,pU,U) ;
04591 knotAveraging(vk,pV,V) ;
04592
04593 Vector< HPoint_nD<T,N> > Pts(Q.rows()) ;
04594 NurbsCurve<T,N> R ;
04595
04596 int i,j ;
04597
04598 for(j=0;j<Q.cols();j++){
04599 for(i=0;i<Q.rows();i++)
04600 Pts[i] = Q(i,j) ;
04601 R.globalInterpH(Pts,uk,U,pU);
04602 for(i=0;i<Q.rows();i++)
04603 P(i,j) = R.ctrlPnts(i) ;
04604 }
04605
04606 Pts.resize(Q.cols()) ;
04607 for(i=0;i<Q.rows();i++){
04608 for(j=0;j<Q.cols();j++)
04609 Pts[j] = P(i,j) ;
04610 R.globalInterpClosedH(Pts,vk,V,pV) ;
04611 for(j=0;j<Q.cols();j++)
04612 P(i,j) = R.ctrlPnts(j) ;
04613 }
04614 }
04615
04616
04635 template <class T, int N>
04636 void NurbsSurface<T,N>::leastSquaresClosedU(const Matrix< Point_nD<T,N> >& Q, int pU, int pV, int nU, int nV){
04637 Vector<T> vk,uk ;
04638
04639 resize(nU+pU,nV,pU,pV) ;
04640
04641 surfMeshParamsClosedU(Q,uk,vk,pU) ;
04642
04643
04644 Vector< HPoint_nD<T,N> > Pts(Q.rows()) ;
04645 NurbsCurve<T,N> R ;
04646
04647 int i,j ;
04648
04649 Matrix< HPoint_nD<T,N> > P2 ;
04650
04651 P2.resize(nU+pU,Q.cols()) ;
04652
04653 for(j=0;j<Q.cols();j++){
04654 for(i=0;i<Q.rows();i++)
04655 Pts[i] = Q(i,j) ;
04656 R.leastSquaresClosedH(Pts,pU,nU,uk);
04657 for(i=0;i<P.rows();i++)
04658 P2(i,j) = R.ctrlPnts(i) ;
04659 if(j==0)
04660 U = R.knot() ;
04661 }
04662
04663 Pts.resize(Q.cols()) ;
04664 for(i=0;i<P.rows();i++){
04665 for(j=0;j<Q.cols();j++)
04666 Pts[j] = P2(i,j) ;
04667 R.leastSquaresH(Pts,pV,nV,vk) ;
04668 for(j=0;j<P.cols();j++)
04669 P(i,j) = R.ctrlPnts(j) ;
04670 if(i==0)
04671 V = R.knot() ;
04672 }
04673
04674 }
04675
04705 template <class T, int N>
04706 int NurbsSurface<T,N>::writeOOGL(const char* filename,
04707 T fDu,
04708 T fDv,
04709 T fBu, T fBv,
04710 T fEu, T fEv,
04711 bool bDrawCP) const {
04712 ofstream fout(filename) ;
04713 if(!fout)
04714 return 0 ;
04715
04716
04717 fout << "{ LIST \n";
04718 fout << "\t{ appearance { shading smooth } \n " ;
04719 fout << "\tNMESH" << endl;
04720 T Nu = (fEu-fBu)/fDu + 1;
04721 T Nv = (fEv-fBv)/fDv + 1;
04722 fout << "\t"<< Nu << ' ' << Nv << endl;
04723
04724
04725 Point_nD<T,N> Sp, Np;
04726 T u,v;
04727 for (u = fBu; u<fEu+fDu/2; u+=fDu)
04728 for (v = fBv; v<fEv+fDv/2; v+=fDv){
04729 Sp = pointAt(u,v);
04730 Np = normal(u,v);
04731 Np = (norm(Np)!=0)?Np.unitLength():Point_nD<T,N>(0.0);
04732 fout << "\t" << Sp << "\t " << Np << endl;
04733 }
04734 fout << "\t}" << endl << std::flush;
04735
04736
04737 if (bDrawCP){
04738 fout << "\t{ " << endl;
04739 fout << "\t appearance {shading smooth linewidth 5 } " << endl;
04740
04741 fout << "\t" << "SKEL" << endl;
04742 fout << P.rows()*P.cols() << ' ' << P.rows()*P.cols() << endl;
04743 for (int i = 0; i<P.rows(); i++)
04744 for (int j = 0; j<P.cols(); j++)
04745 fout << "\t" << project(P(i,j)) << endl;
04746 fout << endl;
04747 for (int i = 0; i<P.rows()*P.cols(); i++)
04748 fout << "\t" << "1 " << i << " 0 0 1 0.5 " << endl;
04749 fout << "\t" << " }" << endl;
04750 }
04751 fout << "} " << endl;
04752 fout << std::flush;
04753
04754 return 1 ;
04755 }
04756
04774 template <class T, int N>
04775 int NurbsSurface<T,N>::writeDisplayQUADMESH(const char* filename, int iNu,int iNv,const Color& color,T fA, T fO) const
04776 {
04777
04778 T fDu = 1/T(iNu);
04779 T fDv = 1/T(iNv-1);
04780
04781 ofstream fout(filename) ;
04782 if(!fout)
04783 return 0 ;
04784
04785
04786 const char QUADMESH='q'+ ('A' - 'a');
04787 fout << QUADMESH << ' '; ;
04788
04789
04790 T a, d, s, se, t;
04791
04792
04793 a = 0.3;
04794
04795 d = 0.3;
04796
04797 s = 0.4;
04798
04799 se = 10;
04800
04801 t = fO;
04802
04803
04804 fout << a << ' '
04805 << d << ' '
04806 << s << ' '
04807 << se << ' '
04808 << t << ' ';
04809
04810
04811 fout << iNu << ' '
04812 << iNv << ' ' ;
04813
04814
04815 fout << "F T ";
04816
04817
04818 fout << endl ;
04819
04820
04821 T fR= T(color.r)/255;
04822 T fG= T(color.g)/255;
04823 T fB= T(color.b)/255;
04824
04825
04826 fout << 0 << ' ' ;
04827
04828 fout << fR << ' '
04829 << fG << ' '
04830 << fB << ' '
04831 << fA << endl;
04832
04833
04834 fout << endl ;
04835
04836
04837 T u,v;
04838 Point_nD<T,N> Sp;
04839 for (v = 0; v<1+fDv/2; v+=fDv)
04840 for (u = 0; u<1-fDu/2; u+=fDu){
04841
04842
04843 Sp = -(T)1.0 * pointAt(u,v) ;
04844 fout << Sp.x() << ' ' << Sp.z() << ' ' << Sp.y() << endl;
04845 }
04846
04847
04848 fout << endl ;
04849
04850
04851 Point_nD<T,N> Np;
04852 for (v = 0; v<1+fDv/2; v+=fDv)
04853 for (u = 0; u<1-fDu/2; u+=fDu){
04854 Np = normal(u,v);
04855 Np = (norm(Np)!=0)?Np.unitLength():Point_nD<T,N>(0.0);
04856 fout << Np.x() << ' ' << Np.z() << ' ' << Np.y() << endl;
04857 }
04858
04859
04860 fout << endl ;
04861
04862
04863 return 1;
04864 }
04865
04880 template <class T, int N>
04881 int NurbsSurface<T,N>::writeOOGL(const char* filename) const {
04882 ofstream fout(filename) ;
04883 if(!fout)
04884 return 0 ;
04885
04886
04887 int iPointDim = 4;
04888 fout << "BEZ" << degU << degV << iPointDim << endl;
04889
04890
04891 NurbsSurfaceArray<T,N> S;
04892 NurbsSurface<T,N> surface(*this);
04893 surface.decompose(S);
04894
04895
04896 for (int iPatch = 0; iPatch < S.n(); iPatch++){
04897 for(int iu = 0; iu < degU + 1; iu++){
04898 for(int iv = 0; iv < degV + 1; iv++)
04899 fout << S[iPatch].ctrlPnts(iu,iv).x() << ' '
04900 << S[iPatch].ctrlPnts(iu,iv).y() << ' '
04901 << S[iPatch].ctrlPnts(iu,iv).z() << ' '
04902 << S[iPatch].ctrlPnts(iu,iv).w() << endl;
04903 }
04904 fout << endl;
04905 }
04906 fout << std::flush;
04907
04908 return 1 ;
04909 }
04910
04911
04926 template <class T, int N>
04927 void wrapPointMatrix(const Matrix< Point_nD<T,N> >& Q, int d, int dir, Matrix< Point_nD<T,N> >& Qw){
04928 int i, row, col;
04929
04930 Qw = Q;
04931
04932 if (dir==0){
04933
04934 Qw.resizeKeep(Q.rows()+d,Q.cols());
04935 for (col=0; col < Q.cols(); col++)
04936 for (i=0; i<d; i++)
04937 Qw(i+Q.rows(),col) = Q(i,col);
04938 }
04939 else{
04940
04941 Qw.resizeKeep(Q.rows(),Q.cols()+d);
04942 for (row=0; row < Q.rows(); row++)
04943 for (i=0; i<d; i++)
04944 Qw(row,i+Q.cols()) = Q(row,i);
04945 }
04946
04947 }
04948
04966 template <class T, int N>
04967 void NurbsSurface<T,N>::dersBasisFuns(T u, T v, int dU, int dV, int uspan, int vspan, Matrix<T> & Niku, Matrix<T> & Njkv ) const {
04968
04969 nurbsDersBasisFuns(dU,u,uspan,degU,U,Niku) ;
04970 nurbsDersBasisFuns(dV,v,vspan,degV,V,Njkv) ;
04971 }
04972
04987 template <class T, int N>
04988 void NurbsSurface<T,N>::makeTorus(const Point_nD<T,N>& O, T R, T r) {
04989
04990 T xvalues[] = { 0.0, -1.0, -1.0, -1.0, 0.0, 1.0, 1.0, 1.0, 0.0 };
04991 T yvalues[] = { 1.0, 1.0, 0.0, -1.0, -1.0, -1.0, 0.0, 1.0, 1.0 };
04992 T zvalues[] = { 0.0, 1.0, 1.0, 1.0, 0.0, -1.0, -1.0, -1.0, 0.0 };
04993 T offsets[] = { -1.0, -1.0, 0.0, 1.0, 1.0, 1.0, 0.0, -1.0, -1.0 };
04994
04995
04996 T knotsMem[] = { 0, 0, 0, 0.25, 0.25, 0.5, 0.5, 0.75, 0.75 , 1, 1, 1 };
04997 Vector<T> knots(knotsMem,12) ;
04998
04999 resize(9,9,2,2);
05000
05001 int i, j;
05002
05003 double r2over2 = sqrt( 2.0 ) / 2.0;
05004 double weight;
05005
05006 for (i = 0; i < 9; i++){
05007 for (j = 0; j < 9; j++) {
05008 HPoint_nD<T,N> hp ;
05009 weight = ((j & 1) ? r2over2 : 1.0) * ((i & 1) ? r2over2 : 1.0);
05010
05011 P(i,j).x() = xvalues[j]* (R + offsets[i] * r) * weight;
05012 P(i,j).y() = yvalues[j]* (R + offsets[i] * r) * weight;
05013 P(i,j).z() = (zvalues[i] * r) * weight;
05014 P(i,j).w() = weight;
05015 }
05016 }
05017
05018
05019
05020
05021 U = knots ;
05022 V = knots ;
05023
05024 MatrixRT<T> Tx ;
05025 Tx.translate(O.x(),O.y(),O.z()) ;
05026 transform(Tx) ;
05027 }
05028
05029
05030 }
05031
05032 #endif // #define PLIB_NURBS_NURBSS_SOURCE