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

gunu_basics.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 "gul_vector.h"
00026 #include "gunu_basics.h"
00027 
00028 
00029 namespace gunu {
00030 
00031 using gul::point1;
00032 using gul::point2;
00033 using gul::hpoint;
00034 using gul::hpoint1;
00035 using gul::hpoint2;
00036 using gul::set;
00037 using gul::euclid;
00038 
00039 /*************************************************************************
00040 
00041   BASICAL NURBS FUNCTIONS
00042 
00043 **************************************************************************/
00044 
00045 /*-------------------------------------------------------------------------
00046   Search for the knotspan containing 'u' in a knot vector 'U' (clamped,degree
00047   'p','n'+1 knots (see "The NURBS book"))
00048 -------------------------------------------------------------------------*/
00049 template< class T >
00050 int FindSpan( const T u, const int n, const int p, 
00051               const Ptr< T >& U )
00052 {
00053   int low,mid,high;
00054   
00055 /* --- search knotspan (from right):   */
00056 
00057   if( u == U[n+1] )
00058   {
00059     if( u == U[n+p+1] ) // clamped
00060       return(n);
00061                       
00062     return( n+1 );   // unclamped, knot span = n+1
00063   }
00064      
00065   low = p;
00066   high = n+1;
00067   mid = (low+high) / 2 ;  
00068 
00069   while( (u < U[mid]) || (u >= U[mid+1]) ) 
00070   {
00071     if( u < U[mid] )
00072       high = mid;
00073     else
00074       low = mid;
00075       
00076     mid = (low+high) / 2;
00077   }
00078   
00079   return(mid);     
00080 }           
00081 // template instantiation
00082 template int FindSpan( const float u, const int n, const int p, 
00083                        const Ptr< float >& U );
00084 template int FindSpan( const double u, const int n, const int p, 
00085                        const Ptr< double >& U );
00086 
00087 /*-------------------------------------------------------------------------
00088   Finds the knotspan containing 'u' in a knot vector 'U' (clamped,degree
00089   'p','n'+1 knots (see "The NURBS book")), and counts the multiplicity
00090   of 'u'
00091 -------------------------------------------------------------------------*/
00092 template< class T >
00093 int FindSpanMultip( const T u, const int n,  const int p, 
00094                     const Ptr< T >& U, int *s )
00095 {
00096   int l,low,mid,high;
00097   
00098 /* --- Knotenspanne suchen (von rechts):   */
00099 
00100   if( u == U[n+1] )
00101   {
00102     if( u == U[n+p+1] ) // clamped
00103     {
00104       *s = p + 1;
00105       return(n);
00106     }
00107                       
00108     l = n;           // if unclamped
00109     while( l >= 0 )  //   count multiplicity
00110     {
00111       if( U[l] != u ) break;
00112       l--;
00113     }
00114     *s = n+1 - l;
00115     return( n+1 );   // knot span = n+1
00116   }
00117      
00118   low = p;
00119   high = n+1;
00120   mid = (low+high) / 2 ;  
00121 
00122   while( (u < U[mid]) || (u >= U[mid+1]) ) 
00123   {
00124     if( u < U[mid] )
00125       high = mid;
00126     else
00127       low = mid;
00128       
00129     mid = (low+high) / 2;
00130   }
00131   
00132   l = mid;
00133   while( l >= 0 )
00134   {
00135     if( U[l] != u ) break;
00136     l--;
00137   }
00138   *s = mid - l;
00139 
00140   return(mid);     
00141 }              
00142 // template instantiation
00143 template int FindSpanMultip( const float u, const int n,  const int p, 
00144                              const Ptr< float >& U, int *s );
00145 template int FindSpanMultip( const double u, const int n,  const int p, 
00146                              const Ptr< double >& U, int *s );
00147 
00148 
00149 /* --------------------------------------------------------------------
00150   Checks whether a knot vector is valid, clamped and normalized
00151 ---------------------------------------------------------------------*/
00152 template< class T >
00153 GULAPI bool ValidateKnotVec( const int n, const int p, const Ptr<T>& knt,
00154                              bool& is_clamped, bool& is_normalized )
00155 {
00156   int m, multi, i;
00157   bool clamped0=false, clamped1=false;
00158   T u;
00159 
00160   m =  knt.nElems() - 1;
00161   if( m != n+p+1 ) return false;
00162 
00163   u = knt[0];
00164   multi = 1;
00165   for( i = 1; i <= m; i++ )
00166   {
00167     if( knt[i] < knt[i-1] ) 
00168       return false;    // knots must be increasing
00169 
00170     if( knt[i] == u )
00171       multi++;
00172     else
00173     {
00174       u = knt[i];
00175       multi = 1;
00176     }
00177 
00178     if( multi > p )
00179     {
00180       if( multi == p+1 )
00181       {
00182         if( i == p )
00183         {
00184           clamped0 = true;
00185           continue;
00186         }
00187         if( i == m )
00188         {
00189           clamped1 = true;
00190           continue;
00191         }
00192       }
00193       return false;
00194     }
00195   }
00196 
00197   is_clamped = clamped0 && clamped1; 
00198   is_normalized = ((knt[p] == (T)0.0) && (knt[n+1] == (T)1.0));
00199 
00200   return true;
00201 }
00202 // template instantiation
00203 template GULAPI bool ValidateKnotVec( 
00204                           const int n, const int p, const Ptr<float>& knt,
00205                           bool& is_clamped, bool& is_normalized );
00206 template GULAPI bool ValidateKnotVec( 
00207                           const int n, const int p, const Ptr<double>& knt,
00208                           bool& is_clamped, bool& is_normalized );
00209 
00210 /*------------------------------------------------------------------
00211   Calculates a single basis function
00212 ------------------------------------------------------------------*/
00213 template< class T >
00214 GULAPI T CalcBasisFunction( int p, int i, T u, int n, const Ptr<T>& U ) 
00215 {
00216   Ptr<T> N;
00217   int j,k;
00218   T saved,Uleft,Uright,temp;
00219 
00220   N.reserve_pool(p+1);
00221 
00222   if( ((i == 0) && (u == U[0])) ||
00223       ((i == n) && (u == U[n+1])) )  // since clamped knot vector
00224     return (T)1;
00225 
00226   if( (u < U[i]) || (u >= U[i+p+1]) )
00227     return 0;
00228 
00229   // zeroth-degree basis functions
00230   for( j = 0; j <= p; j++ )
00231   {
00232     if( (u >= U[i+j]) && (u < U[i+j+1]) )
00233       N[j] = (T)1; 
00234     else
00235       N[j] = (T)0;
00236   }
00237 
00238   // compute triangular table
00239   for( k = 1; k <= p; k++ )
00240   {
00241     if( N[0] == (T)0 )
00242       saved = (T)0;
00243     else
00244       saved = ((u-U[i])*N[0])/(U[i+k]-U[i]);
00245 
00246     for( j = 0; j < p-k+1; j++ )
00247     {
00248       Uleft = U[i+j+1];
00249       Uright = U[i+j+k+1];
00250 
00251       if( N[j+1] == (T)0 )
00252       {
00253         N[j] = saved;
00254         saved = (T)0;
00255       }
00256       else
00257       {
00258         temp = N[j+1]/(Uright-Uleft);
00259         N[j] = saved + (Uright-u)*temp;
00260         saved = (u-Uleft)*temp;
00261       }
00262     }
00263   }
00264 
00265   return N[0];
00266 }
00267 // template instantiation
00268 template GULAPI float CalcBasisFunction( 
00269                  int p, int i, float u, int n, const Ptr<float>& U );
00270 template GULAPI double CalcBasisFunction( 
00271                  int p, int i, double u, int n, const Ptr<double>& U );
00272 
00273 
00274 /*------------------------------------------------------------------
00275   Calculates the non vanishing NURBS basis functions (see "The NURBS book")
00276 -------------------------------------------------------------------*/
00277 template< class T >
00278 void CalcBasisFunctions( const T u, const int i, const int p, const Ptr< T >& U,
00279                          Ptr< T >& N )
00280 {
00281   Ptr< T > left,right;
00282   T saved,temp;
00283   int j,r;
00284   
00285   left.reserve_place( reserve_stack(T,p+1), p+1 );
00286   right.reserve_place( reserve_stack(T,p+1), p+1 );
00287   
00288   N[0] = 1.0;
00289   
00290   for( j = 1; j <= p; j++ )
00291   {
00292     left[j] = u - U[i+1-j];
00293     right[j] = U[i+j] - u;
00294     saved = 0.0;
00295     
00296     for( r = 0; r < j; r++ )
00297     {
00298       temp = N[r] / (right[r+1] + left[j-r]);
00299       N[r] = saved + (right[r+1] * temp);
00300       saved = left[j-r] * temp;
00301     }
00302     
00303     N[j] = saved;
00304   }  
00305 }
00306 // template instantiation
00307 template void CalcBasisFunctions( 
00308        const float u, const int i, const int p, const Ptr<float>& U,
00309        Ptr<float>& N );
00310 template void CalcBasisFunctions( 
00311        const double u, const int i, const int p, const Ptr<double>& U,
00312        Ptr<double>& N );
00313 
00314 
00315 /*--------------------------------------------------------------------------
00316   Constructs a uniform clamped knot vector ( u_{i+1}-u_{i}) is equal
00317   for all inner nodes
00318 --------------------------------------------------------------------------*/ 
00319 template< class T >
00320 GULAPI void UniformKnotVector( const int n, const int p, Ptr< T >& U )
00321 {
00322   int segs,i;
00323   T seglen;
00324   
00325   for( i = 0; i <= p; i++ )
00326   {
00327     U[i] = 0.;
00328     U[n+1+i] = 1.;
00329   }
00330 
00331   segs = n-p+1;
00332   seglen = (T)1. / ((T)segs);
00333   for( i = p+1; i <= n; i++ )
00334   {
00335     // U[i] = U[i-1] + seglen;
00336     U[i] = U[p] + seglen*(T)(i-p);
00337   }
00338 }
00339 // template instantiation
00340 template GULAPI void UniformKnotVector( const int n, const int p, Ptr< float >& U );
00341 template GULAPI void UniformKnotVector( const int n, const int p, Ptr< double >& U );
00342 
00343 /*------------------------------------------------------------------------
00344   Calculates a point on a NURBS curve (see "The NURBS Book")
00345 ----------------------------------------------------------------------- */
00346 template< class T, class HP, class EP >
00347 GULAPI void CurvePoint( 
00348                  const T u, const int n, const int p, const Ptr< T >& U,
00349                  const Ptr< HP >& Pw, EP *C )
00350 {
00351   Ptr< T > N;
00352   HP v1,h;
00353   int span,i;
00354 
00355   N.reserve_place( reserve_stack(T,p+1), p+1 );
00356   
00357   span = FindSpan( u, n, p, U );
00358   CalcBasisFunctions<T>( u, span, p, U, N );
00359 
00360   set( h, (T)0.0 );
00361   
00362   for( i = 0; i <= p; i++ )
00363   {
00364     v1 = N[i] * Pw[span-p+i];
00365     h = h + v1;
00366   } 
00367   *C = euclid( h );
00368 }
00369 // template instantiation
00370 template GULAPI void CurvePoint( 
00371           const float u, const int n, const int p, const Ptr< float >& U,
00372           const Ptr< hpoint<float> >& Pw, point<float> *C );
00373 template GULAPI void CurvePoint( 
00374           const double u, const int n, const int p, const Ptr< double >& U,
00375           const Ptr< hpoint<double> >& Pw, point<double> *C );         
00376 template GULAPI void CurvePoint( 
00377           const float u, const int n, const int p, const Ptr< float >& U,
00378           const Ptr< hpoint2<float> >& Pw, point2<float> *C );
00379 template GULAPI void CurvePoint( 
00380           const double u, const int n, const int p, const Ptr< double >& U,
00381           const Ptr< hpoint2<double> >& Pw, point2<double> *C );
00382 
00383 template GULAPI void CurvePoint( 
00384           const float u, const int n, const int p, const Ptr< float >& U,
00385           const Ptr< point<float> >& Pw, point<float> *C );
00386 template GULAPI void CurvePoint( 
00387           const double u, const int n, const int p, const Ptr< double >& U,
00388           const Ptr< point<double> >& Pw, point<double> *C );         
00389 template GULAPI void CurvePoint( 
00390           const float u, const int n, const int p, const Ptr< float >& U,
00391           const Ptr< point2<float> >& Pw, point2<float> *C );
00392 template GULAPI void CurvePoint( 
00393           const double u, const int n, const int p, const Ptr< double >& U,
00394           const Ptr< point2<double> >& Pw, point2<double> *C );
00395 
00396 
00397 
00398 /*------------------------------------------------------------------------
00399   Calculates a point on a NURBS surface (see "The NURBS Book")
00400 ----------------------------------------------------------------------- */
00401 template< class T, class HP, class EP > 
00402 GULAPI
00403 void SurfacePoint( 
00404                 const T u, const T v, 
00405                 const int nu, const int pu, const Ptr< T >& U,
00406                 const int nv, const int pv, const Ptr< T >& V,                    
00407                 const Ptr< Ptr< HP > >& Pw, EP *retS )
00408 {                          
00409   Ptr< T > Nu,Nv;
00410   int uspan,vspan,uind,vind,l,k;
00411   HP S,temp,v1;
00412 
00413   Nu.reserve_place( reserve_stack(T,pu+1), pu+1 );
00414   Nv.reserve_place( reserve_stack(T,pv+1), pv+1 );
00415  
00416   uspan = FindSpan( u, nu, pu, U );
00417   CalcBasisFunctions( u, uspan, pu, U, Nu );
00418   
00419   vspan = FindSpan( v, nv, pv, V );
00420   CalcBasisFunctions( v, vspan, pv, V, Nv );
00421 
00422   uind = uspan-pu;
00423   set( S, (T)0.0 );
00424   for( l = 0; l <= pv; l++ )
00425   {
00426     set( temp, (T)0.0 );
00427     vind = vspan - pv + l;
00428     for( k = 0; k <= pu; k++ )
00429     {
00430       v1 = Nu[k] * Pw[vind][uind+k]; /* meine Kontrollpunktmatrix ist falschrum,
00431                                         muss daher transponiert werden */
00432       temp = temp + v1;
00433     }
00434     v1 = Nv[l] * temp;
00435     S = S + v1;
00436   }   
00437   *retS = euclid( S );
00438 }          
00439 // template instantiation
00440 template GULAPI void SurfacePoint( 
00441                 const float u, const float v, 
00442                 const int nu, const int pu, const Ptr< float >& U,
00443                 const int nv, const int pv, const Ptr< float >& V,                    
00444                 const Ptr< Ptr< hpoint<float> > >& Pw, point<float> *retS );
00445 template GULAPI void SurfacePoint( 
00446                 const double u, const double v, 
00447                 const int nu, const int pu, const Ptr< double >& U,
00448                 const int nv, const int pv, const Ptr< double >& V,                    
00449                 const Ptr< Ptr< hpoint<double> > >& Pw, point<double> *retS );
00450 template GULAPI void SurfacePoint( 
00451                 const float u, const float v, 
00452                 const int nu, const int pu, const Ptr< float >& U,
00453                 const int nv, const int pv, const Ptr< float >& V,                    
00454                 const Ptr< Ptr< hpoint1<float> > >& Pw, point1<float> *retS );
00455 template GULAPI void SurfacePoint( 
00456                 const double u, const double v, 
00457                 const int nu, const int pu, const Ptr< double >& U,
00458                 const int nv, const int pv, const Ptr< double >& V,                    
00459                 const Ptr< Ptr< hpoint1<double> > >& Pw, point1<double> *retS );
00460 
00461 template GULAPI void SurfacePoint( 
00462                 const float u, const float v, 
00463                 const int nu, const int pu, const Ptr< float >& U,
00464                 const int nv, const int pv, const Ptr< float >& V,                    
00465                 const Ptr< Ptr< point<float> > >& Pw, point<float> *retS );
00466 template GULAPI void SurfacePoint( 
00467                 const double u, const double v, 
00468                 const int nu, const int pu, const Ptr< double >& U,
00469                 const int nv, const int pv, const Ptr< double >& V,                    
00470                 const Ptr< Ptr< point<double> > >& Pw, point<double> *retS );
00471 template GULAPI void SurfacePoint( 
00472                 const float u, const float v, 
00473                 const int nu, const int pu, const Ptr< float >& U,
00474                 const int nv, const int pv, const Ptr< float >& V,                    
00475                 const Ptr< Ptr< point1<float> > >& Pw, point1<float> *retS );
00476 template GULAPI void SurfacePoint( 
00477                 const double u, const double v, 
00478                 const int nu, const int pu, const Ptr< double >& U,
00479                 const int nv, const int pv, const Ptr< double >& V,                    
00480                 const Ptr< Ptr< point1<double> > >& Pw, point1<double> *retS );
00481 
00482 
00483 /*------------------------------------------------------------------------
00484   Calculates a point on a Bezier surface (for Bezier surfaces there is
00485   no need to search the knot span)
00486 ----------------------------------------------------------------------- */
00487 
00488 template< class T, class HP, class EP > 
00489 GULAPI
00490 void BezierSurfacePoint( 
00491                 const T u, const T v, 
00492                 const int pu, const Ptr< T >& U,
00493                 const int pv, const Ptr< T >& V,                    
00494                 const Ptr< Ptr< HP > >& Pw, EP *retS )
00495 {                          
00496   Ptr< T > Nu,Nv;
00497   int uspan,vspan,uind,vind,l,k;
00498   HP S,temp,v1;
00499 
00500   Nu.reserve_place( reserve_stack(T,pu+1), pu+1 );
00501   Nv.reserve_place( reserve_stack(T,pv+1), pv+1 );
00502  
00503   uspan = pu;
00504   CalcBasisFunctions( u, uspan, pu, U, Nu );
00505   
00506   vspan = pv;
00507   CalcBasisFunctions( v, vspan, pv, V, Nv );
00508 
00509   uind = uspan-pu;
00510   set( S, (T)0.0 );
00511   for( l = 0; l <= pv; l++ )
00512   {
00513     set( temp, (T)0.0 );
00514     vind = vspan - pv + l;
00515     for( k = 0; k <= pu; k++ )
00516     {
00517       v1 = Nu[k] * Pw[vind][uind+k]; /* meine Kontrollpunktmatrix ist falschrum,
00518                                         muss daher transponiert werden */
00519       temp = temp + v1;
00520     }
00521     v1 = Nv[l] * temp;
00522     S = S + v1;
00523   }   
00524   *retS = euclid( S );
00525 }          
00526 // template instantiation
00527 template GULAPI void BezierSurfacePoint( 
00528                 const float u, const float v, 
00529                 const int pu, const Ptr< float >& U,
00530                 const int pv, const Ptr< float >& V,                    
00531                 const Ptr< Ptr< hpoint<float> > >& Pw, point<float> *retS );
00532 template GULAPI void BezierSurfacePoint( 
00533                 const double u, const double v, 
00534                 const int pu, const Ptr< double >& U,
00535                 const int pv, const Ptr< double >& V,                    
00536                 const Ptr< Ptr< hpoint<double> > >& Pw, point<double> *retS );
00537 template GULAPI void BezierSurfacePoint( 
00538                 const float u, const float v, 
00539                 const int pu, const Ptr< float >& U,
00540                 const int pv, const Ptr< float >& V,                    
00541                 const Ptr< Ptr< hpoint1<float> > >& Pw, point1<float> *retS );
00542 template GULAPI void BezierSurfacePoint( 
00543                 const double u, const double v, 
00544                 const int pu, const Ptr< double >& U,
00545                 const int pv, const Ptr< double >& V,                    
00546                 const Ptr< Ptr< hpoint1<double> > >& Pw, point1<double> *retS );
00547 
00548 template GULAPI void BezierSurfacePoint( 
00549                 const float u, const float v, 
00550                 const int pu, const Ptr< float >& U,
00551                 const int pv, const Ptr< float >& V,                    
00552                 const Ptr< Ptr< point<float> > >& Pw, point<float> *retS );
00553 template GULAPI void BezierSurfacePoint( 
00554                 const double u, const double v, 
00555                 const int pu, const Ptr< double >& U,
00556                 const int pv, const Ptr< double >& V,                    
00557                 const Ptr< Ptr< point<double> > >& Pw, point<double> *retS );
00558 template GULAPI void BezierSurfacePoint( 
00559                 const float u, const float v, 
00560                 const int pu, const Ptr< float >& U,
00561                 const int pv, const Ptr< float >& V,                    
00562                 const Ptr< Ptr< point1<float> > >& Pw, point1<float> *retS );
00563 template GULAPI void BezierSurfacePoint( 
00564                 const double u, const double v, 
00565                 const int pu, const Ptr< double >& U,
00566                 const int pv, const Ptr< double >& V,                    
00567                 const Ptr< Ptr< point1<double> > >& Pw, point1<double> *retS );
00568 
00569 
00570 
00571 
00572 }
00573 
00574 
00575 
00576 

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