Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

gunu_global_approximate.cpp

Go to the documentation of this file.
00001 /* LIBGUL - Geometry Utility Library
00002  * Copyright (C) 1998-1999 Norbert Irmer
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Library General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Library General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Library General Public
00015  * License along with this library; if not, write to the
00016  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017  * Boston, MA 02111-1307, USA.
00018  */
00019 
00020 #include "stdafx.h"
00021 
00022 #include <iostream>
00023 
00024 #include "gul_types.h"
00025 #include "gunu_parametrize.h"
00026 #include "guma_lineq.h"
00027 #include "gunu_basics.h"
00028 #include "gul_matrix.h"
00029 #include "gul_io.h"
00030 
00031 namespace gunu {
00032 
00033 using gul::Ptr;
00034 using gul::point;
00035 using gul::point1;
00036 using gul::point2;
00037 using guma::BandDecomposition;
00038 using guma::BandBackSubstitution;
00039 using gul::Min;
00040 using gul::Max;
00041 using gul::MMProduct;
00042 using gul::dump_matrix;
00043 using gul::dump_vector;
00044 using guma::LUDecomposition;
00045 using guma::LUBackSubstitution;
00046 using guma::SVDecomposition;
00047 using guma::SVZero;
00048 using guma::SVBackSubstitution;
00049 using gul::ndebug;
00050 using gul::Assert;
00051 using gul::InternalError;
00052 
00053 using std::cout;
00054 
00055 template< class T >
00056 void CASolve( int nQ, const Ptr< point<T> >& Q, const Ptr<T>& Uq,
00057               int n, int p, const Ptr<T>& U, Ptr<int>& M,
00058               Ptr< Ptr< Ptr<T> > >& N, Ptr< Ptr<T> >& A,
00059               Ptr< point<T> >& P )
00060 {
00061   int i,j,k,sign,offset,bw,shift;
00062   Ptr<T> Rx,Ry,Rz;
00063   Ptr< Ptr<T> > L;
00064   Ptr<int> index; 
00065   point<T> r;
00066 
00067   Rx.reserve_pool(n-1);
00068   Ry.reserve_pool(n-1);
00069   Rz.reserve_pool(n-1);
00070   for( i = 0; i < n-1; i++ )
00071   {
00072     Rx[i] = (T)0;
00073     Ry[i] = (T)0;
00074     Rz[i] = (T)0;
00075   }
00076 
00077   // process points in first knotspan
00078 
00079   for( i = 1; i < M[0]; i++ )    
00080   {
00081     r = N[0][0][i] * Q[0];
00082     if( n-p == 0 )               // Q[i] element of first and last knot span 
00083       r = r + N[0][p][i]*Q[nQ-1];   // (then there is only one span)
00084 
00085     for( j = 1; j <= Min(p,n-1); j++ )
00086     {
00087       Rx[j-1] += N[0][j][i] * (Q[i].x - r.x);
00088       Ry[j-1] += N[0][j][i] * (Q[i].y - r.y);
00089       Rz[j-1] += N[0][j][i] * (Q[i].z - r.z);
00090 
00091       /*
00092       cout << "Rx[" << j-1 << "] (first span, Q[" << i << "]): " 
00093            << Rx[j-1] << "\n";
00094       */
00095     }
00096   }
00097 
00098   // process points between firts and last knotspan
00099 
00100   offset = i;
00101   for( k = 1; k < n-p; k++ ) 
00102   {
00103     for( i = 0; i < M[k]; i++ )
00104     {
00105       for( j = 0; j <= p; j++ )
00106       {
00107         Rx[k+j-1] += N[k][j][i] * Q[offset+i].x;
00108         Ry[k+j-1] += N[k][j][i] * Q[offset+i].y;
00109         Rz[k+j-1] += N[k][j][i] * Q[offset+i].z;
00110 
00111         /*
00112         cout << "Rx[" << k+j-1 << "] (Q[" << offset+i << "]): " 
00113              << Rx[k+j-1] << "\n";
00114         */
00115       }
00116     }
00117     offset += M[k];
00118   }   
00119 
00120   // process points in last knotspan
00121 
00122   if( n-p > 0 )  // only when more then one knotspan
00123   {
00124     for( i = 0; i < M[k]-1; i++ )
00125     {
00126       r = N[k][p][i] * Q[nQ-1];
00127 
00128       for( j = 0; j < p; j++ )
00129       {
00130         Rx[k+j-1] += N[k][j][i] * (Q[offset+i].x - r.x);
00131         Ry[k+j-1] += N[k][j][i] * (Q[offset+i].y - r.y);
00132         Rz[k+j-1] += N[k][j][i] * (Q[offset+i].z - r.z);
00133 
00134         /*
00135         cout << "Rx[" << k+j-1 << "] (last span, Q[" << offset+i << "]): " 
00136              << Rx[k+j-1] << "\n";
00137         */
00138       }
00139     }
00140   }
00141   N.reset();  // not needed anymore
00142   M.reset();  // not needed anymore
00143 
00144   /*
00145   cout << "Right side for X (version 2):\n";
00146   cout << dump_vector<T>(n-1,Rx);
00147   cout << "Right side for Y (version 2):\n";
00148   cout << dump_vector<T>(n-1,Ry);
00149   cout << "Right side for Z (version 2):\n";
00150   cout << dump_vector<T>(n-1,Rz);
00151   */
00152 
00153   L.reserve_pool(n-1);
00154   for( i = 0; i < n-1; i++ )
00155     L[i].reserve_pool(p);
00156   index.reserve_pool(n-1);
00157 
00158   if( n-1 < p )  // band width adjustment necessary
00159   {
00160     bw = n-1;
00161     shift = p - bw;
00162 
00163     for( i = 0;  i < n-1; i++ )
00164     {
00165       offset = bw-i;
00166       for( j = 0; j < bw+bw+1-offset; j++ ) 
00167         A[i][offset+j] = A[i][offset+j+shift];
00168     }
00169   } 
00170   else
00171     bw = p;
00172 
00173   /*
00174   cout << "MATRIX A (1):\n";
00175   cout << dump_matrix<T>(n-1,p+p+1,A);
00176   */
00177 
00178   BandDecomposition( n-1, bw, bw, A, L, &sign, index );
00179 
00180   /*
00181   cout << "MATRIX A (1):\n";
00182   cout << dump_matrix<T>(n-1,p+p+1,A);
00183   cout << "MATRIX L (1):\n";
00184   cout << dump_matrix<T>(n-1,p,L);
00185   */
00186 
00187   BandBackSubstitution( n-1, bw, bw, A, L, index, Rx ); 
00188   for( i = 0; i < n-1; i++ ) P[i+1].x = Rx[i];
00189   BandBackSubstitution( n-1, bw, bw, A, L, index, Ry ); 
00190   for( i = 0; i < n-1; i++ ) P[i+1].y = Ry[i];
00191   BandBackSubstitution( n-1, bw, bw, A, L, index, Rz ); 
00192   for( i = 0; i < n-1; i++ ) P[i+1].z = Rz[i];
00193 
00194   P[0] = Q[0];
00195   P[n] = Q[nQ-1];
00196 }
00197 
00198 template< class T >
00199 void CASolve( int nQ, const Ptr< point2<T> >& Q, const Ptr<T>& Uq,
00200               int n, int p, const Ptr<T>& U, Ptr<int>& M,
00201               Ptr< Ptr< Ptr<T> > >& N, Ptr< Ptr<T> >& A,
00202               Ptr< point2<T> >& P )
00203 {
00204   int i,j,k,sign,offset,bw,shift;
00205   Ptr<T> Rx,Ry,Rz;
00206   Ptr< Ptr<T> > L;
00207   Ptr<int> index; 
00208   point2<T> r;
00209 
00210   Rx.reserve_pool(n-1);
00211   Ry.reserve_pool(n-1);
00212   for( i = 0; i < n-1; i++ )
00213   {
00214     Rx[i] = (T)0;
00215     Ry[i] = (T)0;
00216   }
00217   // process points in first knotspan
00218 
00219   for( i = 1; i < M[0]; i++ )    
00220   {
00221     r = N[0][0][i] * Q[0];
00222     if( n-p == 0 )               // Q[i] element of first and last knot span 
00223       r = r + N[0][p][i]*Q[nQ-1];   // (then there is only one span)
00224 
00225     for( j = 1; j <= Min(p,n-1); j++ )
00226     {
00227       Rx[j-1] += N[0][j][i] * (Q[i].x - r.x);
00228       Ry[j-1] += N[0][j][i] * (Q[i].y - r.y);
00229     }
00230   }
00231 
00232   // process points between firts and last knotspan
00233 
00234   offset = i;
00235   for( k = 1; k < n-p; k++ ) 
00236   {
00237     for( i = 0; i < M[k]; i++ )
00238     {
00239       for( j = 0; j <= p; j++ )
00240       {
00241         Rx[k+j-1] += N[k][j][i] * Q[offset+i].x;
00242         Ry[k+j-1] += N[k][j][i] * Q[offset+i].y;
00243       }
00244     }
00245     offset += M[k];
00246   }   
00247 
00248   // process points in last knotspan
00249 
00250   if( n-p > 0 )  // only when more then one knotspan
00251   {
00252     for( i = 0; i < M[k]-1; i++ )
00253     {
00254       r = N[k][p][i] * Q[nQ-1];
00255 
00256       for( j = 0; j < p; j++ )
00257       {
00258         Rx[k+j-1] += N[k][j][i] * (Q[offset+i].x - r.x);
00259         Ry[k+j-1] += N[k][j][i] * (Q[offset+i].y - r.y);
00260       }
00261     }
00262   }
00263   N.reset();  // not needed anymore
00264   M.reset();  // not needed anymore
00265 
00266   L.reserve_pool(n-1);
00267   for( i = 0; i < n-1; i++ )
00268     L[i].reserve_pool(p+p+1);
00269   index.reserve_pool(n-1);
00270 
00271   if( n-1 < p )  // band width adjustment necessary
00272   {
00273     bw = n-1;
00274     shift = p - bw;
00275 
00276     for( i = 0;  i < n-1; i++ )
00277     {
00278       offset = bw-i;
00279       for( j = 0; j < bw+bw+1-offset; j++ ) 
00280         A[i][offset+j] = A[i][offset+j+shift];
00281     }
00282   } 
00283   else
00284     bw = p;
00285 
00286   BandDecomposition( n-1, bw, bw, A, L, &sign, index );
00287 
00288   BandBackSubstitution( n-1, bw, bw, A, L, index, Rx ); 
00289   for( i = 0; i < n-1; i++ ) P[i+1].x = Rx[i];
00290   BandBackSubstitution( n-1, bw, bw, A, L, index, Ry ); 
00291   for( i = 0; i < n-1; i++ ) P[i+1].y = Ry[i];
00292 
00293   P[0] = Q[0];
00294   P[n] = Q[nQ-1];
00295 }
00296 
00297 template< class T >
00298 void CASolveToCol( 
00299                      int nQ, const Ptr< point<T> >& Q, const Ptr<T>& Uq,
00300                      int n, int p, const Ptr<T>& U, const Ptr<int>& M,
00301                      const Ptr< Ptr< Ptr<T> > >& N, Ptr< Ptr<T> >& A,
00302                      Ptr< Ptr<T> >& L, Ptr<int> index,
00303                      int iCol, Ptr< Ptr< point<T> > >& P )
00304 {
00305   int i,j,k,offset;
00306   Ptr<T> Rx,Ry,Rz;
00307   point<T> r;
00308 
00309   Rx.reserve_pool(n-1);
00310   Ry.reserve_pool(n-1);
00311   Rz.reserve_pool(n-1);
00312   for( i = 0; i < n-1; i++ )
00313   {
00314     Rx[i] = (T)0;
00315     Ry[i] = (T)0;
00316     Rz[i] = (T)0;
00317   }
00318 
00319   // process points in first knotspan
00320 
00321   for( i = 1; i < M[0]; i++ )    
00322   {
00323     r = N[0][0][i] * Q[0];
00324     if( n-p == 0 )               // Q[i] element of first and last knot span 
00325       r = r + N[0][p][i]*Q[nQ-1];   // (then there is only one span)
00326 
00327     for( j = 1; j <= Min(p,n-1); j++ )
00328     {
00329       Rx[j-1] += N[0][j][i] * (Q[i].x - r.x);
00330       Ry[j-1] += N[0][j][i] * (Q[i].y - r.y);
00331       Rz[j-1] += N[0][j][i] * (Q[i].z - r.z);
00332     }
00333   }
00334 
00335   // process points between first and last knotspan
00336 
00337   offset = i;
00338   for( k = 1; k < n-p; k++ ) 
00339   {
00340     for( i = 0; i < M[k]; i++ )
00341     {
00342       for( j = 0; j <= p; j++ )
00343       {
00344         Rx[k+j-1] += N[k][j][i] * Q[offset+i].x;
00345         Ry[k+j-1] += N[k][j][i] * Q[offset+i].y;
00346         Rz[k+j-1] += N[k][j][i] * Q[offset+i].z;
00347       }
00348     }
00349     offset += M[k];
00350   }   
00351 
00352   // process points in last knotspan
00353 
00354   if( n-p > 0 )  // only when more then one knotspan
00355   {
00356     for( i = 0; i < M[k]-1; i++ )
00357     {
00358       r = N[k][p][i] * Q[nQ-1];
00359 
00360       for( j = 0; j < p; j++ )
00361       {
00362         Rx[k+j-1] += N[k][j][i] * (Q[offset+i].x - r.x);
00363         Ry[k+j-1] += N[k][j][i] * (Q[offset+i].y - r.y);
00364         Rz[k+j-1] += N[k][j][i] * (Q[offset+i].z - r.z);
00365       }
00366     }
00367   }
00368 
00369   // calculate the x coordinates of the controlpoints
00370   BandBackSubstitution( n-1, Min(p,n-1), Min(p,n-1), A, L, index, Rx ); 
00371   for( i = 0; i < n-1; i++ ) P[i+1][iCol].x = Rx[i];
00372   BandBackSubstitution( n-1, Min(p,n-1), Min(p,n-1), A, L, index, Ry ); 
00373   for( i = 0; i < n-1; i++ ) P[i+1][iCol].y = Ry[i];
00374   BandBackSubstitution( n-1, Min(p,n-1), Min(p,n-1), A, L, index, Rz ); 
00375   for( i = 0; i < n-1; i++ ) P[i+1][iCol].z = Rz[i];
00376 
00377   P[0][iCol] = Q[0];
00378   P[n][iCol] = Q[nQ-1];
00379 }
00380 
00381 template< class T >
00382 void CACalcNTN( int nQ, const Ptr<T>& Uq,
00383                 int n, int p, const Ptr<T>& U, Ptr<int>& M,
00384                 Ptr< Ptr< Ptr<T> > >& N, Ptr< Ptr<T> >& A )
00385 {
00386   Ptr<T> B;
00387   T u,sum;
00388   int offset,span,i,j,k,l,m;
00389 
00390   B.reserve_pool(p+1);
00391 
00392   span = p;
00393   offset = 0;
00394 
00395   for( i = 0; i < nQ; i++ )
00396   {
00397     u = Uq[i];
00398 
00399     while( (u >= U[span+1]) && (span != n) )
00400     {
00401       M[span-p] = i - offset;  // number of points in previous knot span 
00402       span++;
00403       offset = i;
00404     }
00405     CalcBasisFunctions( u, span, p, U, B );
00406 
00407     for( j = 0; j <= p; j++ )
00408       N[span-p][j][i-offset] = B[j];
00409   }
00410   M[n-p] = nQ - offset;  // number of points in last knot span
00411   
00412   /* 
00413    * calculate A = N^T * N of the normal equation (as a band matrix),
00414    * but without the first and last row/column. This doesn't affects
00415    * the remaining matrix, since the knot vector is clamped 
00416    */
00417 
00418   for( i = 1; i < n; i++ )
00419   {
00420     m = i-p;
00421 
00422     for( j = Max(0,-m); j <= p; j++ ) // subdiagonals
00423     {
00424       sum = (T)0;
00425       for( k = Min(j,n-i); k >= Max(0,-m); k-- )
00426       {
00427         for( l = 0; l < M[m+k]; l++ )
00428           sum += N[m+k][p-k][l]*N[m+k][j-k][l];
00429       }
00430       A[i-1][j] = sum;
00431     }
00432     for( j = Max(0,i+p-n); j < p; j++ ) // superdiagonals
00433     {
00434       sum = (T)0;
00435       for( k = Max(0,i+p-n); k <= Min(j,i); k++ )
00436       {
00437         for( l = 0; l < M[i-k]; l++ )
00438           sum += N[i-k][k][l]*N[i-k][p-j+k][l];
00439       }
00440       A[i-1][p+p-j] = sum;
00441     }
00442   }
00443 }
00444 
00445 /*----------------------------------------------------------------------
00446   Least squares approximation of a set of data points with a curve of a
00447   certain degree, number of knots and number of control points
00448   (knot vector of the curve and parameter values of the data points have
00449   to be provided by the caller; also the maximum number of data points per
00450   knot span must be given) 
00451 -----------------------------------------------------------------------*/
00452 template< class T, class EP >
00453 GULAPI bool DoGlobalCurveApproximation(
00454           int nQ, 
00455           const Ptr<EP>& Q, const 
00456           Ptr<T>& QU,
00457           int n, 
00458           int p, 
00459           const Ptr<T>& U, 
00460           int max_pts_span, 
00461           Ptr<EP>& P )
00462 {
00463   Ptr< Ptr< Ptr<T> > > N;
00464   int i,j;
00465   Ptr< Ptr<T> > A;
00466   Ptr<int> M;
00467  
00468   if( p < 2 ) return false;
00469   if( n < p ) return false;
00470   if( nQ <= n+1 ) return false; // else no unique minimum
00471 
00472   M.reserve_pool(n-p+1);
00473   N.reserve_pool(n-p+1);
00474   for( i = 0; i <= n-p; i++ ) {
00475     N[i].reserve_pool(p+1);
00476     for( j = 0; j <= p; j++ ) N[i][j].reserve_pool(max_pts_span);
00477   }
00478   A.reserve_pool(n-1);
00479   for( i = 0; i < n-1; i++ )
00480     A[i].reserve_pool(p+p+1);
00481 
00482   CACalcNTN<T>( nQ, QU, n, p, U, M, N, A );
00483 
00484   // cout << "MATRIX NTN (version 2):\n";
00485   // cout << dump_matrix<T>(n-1,p+p+1,A);
00486 
00487   CASolve( nQ, Q, QU, n, p, U, M, N, A, P );
00488   
00489   return true;
00490 }
00491 // template instantiation 
00492 template GULAPI bool DoGlobalCurveApproximation(
00493           int nQ, 
00494           const Ptr< point<float> >& Q, const 
00495           Ptr<float>& QU,
00496           int n, 
00497           int p, 
00498           const Ptr<float>& U, 
00499           int max_pts_span, 
00500           Ptr< point<float> >& P );
00501 template GULAPI bool DoGlobalCurveApproximation(
00502           int nQ, 
00503           const Ptr< point<double> >& Q, const 
00504           Ptr<double>& QU,
00505           int n, 
00506           int p, 
00507           const Ptr<double>& U, 
00508           int max_pts_span, 
00509           Ptr< point<double> >& P );
00510 template GULAPI bool DoGlobalCurveApproximation(
00511           int nQ, 
00512           const Ptr< point2<float> >& Q, const 
00513           Ptr<float>& QU,
00514           int n, 
00515           int p, 
00516           const Ptr<float>& U, 
00517           int max_pts_span, 
00518           Ptr< point2<float> >& P );
00519 template GULAPI bool DoGlobalCurveApproximation(
00520           int nQ, 
00521           const Ptr< point2<double> >& Q, const 
00522           Ptr<double>& QU,
00523           int n, 
00524           int p, 
00525           const Ptr<double>& U, 
00526           int max_pts_span, 
00527           Ptr< point2<double> >& P );
00528 
00529 /*----------------------------------------------------------------------
00530   Least squares approximation of a set of data points with a curve of a
00531   certain degree, number of knots and number of control points
00532 -----------------------------------------------------------------------*/
00533 template< class T, class EP >
00534 GULAPI bool GlobalCurveApproximation(int nQ, const Ptr<EP>& Q,
00535                          int n, int p, Ptr<T>& U, Ptr<EP>& P )
00536 {
00537   Ptr<T> Uq,d;
00538   T sum;
00539   Ptr< Ptr< Ptr<T> > > N;
00540   int Mmax;
00541   Ptr< Ptr<T> > A;
00542   Ptr<int> M;
00543  
00544   // return GlobalCurveApproximationDBG<T>(nQ,Q,n,p,U,P);
00545 
00546   d.reserve_pool(nQ);
00547   Uq.reserve_pool(nQ);
00548 
00549   sum = ChordLength( nQ, Q, d );
00550   if( sum == (T)0 ) return false;
00551   ChordLengthParameters( nQ, sum, d, Uq );
00552   if( !(Mmax = KnotVectorByAveraging(nQ, Uq, n, p, U)) ) return false;
00553 
00554   /*
00555   cout << "Parameters:\n";
00556   cout << dump_vector<T>(nQ,Uq);
00557   cout << "Knot Vector:\n";
00558   cout << dump_vector<T>(n+p+2,U);
00559   */
00560 
00561   return DoGlobalCurveApproximation(nQ,Q,Uq,n,p,U,Mmax,P);
00562 }
00563 // template instantiation
00564 template GULAPI bool GlobalCurveApproximation(
00565                int nQ, const Ptr< point<float> >& Q,
00566                int n, int p, Ptr<float>& U, Ptr< point<float> >& P );
00567 template GULAPI bool GlobalCurveApproximation(
00568                int nQ, const Ptr< point<double> >& Q,
00569                int n, int p, Ptr<double>& U, Ptr< point<double> >& P );
00570 template GULAPI bool GlobalCurveApproximation(
00571                int nQ, const Ptr< point2<float> >& Q,
00572                int n, int p, Ptr<float>& U, Ptr< point2<float> >& P );
00573 template GULAPI bool GlobalCurveApproximation(
00574                int nQ, const Ptr< point2<double> >& Q,
00575                int n, int p, Ptr<double>& U, Ptr< point2<double> >& P );
00576 
00577 
00578 /*----------------------------------------------------------------------
00579   Least squares approximation of a set of data points with a surface
00580 -----------------------------------------------------------------------*/
00581 template< class T, class EP >
00582 GULAPI bool GlobalSurfaceApproximation(
00583            int nRows, int nCols, const Ptr< Ptr<EP> >& Q,
00584            int nu, int pu, Ptr<T>& U, int nv, int pv, Ptr<T>& V,
00585            Ptr< Ptr<EP> > &P )
00586 {
00587   Ptr<T> Uq,Vq;
00588   Ptr< Ptr< Ptr<T> > > N;
00589   int i,j,Mmaxu,Mmaxv,sign,offset,bw,shift;
00590   Ptr< Ptr<T> > A,L;
00591   Ptr< Ptr<EP> > R;
00592   Ptr<int> index,M;
00593 
00594   if( (pu < 2) || (pv < 2) ) return false;
00595   if( (nu < pu) || (nv < pv) ) return false;
00596   if( (nRows <= nv+1) || (nCols <= nu+1) ) return false;
00597   
00598   Uq.reserve_pool(nCols);
00599   Vq.reserve_pool(nRows);
00600 
00601   if( !ChordLengthMeshParams( nRows, nCols, Q, Uq, Vq ) ) return false; 
00602 
00603   if( !(Mmaxu = KnotVectorByAveraging(nCols, Uq, nu, pu, U)) ) return false;
00604   if( !(Mmaxv = KnotVectorByAveraging(nRows, Vq, nv, pv, V)) ) return false;
00605 
00606   // calcuate the row curves
00607 
00608   M.reserve_pool(nu-pu+1);
00609   N.reserve_pool(nu-pu+1);
00610   for( i = 0; i <= nu-pu; i++ ) {
00611     N[i].reserve_pool(pu+1);
00612     for( j = 0; j <= pu; j++ ) N[i][j].reserve_pool(Mmaxu);
00613   }
00614   A.reserve_pool(nu-1);
00615   for( i = 0; i < nu-1; i++ )
00616     A[i].reserve_pool(pu+pu+1);
00617 
00618   R.reserve_pool(nu+1);
00619   for( i = 0; i <= nu; i++ )
00620     R[i].reserve_pool(nRows);
00621 
00622   CACalcNTN<T>( nCols, Uq, nu, pu, U, M, N, A );
00623 
00624   L.reserve_pool(nu-1);
00625   for( i = 0; i < nu-1; i++ )
00626     L[i].reserve_pool(pu+pu+1);
00627   index.reserve_pool(nu-1);
00628 
00629   if( nu-1 < pu )  // band width adjustment necessary
00630   {
00631     bw = nu-1;
00632     shift = pu - bw;
00633 
00634     for( i = 0;  i < nu-1; i++ )
00635     {
00636       offset = bw-i;
00637       for( j = 0; j < bw+bw+1-offset; j++ ) 
00638         A[i][offset+j] = A[i][offset+j+shift];
00639     }
00640   } 
00641   else
00642     bw = pu;
00643 
00644   BandDecomposition( nu-1, bw, bw, A, L, &sign, index );
00645 
00646   for( i = 0; i < nRows; i++ )
00647   {
00648     CASolveToCol( nCols, Q[i], Uq, nu, pu, U, M, N, A, L, index, i, R );
00649   }
00650 
00651   // calcuate the column curves
00652 
00653   M.reserve_pool(nv-pv+1);
00654   N.reserve_pool(nv-pv+1);  // this automatically frees old content of N
00655   for( i = 0; i <= nv-pv; i++ ) {
00656     N[i].reserve_pool(pv+1);
00657     for( j = 0; j <= pv; j++ ) N[i][j].reserve_pool(Mmaxv);
00658   }
00659   A.reserve_pool(nv-1);
00660   for( i = 0; i < nv-1; i++ )
00661     A[i].reserve_pool(pv+pv+1);
00662 
00663   CACalcNTN<T>( nRows, Vq, nv, pv, V, M, N, A );
00664 
00665   L.reserve_pool(nv-1);
00666   for( i = 0; i < nv-1; i++ )
00667     L[i].reserve_pool(pv+pv+1);
00668   index.reserve_pool(nv-1);
00669 
00670   if( nv-1 < pv )  // band width adjustment necessary
00671   {
00672     bw = nv-1;
00673     shift = pv - bw;
00674 
00675     for( i = 0;  i < nv-1; i++ )
00676     {
00677       offset = bw-i;
00678       for( j = 0; j < bw+bw+1-offset; j++ ) 
00679         A[i][offset+j] = A[i][offset+j+shift];
00680     }
00681   } 
00682   else
00683     bw = pv;
00684 
00685   BandDecomposition( nv-1, bw, bw, A, L, &sign, index );
00686 
00687   for( i = 0; i <= nu; i++ )
00688   {
00689     CASolveToCol( nRows, R[i], Vq, nv, pv, V, M, N, A, L, index, i, P );
00690   }
00691 
00692   return true;
00693 }
00694 // template instantiation
00695 template GULAPI bool GlobalSurfaceApproximation< float,point<float> >( 
00696            int nRows, int nCols, const Ptr< Ptr< point<float> > >& Q,
00697            int pu, int nu, Ptr<float>& U, int nv, int pv, Ptr<float>& V,
00698            Ptr< Ptr< point<float> > >& P );
00699 template GULAPI bool GlobalSurfaceApproximation< double,point<double> >( 
00700            int nRows, int nCols, const Ptr< Ptr< point<double> > >& Q,
00701            int pu, int nu, Ptr<double>& U, int nv, int pv, Ptr<double>& V,
00702            Ptr< Ptr< point<double> > >& P );
00703 /*
00704 template bool GlobalSurfaceApproximation< float,point1<float> >( 
00705            int nRows, int nCols, const Ptr< Ptr< point1<float> > >& Q,
00706            int pu, int nu, Ptr<float>& U, int nv, int pv, Ptr<float>& V,
00707            Ptr< Ptr< point1<float> > >& P );
00708 template bool GlobalSurfaceApproximation< double,point1<double> >( 
00709            int nRows, int nCols, const Ptr< Ptr< point1<double> > >& Q,
00710            int pu, int nu, Ptr<double>& U, int nv, int pv, Ptr<double>& V,
00711            Ptr< Ptr< point1<double> > >& P );
00712 */
00713 
00714 
00715 
00716 #if 0
00717 /*
00718  * Debug functions for finding errors in the band matrix solver
00719  *
00720  * I thought there was an error in the approximation function, but
00721  * this function delivers the same result. When the number of knotspans
00722  * is almost as high as the number of data points, the function does
00723  * a big loop between the first and second data point (with a testcase of 
00724  * collinear points). Though the approximation at the data points is
00725  * still very good, this doesn't look allright !!!!! 
00726  */
00727 
00728 template< class T >
00729 bool GlobalCurveApproximationDBG(int nQ, const Ptr< point<T> >& Q,
00730                          int n, int p, Ptr<T>& U, Ptr< point<T> >& P )
00731 {
00732   Ptr<T> Uq,d,B,rx,ry,rz,Rx,Ry,Rz;
00733   T sum,u;
00734   int i,j,Mmax,span,sign;
00735   Ptr< Ptr<T> > N,NT,NTN,A;
00736   Ptr<int> index;
00737 
00738   d.reserve_pool(nQ);
00739   Uq.reserve_pool(nQ);
00740 
00741   sum = ChordLength( nQ, Q, d );
00742   if( sum == (T)0 ) return false;
00743   ChordLengthParameters( nQ, sum, d, Uq );
00744   if( !(Mmax = KnotVectorByAveraging(nQ, Uq, n, p, U)) ) return false;
00745 
00746   /*
00747   cout << "Parameters:\n";
00748   cout << dump_vector<T>(nQ,Uq);
00749   cout << "Knot Vector:\n";
00750   cout << dump_vector<T>(n+p+2,U);
00751   */
00752   
00753   N.reserve_pool(nQ);
00754   for( i = 0; i < nQ; i++ )
00755     N[i].reserve_pool(n+1);
00756 
00757   span = p;
00758   for( i = 0; i < nQ; i++ )
00759   {
00760     u = Uq[i];
00761 
00762     if( (u >= U[span+1]) && (span != n) ) span++;
00763 
00764     B.use_pointer(&N[i][span-p],p+1);
00765     CalcBasisFunctions( u, span, p, U, B );
00766 
00767     for( j = 0; j < span-p; j++ ) N[i][j] = (T)0;
00768     for( j = span+1; j <= n; j++ ) N[i][j] = (T)0;
00769   }
00770 
00771   /*
00772   cout << "MATRIX N:\n";
00773   cout << dump_matrix<T>(nQ,n+1,N);
00774   */
00775 
00776   NT.reserve_pool(n+1);
00777   for( i = 0; i <= n; i++ )
00778     NT[i].reserve_pool(nQ);
00779 
00780   for( i = 0; i <= n; i++ )
00781     for( j = 0; j < nQ; j++ )
00782       NT[i][j] = N[j][i];
00783 
00784   NTN.reserve_pool(n+1);
00785   for( i = 0; i <= n; i++ )
00786     NTN[i].reserve_pool(n+1);
00787 
00788   MMProduct( n+1, nQ, n+1, NT, N, NTN ); 
00789 
00790   /*
00791   cout << "MATRIX NTN:\n";
00792   cout << dump_matrix<T>(n+1,n+1,NTN);
00793   */
00794 
00795   rx.reserve_pool(nQ);
00796   ry.reserve_pool(nQ);
00797   rz.reserve_pool(nQ);
00798 
00799   for( i = 1; i < nQ-1; i++ )
00800   { 
00801     rx[i] = Q[i].x - N[i][0]*Q[0].x - N[i][n]*Q[nQ-1].x;
00802     ry[i] = Q[i].y - N[i][0]*Q[0].y - N[i][n]*Q[nQ-1].y;
00803     rz[i] = Q[i].z - N[i][0]*Q[0].z - N[i][n]*Q[nQ-1].z;
00804   }
00805 
00806   Rx.reserve_pool(n-1);
00807   Ry.reserve_pool(n-1);
00808   Rz.reserve_pool(n-1);
00809 
00810   for( i = 1; i < n; i++ )
00811   {
00812     Rx[i-1] = (T)0;
00813     Ry[i-1] = (T)0;
00814     Rz[i-1] = (T)0;
00815     for( j = 1; j < nQ-1; j++ )
00816     {
00817       Rx[i-1] += N[j][i]*rx[j];
00818       Ry[i-1] += N[j][i]*ry[j];
00819       Rz[i-1] += N[j][i]*rz[j];
00820 
00821       /*
00822       cout << "Rx[" << i-1 << "] (Q[" << j << "]): " 
00823            << Rx[i-1] << "\n";
00824       */
00825     }
00826   }
00827 
00828   /*
00829   cout << "Right side for X:\n";
00830   cout << dump_vector<T>(n-1,Rx);
00831   cout << "Right side for Y:\n";
00832   cout << dump_vector<T>(n-1,Ry);
00833   cout << "Right side for Z:\n";
00834   cout << dump_vector<T>(n-1,Rz);
00835   */
00836 
00837   A.reserve_pool(n-1);
00838   for( i = 0; i < n-1; i++ ) A[i].reserve_pool(n-1);
00839   index.reserve_pool(n-1);
00840 
00841   for( i = 0; i < n-1; i++ )
00842     for( j = 0; j < n-1; j++ )
00843       A[i][j] = NTN[i+1][j+1];
00844 
00845   // solve with SVD
00846   cout << "solving with SVD\n";
00847 
00848   Ptr< Ptr<T> > SV;
00849   Ptr<T>        Sw;
00850 
00851   SV.reserve_pool(n-1);
00852   for( i = 0; i < n-1; i++ ) SV[i].reserve_pool(n-1);
00853   Sw.reserve_pool(n-1);
00854 
00855   SVDecomposition( n-1, n-1, A, Sw, SV );
00856 
00857   bool illcond = !SVZero( n-1, Sw );
00858   if( illcond ) cout << "Coefficients matrix ill conditioned!\n";
00859  
00860   SVBackSubstitution( n-1, n-1, A, Sw, SV, Rx );
00861   SVBackSubstitution( n-1, n-1, A, Sw, SV, Ry );
00862   SVBackSubstitution( n-1, n-1, A, Sw, SV, Rz );
00863 
00864   /*
00865   // solve with LUD
00866 
00867   LUDecomposition( n-1, A, &sign, index );
00868 
00869   LUBackSubstitution( n-1, index, A, Rx );
00870   LUBackSubstitution( n-1, index, A, Ry );
00871   LUBackSubstitution( n-1, index, A, Rz );
00872   */
00873 
00874   for( i = 1; i <= n-1; i++ )
00875   {
00876     P[i].x = Rx[i-1];
00877     P[i].y = Ry[i-1];
00878     P[i].z = Rz[i-1];
00879   }
00880   P[0] = Q[0];
00881   P[n] = Q[nQ-1];
00882 
00883   return true;
00884 }
00885 // template instantiation
00886 template bool GlobalCurveApproximationDBG(
00887                int nQ, const Ptr< point<float> >& Q,
00888                int n, int p, Ptr<float>& U, Ptr< point<float> >& P );
00889 template bool GlobalCurveApproximationDBG(
00890                int nQ, const Ptr< point<double> >& Q,
00891                int n, int p, Ptr<double>& U, Ptr< point<double> >& P );
00892 
00893 
00894 template< class T >
00895 bool GlobalCurveApproximationDBG(int nQ, const Ptr< point2<T> >& Q,
00896                          int n, int p, Ptr<T>& U, Ptr< point2<T> >& P )
00897 {
00898   Ptr<T> Uq,d,B,rx,ry,rz,Rx,Ry,Rz;
00899   T sum,u;
00900   int i,j,Mmax,span,sign;
00901   Ptr< Ptr<T> > N,NT,NTN,A;
00902   Ptr<int> index;
00903 
00904   d.reserve_pool(nQ);
00905   Uq.reserve_pool(nQ);
00906 
00907   sum = ChordLength( nQ, Q, d );
00908   if( sum == (T)0 ) return false;
00909   ChordLengthParameters( nQ, sum, d, Uq );
00910   if( !(Mmax = KnotVectorByAveraging(nQ, Uq, n, p, U)) ) return false;
00911 
00912   N.reserve_pool(nQ);
00913   for( i = 0; i < nQ; i++ )
00914     N[i].reserve_pool(n+1);
00915 
00916   span = p;
00917   for( i = 0; i < nQ; i++ )
00918   {
00919     u = Uq[i];
00920 
00921     if( (u >= U[span+1]) && (span != n) ) span++;
00922 
00923     B.use_pointer(&N[i][span-p],p+1);
00924     CalcBasisFunctions( u, span, p, U, B );
00925 
00926     for( j = 0; j < span-p; j++ ) N[i][j] = (T)0;
00927     for( j = span+1; j <= n; j++ ) N[i][j] = (T)0;
00928   }
00929 
00930   /*
00931   cout << "MATRIX N:\n";
00932   cout << dump_matrix<T>(nQ,n+1,N);
00933   */
00934 
00935   NT.reserve_pool(n+1);
00936   for( i = 0; i <= n; i++ )
00937     NT[i].reserve_pool(nQ);
00938 
00939   for( i = 0; i <= n; i++ )
00940     for( j = 0; j < nQ; j++ )
00941       NT[i][j] = N[j][i];
00942 
00943   NTN.reserve_pool(n+1);
00944   for( i = 0; i <= n; i++ )
00945     NTN[i].reserve_pool(n+1);
00946 
00947   MMProduct( n+1, nQ, n+1, NT, N, NTN ); 
00948 
00949   /*
00950   cout << "MATRIX NTN:\n";
00951   cout << dump_matrix<T>(n+1,n+1,NTN);
00952   */
00953 
00954   rx.reserve_pool(nQ);
00955   ry.reserve_pool(nQ);
00956   rz.reserve_pool(nQ);
00957 
00958   for( i = 1; i < nQ-1; i++ )
00959   { 
00960     rx[i] = Q[i].x - N[i][0]*Q[0].x - N[i][n]*Q[nQ-1].x;
00961     ry[i] = Q[i].y - N[i][0]*Q[0].y - N[i][n]*Q[nQ-1].y;
00962   }
00963 
00964   Rx.reserve_pool(n-1);
00965   Ry.reserve_pool(n-1);
00966 
00967   for( i = 1; i < n; i++ )
00968   {
00969     Rx[i-1] = (T)0;
00970     Ry[i-1] = (T)0;
00971     for( j = 1; j < nQ-1; j++ )
00972     {
00973       Rx[i-1] += N[j][i]*rx[j];
00974       Ry[i-1] += N[j][i]*ry[j];
00975     }
00976   }
00977   /*
00978   cout << "Right side for X:\n";
00979   cout << dump_vector<T>(n-1,Rx);
00980   cout << "Right side for Y:\n";
00981   cout << dump_vector<T>(n-1,Ry);
00982   cout << "Right side for Z:\n";
00983   cout << dump_vector<T>(n-1,Rz);
00984   */
00985 
00986   A.reserve_pool(n-1);
00987   for( i = 0; i < n-1; i++ ) A[i].reserve_pool(n-1);
00988   index.reserve_pool(n-1);
00989 
00990   for( i = 0; i < n-1; i++ )
00991     for( j = 0; j < n-1; j++ )
00992       A[i][j] = NTN[i+1][j+1];
00993 
00994   // solve with SVD
00995   // cout << "solving with SVD\n";
00996 
00997   Ptr< Ptr<T> > SV;
00998   Ptr<T>        Sw;
00999 
01000   SV.reserve_pool(n-1);
01001   for( i = 0; i < n-1; i++ ) SV[i].reserve_pool(n-1);
01002   Sw.reserve_pool(n-1);
01003 
01004   SVDecomposition( n-1, n-1, A, Sw, SV );
01005 
01006   bool illcond = !SVZero( n-1, Sw );
01007   if( illcond ) cout << "Coefficients matrix ill conditioned!\n";
01008  
01009   SVBackSubstitution( n-1, n-1, A, Sw, SV, Rx );
01010   SVBackSubstitution( n-1, n-1, A, Sw, SV, Ry );
01011 
01012   /*
01013   // solve with LUD
01014 
01015   LUDecomposition( n-1, A, &sign, index );
01016 
01017   LUBackSubstitution( n-1, index, A, Rx );
01018   LUBackSubstitution( n-1, index, A, Ry );
01019   LUBackSubstitution( n-1, index, A, Rz );
01020   */
01021 
01022   for( i = 1; i <= n-1; i++ )
01023   {
01024     P[i].x = Rx[i-1];
01025     P[i].y = Ry[i-1];
01026   }
01027   P[0] = Q[0];
01028   P[n] = Q[nQ-1];
01029 
01030   return true;
01031 }
01032 template bool GlobalCurveApproximationDBG(
01033                int nQ, const Ptr< point2<float> >& Q,
01034                int n, int p, Ptr<float>& U, Ptr< point2<float> >& P );
01035 template bool GlobalCurveApproximationDBG(
01036                int nQ, const Ptr< point2<double> >& Q,
01037                int n, int p, Ptr<double>& U, Ptr< point2<double> >& P );
01038 #endif
01039 
01040 }
01041 
01042 
01043 

Generated on Mon Jan 21 04:17:38 2002 for GUL 0.6 - Geometry Utility Library by doxygen1.2.13.1 written by Dimitri van Heesch, © 1997-2001