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

gunu_mba_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 "gul_vector.h"
00026 #include "gul_matrix.h"
00027 #include "guge_normalize.h"
00028 #include "guma_minimize.h"
00029 #include "gunu_basics.h"
00030 #include "gunu_refine.h"
00031 #include "gunu_make_compatible.h"
00032 #include "gunu_mba_approximate.h"
00033 
00034 namespace gunu {
00035 
00036 using gul::rtr;
00037 using gul::Max;
00038 using gul::Ptr;
00039 using gul::point;
00040 using gul::point1;
00041 using gul::point2;
00042 using gul::vec4;
00043 using gul::mat4x4;
00044 using guge::CalcBoundingBoxE;
00045 using guma::GoldenSectionSearch;
00046 using gul::set;
00047 
00048 /*-------------------------------------------------------------------------*//**
00049   BSpline approximation,
00050   calculates the points of a control lattice 'delta', which approximates
00051   data points in 'P'. (P[].z contains the function value, P[].x and P[].y
00052   the location in the domain)                                                 */
00053 /*----------------------------------------------------------------------------*/
00054 template< class T >
00055 void BAapproximate( 
00056              int nP, Ptr< point<T> >& P, 
00057              int nu, int pu, Ptr<T>& U,  
00058              int nv, int pv, Ptr<T>& V,
00059              Ptr< Ptr< point1<T> > >& delta )
00060 {
00061   Ptr<T> Nu, Nv;
00062   Ptr< Ptr<T> > omega, w, w2;
00063   int i,j,k,l,C,uspan,vspan,uind,vind; 
00064   T sum_w2;
00065 
00066 /* ---- reserve local arrays ------------------- */ 
00067 
00068   omega.reserve_pool(nv+1);
00069   for( i = 0; i < nv+1; i++ )
00070     omega[i].reserve_pool(nu+1);
00071 
00072   w.reserve_pool(pu+1);
00073   w2.reserve_pool(pu+1);
00074   for( i = 0; i < pu+1; i++ )
00075   {
00076     w[i].reserve_pool(pv+1);
00077     w2[i].reserve_pool(pv+1);
00078   }
00079   Nu.reserve_pool(pu+1);
00080   Nv.reserve_pool(pv+1);
00081   
00082   for( j = 0; j <= nv; j++ )
00083   {
00084     for( i = 0; i <= nu; i++ )
00085     {
00086       delta[j][i].x = (T)0;
00087       omega[j][i] = (T)0;
00088     }  
00089   }          
00090   for( C = 0; C < nP; C++ )
00091   {
00092     uspan = FindSpan( P[C].x, nu, pu, U );
00093     CalcBasisFunctions( P[C].x, uspan, pu, U, Nu );
00094 
00095     vspan = FindSpan( P[C].y, nv, pv, V );
00096     CalcBasisFunctions( P[C].y, vspan, pv, V, Nv );
00097 
00098     sum_w2 = (T)0;
00099     for( k = 0; k <= pu; k++ ) 
00100     {
00101       for( l = 0; l <= pv; l++ )
00102       {
00103         w[k][l] = Nu[k] * Nv[l];
00104         w2[k][l] = w[k][l] * w[k][l];
00105         sum_w2 += w2[k][l];      
00106       }
00107     }
00108     uind = uspan - pu;
00109     vind = vspan - pv;
00110     for( k = 0; k <= pu; k++ )
00111     {
00112       for( l = 0; l <= pv; l++ )
00113       {
00114         delta[vind+l][uind+k].x += w2[k][l] * w[k][l] * P[C].z / sum_w2;
00115         omega[vind+l][uind+k] += w2[k][l];
00116       }
00117     }
00118   }
00119   for( j = 0; j <= nv; j++ )
00120   {
00121     for( i = 0; i <= nu; i++ )
00122     {
00123       if( omega[j][i] != (T)0 )
00124         delta[j][i].x /= omega[j][i];
00125       else
00126         delta[j][i].x = (T)0;
00127     }
00128   }                 
00129 }
00130 template void BAapproximate( 
00131              int nP, Ptr< point<float> >& P, 
00132              int nu, int pu, Ptr<float>& U,  
00133              int nv, int pv, Ptr<float>& V,
00134              Ptr< Ptr< point1<float> > >& delta );
00135 template void BAapproximate( 
00136              int nP, Ptr< point<double> >& P, 
00137              int nu, int pu, Ptr<double>& U,  
00138              int nv, int pv, Ptr<double>& V,
00139              Ptr< Ptr< point1<double> > >& delta );
00140 
00141 /*-------------------------------------------------------------------------*//**
00142   BSpline approximation,
00143   calculates the points of a control lattice 'delta', which approximates
00144   data points in 'P'. (P[].z contains the function value, P[].x and P[].y
00145   the location in the domain). An individual standard deviation for each data
00146   point must be given in 'Sigma'                                              */
00147 /*----------------------------------------------------------------------------*/
00148 template< class T >
00149 void BAapproximate( 
00150              int nP, Ptr< point<T> >& P, Ptr<T>& Sigma,
00151              int nu, int pu, Ptr<T>& U,  
00152              int nv, int pv, Ptr<T>& V,
00153              Ptr< Ptr< point1<T> > >& delta )
00154 {
00155   Ptr<T> Nu, Nv;
00156   Ptr< Ptr<T> > omega, w, w2;
00157   int i,j,k,l,C,uspan,vspan,uind,vind; 
00158   T factor, sum_w2;
00159 
00160 /* ---- reserve local arrays ------------------- */ 
00161 
00162   omega.reserve_pool(nv+1);
00163   for( i = 0; i < nv+1; i++ )
00164     omega[i].reserve_pool(nu+1);
00165 
00166   w.reserve_pool(pu+1);
00167   w2.reserve_pool(pu+1);
00168   for( i = 0; i < pu+1; i++ )
00169   {
00170     w[i].reserve_pool(pv+1);
00171     w2[i].reserve_pool(pv+1);
00172   }
00173   Nu.reserve_pool(pu+1);
00174   Nv.reserve_pool(pv+1);
00175   
00176   for( j = 0; j <= nv; j++ )
00177   {
00178     for( i = 0; i <= nu; i++ )
00179     {
00180       delta[j][i].x = (T)0;
00181       omega[j][i] = (T)0;
00182     }  
00183   }          
00184   for( C = 0; C < nP; C++ )
00185   {
00186     uspan = FindSpan( P[C].x, nu, pu, U );
00187     CalcBasisFunctions( P[C].x, uspan, pu, U, Nu );
00188 
00189     vspan = FindSpan( P[C].y, nv, pv, V );
00190     CalcBasisFunctions( P[C].y, vspan, pv, V, Nv );
00191 
00192     sum_w2 = (T)0;
00193     for( k = 0; k <= pu; k++ ) 
00194     {
00195       for( l = 0; l <= pv; l++ )
00196       {
00197         w[k][l] = Nu[k] * Nv[l];
00198         w2[k][l] = w[k][l] * w[k][l];
00199         sum_w2 += w2[k][l];      
00200       }
00201     }
00202     factor = (T)1 / (Sigma[C] * Sigma[C]); 
00203       
00204     uind = uspan - pu;
00205     vind = vspan - pv;
00206     for( k = 0; k <= pu; k++ )
00207     {
00208       for( l = 0; l <= pv; l++ )
00209       {
00210         w2[k][l] *= factor;             /* (weight/standard_deviation)^2 */
00211         
00212         delta[vind+l][uind+k].x += w2[k][l] * w[k][l] * P[C].z / sum_w2;
00213         omega[vind+l][uind+k] += w2[k][l];
00214       }
00215     }
00216   }
00217   for( j = 0; j <= nv; j++ )
00218   {
00219     for( i = 0; i <= nu; i++ )
00220     {
00221       if( omega[j][i] != (T)0 )
00222         delta[j][i].x /= omega[j][i];
00223       else
00224         delta[j][i].x = (T)0;
00225     }
00226   }                 
00227 }
00228 template void BAapproximate( 
00229              int nP, Ptr< point<float> >& P, Ptr<float>& Sigma,
00230              int nu, int pu, Ptr<float>& U,  
00231              int nv, int pv, Ptr<float>& V,
00232              Ptr< Ptr< point1<float> > >& delta );
00233 template void BAapproximate( 
00234              int nP, Ptr< point<double> >& P, Ptr<double>& Sigma,
00235              int nu, int pu, Ptr<double>& U,  
00236              int nv, int pv, Ptr<double>& V,
00237              Ptr< Ptr< point1<double> > >& delta );
00238 
00239 
00240 /*-------------------------------------------------------------------------*//**
00241   Multilevel BSpline approximation,
00242   Calculates a NURBS surface (one-dimensional), which approximates
00243   data points in 'P', (P[].z contains the function value, P[].x and P[] the
00244   location in the domain). An individual standard deviation for each data
00245   point can be given in 'Sigma'.
00246   (Remarks: the data point array P is changed - after the algorithm the P[].z
00247   contain the difference between the function values of the calculated
00248   surface and and the original value!!!,
00249   Output arrays U,V,Psi must be reserved by the caller:
00250   U: 2*pu + 2^(nIter-1) + 1,
00251   V: 2*pv + 2^(nIter-1) + 1,
00252   Psi: (pv + 2^(nIter-1))*(pu + 2^(nIter-1))                                  */   
00253 /*----------------------------------------------------------------------------*/
00254 template< class T >
00255 void MBAapproximate( 
00256        int nP, Ptr< point<T> >& P, bool useSigma, Ptr<T>& Sigma, int nIter,
00257        int pu, int pv, Ptr<T>& U, Ptr<T>& V, Ptr< Ptr< point1<T> > >& Psi )                      
00258 {
00259   Ptr<T> U1,V1,X;
00260   Ptr< Ptr< point1<T> > > Phi;
00261   int xp,i,j,nu,nv,s,maxSpans;
00262   point1<T> S;
00263   T d;
00264 
00265   if( nIter < 1 ) return;
00266   maxSpans = 1 << (nIter-1);
00267 
00268 /* --- reserve memory for local arrays ----------------------------- */
00269   
00270   U1.reserve_pool(pu + maxSpans + pu + 1);
00271   V1.reserve_pool(pv + maxSpans + pv + 1);
00272   i = Max(pu,pv);
00273   X.reserve_pool(i + maxSpans + i + 1);
00274 
00275   Phi.reserve_pool(pv + maxSpans);
00276   for( i = 0; i < maxSpans + pv; i++ )
00277     Phi[i].reserve_pool(pu + maxSpans);
00278 
00279 /* ----------------------------------------------------------------- */
00280 
00281   for( i = 0; i <= pu; i++ )
00282   {
00283     U[i] = (T)0;
00284     U[pu+1+i] = (T)1;
00285   }
00286   for( i = 0; i <= pv; i++ )
00287   {
00288     V[i] = (T)0;
00289     V[pv+1+i] = (T)1;
00290   }  
00291   
00292   for( j = 0; j <= pv; j++ )
00293     for( i = 0; i <= pu; i++ )
00294       set( Psi[j][i], (T)0 );
00295 
00296   s = 1;
00297   nu = pu;
00298   nv = pv;
00299 
00300   do
00301   {
00302     if( useSigma )
00303        BAapproximate( nP, P, Sigma, nu, pu, U, nv, pv, V, Phi );
00304     else
00305        BAapproximate( nP, P, nu, pu, U, nv, pv, V, Phi );
00306 
00307     for( j = 0; j <= nv; j++ )
00308       for( i = 0; i <= nu; i++ )
00309         Psi[j][i].x += Phi[j][i].x;
00310        
00311     for( i = 0; i < nP; i++ )
00312     {
00313       SurfacePoint( P[i].x, P[i].y, nu, pu, U, nv, pv, V, Phi, &S );               
00314       P[i].z -= S.x;
00315     }
00316 
00317     if( s >= maxSpans )          /* --- ready --- */
00318       break;         
00319 
00320     s <<= 1;
00321     
00322     d = (T)1/(T)s;
00323     for( i = pu+1, xp = 0; i <= nu+1; i++, xp++ ) 
00324       X[xp] = U[i] - d;
00325     RefineSurface( nu, pu, U, nv, pv, V, Psi, 
00326                    X, xp-1, gul::u_direction, U1, V1, Phi );      
00327     nu += xp;
00328     
00329     for( i = pv+1, xp = 0; i <= nv+1; i++, xp++ ) 
00330       X[xp] = V[i] - d;
00331     RefineSurface( nu, pu, U1, nv, pv, V1, Phi,
00332                    X, xp-1, gul::v_direction, U, V, Psi );
00333     nv += xp;
00334       
00335   }while(1);
00336 }
00337 template void MBAapproximate( 
00338        int nP, Ptr< point<float> >& P, bool useSigma, Ptr<float>& Sigma,
00339        int nIter, int pu, int pv, Ptr<float>& U, Ptr<float>& V,
00340        Ptr< Ptr< point1<float> > >& Psi );
00341 template void MBAapproximate( 
00342        int nP, Ptr< point<double> >& P, bool useSigma, Ptr<double>& Sigma,
00343        int nIter, int pu, int pv, Ptr<double>& U, Ptr<double>& V,
00344        Ptr< Ptr< point1<double> > >& Psi );
00345 
00346 
00347 /*------------------------------------------------------------------------*//**
00348   utility class for finding a rotation, so that the volume of the bounding 
00349   box of a set of points gets minimal volume. this can be done much more
00350   optimal (by using RAPID's method for calculating oriented bounding boxes)! */
00351 /*---------------------------------------------------------------------------*/
00352 template< class T >
00353 class minbbox_rec
00354 { 
00355 public:
00356   Ptr< point<T> > P;
00357   int             nP;
00358   T theta0_x;
00359   T theta0_y;
00360   T theta0_z;
00361 
00362   minbbox_rec( int anP, Ptr< point<T> >& aP, T theta0x, T theta0y, T theta0z )
00363   {
00364     nP = anP; P = aP; 
00365     theta0_x = theta0x; theta0_y = theta0y; theta0_z = theta0z;
00366   }
00367   T volume( T theta_x, T theta_y, T theta_z )
00368   {
00369     mat4x4<T> m1 = mat4x4<T>::rotate_x(theta0_x + theta_x);
00370     mat4x4<T> m2 = mat4x4<T>::rotate_y(theta0_y + theta_y);
00371     mat4x4<T> m3 = mat4x4<T>::rotate_z(theta0_z + theta_z);
00372     mat4x4<T> m;
00373     m = m1 * m2 * m3;
00374     vec4<T> v,vt;
00375     T minx,maxx,miny,maxy,minz,maxz;
00376 
00377     v[0] = P[0].x;  v[1] = P[0].y;  v[2] = P[0].z;  v[3] = 1.0;
00378     vt = v * m;
00379     minx = maxx = vt[0];
00380     miny = maxy = vt[1];
00381     minz = maxz = vt[2];
00382 
00383     for( int i = 1; i < nP; i++ )
00384     {
00385       v[0] = P[i].x;  v[1] = P[i].y;  v[2] = P[i].z;  v[3] = 1.0;
00386       vt = v * m;
00387       if( vt[0] < minx ) minx = vt[0];
00388       else if( vt[0] > maxx ) maxx = vt[0];
00389       if( vt[1] < miny ) miny = vt[1];
00390       else if( vt[1] > maxy ) maxy = vt[1];
00391       if( vt[2] < minz ) minz = vt[2];
00392       else if( vt[2] > maxz ) maxz = vt[2];
00393     }
00394     return (maxx-minx)*(maxy-miny)*(maxz-minz);  /* volume */  
00395   }
00396   static T minimize_about_z_cb( T theta, void *data )
00397   {
00398     minbbox_rec *m = (minbbox_rec *)data;
00399     return m->volume( (T)0, (T)0, theta );
00400   }
00401 };
00402 template class minbbox_rec<float>;
00403 template class minbbox_rec<double>;
00404 
00405 
00406 /*-----------------------------------------------------------------------*//**
00407   calculate the rotation about the Z-axis, so that the bounding box
00408   of the given Points 'P' gets minimal volume. 'mintol' is the minimum change
00409   in the domaain between two iterations (in degree), and 'maxits' the maximum
00410   number of iterations                                                      */
00411 /*------------------------------------------------------------------------- */
00412 template< class T >
00413 T MinimizeBBoxAboutZ( int nP, Ptr< point<T> >& P, T mintol, int maxits )
00414 {
00415   T minx,maxx,miny,maxy,minz,maxz,theta,V,V1;
00416   minbbox_rec<T> mr( nP, P, (T)0, (T)0, (T)0 );
00417   
00418   CalcBoundingBoxE( nP, P, minx, maxx, miny, maxy, minz, maxz );
00419   V = (maxx-minx)*(maxy-miny)*(maxz-minz);  /* volume at 0 and 90 degree */
00420                                             /* between these: */
00421   V1 = mr.volume( (T)0, (T)0, rtr<T>::golden_c() * rtr<T>::pi()/(T)2 );  
00422   if( V1 < V )  
00423   {
00424     GoldenSectionSearch( 
00425        (T)0, rtr<T>::golden_c() * rtr<T>::pi()/(T)2, rtr<T>::pi()/(T)2,
00426        minbbox_rec<T>::minimize_about_z_cb, (void *)&mr, 
00427        mintol*rtr<T>::pi()/(T)180, maxits, &theta,
00428        &V );
00429   }
00430   else
00431     theta = (T)0;
00432 
00433   return theta;
00434 }  
00435 template float MinimizeBBoxAboutZ( int nP, Ptr< point<float> >& P, 
00436                                    float mintol, int maxits );
00437 template double MinimizeBBoxAboutZ( int nP, Ptr< point<double> >& P,
00438                                     double mintol, int maxits );
00439 
00440 
00441 /*-------------------------------------------------------------------*//**
00442   executes the MBA algorithm and constructs a 3-dimensional surface
00443   from the results (x(),y() are identity mappings).
00444   when 'minimize' is set, the base rectangle in the xy-plane is
00445   chosen so that its area is minimal                                    */
00446 /* ---------------------------------------------------------------------*/
00447 template< class T, class HP >
00448 GULAPI void SurfaceOverXYPlane( 
00449           int nDatPoints, Ptr< point<T> >& datPoints,
00450           bool useStdDevs, Ptr<T>& StdDevs,
00451           bool minimize, int nIter,
00452           int pu, int pv,
00453           int *ret_nu, Ptr<T> *retU,
00454           int *ret_nv, Ptr<T> *retV,
00455           Ptr< Ptr<HP> > *retPw )
00456 {
00457 
00458   T minx,maxx,miny,maxy,minz,maxz;
00459   Ptr< point<T> > mbaPoints;
00460   int ref_nu, ref_nv, mba_nu, mba_nv, nu, nv;
00461   int ref_pu, ref_pv, mba_pu, mba_pv, i, j; 
00462   Ptr<T> refU, refV, mbaU, mbaV, U, V;
00463   Ptr< Ptr< point<T> > > refP, tmp1P, P;
00464   Ptr< Ptr< point1<T> > > mbaPz, tmp2P;
00465   Ptr<T> tmp1U, tmp1V, tmp2U, tmp2V;
00466   int tmp1_nu, tmp1_nv, tmp2_nu, tmp2_nv;
00467   int tmp1_pu, tmp1_pv, tmp2_pu, tmp2_pv;
00468   T x,y,z,ox,oy,sint,cost,theta;
00469   Ptr< Ptr<HP> > Pw;
00470   point<T> CP;
00471 
00472   mbaPoints.reserve_pool(nDatPoints);
00473 
00474   if( minimize != 0 )
00475   {
00476     /* --- minimize area of base rectangle in xy-plane --------- */ 
00477 
00478     theta = MinimizeBBoxAboutZ( nDatPoints, datPoints, (T)1, 20 );
00479 
00480     sint = rtr<T>::sin(theta);
00481     cost = rtr<T>::cos(theta);
00482 
00483     // 1. point:
00484     ox = datPoints[0].x;
00485     oy = datPoints[0].y;
00486     z = datPoints[0].z;
00487     minz = maxz = z;
00488     minx = maxx = x = cost * ox + sint * oy;
00489     miny = maxy = y = cost * oy - sint * ox;
00490     mbaPoints[0].x = x;
00491     mbaPoints[0].y = y;
00492     mbaPoints[0].z = z;         
00493       
00494     // remaining points:      
00495     for( i = 1; i < nDatPoints; i++ )
00496     {
00497       ox = datPoints[i].x;
00498       oy = datPoints[i].y;
00499       z = datPoints[i].z;
00500       x = cost * ox + sint * oy;
00501       y = cost * oy - sint * ox;
00502 
00503       if( x < minx ) minx = x;
00504       else if( x > maxx ) maxx = x;
00505       if( y < miny ) miny = y;
00506       else if( y > maxy ) maxy = y;
00507       if( z < minz ) minz = z;
00508       else if( z > maxz ) maxz = z;
00509 
00510       mbaPoints[i].x = x;
00511       mbaPoints[i].y = y;
00512       mbaPoints[i].z = z;         
00513     }
00514     // normalise coordinates:
00515     for( i = 0; i < nDatPoints; i++ )
00516     {
00517       mbaPoints[i].x = (mbaPoints[i].x - minx) / (maxx-minx);
00518       if( mbaPoints[i].x < (T)0 ) mbaPoints[i].x = (T)0;
00519       else if( mbaPoints[i].x > (T)1 ) mbaPoints[i].x = (T)1;
00520       mbaPoints[i].y = (mbaPoints[i].y - miny) / (maxy-miny);
00521       if( mbaPoints[i].y < (T)0 ) mbaPoints[i].y = (T)0;
00522       else if( mbaPoints[i].y > (T)1 ) mbaPoints[i].y = (T)1;
00523       mbaPoints[i].z = (mbaPoints[i].z - minz) / (maxz-minz);
00524     } 
00525   }
00526   else
00527   {
00528     /* --- do not minimize area of base rectangle in xy-plane --------- */ 
00529 
00530     CalcBoundingBoxE( nDatPoints, datPoints,
00531                       minx, maxx, miny, maxy, minz, maxz );
00532     // normalise coordinates:
00533     for( i = 0; i < nDatPoints; i++ )
00534     {
00535       mbaPoints[i].x = (datPoints[i].x - minx) / (maxx-minx);
00536       if( mbaPoints[i].x < (T)0 ) mbaPoints[i].x = (T)0;
00537       else if( mbaPoints[i].x > (T)1 ) mbaPoints[i].x = (T)1;
00538       mbaPoints[i].y = (datPoints[i].y - miny) / (maxy-miny);
00539       if( mbaPoints[i].y < (T)0 ) mbaPoints[i].y = (T)0;
00540       else if( mbaPoints[i].y > (T)1 ) mbaPoints[i].y = (T)1;
00541       mbaPoints[i].z = (datPoints[i].z - minz) / (maxz-minz);
00542     }
00543   }  
00544   /* ------ do the MBA-Algorithm: ------------------------------------ */
00545 
00546   // reserve return arrays
00547   mba_nu = pu + (1<<(nIter-1)) - 1;
00548   mbaU.reserve_pool( 2*pu + (1<<(nIter-1)) + 1 );
00549   mba_nv = pv + (1<<(nIter-1)) - 1;
00550   mbaV.reserve_pool( 2*pv + (1<<(nIter-1)) + 1 );
00551   mbaPz.reserve_pool(mba_nv+1);
00552   Pw.reserve_pool(mba_nv+1);
00553   for( i = 0; i < mba_nv+1; i++ )
00554   {
00555     mbaPz[i].reserve_pool(mba_nu+1);
00556     Pw[i].reserve_pool(mba_nu+1);
00557   }             
00558   MBAapproximate<T>( nDatPoints, mbaPoints, useStdDevs, StdDevs,
00559                      nIter, pu, pv, mbaU, mbaV, mbaPz ); 
00560 
00561   /* ---- construct a 3d return surface: --------------------------------- */
00562 
00563   // build a bilinear basis surface
00564   refU.reserve_pool(4);
00565   for( i = 0; i < 2; i++ )
00566   {
00567     refU[i] = (T)0;
00568     refU[i+2] = (T)1;
00569   }     
00570   refV = refU;
00571   ref_nu = 1;
00572   ref_pu = 1;
00573   ref_nv = 1;
00574   ref_pv = 1;
00575 
00576   refP.reserve_pool(2);
00577   refP[0].reserve_pool(2);
00578   refP[1].reserve_pool(2);
00579 
00580   refP[0][0].x = (T)0; refP[0][0].y = (T)0; refP[0][0].z = (T)0;
00581   refP[0][1].x = (T)1; refP[0][1].y = (T)0; refP[0][1].z = (T)0;
00582   refP[1][0].x = (T)0; refP[1][0].y = (T)1; refP[1][0].z = (T)0;
00583   refP[1][1].x = (T)1; refP[1][1].y = (T)1; refP[1][1].z = (T)0;
00584 
00585   /* --- make base surface and surface created by MBA compatible ------ */
00586 
00587   MakeSurfacesCompatible<T,point1<T>,point<T> >( 
00588               mba_nu, pu, mbaU,  mba_nv, pv, mbaV, mbaPz, 
00589               ref_nu, ref_pu, refU, ref_nv, ref_pv, refV, refP,
00590               gul::v_direction,
00591               &tmp2_nu, &tmp2_pu, &tmp2U, &tmp2_nv, &tmp2_pv, &tmp2V, &tmp2P,
00592               &tmp1_nu, &tmp1_pu, &tmp1U, &tmp1_nv, &tmp1_pv, &tmp1V, &tmp1P );
00593 
00594   MakeSurfacesCompatible<T,point1<T>,point<T> >( 
00595               tmp2_nu, tmp2_pu, tmp2U, tmp2_nv, tmp2_pv, tmp2V, tmp2P,
00596               tmp1_nu, tmp1_pu, tmp1U, tmp1_nv, tmp1_pv, tmp1V, tmp1P,
00597               gul::u_direction,
00598               &mba_nu, &mba_pu, &mbaU, &mba_nv, &mba_pv, &mbaV, &mbaPz,
00599               &nu, &pu, &U, &nv, &pv, &V, &P );
00600 
00601   /* set z-coordinate of result surface control points: */
00602 
00603   for( j = 0; j <= nv; j++ )
00604     for( i = 0; i <= nu; i++ ) 
00605       P[j][i].z = mbaPz[j][i].x;
00606 
00607   /* denormalise control points: */
00608 
00609   for( j = 0; j <= nv; j++ )
00610     for( i = 0; i <= nu; i++ ) 
00611     {
00612       CP.x = (P[j][i].x * (maxx-minx)) + minx;
00613       CP.y = (P[j][i].y * (maxy-miny)) + miny;
00614       CP.z = (P[j][i].z * (maxz-minz)) + minz;
00615       Pw[j][i] = CP;
00616    }  
00617 
00618   if( minimize != 0 )
00619   {
00620     /* --- rotate surface to the original orientation ------------------ */
00621 
00622     sint = rtr<T>::sin(-theta);
00623     cost = rtr<T>::cos(-theta);
00624 
00625     for( j = 0; j <= nv; j++ )
00626       for( i = 0; i <= nu; i++ ) 
00627       {
00628         ox = Pw[j][i].x;
00629         oy = Pw[j][i].y; 
00630 
00631         x = cost * ox + sint * oy;
00632         y = cost * oy - sint * ox;
00633 
00634         Pw[j][i].x = x;
00635         Pw[j][i].y = y;        
00636       }  
00637   }        
00638     
00639   /* ready: */
00640 
00641   *ret_nu = nu;
00642   *retU = U;
00643   *ret_nv = nv;
00644   *retV = V;
00645   *retPw = Pw;
00646 }
00647 template GULAPI void SurfaceOverXYPlane( 
00648           int nDatPoints, Ptr< point<float> >& datPoints,
00649           bool useStdDevs, Ptr<float>& StdDevs,
00650           bool minimize, int nIterations,
00651           int pu, int pv,
00652           int *ret_nu, Ptr<float> *retU,
00653           int *ret_nv, Ptr<float> *retV,
00654           Ptr< Ptr< point<float> > > *retPw );
00655 template GULAPI void SurfaceOverXYPlane( 
00656           int nDatPoints, Ptr< point<double> >& datPoints,
00657           bool useStdDevs, Ptr<double>& StdDevs,
00658                 bool minimize, int nIterations,
00659           int pu, int pv,
00660           int *ret_nu, Ptr<double> *retU,
00661           int *ret_nv, Ptr<double> *retV,
00662           Ptr< Ptr< point<double> > > *retPw );
00663 
00664 
00665 /*-------------------------------------------------------------------*//**
00666   creates a surface with the MBA algorithm. 'Dat' contains the 3d
00667   values and 'Dom' the locations in the parametric domain 
00668   (output arrays are reserved automatically)                            */
00669 /* ---------------------------------------------------------------------*/
00670 
00671 template< class T >
00672 void GULAPI MBASurface( int nDat, Ptr< point<T> > Dat, Ptr< point2<T> > Dom, 
00673                  int nIter, int pu, int pv,          
00674                  int *ret_nu, Ptr<T> *retU,
00675                  int *ret_nv, Ptr<T> *retV,
00676                  Ptr< Ptr< point<T> > > *retP )
00677 {
00678   T minu,maxu,minv,maxv;
00679   int nu,nv,i,j;
00680   Ptr<T> U,V,null;
00681   Ptr< Ptr< point1<T> > > F;
00682   Ptr< point<T> > coord;
00683   Ptr< Ptr< point<T> > > Pw;
00684 
00685   // reserve work arrays
00686 
00687   coord.reserve_pool(nDat);
00688 
00689   nu = pu + (1<<(nIter-1)) - 1;
00690   U.reserve_pool( 2*pu + (1<<(nIter-1)) + 1 );
00691   nv = pv + (1<<(nIter-1)) - 1;
00692   V.reserve_pool( 2*pv + (1<<(nIter-1)) + 1 );
00693   F.reserve_pool(nv+1);
00694   Pw.reserve_pool(nv+1);
00695   for( i = 0; i < nv+1; i++ )
00696   {
00697     F[i].reserve_pool(nu+1);
00698     Pw[i].reserve_pool(nu+1);
00699   }  
00700 
00701   // normalize domain points
00702 
00703   CalcBoundingBoxE( nDat, Dom, minu, maxu, minv, maxv );
00704 
00705   for( i = 0; i < nDat; i++ )
00706   {
00707     coord[i].x = (Dom[i].x - minu) / (maxu-minu);
00708     if( coord[i].x < (T)0 ) coord[i].x = (T)0;
00709     else if( coord[i].x > (T)1 ) coord[i].x = (T)1;
00710 
00711     coord[i].y = (Dom[i].y - minv) / (maxv-minv);
00712     if( coord[i].y < (T)0 ) coord[i].y = (T)0;
00713     else if( coord[i].y > (T)1 ) coord[i].y = (T)1;
00714   }
00715 
00716   /* -------- calculate x-coordinate function ----------------------------- */
00717 
00718   for( i = 0; i < nDat; i++ )
00719     coord[i].z = Dat[i].x;
00720 
00721   MBAapproximate<T>( nDat, coord, false, null,
00722                      nIter, pu, pv, U, V, F ); 
00723 
00724   for( i = 0; i <= nv; i++ )
00725     for( j = 0; j <= nu; j++ )
00726       Pw[i][j].x = F[i][j].x;  
00727 
00728   /* -------- calculate y-coordinate function ----------------------------- */
00729 
00730   for( i = 0; i < nDat; i++ )
00731     coord[i].z = Dat[i].y;
00732 
00733   MBAapproximate<T>( nDat, coord, false, null,
00734                      nIter, pu, pv, U, V, F ); 
00735 
00736   for( i = 0; i <= nv; i++ )
00737     for( j = 0; j <= nu; j++ )
00738       Pw[i][j].y = F[i][j].x;  
00739 
00740   /* -------- calculate z-coordinate function ----------------------------- */
00741 
00742   for( i = 0; i < nDat; i++ )
00743     coord[i].z = Dat[i].z;
00744 
00745   MBAapproximate<T>( nDat, coord, false, null,
00746                      nIter, pu, pv, U, V, F ); 
00747 
00748   for( i = 0; i <= nv; i++ )
00749     for( j = 0; j <= nu; j++ )
00750       Pw[i][j].z = F[i][j].x;  
00751 
00752   /* ----------- ready ---------------------------------------------------- */
00753 
00754   *ret_nu = nu;
00755   *retU = U;
00756   *ret_nv = nv;
00757   *retV = V;
00758   *retP = Pw;
00759 }
00760 
00761 // template instantiation
00762 template GULAPI void MBASurface( 
00763                      int nDat, const Ptr< point<float> > Dat, const Ptr< point2<float> > Dom, 
00764                      int nIter, int pu, int pv,          
00765                      int *ret_nu, Ptr<float> *retU,
00766                      int *ret_nv, Ptr<float> *retV,
00767                      Ptr< Ptr< point<float> > > *retP );
00768 // template instantiation
00769 template GULAPI void MBASurface( 
00770                      int nDat, const Ptr< point<double> > Dat, const Ptr< point2<double> > Dom, 
00771                      int nIter, int pu, int pv,          
00772                      int *ret_nu, Ptr<double> *retU,
00773                      int *ret_nv, Ptr<double> *retV,
00774                      Ptr< Ptr< point<double> > > *retP );
00775 
00776 
00777 
00778 }
00779 
00780 
00781 

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