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

gunu_tesselate.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 "gust_new.h"
00026 #include "gul_vector.h"
00027 #include "guge_linear.h"
00028 #include "guge_normalize.h"
00029 #include "gunu_basics.h"
00030 #include "gunu_derivatives.h"
00031 #include "gunu_divide.h"
00032 #include "gunu_intersect.h"
00033 #include "gunu_linearize.h"
00034 #include "guar_exact.h"
00035 #include "gugr_basics.h"
00036 #include "gugr_split.h"
00037 #include "gul_std.h"
00038 #include "gugr_regularize.h"
00039 #include "gugr_triangulate.h"
00040 #include "gugr_planesweep.h"
00041 #include "gul_io.h"
00042 #include "gul_std.h"
00043 #include "gugr_io.h"
00044 
00045 #include "gunu_tesselate.h"
00046 
00047 using gul::List;
00048 using gul::List2;
00049 using gul::ListNode;
00050 using gul::point;
00051 using gul::hpoint;
00052 using gul::point2;
00053 using gul::hpoint2;
00054 using gul::curve;
00055 using gul::Min;
00056 using gul::set;
00057 // using gul::is_zero;
00058 using gul::normalize;
00059 using gul::euclid;
00060 using guar::rational;
00061 using gugr::graph_vertex;
00062 using gugr::graph_edge;
00063 using gugr::cut_info;
00064 using gugr::IntersectWithVerticals;
00065 using gugr::DivideVerticalStrips;
00066 using gugr::IntersectWithHorizontals;
00067 using gugr::DivideHorizontalStrips;
00068 using gugr::EdgeCycle;
00069 using gugr::graph_vertex_list;
00070 using gugr::graph_edge_list;
00071 using gugr::vertex_rep;
00072 using gugr::coord2int;
00073 
00074 /*-------------------------------------------------------------------
00075   approximate trimmed NURBS surface with triangles
00076 --------------------------------------------------------------------*/
00077 namespace gunu {
00078 
00079 template< class T, class HP >
00080 void _DoLinearizeTrimmedSurface( 
00081             int current_iter, int max_iter,
00082             TessInfo<T,HP> *A,
00083             gugr::GraphInfo *G, gugr::GraphConvInfo<T> *Gconv,
00084             const T tol,
00085             void outfunc1( gunu::TessInfo<T,HP> *, void * ),                                   
00086             void outfunc2( gunu::TessInfo<T,HP> *, gugr::GraphInfo *, 
00087                            gugr::GraphConvInfo<T> *, void * ),
00088             void *usrdata )
00089 {
00090   int nA,i;
00091   TessInfo<T,HP> **pA;  
00092   gugr::GraphInfo *Gsub[4];
00093 
00094   /*
00095   cout << "iter: " << current_iter << "\n";
00096       
00097   cout << gul::dump_surf<T,HP>( 
00098               A->org->nu, A->org->pu, A->org->U,
00099               A->org->nv, A->org->pv, A->org->V,
00100               A->org->Pw ) << "\n";  
00101   */
00102 
00103   if( !A->linearized && !A->divided )
00104   {      
00105     if( current_iter < max_iter )
00106       LinearizeOrDivide<T,HP>( A, tol );
00107     else
00108       A->linearized = 1;
00109   }
00110 
00111   /*
00112   cout << "in LinearizeTrimmedSurface\n";
00113   cout << "**************************\n";
00114   gugr::Dump<T>::dump_vertices( G->V.head );
00115   gugr::Dump<T>::dump_edges( G->E.head );
00116   */
00117 
00118   if( !A->linearized )
00119   {
00120 
00121     for( i = 0; i < 4; i++ ) Gsub[i] = new gugr::GraphInfo();
00122     gugr::SplitGraph( G, (A->u1+A->u2)/(T)2.0, (A->v1+A->v2)/(T)2.0, Gconv, 
00123                       Gsub );
00124     
00125     nA = 4;
00126     pA = A->sub;
00127 
00128     for( i = 0; i < nA; i++ )          /* Rekursion */
00129     {
00130       if( (Gsub[i]->V.nElems==4) && (Gsub[i]->E.nElems==4) )
00131       {
00132         if( Gsub[i]->face > 0 ) 
00133           DoLinearizeSurface( current_iter+1, max_iter, pA[i], tol,
00134                               outfunc1, usrdata );
00135       }
00136       else
00137       {
00138         _DoLinearizeTrimmedSurface( current_iter+1, max_iter, 
00139                   pA[i], Gsub[i], Gconv, tol, outfunc1, outfunc2, usrdata );
00140       }
00141      
00142       delete pA[i];
00143       pA[i] = 0;      
00144       delete Gsub[i];
00145       Gsub[i] = 0;
00146     }
00147   }
00148   else       /* ------- output ------------------ */  
00149   {
00150     if( (G->V.nElems==4) && (G->E.nElems==4) )
00151     {
00152       if( G->face > 0 ) outfunc1( A, usrdata );
00153     }
00154     else
00155     {
00156       outfunc2( A, G, Gconv, usrdata );
00157     }    
00158   }
00159 }
00160 
00161 /*-------------------------------------------------------------------
00162   approximate trimmed NURBS surface with triangles
00163 --------------------------------------------------------------------*/
00164 
00165 template void _DoLinearizeTrimmedSurface( 
00166        int current_iter, int max_iter,
00167        TessInfo<float,hpoint<float> > *A,
00168        gugr::GraphInfo *G, gugr::GraphConvInfo<float> *Gconv,
00169        const float tol,
00170        void outfunc1( TessInfo<float,hpoint<float> > *, void * ),                                   
00171        void outfunc2( TessInfo<float,hpoint<float> > *, gugr::GraphInfo *, 
00172                       gugr::GraphConvInfo<float> *, void * ),
00173        void *usrdata );
00174 template void _DoLinearizeTrimmedSurface( 
00175        int current_iter, int max_iter,
00176        TessInfo<double,hpoint<double> > *A,
00177        gugr::GraphInfo *G, gugr::GraphConvInfo<double> *Gconv,
00178        const double tol,
00179        void outfunc1( TessInfo<double,hpoint<double> > *, void * ),                                   
00180        void outfunc2( TessInfo<double,hpoint<double> > *, gugr::GraphInfo *, 
00181                       gugr::GraphConvInfo<double> *, void * ),
00182        void *usrdata );
00183 
00184 template void _DoLinearizeTrimmedSurface( 
00185        int current_iter, int max_iter,
00186        TessInfo<float,point<float> > *A,
00187        gugr::GraphInfo *G, gugr::GraphConvInfo<float> *Gconv,
00188        const float tol,
00189        void outfunc1( TessInfo<float,point<float> > *, void * ),                                   
00190        void outfunc2( TessInfo<float,point<float> > *, gugr::GraphInfo *, 
00191                       gugr::GraphConvInfo<float> *, void * ),
00192        void *usrdata );
00193 template void _DoLinearizeTrimmedSurface( 
00194        int current_iter, int max_iter,
00195        TessInfo<double,point<double> > *A,
00196        gugr::GraphInfo *G, gugr::GraphConvInfo<double> *Gconv,
00197        const double tol,
00198        void outfunc1( TessInfo<double,point<double> > *, void * ),                                   
00199        void outfunc2( TessInfo<double,point<double> > *, gugr::GraphInfo *, 
00200                       gugr::GraphConvInfo<double> *, void * ),
00201        void *usrdata );
00202 
00203 
00204 /*-------------------------------------------------------------------------
00205   approximate trimmed NURBS surface with triangles, another user interface
00206   function
00207 -------------------------------------------------------------------------*/
00208 
00209 template< class T, class HP >
00210 GULAPI void TessQuadCb( TessInfo<T,HP> *A, void *usrdata )
00211 {
00212   gul::point<T> P00,P01,P10,P11,T00,T01,T10,T11;
00213   int nu,nv,pu,pv;
00214   TessCbData<T> *cb = (TessCbData<T> *)usrdata;
00215 
00216   P00 = A->org->P00;
00217   P01 = A->org->P01;
00218   P10 = A->org->P10;
00219   P11 = A->org->P11;
00220 
00221   if( cb->need_normals == 0 )
00222   {
00223     cb->quadfunc( cb->usrdata, 
00224                  &P00, &P01, &P10, &P11, NULL, NULL, NULL, NULL,
00225                  NULL, NULL, NULL, NULL );
00226   }
00227   else                             /* Calc Normals */
00228   {
00229     nu = A->org->nu;
00230     pu = A->org->pu;
00231     nv = A->org->nv;
00232     pv = A->org->pv;
00233     Ptr< Ptr < HP > >& Pw = A->org->Pw;
00234 
00235     CalcNormal_U0V0<T>( nu, pu, nv, pv, Pw, &T00 );
00236     CalcNormal_U1V0<T>( nu, pu, nv, pv, Pw, &T01 );
00237     CalcNormal_U0V1<T>( nu, pu, nv, pv, Pw, &T10 );
00238     CalcNormal_U1V1<T>( nu, pu, nv, pv, Pw, &T11 );
00239 
00240     cb->quadfunc( cb->usrdata, &P00, &P01, &P10, &P11,
00241                   &T00, &T01, &T10, &T11, &A->u1, &A->u2, &A->v1, &A->v2 );
00242   }
00243 }
00244 
00245 // template instantiation
00246 template GULAPI void TessQuadCb( TessInfo<float,hpoint<float> > *A, void *usrdata );
00247 template GULAPI void TessQuadCb( TessInfo<float,point<float> > *A, void *usrdata );
00248 template GULAPI void TessQuadCb( TessInfo<double,hpoint<double> > *A, void *usrdata );
00249 template GULAPI void TessQuadCb( TessInfo<double,point<double> > *A, void *usrdata );
00250 
00251 /*--------------------------------------------------------------------- 
00252   function values and normals in the inside of a quad are calculated
00253   
00254  V1 *----------* U1 = U2   with triangular interpolation 
00255     |        / |           (Barycentric coordinates)
00256     |      /   |
00257     |    /     |
00258     |  /       |
00259     |/         /
00260     *----------* V2
00261  W1 = W2
00262 
00263 --------------------------------------------------------------------- */
00264 
00265 template< class T >
00266 struct vertex_convert_cache
00267 {
00268   point<T>  p;
00269   point<T>  n;
00270   point2<T> d;  // domain coordinates
00271 
00272   void *operator new( size_t s )
00273   {
00274     size_t dummy;
00275     void *p = gust::PoolAlloc( s, &dummy );
00276     if( p == NULL ) throw gul::PoolAllocError();
00277     return(p);
00278   }
00279   void operator delete( void *p, size_t s )
00280   {
00281     if( p != 0 ) gust::PoolFree( p, s );
00282   }
00283 };
00284 
00285 template< class T >
00286 vertex_convert_cache<T> *FillVertexCache( 
00287          vertex_rep *vert, const int code, bool normals,
00288          const T& orgx, const T& orgy, const T& scale,
00289          const T& u0, const T& v0, const T& w, const T& h, const T& a,
00290          const point<T>& W1, const point<T>& V2,
00291          const point<T>& V1, const point<T>& U1,
00292          const point<T>& W1n, const point<T>& V2n,
00293          const point<T>& V1n, const point<T>& U1n )
00294 {
00295   guar::Interval iu,iv;
00296   T u,v,ru,rv,tu,tv,tw;
00297   vertex_convert_cache<T> *buf;
00298   
00299   vert->reserved.p = buf = new vertex_convert_cache<T>();
00300       
00301   iu = vert->v.x.get_bounds();
00302   iv = vert->v.y.get_bounds();
00303   u = (T)((iu.m_low+iu.m_high)/2.0);
00304   v = (T)((iv.m_low+iv.m_high)/2.0);
00305   u = buf->d.x = gugr::cnv2coord(u)*scale + orgx; 
00306   v = buf->d.y = gugr::cnv2coord(v)*scale + orgy; 
00307   ru = u-u0;
00308   rv = v-v0;
00309   if( code > 0 )  // vertex lies above quad diagonal
00310   {
00311     tu = h*ru/a;
00312     tw = w*(h-rv)/a;
00313     tv = (T)1.0 - tu - tw;
00314     buf->p = tu*U1 + tv*V1 + tw*W1;
00315     if( normals ) buf->n = tu*U1n + tv*V1n + tw*W1n;       
00316   }
00317   else if( code < 0 )  // below diagonal
00318   {
00319     tu = w*rv/a;
00320     tw = h*(w-ru)/a;
00321     tv = (T)1.0 - tu - tw;
00322     buf->p = tu*U1 + tv*V2 + tw*W1;
00323     if( normals ) buf->n = tu*U1n + tv*V2n + tw*W1n;
00324   }
00325   else       // on diagonal 
00326   {
00327     tw = (w-ru)/w;        /* interpolate linearly on diagonal */
00328     tu = (T)1.0 - tw;
00329     buf->p = tw*W1 + tu*U1;
00330     if( normals ) buf->n = tw*W1n + tu*U1n;
00331   }
00332   return buf;
00333 }
00334 
00335 template< class T, class HP > 
00336 GULAPI void TessTriCb( TessInfo<T,HP> *A, gugr::GraphInfo *G, 
00337                        gugr::GraphConvInfo<T> *Gconv, void *data )
00338 {
00339   gugr::triangle_list Tri;
00340   gugr::triangle *tri,*tri_next;
00341   TessCbData<T> *cb = (TessCbData<T> *)data;
00342   point<T> T00,T01,T10,T11;
00343   vertex_convert_cache<T> *c1,*c2,*c3;
00344  
00345   const point<T>& P00 = A->org->P00;
00346   const point<T>& P01 = A->org->P01;
00347   const point<T>& P10 = A->org->P10;
00348   const point<T>& P11 = A->org->P11;
00349   const int& nu = A->org->nu;
00350   const int& pu = A->org->pu;  
00351   const int& nv = A->org->nv;
00352   const int& pv = A->org->pv;
00353   Ptr< Ptr< HP > >& Pw = A->org->Pw;
00354 
00355   const T& orgx = Gconv->minx;
00356   const T& orgy = Gconv->miny;
00357   const T& scale = Gconv->scale;
00358 
00359   const T& u0 = A->u1;
00360   const T& u1 = A->u2;
00361   const T& v0 = A->v1;
00362   const T& v1 = A->v2;
00363   
00364   bool normals = cb->need_normals;
00365   void *usrdata = cb->usrdata;
00366 
00367   T w = u1-u0; // width of quad  (u)
00368   T h = v1-v0; // height of quad (v)
00369   T a = w*h;   // area of quad
00370 
00371   /*
00372   cout << "before insertion of diagonal\n";
00373   cout << "***************************\n";
00374   gugr::Dump<T>::dump_vertices( G->V.head );
00375   gugr::Dump<T>::dump_edges( G->E.head );
00376   */
00377 
00378   gugr::InsertDiagonal( &(G->E), &(G->V), G->P[0][0], G->P[1][1] );
00379 
00380   /* 
00381   cout << "after insertion of diagonal\n";
00382   cout << "***************************\n";
00383   gugr::Dump<T>::dump_vertices( G->V.head );
00384   gugr::Dump<T>::dump_edges( G->E.head );
00385   */
00386 
00387   gugr::Regularize( &(G->E), &(G->V) );
00388 
00389   /*
00390   cout << "after regularization\n";
00391   cout << "***************************\n";
00392   gugr::Dump<T>::dump_vertices( G->V.head );
00393   gugr::Dump<T>::dump_edges( G->E.head );
00394   */
00395 
00396   gugr::Triangulate( &(G->E), &(G->V), Gconv->FarMinX, &Tri );
00397 //  Tri.DeleteElems();  
00398 
00399   if( normals )     /* calc Normals */
00400   {
00401     CalcNormal_U0V0<T>( nu, pu, nv, pv, Pw, &T00 );
00402     CalcNormal_U1V0<T>( nu, pu, nv, pv, Pw, &T01 );
00403     CalcNormal_U0V1<T>( nu, pu, nv, pv, Pw, &T10 );
00404     CalcNormal_U1V1<T>( nu, pu, nv, pv, Pw, &T11 );
00405   }
00406 
00407   tri = Tri.head;
00408   while( tri != 0 )
00409   {
00410     if( tri->v[0].m_rep->reserved.p == 0 )
00411       c1 = FillVertexCache( 
00412                      tri->v[0].m_rep, tri->code0, normals, orgx, orgy, scale,
00413                      u0, v0, w, h, a, P00, P01, P10, P11, T00, T01, T10, T11 );
00414     else
00415       c1 = (vertex_convert_cache<T> *)tri->v[0].m_rep->reserved.p;
00416       
00417     if( tri->v[1].m_rep->reserved.p == 0 )
00418       c2 = FillVertexCache( 
00419                      tri->v[1].m_rep, tri->code1, normals, orgx, orgy, scale,
00420                      u0, v0, w, h, a, P00, P01, P10, P11, T00, T01, T10, T11 );
00421     else
00422       c2 = (vertex_convert_cache<T> *)tri->v[1].m_rep->reserved.p;
00423 
00424     if( tri->v[2].m_rep->reserved.p == 0 )
00425       c3 = FillVertexCache( 
00426                      tri->v[2].m_rep, tri->code2, normals, orgx, orgy, scale,
00427                      u0, v0, w, h, a, P00, P01, P10, P11, T00, T01, T10, T11 );
00428     else
00429       c3 = (vertex_convert_cache<T> *)tri->v[2].m_rep->reserved.p;
00430 
00431     /*
00432     cout << "(" << c1->d.x << ", " << c1->d.y << ")  (" <<
00433               c2->d.x << ", " << c2->d.y << ")  (" <<
00434               c3->d.x << ", " << c3->d.y << ")\n";              
00435     */
00436 
00437     cb->trifunc( usrdata, &c1->p, &c2->p, &c3->p,  &c1->n, &c2->n, &c3->n,
00438                  &c1->d, &c2->d, &c3->d );    
00439     tri = tri->next;
00440   }
00441   tri = Tri.First();
00442   Tri.ReleaseElems();
00443   while( tri != 0 )   // delete vertex_convert_caches
00444   {
00445     delete ((vertex_convert_cache<T> *)tri->v[0].m_rep->reserved.p);
00446     tri->v[0].m_rep->reserved.p = 0;
00447     delete ((vertex_convert_cache<T> *)tri->v[1].m_rep->reserved.p);
00448     tri->v[1].m_rep->reserved.p = 0;
00449     delete ((vertex_convert_cache<T> *)tri->v[2].m_rep->reserved.p);
00450     tri->v[2].m_rep->reserved.p = 0;
00451 
00452     tri_next = tri->next;
00453     delete tri;     // delete triangle rec;
00454     tri = tri_next;
00455   }
00456 }
00457 
00458 // template instantiation
00459 template GULAPI void TessTriCb( 
00460                          TessInfo<float,hpoint<float> > *A, gugr::GraphInfo *G, 
00461                          gugr::GraphConvInfo<float> *Gconv, void *data );
00462 template GULAPI void TessTriCb( 
00463                          TessInfo<float,point<float> > *A, gugr::GraphInfo *G, 
00464                          gugr::GraphConvInfo<float> *Gconv, void *data );
00465 template GULAPI void TessTriCb( 
00466                          TessInfo<double,hpoint<double> > *A, gugr::GraphInfo *G, 
00467                          gugr::GraphConvInfo<double> *Gconv, void *data );
00468 template GULAPI void TessTriCb( 
00469                          TessInfo<double,point<double> > *A, gugr::GraphInfo *G, 
00470                          gugr::GraphConvInfo<double> *Gconv, void *data );
00471 
00472 
00473 /*
00474 template< class T, class HP, class EP >
00475 GULAPI void LinearizeTrimmedSurface( 
00476             int max_iter,
00477             const int nu, const int pu, Ptr< T >& KnotsU,
00478             const int nv, const int pv, Ptr< T >& KnotsV,
00479             Ptr< Ptr < HP > >& Pw,
00480             const T tol, const rtl<T>& t,
00481             Ptr< Ptr< point2<T> > >& contour,
00482             bool normal_flag,
00483             void (*quadfunc)( void *, 
00484                    const EP *, const EP *, const EP *, const EP *,
00485                    const EP *, const EP *, const EP *, const EP *,
00486                    const T *, const T *, const T *, const T * ),
00487             void (*trifunc)( void *, 
00488                    const EP *, const EP *, const EP *,
00489                    const EP *, const EP *, const EP *,
00490                    const point2<T> *, const point2<T> *, const point2<T> * ),
00491             void *usrdata )
00492 {
00493   TessCbData<T> Cb(normal_flag,t,quadfunc,trifunc,usrdata);
00494 
00495   DoLinearizeTrimmedSurface( max_iter,nu,pu,KnotsU,nv,pv,KnotsV,Pw,tol,t,contour,
00496                              TessQuadCb,TessTriCb,(void *)&Cb );
00497 }
00498 */
00499 
00500 
00501 // template instantiation
00502 /*
00503 template class Linearize< float,hpoint<float>,point<float> >;
00504 template class Linearize< double,hpoint<double>,point<double> >;
00505 template class Linearize< float,point<float>,point<float> >;
00506 template class Linearize< double,point<double>,point<double> >;
00507 */
00508 
00509 }
00510 

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