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

gunu_intersect.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 // #if !defined(_MSC_VER) || defined(NEED_NEW_H)
00023 //  #include <new.h>
00024 // #endif
00025 
00026 #include <iostream>
00027 
00028 #include "gul_types.h"
00029 #include "gul_float.h"
00030 #include "gul_vector.h" 
00031 #include "guge_normalize.h"
00032 #include "guge_linear.h"
00033 #include "gunu_basics.h"
00034 #include "gunu_divide.h"
00035 #include "gunu_intersect.h"
00036 #include "guar_exact.h"
00037 #include "gugr_basics.h"
00038 #include "guar_intersect.h"
00039 #include "guma_random.h"
00040 #include "guma_rkdtree.h"
00041 #include "gunu_project.h"
00042 #include "gul_io.h"
00043 
00044 namespace gunu {
00045 
00046 using guge::IsLinear;
00047 using guge::CalcBoundingBoxVerts;
00048 using guar::rational;
00049 using gul::rtr;
00050 using gul::rel_equal;
00051 using gugr::coord2int;
00052 using gul::point2;
00053 using gul::point;
00054 using gul::rel_equal;
00055 using gul::triangle;
00056 using gul::triangle2;
00057 using guar::IntersectTrianglesUV;
00058 using gul::Max;
00059 using gul::Min;
00060 using gul::test;
00061 using gul::List;
00062 using gul::ListNode;
00063 using gugr::cnv2coord_rnd;
00064 using gul::kdpoint;
00065 using guma::kdnnrec;
00066 using guma::kdrec;
00067 using guma::rkdtree;
00068 using guma::random_des;
00069 using gul::line;
00070 using std::cout;
00071 
00072 /*--------------------------------------------------------------------
00073   Check if a NURBS surface can be approximated with two triangles through
00074   its four corners. If not the surface is subdivided into four parts
00075 ----------------------------------------------------------------------*/
00076 
00077 template< class T, class HP >
00078 void LinearizeOrDivide( TessInfo<T,HP> *A, const T tol, 
00079                         bool need_bbox )
00080 {
00081   int nu,nv,i,pu,pv,j;
00082   Ptr< T > U,V;
00083   Ptr< Ptr< HP > > Pw;
00084   point<T> P00, P01, P10, P11, SP0, SP1, SP2, SP3, CP, minP, maxP;
00085   bool subdiv;
00086   surface< T, HP > S[4], surf;
00087   Ptr< HP > buf;
00088   gul::Ptr< int > test;
00089  
00090   nu = A->org->nu;
00091   pu = A->org->pu;
00092   nv = A->org->nv;
00093   pv = A->org->pv;
00094   U = A->org->U;
00095   V = A->org->V;
00096   Pw = A->org->Pw;
00097 
00098   P00 = A->org->P00;
00099   P01 = A->org->P01;
00100   P10 = A->org->P10;
00101   P11 = A->org->P11;
00102   
00103   buf.reserve_place( reserve_stack(hpoint<T>,nv+1), nv+1 );
00104   
00105                           /*** Pruefen, ob Randkurven linear approximierbar: ***/
00106   subdiv = false;
00107                                                    /* --- obere Randkurve: --- */
00108   if( !guge::IsLinear< T,HP,point<T> >( nu, Pw[0], tol ) ) 
00109   {
00110     subdiv = true; 
00111     CurvePoint< T, HP, point<T> >( (T)0.5, nu, pu, U, Pw[0], &SP0 );
00112   }
00113   else
00114   {
00115     SP0 = (T)0.5 * (P00 + P01);
00116   }
00117                                                   /* --- untere Randkurve: --- */
00118   if( !guge::IsLinear<T,HP,point<T> >( nu, Pw[nv], tol ) ) 
00119   {
00120     subdiv = true;
00121     CurvePoint< T, HP, point<T> >( (T)0.5, nu, pu, U, Pw[nv], &SP1 );  
00122   }
00123   else
00124   {
00125     SP1 = (T)0.5 * (P10 + P11);
00126   }
00127                                                    /* --- linke Randkurve: --- */
00128   for( i = 0; i <= nv; i++ )
00129     buf[i] = Pw[i][0];
00130   if( !guge::IsLinear<T,HP,point<T> >( nv, buf, tol ) ) 
00131   {
00132     subdiv = true;
00133     CurvePoint< T, HP, point<T> >( (T)0.5, nv, pv, V, buf, &SP2 );
00134   }
00135   else
00136   {
00137     SP2 = (T)0.5 * (P00 + P10);
00138   }
00139                                                   /* --- rechte Randkurve: --- */
00140   for( i = 0; i <= nv; i++ )
00141     buf[i] = Pw[i][nu];
00142   if( !guge::IsLinear<T,HP,point<T> >( nv, buf, tol ) ) 
00143   {
00144     subdiv = true;
00145     CurvePoint< T, HP, point<T> >( (T)0.5, nv, pv, V, buf, &SP3 );
00146   }
00147   else
00148   {
00149     SP3 = (T)0.5 * (P01 + P11);
00150   }  
00151 
00152   #if 0
00153   /* not necessary if the tesselation tolerance is fine enough and the
00154      surface doesn't intersect itself, i.e. in normal cases 
00155   */
00156   
00157   // check if iso curves are linear enough 
00158   if( !subdiv )
00159   { 
00160     for( i = 1; i < nv; i++ )
00161     {
00162       if( !guge::IsLinear< T,HP,point<T> >( nu, Pw[i], tol, t ) ) 
00163       {
00164         subdiv = true;
00165         break;
00166       }
00167     }
00168   }
00169   if( !subdiv )
00170   { 
00171     for( j = 1; j < nu; j++ )
00172     {
00173       for( i = 0; i <= nv; i++ )
00174         buf[i] = Pw[i][j];
00175       if( !guge::IsLinear<T,HP,point<T> >( nv, buf, tol, t ) ) 
00176       {
00177         subdiv = true;
00178         break;
00179       }
00180     }
00181   }
00182   #endif
00183                           /* --- Pruefen ob Flaeche linear approxmierbar --- */
00184   if( !subdiv )
00185   {
00186     if( !guge::IsPlanar<T,HP>( nu, nv, Pw, tol ) )
00187       subdiv = true;
00188   }
00189                 /*** Flaeche nicht linear approximierbar, also unterteilen: ***/
00190   if( subdiv )
00191   {
00192     surf.pu = pu;
00193     surf.pv = pv;
00194     surf.net.nu = nu;
00195     surf.net.nv = nv;  
00196     surf.net.Pw = Pw;
00197     surf.knu.m = nu+pu+1;
00198     surf.knu.U = U;
00199     surf.knv.m = nv+pv+1;
00200     surf.knv.U = V;
00201    
00202     SplitSurface< T, HP >( &surf, 0.5, 0.5, &S[0], &S[1], &S[2], &S[3] );
00203 
00204     A->divided = 1;
00205     delete A->org; /* Speicher fuer ungeteilte Flaeche freigeben */
00206     A->org = 0;  
00207     for( i = 0; i < 4; i++ ) A->sub[i] = new TessInfo<T,HP>();
00208 
00209     for( i = 0; i < 4; i++ )
00210     {
00211       if( need_bbox )
00212       {
00213         guge::CalcBoundingBoxVerts< HP, point<T> >( 
00214                                    S[i].net.nu+1, S[i].net.Pw[0], minP, maxP );
00215         for( j = 1; j < S[i].net.nv+1; j++ )
00216           guge::UpdateBoundingBoxVerts< HP, point<T> >( 
00217                                    S[i].net.nu+1, S[i].net.Pw[j], minP, maxP );
00218         A->sub[i]->x1 = minP.x; A->sub[i]->x2 = maxP.x; 
00219         A->sub[i]->y1 = minP.y; A->sub[i]->y2 = maxP.y;
00220         A->sub[i]->z1 = minP.z; A->sub[i]->z2 = maxP.z;
00221       }
00222       A->sub[i]->org->nu = S[i].net.nu;
00223       A->sub[i]->org->pu = S[i].pu;
00224       A->sub[i]->org->nv = S[i].net.nv;
00225       A->sub[i]->org->pv = S[i].pv;
00226       A->sub[i]->org->U = S[i].knu.U;
00227       A->sub[i]->org->V = S[i].knv.U;
00228       A->sub[i]->org->Pw = S[i].net.Pw;
00229     }
00230     CP = euclid( A->sub[0]->org->Pw[ A->sub[0]->org->nv ][ A->sub[0]->org->nu ] );
00231 
00232     A->sub[0]->org->P00 = P00;
00233     A->sub[0]->org->P01 = SP0;
00234     A->sub[0]->org->P10 = SP2;
00235     A->sub[0]->org->P11 = CP;
00236     A->sub[0]->u1 = A->u1;
00237     A->sub[0]->u2 = (A->u1 + A->u2) / (T)2.0;
00238     A->sub[0]->v1 = A->v1;
00239     A->sub[0]->v2 = (A->v1 + A->v2) / (T)2.0;    
00240     
00241     A->sub[1]->org->P00 = SP0;
00242     A->sub[1]->org->P01 = P01;
00243     A->sub[1]->org->P10 = CP;
00244     A->sub[1]->org->P11 = SP3;
00245     A->sub[1]->u1 = (A->u1 + A->u2) / (T)2.0;;
00246     A->sub[1]->u2 = A->u2;
00247     A->sub[1]->v1 = A->v1;
00248     A->sub[1]->v2 = (A->v1 + A->v2) / (T)2.0;    
00249 
00250     A->sub[2]->org->P00 = SP2;
00251     A->sub[2]->org->P01 = CP;
00252     A->sub[2]->org->P10 = P10;
00253     A->sub[2]->org->P11 = SP1;
00254     A->sub[2]->u1 = A->u1;
00255     A->sub[2]->u2 = (A->u1 + A->u2) / (T)2.0;
00256     A->sub[2]->v1 = (A->v1 + A->v2) / (T)2.0;
00257     A->sub[2]->v2 = A->v2;    
00258 
00259     A->sub[3]->org->P00 = CP;
00260     A->sub[3]->org->P01 = SP3;
00261     A->sub[3]->org->P10 = SP1;
00262     A->sub[3]->org->P11 = P11;
00263     A->sub[3]->u1 = (A->u1 + A->u2) / (T)2.0;;
00264     A->sub[3]->u2 = A->u2;
00265     A->sub[3]->v1 = (A->v1 + A->v2) / (T)2.0;
00266     A->sub[3]->v2 = A->v2;    
00267   }
00268   else
00269   {                    /****** Flaeche durch 2 Dreiecke approximierbar *****/
00270     A->linearized = 1;
00271     A->divided = 0;
00272   }
00273   return;
00274 }
00275 
00276 /*--------------------------------------------------------------------
00277   Check if a NURBS surface can be approximated with two triangles through
00278   its four corners. If not the surface is subdivided into four parts
00279 ----------------------------------------------------------------------*/
00280 template
00281 void LinearizeOrDivide( TessInfo<float,hpoint<float> > *A, const float tol, 
00282                         bool need_bbox );
00283 template
00284 void LinearizeOrDivide( TessInfo<float,point<float> > *A, const float tol, 
00285                         bool need_bbox );
00286 
00287 template 
00288 void LinearizeOrDivide( TessInfo<double,hpoint<double> > *A, const double tol, 
00289                         bool need_bbox );
00290 template
00291 void LinearizeOrDivide( TessInfo<double,point<double> > *A, const double tol, 
00292                         bool need_bbox );
00293 
00294 /*-------------------------------------------------------------------
00295   Approximate NURBS-Surface with triangles
00296 --------------------------------------------------------------------*/
00297 template< class T, class HP >
00298 void DoLinearizeSurface( 
00299                  int current_iter, int max_iter,
00300                  TessInfo<T,HP> *A,
00301                  const T tol,
00302                  void    outfunc( TessInfo<T,HP> *, void * ),                                   
00303                  void   *outfunc_data )
00304 {
00305   int nA,i;
00306   TessInfo<T,HP> **pA;  
00307 
00308   /*
00309   cout << "iter: " << current_iter << "\n";
00310       
00311   cout << gul::dump_surf<T,HP>( 
00312               A->org->nu, A->org->pu, A->org->U,
00313               A->org->nv, A->org->pv, A->org->V,
00314               A->org->Pw ) << "\n";  
00315   */
00316 
00317 /* --- A vierteln falls A nicht durch Dreiecke approximierbar: */    
00318 
00319   if( !A->linearized && !A->divided )
00320   {      
00321     if( current_iter < max_iter )
00322       gunu::LinearizeOrDivide( A, tol, false );
00323     else
00324       A->linearized = 1;
00325   }
00326 
00327   if( !A->linearized )
00328   {
00329     nA = 4;
00330     pA = A->sub;
00331 
00332     for( i = 0; i < nA; i++ )          /* Rekursion */
00333     {         
00334       DoLinearizeSurface( current_iter+1, max_iter, pA[i], tol,
00335                           outfunc, outfunc_data );
00336       delete pA[i];
00337       pA[i] = 0;      
00338     }
00339   }
00340   else       /* ------- Dreiecke ausgeben ------------------ */  
00341   {
00342     outfunc( A, outfunc_data ); 
00343   }
00344 }
00345 /*-------------------------------------------------------------------
00346   Approximate NURBS-Surface with triangles
00347 --------------------------------------------------------------------*/
00348 template void DoLinearizeSurface( 
00349                  int current_iter, int max_iter,
00350                  TessInfo<float,hpoint<float> > *A,
00351                  const float tol,
00352                  void    outfunc( TessInfo<float,hpoint<float> > *, void * ),                                   
00353                  void   *outfunc_data );
00354 template void DoLinearizeSurface( 
00355                  int current_iter, int max_iter,
00356                  TessInfo<double,hpoint<double> > *A,
00357                  const double tol,
00358                  void    outfunc( TessInfo<double,hpoint<double> > *, void * ),                                   
00359                  void   *outfunc_data );
00360 
00361 template void DoLinearizeSurface( 
00362                  int current_iter, int max_iter,
00363                  TessInfo<float,point<float> > *A,
00364                  const float tol,
00365                  void    outfunc( TessInfo<float,point<float> > *, void * ),                                   
00366                  void   *outfunc_data );
00367 template void DoLinearizeSurface( 
00368                  int current_iter, int max_iter,
00369                  TessInfo<double,point<double> > *A,
00370                  const double tol,
00371                  void    outfunc( TessInfo<double,point<double> > *, void * ),                                   
00372                  void   *outfunc_data );
00373 
00374 /*--------------------------------------------------------------------
00375   stores an intersection line segment
00376 --------------------------------------------------------------------*/
00377 template< class T >
00378 inline void StoreIntersectionSegmentUV(
00379    point2<rational>                           *Suv,
00380    int                                        *Sflag,
00381    List<ListNode<IntersectionLineInfo<T> > >& I )
00382 {
00383   ListNode<IntersectionLineInfo<T> > *in;
00384   T u,v;
00385 
00386   in = new ListNode<IntersectionLineInfo<T> >;
00387   I.Append(in);
00388   cnv2coord_rnd(Suv[0].x,&u);
00389   in->el.Suv[0].x = u - (T)1;
00390   cnv2coord_rnd(Suv[0].y,&v);
00391   in->el.Suv[0].y = v - (T)1;
00392   cnv2coord_rnd(Suv[1].x,&u);
00393   in->el.Suv[1].x = u - (T)1;
00394   cnv2coord_rnd(Suv[1].y,&v);
00395   in->el.Suv[1].y = v - (T)1;
00396   in->el.Sflag[0] = Sflag[0];
00397   in->el.Sflag[1] = Sflag[1];
00398 }
00399 
00400 // the 3D representation of the intersection segments is not really needed, 
00401 // only for debugging
00402 template< class T >
00403 inline void StoreIntersectionSegment(
00404    point<rational>                            *S,
00405    IntersectInfo<T>                           *II )
00406 {
00407   T scale,x,y,z;
00408   ListNode<line<T> > *in;
00409 
00410   in = new ListNode<line<T> >;
00411   II->IS.Append(in);
00412 
00413   scale = (T)1/II->scalei;
00414 
00415   cnv2coord_rnd(S[0].x,&x);
00416   in->el.P1.x = x * scale + II->minx;
00417   cnv2coord_rnd(S[0].y,&y);
00418   in->el.P1.y = y * scale + II->miny;
00419   cnv2coord_rnd(S[0].z,&z);
00420   in->el.P1.z = z * scale + II->minz;
00421 
00422   cnv2coord_rnd(S[1].x,&x);
00423   in->el.P2.x = x * scale + II->minx;
00424   cnv2coord_rnd(S[1].y,&y);
00425   in->el.P2.y = y * scale + II->miny;
00426   cnv2coord_rnd(S[1].z,&z);
00427   in->el.P2.z = z * scale + II->minz;
00428 }
00429 
00430 /*---------------------------------------------------------------------
00431   intersect the linear approximation of two nurbs surfaces
00432 ----------------------------------------------------------------------*/
00433 template< class T, class HP >
00434 void DoIntersectSurfaces( 
00435                  TessInfo<T,HP> *A, TessInfo<T,HP> *B,
00436                  T tol,
00437                  IntersectInfo<T> *II )
00438 {
00439   int nA, nB, i, j;
00440   TessInfo<T,HP> **pA, **pB;  
00441   // IntersectionLineInfo<T> linfo;
00442 
00443   // do the bounding boxes overlap ?  
00444   if( (A->x1 > B->x2) || (A->x2 < B->x1) ||
00445       (A->y1 > B->y2) || (A->y2 < B->y1) ||
00446       (A->z1 > B->z2) || (A->z2 < B->z1) )
00447   {
00448     return;
00449   }   
00450 
00451   // split A into 4 parts, if A cannot be approximated by 2 triangles    
00452   if( !A->linearized && !A->divided )
00453   {      
00454     LinearizeOrDivide<T,HP>( A, tol, true );
00455   }
00456 
00457   // split B into 4 parts, if B cannot be approximated by 2 triangles    
00458   if( !B->linearized && !B->divided )
00459   {      
00460     LinearizeOrDivide<T,HP>( B, tol, true );
00461   }
00462 
00463   // recursion, if not both surfaces can be approximated by triangles
00464   if( !A->linearized || !B->linearized )
00465   {
00466     if( !A->linearized )
00467     {
00468       nA = 4;
00469       pA = A->sub;
00470     }
00471     else
00472     {
00473       nA = 1;
00474       pA = &A;        
00475     }
00476 
00477     if( !B->linearized )
00478     {
00479       nB = 4;
00480       pB = B->sub;
00481     }
00482     else
00483     {
00484       nB = 1;
00485       pB = &B;        
00486     }
00487 
00488     for( i = 0; i < nA; i++ )          // recursion
00489     {
00490       for( j = 0; j < nB; j++ )
00491       {
00492         DoIntersectSurfaces( pA[i], pB[j], tol, II );
00493       }      
00494     }
00495   }
00496   else  // intersect triangles pairwise
00497   {
00498     point<T>         PA[2][2],PB[2][2];
00499     point<rational>  PRA[2][2],PRB[2][2];
00500     point2<rational> PRA_UV[2][2],PRB_UV[2][2];
00501     T                x,y,z;
00502     unsigned long    *cbuf = 
00503       (unsigned long *)alloca(gul::rtr<T>::mantissa_length());
00504     triangle<rational> TA[2],TB[2];
00505     triangle2<rational> TAuv[2],TBuv[2];
00506     point<rational> S[2];
00507     point2<rational> S1uv[2], S2uv[2];
00508     int S1flag[2], S2flag[2];
00509     bool result;
00510 
00511     // convert A to rational representation
00512     PA[0][0] = A->org->P00;
00513     PA[0][1] = A->org->P01;
00514     PA[1][0] = A->org->P10;
00515     PA[1][1] = A->org->P11;
00516 
00517     for( i = 0; i < 2; i++ )
00518     {
00519       for( j = 0; j < 2; j++ )
00520       {
00521         x = (PA[i][j].x - II->minx)*II->scalei;
00522         y = (PA[i][j].y - II->miny)*II->scalei;
00523         z = (PA[i][j].z - II->minz)*II->scalei;
00524 
00525         PRA[i][j].x = rational(coord2int(x,cbuf),cbuf);
00526         PRA[i][j].y = rational(coord2int(y,cbuf),cbuf);
00527         PRA[i][j].z = rational(coord2int(z,cbuf),cbuf);
00528       }
00529     }
00530     // domain coordinates
00531     PRA_UV[0][0].x = rational(coord2int(A->u1+(T)1,cbuf),cbuf);
00532     PRA_UV[0][0].y = rational(coord2int(A->v1+(T)1,cbuf),cbuf);
00533 
00534     PRA_UV[0][1].x = rational(coord2int(A->u2+(T)1,cbuf),cbuf);
00535     PRA_UV[0][1].y = PRA_UV[0][0].y ;
00536 
00537     PRA_UV[1][0].x = PRA_UV[0][0].x;
00538     PRA_UV[1][0].y = rational(coord2int(A->v2+(T)1,cbuf),cbuf);
00539 
00540     PRA_UV[1][1].x = PRA_UV[0][1].x;
00541     PRA_UV[1][1].y = PRA_UV[1][0].y;
00542 
00543     // convert B to rational representation
00544     PB[0][0] = B->org->P00;
00545     PB[0][1] = B->org->P01;
00546     PB[1][0] = B->org->P10;
00547     PB[1][1] = B->org->P11;
00548 
00549     for( i = 0; i < 2; i++ )
00550     {
00551       for( j = 0; j < 2; j++ )
00552       {
00553         x = (PB[i][j].x - II->minx)*II->scalei;
00554         y = (PB[i][j].y - II->miny)*II->scalei;
00555         z = (PB[i][j].z - II->minz)*II->scalei;
00556 
00557         PRB[i][j].x = rational(coord2int(x,cbuf),cbuf);
00558         PRB[i][j].y = rational(coord2int(y,cbuf),cbuf);
00559         PRB[i][j].z = rational(coord2int(z,cbuf),cbuf);
00560       }
00561     }
00562    // domain coordinates
00563     PRB_UV[0][0].x = rational(coord2int(B->u1+(T)1,cbuf),cbuf);
00564     PRB_UV[0][0].y = rational(coord2int(B->v1+(T)1,cbuf),cbuf);
00565 
00566     PRB_UV[0][1].x = rational(coord2int(B->u2+(T)1,cbuf),cbuf);
00567     PRB_UV[0][1].y = PRB_UV[0][0].y;
00568 
00569     PRB_UV[1][0].x = PRB_UV[0][0].x;
00570     PRB_UV[1][0].y = rational(coord2int(B->v2+(T)1,cbuf),cbuf);
00571 
00572     PRB_UV[1][1].x = PRB_UV[0][1].x;
00573     PRB_UV[1][1].y = PRB_UV[1][0].y;
00574 
00575     // form triangles for A
00576     TA[0].P1 = PRA[0][0];
00577     TA[0].P2 = PRA[0][1];
00578     TA[0].P3 = PRA[1][0];
00579     TAuv[0].P1 = PRA_UV[0][0];
00580     TAuv[0].P2 = PRA_UV[0][1];
00581     TAuv[0].P3 = PRA_UV[1][0];
00582 
00583     TA[1].P1 = PRA[1][1];
00584     TA[1].P2 = PRA[1][0];
00585     TA[1].P3 = PRA[0][1];
00586     TAuv[1].P1 = PRA_UV[1][1];
00587     TAuv[1].P2 = PRA_UV[1][0];
00588     TAuv[1].P3 = PRA_UV[0][1];
00589 
00590     // form triangles for B
00591     TB[0].P1 = PRB[0][0];
00592     TB[0].P2 = PRB[0][1];
00593     TB[0].P3 = PRB[1][0];
00594     TBuv[0].P1 = PRB_UV[0][0];
00595     TBuv[0].P2 = PRB_UV[0][1];
00596     TBuv[0].P3 = PRB_UV[1][0];
00597 
00598     TB[1].P1 = PRB[1][1];
00599     TB[1].P2 = PRB[1][0];
00600     TB[1].P3 = PRB[0][1];
00601     TBuv[1].P1 = PRB_UV[1][1];
00602     TBuv[1].P2 = PRB_UV[1][0];
00603     TBuv[1].P3 = PRB_UV[0][1];
00604 
00605     result = IntersectTrianglesUV(TA[0],TAuv[0],TB[0],TBuv[0],
00606                                   S1uv,S1flag,S2uv,S2flag,S);
00607     if( result )
00608     {
00609       // cout << "Intersection line segment: ((" << S[0] << "), (" 
00610       //     << S[1] << "))\n"; 
00611       StoreIntersectionSegment(S,II);
00612       StoreIntersectionSegmentUV(S1uv,S1flag,II->IA);
00613       StoreIntersectionSegmentUV(S2uv,S2flag,II->IB);
00614     }
00615 
00616     result = IntersectTrianglesUV(TA[1],TAuv[1],TB[0],TBuv[0],
00617                                   S1uv,S1flag,S2uv,S2flag,S);
00618     if( result )
00619     {
00620       StoreIntersectionSegment(S,II);
00621       StoreIntersectionSegmentUV(S1uv,S1flag,II->IA);
00622       StoreIntersectionSegmentUV(S2uv,S2flag,II->IB);
00623     }
00624 
00625     result = IntersectTrianglesUV(TA[0],TAuv[0],TB[1],TBuv[1],
00626                                   S1uv,S1flag,S2uv,S2flag,S);
00627     if( result )
00628     {
00629       StoreIntersectionSegment(S,II);
00630       StoreIntersectionSegmentUV(S1uv,S1flag,II->IA);
00631       StoreIntersectionSegmentUV(S2uv,S2flag,II->IB);
00632     }
00633 
00634     result = IntersectTrianglesUV(TA[1],TAuv[1],TB[1],TBuv[1],
00635                                   S1uv,S1flag,S2uv,S2flag,S);
00636     if( result )
00637     {
00638       StoreIntersectionSegment(S,II);
00639       StoreIntersectionSegmentUV(S1uv,S1flag,II->IA);
00640       StoreIntersectionSegmentUV(S2uv,S2flag,II->IB);
00641     }
00642   }
00643 }
00644 // template instantiation
00645 template void DoIntersectSurfaces( 
00646      TessInfo<float, hpoint<float> > *A, TessInfo<float,hpoint<float> > *B,
00647      float tol,
00648      IntersectInfo<float> *II );
00649 
00650 
00651 /*---------------------------------------------------------------------
00652   this structure is used to find intersection segments which are
00653   connected at their endpoints with the help of a kd-tree
00654 ----------------------------------------------------------------------*/
00655 template< class T >
00656 // class is_uv_point : public gul::kdpoint<T,point2<T> >
00657 class is_uv_point : public gul::point2<T>
00658 {
00659 public:
00660   IntersectionLineInfo<T> *ii;
00661   point2<T>               *ip;
00662 
00663   is_uv_point *next;
00664   is_uv_point *prev;
00665 
00666   is_uv_point( point2<T> *inP, IntersectionLineInfo<T> *inii )
00667     : point2<T>( *inP )
00668   {
00669     ip = inP;
00670     ii = inii;
00671   }
00672 };
00673 
00674 /*---------------------------------------------------------------------
00675   intersects the linear approximation of two nurbs surfaces
00676 ----------------------------------------------------------------------*/
00677 template< class T, class HP >
00678 GULAPI void IntersectSurfaces( 
00679             int nu1, int pu1, const Ptr< T >& U1,
00680             int nv1, int pv1, const Ptr< T >& V1,
00681             const Ptr< Ptr < HP > >& Pw1,
00682             int nu2, int pu2, const Ptr< T >& U2,
00683             int nv2, int pv2, const Ptr< T >& V2,
00684             const Ptr< Ptr < HP > >& Pw2,
00685             T tol,
00686             List<ListNode<IntersectionLineInfo<T> > >& S1,
00687             List<ListNode<IntersectionLineInfo<T> > >& S2,
00688             List<ListNode<line<T> > >& S )
00689 {
00690   TessInfo<T,HP> A,B;
00691   point<T> maxP,minP;
00692   int j;
00693   IntersectInfo<T> II;
00694   T maxx,maxy,maxz,scale,d;
00695   rkdtree<point2<T>,T,random_des> KDT(2);
00696   is_uv_point<T> *Puv,*Peq,*Puv_next;
00697   List< is_uv_point<T> > LPuv,LPeq,LPtmp;
00698   ListNode<kdrec<point2<T>,T> > *nn;
00699   ListNode<IntersectionLineInfo<T> > *iin;
00700   Ptr<kdnnrec<point2<T>,T> > N; 
00701   List< gul::ListNode<kdrec<point2<T>,T> > > outrecs;
00702   point2<T> M;
00703 
00704   // initialize tesselation info structure for A
00705   A.org->nu = nu1;
00706   A.org->pu = pu1;  
00707   A.org->U =  U1;
00708   A.org->nv = nv1;
00709   A.org->pv = pv1;  
00710   A.org->V =  V1;
00711   A.org->Pw = Pw1;
00712 
00713   guge::CalcBoundingBoxVerts<HP,point<T> >( 
00714                   A.org->nu+1, A.org->Pw[0], minP, maxP );
00715   for( j = 1; j < A.org->nv+1; j++ )
00716     guge::UpdateBoundingBoxVerts<HP,point<T> >( 
00717                   A.org->nu+1, A.org->Pw[j], minP, maxP );
00718   A.x1 = minP.x; A.x2 = maxP.x; 
00719   A.y1 = minP.y; A.y2 = maxP.y;
00720   A.z1 = minP.z; A.z2 = maxP.z;
00721 
00722   A.org->P00 = euclid( A.org->Pw[0][0] );
00723   A.org->P01 = euclid( A.org->Pw[0][A.org->nu] );
00724   A.org->P10 = euclid( A.org->Pw[A.org->nv][0] );
00725   A.org->P11 = euclid( A.org->Pw[A.org->nv][A.org->nu] );
00726 
00727   A.u1 = 0.0;
00728   A.u2 = 1.0; 
00729   A.v1 = 0.0;
00730   A.v2 = 1.0; 
00731 
00732   // initialize tesselation info structure for B
00733   B.org->nu = nu2;
00734   B.org->pu = pu2;  
00735   B.org->U =  U2;
00736   B.org->nv = nv2;
00737   B.org->pv = pv2;  
00738   B.org->V =  V2;
00739   B.org->Pw = Pw2;
00740 
00741   guge::CalcBoundingBoxVerts<HP,point<T> >( 
00742                   B.org->nu+1, B.org->Pw[0], minP, maxP );
00743   for( j = 1; j < B.org->nv+1; j++ )
00744     guge::UpdateBoundingBoxVerts<HP,point<T> >( 
00745                   B.org->nu+1, B.org->Pw[j], minP, maxP );
00746   B.x1 = minP.x; B.x2 = maxP.x; 
00747   B.y1 = minP.y; B.y2 = maxP.y;
00748   B.z1 = minP.z; B.z2 = maxP.z;
00749 
00750   B.org->P00 = euclid( B.org->Pw[0][0] );
00751   B.org->P01 = euclid( B.org->Pw[0][B.org->nu] );
00752   B.org->P10 = euclid( B.org->Pw[B.org->nv][0] );
00753   B.org->P11 = euclid( B.org->Pw[B.org->nv][B.org->nu] );
00754 
00755   B.u1 = 0.0;
00756   B.u2 = 1.0; 
00757   B.v1 = 0.0;
00758   B.v2 = 1.0;   
00759 
00760   // initialize float to rational conversion parameters
00761   II.minx = Min(A.x1,B.x1);
00762   maxx = Max(A.x2,B.x2);
00763   II.miny = Min(A.y1,B.y1);
00764   maxy = Max(A.y2,B.y2);
00765   II.minz = Min(A.z1,B.z1);
00766   maxz = Max(A.z2,B.z2);
00767   
00768   scale = maxx - II.minx;
00769   d = maxy - II.miny;
00770   if( d > scale ) scale = d;
00771   d = maxz - II.minz;
00772   if( d > scale ) scale = d;
00773   if( !test(scale) ) return;
00774   II.minx -= scale;
00775   II.miny -= scale;
00776   II.minz -= scale;
00777   II.scalei = (T)1/scale;
00778 
00779   DoIntersectSurfaces(&A,&B,tol,&II);
00780 
00781   // cout << "number of intersection segments = " 
00782   //      << II.IA.nElems << "\n";
00783 
00784   // insert endpoints of intersection segments into kd-tree
00785   for( iin = II.IA.First(); iin; iin = iin->next )
00786   {
00787     Puv = new is_uv_point<T>(&iin->el.Suv[0],&iin->el);
00788     LPuv.Append(Puv);
00789     KDT.insert(Puv);
00790 
00791     Puv = new is_uv_point<T>(&iin->el.Suv[1],&iin->el);
00792     LPuv.Append(Puv);
00793     KDT.insert(Puv);
00794   }
00795 
00796   // compress points which are approximately equal into a single point
00797   for(;;)
00798   {
00799     Puv = LPuv.First();
00800     if( !Puv ) break;
00801 
00802     LPuv.Remove(Puv);
00803     KDT.remove(Puv,outrecs);
00804     // cout << "removed " << outrecs.nElems << " record(s)\n";
00805     LPtmp.Append(Puv);
00806 
00807     for(;;)
00808     {
00809       Puv = LPtmp.First();
00810       if( !Puv ) break;
00811       LPtmp.Remove(Puv);
00812       LPeq.Append(Puv);
00813 
00814       N.reserve_pool(1);
00815       if( KDT.nearest_neighbors(  *Puv, 1, N ) )
00816       {
00817         nn = N[0].m_recs.First();
00818 
00819         if( rel_equal(*Puv,*nn->el.m_base,rtr<T>::zero_tol()) )
00820         {
00821           for(  ; nn; nn = nn->next ) // all records have the same distance
00822           {
00823             // cast back to derived class
00824             Peq = (is_uv_point<T> *)nn->el.m_base;
00825             LPuv.Remove(Peq);
00826             KDT.remove(Peq,outrecs);
00827             // cout << "removed " << outrecs.nElems << " record(s)\n";
00828             LPtmp.Append(Peq);
00829           }
00830         }
00831       }
00832     }
00833 
00834     if( LPeq.nElems > 1 )
00835     {
00836       // calculate center of "equal" points
00837       Puv = LPeq.First();
00838       M = *Puv;
00839       j = 1;
00840       Puv = Puv->next;
00841       for( ; Puv; Puv = Puv->next )
00842       {
00843         M += *Puv;
00844         j++;
00845       }
00846       M = ((T)1/(T)j)*M;
00847  
00848       // change points in affected intersection segments 
00849       Puv = LPeq.First();
00850       LPeq.ReleaseElems();
00851       for( ; Puv; Puv = Puv_next )
00852       {
00853         *Puv->ip = M;
00854         Puv_next = Puv->next;
00855         delete Puv;
00856       }
00857     }
00858     else
00859       LPeq.DeleteElems();
00860   }
00861 
00862   S1 = II.IA;
00863   S2 = II.IB;
00864   S = II.IS;
00865 }
00866 // template instantiation
00867 template GULAPI void IntersectSurfaces( 
00868             int nu1, int pu1, const Ptr< float >& U1,
00869             int nv1, int pv1, const Ptr< float >& V1,
00870             const Ptr< Ptr < hpoint<float> > >& Pw1,
00871             int nu2, int pu2, const Ptr< float >& U2,
00872             int nv2, int pv2, const Ptr< float >& V2,
00873             const Ptr< Ptr < hpoint<float> > >& Pw2,
00874             float tol,
00875             List<ListNode<IntersectionLineInfo<float> > >& S1,
00876             List<ListNode<IntersectionLineInfo<float> > >& S2,
00877             List<ListNode<line<float> > >& S );
00878 
00879 
00880 #if 0
00881 /*---------------------------------------------------------------------
00882   Intersect linear approximation of two NURBS-Surfaces
00883 ----------------------------------------------------------------------*/
00884 /*
00885 template< class T >
00886 void IntersectSurfaces( 
00887                  IntersectInfo<T> *A, IntersectInfo<T> *B,
00888                  T tol, const rtl<T>& t,
00889                  void    outfunc( IntersectionLineInfo<T> *, void * ),                                   
00890                  void   *outfunc_data )
00891 {
00892   int result, nA, nB, i, j;
00893   IntersectInfo<T> **pA, **pB;  
00894   IntersectionLineInfo<T> linfo;
00895   T u,v;
00896   
00897   // --- Ueberschneiden sich die Bounding Boxen ? -----------
00898 
00899   if( (A->x1 > B->x2) || (A->x2 < B->x1) ||
00900       (A->y1 > B->y2) || (A->y2 < B->y1) ||
00901       (A->z1 > B->z2) || (A->z2 < B->z1) )
00902   {
00903     return;
00904   }   
00905     
00906   // --- A vierteln falls A nicht durch Dreiecke approximierbar:    
00907 
00908   if( !A->f.linearized && !A->f.divided )
00909   {      
00910     LinearizeOrDivide<T>( A, tol, t );
00911   }
00912   if( !B->f.linearized && !B->f.divided )
00913   {      
00914     LinearizeOrDivide<T>( B, tol, t );
00915   }
00916 
00917   // --- falls noch nicht beide Flaechen durch Dreiecke darstellbar Rekursion:
00918 
00919   if( !A->f.linearized || !B->f.linearized )
00920   {
00921     if( !A->f.linearized )
00922     {
00923       nA = 4;
00924       pA = A->sub;
00925     }
00926     else
00927     {
00928       nA = 1;
00929       pA = &A;        
00930     }
00931 
00932     if( !B->f.linearized )
00933     {
00934       nB = 4;
00935       pB = B->sub;
00936     }
00937     else
00938     {
00939       nB = 1;
00940       pB = &B;        
00941     }
00942 
00943     for( i = 0; i < nA; i++ )          // Rekursion
00944     {
00945       for( j = 0; j < nB; j++ )
00946       {
00947         IntersectSurfaces( pA[i], pB[j], tol, t, outfunc, outfunc_data );
00948       }      
00949     }
00950   }
00951   else       // ------- Dreiecke schneiden ------------------
00952   {
00953     point<T> P00,P01,P10,P11;
00954     triangle<T> Atri[2], Btri[2];
00955     
00956     P00 = A->org.P00;
00957     P01 = A->org.P01;
00958     P10 = A->org.P10;
00959     P11 = A->org.P11;
00960 
00961     Atri[0].P1 = P00;
00962     Atri[0].P2 = P10;
00963     Atri[0].P3 = P01;
00964 
00965     Atri[1].P1 = P10;
00966     Atri[1].P2 = P11;
00967     Atri[1].P3 = P01;
00968 
00969     P00 = B->org.P00;
00970     P01 = B->org.P01;
00971     P10 = B->org.P10;
00972     P11 = B->org.P11;
00973 
00974     Btri[0].P1 = P00;
00975     Btri[0].P2 = P10;
00976     Btri[0].P3 = P01;
00977 
00978     Btri[1].P1 = P10;
00979     Btri[1].P2 = P11;
00980     Btri[1].P3 = P01;
00981 
00982 
00983     result = guge::IntersectTriangles<T>( Atri[0], Btri[0],
00984                                     &linfo.P1, &linfo.P2 );
00985     if( result != 0 )
00986     {
00987       // --- Parameterraumdarstellung bzgl. beider Flaechen bestimmen: ---
00988 
00989       BarycentricUV<T>( Atri[0].P1, Atri[0].P3, Atri[0].P2,
00990                         linfo.P1, &u, &v ); 
00991       linfo.F1.P1.x = A->u1 + u * (A->u2 - A->u1);
00992       linfo.F1.P1.y = A->v1 + v * (A->v2 - A->v1);
00993 
00994       BarycentricUV( Atri[0].P1, Atri[0].P3, Atri[0].P2,
00995                      linfo.P2, &u, &v ); 
00996       linfo.F1.P2.x = A->u1 + u * (A->u2 - A->u1);
00997       linfo.F1.P2.y = A->v1 + v * (A->v2 - A->v1);
00998 
00999       // --- 2. Flaeche: ---
01000 
01001       BarycentricUV<T>( Btri[0].P1, Btri[0].P3, Btri[0].P2,
01002                         linfo.P1, &u, &v ); 
01003       linfo.F2.P1.x = B->u1 + u * (B->u2 - B->u1);
01004       linfo.F2.P1.y = B->v1 + v * (B->v2 - B->v1);
01005 
01006       BarycentricUV<T>( Btri[0].P1, Btri[0].P3, Btri[0].P2,
01007                         linfo.P2, &u, &v ); 
01008       linfo.F2.P2.x = B->u1 + u * (B->u2 - B->u1);
01009       linfo.F2.P2.y = B->v1 + v * (B->v2 - B->v1);
01010 
01011       // --- abspeichern: ---
01012 
01013       outfunc( &linfo, outfunc_data );
01014     }
01015     
01016 // ------------------------------------------------------------------------
01017 
01018     result = guge::IntersectTriangles<T>( Atri[0], Btri[1],
01019                                     &linfo.P1, &linfo.P2 );
01020     if( result != 0 )
01021     {
01022       // --- Parameterraumdarstellung bzgl. beider Flaechen bestimmen: ---
01023 
01024       BarycentricUV<T>( Atri[0].P1, Atri[0].P3, Atri[0].P2,
01025                         linfo.P1, &u, &v ); 
01026       linfo.F1.P1.x = A->u1 + u * (A->u2 - A->u1);
01027       linfo.F1.P1.y = A->v1 + v * (A->v2 - A->v1);
01028 
01029       BarycentricUV<T>( Atri[0].P1, Atri[0].P3, Atri[0].P2,
01030                         linfo.P2, &u, &v ); 
01031       linfo.F1.P2.x = A->u1 + u * (A->u2 - A->u1);
01032       linfo.F1.P2.y = A->v1 + v * (A->v2 - A->v1);
01033 
01034       // --- 2. Flaeche: ---
01035 
01036       BarycentricUV<T>( Btri[1].P2, Btri[1].P1, Btri[1].P3,
01037                         linfo.P1, &u, &v ); 
01038       linfo.F2.P1.x = B->u2 - u * (B->u2 - B->u1);
01039       linfo.F2.P1.y = B->v2 - v * (B->v2 - B->v1);
01040 
01041       BarycentricUV<T>( Btri[1].P2, Btri[1].P1, Btri[1].P3,
01042                         linfo.P2, &u, &v ); 
01043       linfo.F2.P2.x = B->u2 - u * (B->u2 - B->u1);
01044       linfo.F2.P2.y = B->v2 - v * (B->v2 - B->v1);
01045 
01046       // --- abspeichern: ---
01047 
01048       outfunc( &linfo, outfunc_data ); 
01049     }
01050 
01051 /* ------------------------------------------------------------------------
01052 
01053     result = guge::IntersectTriangles<T>( Atri[1], Btri[0],
01054                                     &linfo.P1, &linfo.P2 );
01055     if( result != 0 )
01056     {
01057       // --- Parameterraumdarstellung bzgl. beider Flaechen bestimmen: ---
01058 
01059       BarycentricUV<T>( Atri[1].P2, Atri[1].P1, Atri[1].P3,
01060                         linfo.P1, &u, &v ); 
01061       linfo.F1.P1.x = A->u2 - u * (A->u2 - A->u1);
01062       linfo.F1.P1.y = A->v2 - v * (A->v2 - A->v1);
01063 
01064       BarycentricUV<T>( Atri[1].P2, Atri[1].P1, Atri[1].P3,
01065                         linfo.P2, &u, &v ); 
01066       linfo.F1.P2.x = A->u2 - u * (A->u2 - A->u1);
01067       linfo.F1.P2.y = A->v2 - v * (A->v2 - A->v1);
01068 
01069       // --- 2. Flaeche: ---
01070 
01071       BarycentricUV<T>( Btri[0].P1, Btri[0].P3, Btri[0].P2,
01072                         linfo.P1, &u, &v ); 
01073       linfo.F2.P1.x = B->u1 + u * (B->u2 - B->u1);
01074       linfo.F2.P1.y = B->v1 + v * (B->v2 - B->v1);
01075 
01076       BarycentricUV<T>( Btri[0].P1, Btri[0].P3, Btri[0].P2,
01077                         linfo.P2, &u, &v ); 
01078       linfo.F2.P2.x = B->u1 + u * (B->u2 - B->u1);
01079       linfo.F2.P2.y = B->v1 + v * (B->v2 - B->v1);
01080 
01081       // --- abspeichern: ---
01082 
01083       outfunc( &linfo, outfunc_data ); 
01084     }
01085 
01086 // ----------------------------------------------------------------------
01087 
01088     result = guge::IntersectTriangles<T>( Atri[1], Btri[1],
01089                                     &linfo.P1, &linfo.P2 );
01090     if( result != 0 )
01091     {
01092       // --- Parameterraumdarstellung bzgl. beider Flaechen bestimmen: ---
01093 
01094       BarycentricUV<T>( Atri[1].P2, Atri[1].P1, Atri[1].P3,
01095                         linfo.P1, &u, &v ); 
01096       linfo.F1.P1.x = A->u2 - u * (A->u2 - A->u1);
01097       linfo.F1.P1.y = A->v2 - v * (A->v2 - A->v1);
01098 
01099       BarycentricUV<T>( Atri[1].P2, Atri[1].P1, Atri[1].P3,
01100                         linfo.P2, &u, &v ); 
01101       linfo.F1.P2.x = A->u2 - u * (A->u2 - A->u1);
01102       linfo.F1.P2.y = A->v2 - v * (A->v2 - A->v1);
01103 
01104       // --- 2. Flaeche: ---
01105 
01106       BarycentricUV<T>( Btri[1].P2, Btri[1].P1, Btri[1].P3,
01107                         linfo.P1, &u, &v ); 
01108       linfo.F2.P1.x = B->u2 - u * (B->u2 - B->u1);
01109       linfo.F2.P1.y = B->v2 - v * (B->v2 - B->v1);
01110 
01111       BarycentricUV<T>( Btri[1].P2, Btri[1].P1, Btri[1].P3,
01112                         linfo.P2, &u, &v ); 
01113       linfo.F2.P2.x = B->u2 - u * (B->u2 - B->u1);
01114       linfo.F2.P2.y = B->v2 - v * (B->v2 - B->v1);
01115 
01116       // --- abspeichern: ---
01117 
01118       outfunc( &linfo, outfunc_data ); 
01119     }
01120   }
01121 }
01122 */
01123 
01124 /*---------------------------------------------------------------------
01125   Intersect linear approximation of two NURBS-Surfaces
01126 ----------------------------------------------------------------------*/
01127 /*
01128 template
01129 void IntersectSurfaces( 
01130                  IntersectInfo<float> *A, IntersectInfo<float> *B,
01131                  float tol, const rtl<float>& t,
01132                  void    outfunc( IntersectionLineInfo<float> *, void * ),                                   
01133                  void   *outfunc_data );
01134 template
01135 void IntersectSurfaces( 
01136                  IntersectInfo<double> *A, IntersectInfo<double> *B,
01137                  double tol, const rtl<double>& t,
01138                  void    outfunc( IntersectionLineInfo<double> *, void * ),                                   
01139                  void   *outfunc_data );
01140 */
01141 #endif
01142 
01143 }

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