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

gugr_face.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_lineq.h"
00029 #include "guar_exact.h"
00030 #include "gugr_basics.h"
00031 #include "gugr_regularize.h"
00032 #include "gugr_triangulate.h"
00033 #include "gugr_planesweep.h"
00034 #include "gugr_contour.h"
00035 #include "gul_io.h"
00036 #include "gul_std.h"
00037 #include "gugr_io.h"
00038 
00039 namespace gugr {
00040 
00041 using gul::VMProduct;
00042 using guma::GaussJordan;
00043 using gul::point;
00044 using gul::point2;
00045 using gul::Ptr;
00046 using guge::CalcBoundingBoxE;
00047 using guge::UpdateBoundingBoxE;
00048 using guar::Interval;
00049 using gul::Max;
00050 using guar::GetRatio;
00051 using guar::Test;
00052 using gul::rtr;
00053 using gul::Swap;
00054 using gul::cross_product;
00055 
00056 using gul::ListNode;
00057 using gul::List;
00058 using gul::ListNodeInfo;
00059 using gul::point;
00060 using gul::itriangle;
00061 
00062 using gul::set;
00063 using gul::normalize;
00064 using guar::Interval;
00065 using guar::Sqrt;
00066 using guar::Test;
00067 
00068 #if 0
00069 
00070 template< class T >
00071 bool FaceArea( 
00072        int nVerts, const Ptr< point<T> >& Verts, int faceleft, int faceright,
00073        point<T> *retNormal, int *retFaceleft, int *retFaceright, T *retArea,
00074        int *ret_nTrii, Ptr<int[3]> *retTrii )
00075 {
00076   gugr::triangle_list Tri;
00077   gugr::triangle *tri,*tri_next;
00078   T area;
00079   point<T> v,p1,p2,p3;
00080   Ptr<int[3]> Trii;
00081   int count,i0,i1,i2;
00082 
00083   if( !DoTriangulateFace( nVerts, Verts, faceleft, faceright, &Tri, retNormal,
00084                           retFaceleft, retFaceright ) )
00085     return false;
00086 
00087   // calculate the area of the polygon (for lighting calculations)
00088 
00089   Trii.reserve_pool(Tri.nElems);
00090   count = 0;
00091   
00092   tri = Tri.First();
00093   Tri.ReleaseElems();
00094   area = (T)0;
00095   while( tri != 0 )
00096   {
00097     // this could be done more optimal !!!!
00098 
00099     i0 = Trii[count][0] = (int)tri->v[0].m_rep->reserved;
00100     i1 = Trii[count][1] = (int)tri->v[1].m_rep->reserved;
00101     i2 = Trii[count][2] = (int)tri->v[2].m_rep->reserved;
00102     p1 = Verts[i0];
00103     p2 = Verts[i1];
00104     p3 = Verts[i2];
00105 
00106     v = gul::cross_product(p2-p1,p3-p1);
00107     area += gul::length(v)/(T)2;
00108 
00109     tri_next = tri->next;
00110     delete tri;     // delete triangle rec;
00111     tri = tri->next;
00112 
00113     count++;
00114   }
00115   *retArea = area;
00116   *ret_nTrii = count;
00117   *retTrii = Trii;
00118 
00119   return true;
00120 }
00121 // template instantiation
00122 template bool FaceArea<float>( 
00123   int nVerts, const Ptr< point<float> >& Verts, int faceleft, int faceright,
00124   point<float> *retNormal, int *retFaceleft, int *retFaceright, float *retArea,
00125   int *ret_nfloatrii, Ptr<int[3]> *retfloatrii );
00126 template bool FaceArea<double>( 
00127  int nVerts, const Ptr< point<double> >& Verts, int faceleft, int faceright,
00128  point<double> *retNormal, int *retFaceleft, int *retFaceright, double *retArea,
00129  int *ret_ndoublerii, Ptr<int[3]> *retdoublerii );
00130 
00131 #endif
00132 
00133 /*-------------------------------------------------------------------------
00134   calculates the plane in which the vertices of a polygon, consisting of a
00135   single contour with coplanar 3d vertices, lies.
00136  
00137   it tries to avoid calculating a normal vector which is totally
00138   wrong (because of rounding errors) by calculating the normal at the vertex
00139   which gives the smallest upper/lower bound ratio by interval arithmetic
00140 --------------------------------------------------------------------------*/
00141 
00142 template< class T >
00143 GULAPI bool CalcPlane( 
00144                 int nVerts, const Ptr< point<T> >& Verts,
00145                 point<T>& o, point<T>& b1, point<T>& b2, point<T>& b3 )
00146 {
00147   Interval ix0,iy0,iz0,ix1,iy1,iz1,ix2,iy2,iz2,ibx1,iby1,ibz1,ibx2,iby2,ibz2;
00148   Interval ilen,ilen2,inx,iny,inz;
00149   double rat,rat1;
00150   int i0,i1,i2,irat0,irat1,irat2;
00151   point<T> v1,v2;
00152 
00153   irat0 = -1;
00154   rat = rtr<double>::giant();  // start with a gigantic ratio
00155 
00156   for( i0 = 0; i0 < nVerts; i0++ )
00157   {
00158     ix0 = Verts[i0].x;
00159     iy0 = Verts[i0].y;
00160     iz0 = Verts[i0].z;
00161     
00162     i1 = i0+1; if( i1 == nVerts ) i1 = 0;
00163     i2 = i1+1; if( i2 == nVerts ) i2 = 0;
00164 
00165     // calc first basis vector
00166 
00167     ix1 = Verts[i1].x;
00168     iy1 = Verts[i1].y;
00169     iz1 = Verts[i1].z;
00170 
00171     ibx1 = ix1 - ix0;
00172     iby1 = iy1 - iy0;
00173     ibz1 = iz1 - iz0;
00174 
00175     // normalize b1
00176 
00177     ilen2 = ibx1*ibx1 + iby1*iby1 + ibz1*ibz1;
00178     ilen = Sqrt( ilen2 ); 
00179     if( Test(ilen)==0 ) continue;   // avoid division by zero
00180 
00181     ibx1 = ibx1 / ilen;
00182     iby1 = iby1 / ilen;
00183     ibz1 = ibz1 / ilen;
00184 
00185     // calc second basis vector of plane
00186 
00187     ix2 = Verts[i2].x;
00188     iy2 = Verts[i2].y;
00189     iz2 = Verts[i2].z;
00190 
00191     ibx2 = ix2 - ix0;
00192     iby2 = iy2 - iy0;
00193     ibz2 = iz2 - iz0;
00194 
00195     // project vector onto b1 
00196 
00197     ilen = ibx2*ibx1 + iby2*iby1 + ibz2*ibz1;
00198 
00199     // get the component orthogonal to b1
00200 
00201     ibx2 = ibx2 - ilen * ibx1;
00202     iby2 = iby2 - ilen * iby1;
00203     ibz2 = ibz2 - ilen * ibz1;
00204 
00205     // normalize b2
00206 
00207     ilen2 = ibx2*ibx2 + iby2*iby2 + ibz2*ibz2;
00208     ilen = Sqrt( ilen2 ); 
00209     if( Test(ilen)==0 ) continue;   // avoid division by zero
00210 
00211     ibx2 = ibx2 / ilen;
00212     iby2 = iby2 / ilen;
00213     ibz2 = ibz2 / ilen;
00214 
00215     // calculate the crossproduct of b1 and b2
00216 
00217     inx = iby1*ibz2 - ibz1*iby2;
00218     iny = ibz1*ibx2 - ibx1*ibz2;
00219     inz = ibx1*iby2 - iby1*ibx2;
00220 
00221     // normalize it (superfluous since b1 and b2 are orthonormal)
00222 
00223     ilen2 = inx*inx + iny*iny + inz*inz;
00224     ilen = Sqrt( ilen2 ); 
00225     if( Test(ilen)==0 ) continue;
00226 
00227     inx = inx / ilen;
00228     iny = iny / ilen;
00229     inz = inz / ilen;
00230 
00231     rat1 = GetRatio(inx*inx + iny*iny + inz*inz);
00232     if( rat1 < rat ) 
00233     {
00234       rat  = rat1;
00235       irat0 = i0;
00236       irat1 = i1;
00237       irat2 = i2;
00238     }
00239   }
00240   if( (irat0 < 0) || (rat == rtr<double>::giant()) ) return false;
00241   i0 = irat0;
00242   i1 = irat1;
00243   i2 = irat2;
00244  
00245   // the same calculation as above, now with floating point arithmetic
00246 
00247   o = Verts[i0];
00248   v1 = Verts[i1] - o;
00249   v2 = Verts[i2] - o;
00250   normalize(&b1,v1);
00251   b2 = v2 - (v2*b1)*b1;
00252   normalize(&b2,b2);
00253   b3 = cross_product(b1,b2);
00254   normalize(&b3,b3);
00255 
00256   return true;
00257 }
00258 // template instantiation
00259 template GULAPI bool CalcPlane( 
00260        int nVerts, const Ptr< point<float> >& Verts,
00261        point<float>& o, point<float>& b1, point<float>& b2, point<float>& b3 );
00262 template GULAPI bool CalcPlane( 
00263    int nVerts, const Ptr< point<double> >& Verts,
00264    point<double>& o, point<double>& b1, point<double>& b2, point<double>& b3 );
00265 
00266 /*----------------------------------------------------------------------
00267   Check if a contour is lefthanded (if the contour self-intersects this
00268   check makes no sense)
00269 ----------------------------------------------------------------------*/
00270 
00271 template< class T >
00272 GULAPI bool CheckLeftHandedness( 
00273              int nP, const Ptr< point<T> >& P, const Ptr< Ptr<T> >& Ti,
00274              bool& lefthanded, bool& selfintersect )
00275 {
00276   polyline pl;
00277   Ptr< point2<T> > P2;
00278   Ptr<T> v3,v2;
00279   List< ListNode<segment> > segs,outsegs;
00280   ListNode<segment> *seg;
00281   graph_edge_list E;
00282   graph_vertex_list V;
00283   rational far_minx,far_maxx,far_miny,far_maxy;
00284   T minx,maxx,miny,maxy;
00285   T dx,dy,scale,scalei;
00286   int i,left;
00287   List< ListNode< ListNodeInfo< ListNode<graph_edge *> > > > *L;
00288   graph_edge *e;
00289   List< ListNode<graph_edge *> > *Le;
00290   unsigned long *cbuf = 
00291     (unsigned long *)alloca(gul::rtr<T>::mantissa_length());
00292   
00293   if( !nP ) return false;
00294 
00295   // project vertices onto plane
00296 
00297   P2.reserve_pool(nP);
00298   v3.reserve_pool(4);
00299   v2.reserve_pool(4);
00300 
00301   for( i = 0; i < nP; i++ )
00302   {
00303     v3[0] = P[i].x;
00304     v3[1] = P[i].y;
00305     v3[2] = P[i].z;
00306     v3[3] = (T)1;
00307 
00308     VMProduct(4,4,v3,Ti,v2);
00309 
00310     P2[i].x = v2[0];
00311     P2[i].y = v2[1];
00312   }
00313 
00314   CalcBoundingBoxE( nP, P2, minx, maxx, miny, maxy );
00315 
00316   dx = maxx - minx;
00317   dy = maxy - miny;
00318   scale = dx > dy ? dx : dy;
00319   minx -= scale;
00320   miny -= scale;
00321   scalei = (T)1.0/scale;
00322 
00323   /*
00324   Dump<float>::set_transformation(minx,miny,scale,scale);
00325   */
00326 
00327   pl.init( nP, P2, minx, miny, scalei ); 
00328 
00329   AppendContour( &pl, 0, 1, segs );
00330  
00331   IntersectSegments( segs, &E, &V, true );
00332 
00333   /*
00334   std::cout << "EDGES AFTER INTERSECTION\n";
00335   std::cout << "========================\n";
00336   Dump<float>::dump_edges( E.head );
00337   std::cout << "\n";
00338   */
00339 
00340   far_miny = far_minx = rational( guar::ULong(0x100000), -1 );
00341   far_maxy = far_maxx = rational( coord2int((T)2,cbuf),cbuf) +
00342                                       rational( guar::ULong(0x100000) );
00343 
00344   RemoveUnnecessaryEdges( E, V, far_maxx, far_maxy, 1, 0, outsegs );
00345 
00346   e = E.First(); if( !e ) return false; // internal error
00347 
00348   // backpointer to the segment edge lists which contain the fist edge
00349   L = (List< ListNode< ListNodeInfo< ListNode<graph_edge *> > > > *)
00350                                                                e->reserved[1].p;
00351   // the first backpointed List
00352   Le = L->First()->el.m_L;
00353 
00354   // find the corresponding segment 
00355   for( seg = segs.First(); seg != 0; seg = seg->next )
00356     if( &seg->el.e == Le ) break;
00357 
00358   if( !seg ) return false;  // internal error
00359   
00360   if( e->l.IsHorizontal() || (e->l.dx().test() < 0) )
00361     left = e->f[1].i;         // edge orientation different
00362   else
00363     left = e->f[0].i;
00364 
00365   lefthanded = (left != 1);
00366 
00367   // check if there were self-intersections
00368   
00369   for( seg = segs.First(); seg != 0; seg = seg->next )
00370     if( seg->el.e.nElems != 1 ) break;
00371 
00372   selfintersect = (seg != 0);
00373 
00374   // delete data which would not be automatically destructed
00375 
00376   e = E.First();
00377   while( e )         // delete backpointer lists
00378   {
00379     L = (List< ListNode< ListNodeInfo< ListNode<graph_edge *> > > > *)
00380                                                                e->reserved[1].p;
00381     L->DeleteElems();
00382     delete L; 
00383     e->reserved[1].p = 0;
00384     e = e->next;
00385   }    
00386 
00387   return true;
00388 }
00389 template GULAPI bool CheckLeftHandedness( 
00390            int nP, const Ptr< point<float> >& P,  const Ptr< Ptr<float> >& Ti,
00391            bool& lefthanded, bool& selfintersect );
00392 template GULAPI bool CheckLeftHandedness( 
00393            int nP, const Ptr< point<double> >& P, const Ptr< Ptr<double> >& Ti,
00394            bool& lefthanded, bool& selfintersect );
00395 
00396 
00397 template< class T >
00398 void Polygon3dTo2d(
00399             const List< ListNode< gul::polyline< point<T> > > >& C3, 
00400             const Ptr< Ptr< T > >& Ti,
00401             List< ListNode< gul::polyline< point2<T> > > >& C2 )
00402 {
00403   ListNode< gul::polyline< point<T> > > *c3;
00404   ListNode< gul::polyline< point2<T> > > *c2;
00405   int i;
00406   Ptr<T> v3,v2;
00407 
00408   v3.reserve_pool(4);
00409   v2.reserve_pool(4);
00410 
00411   c3 = C3.First();
00412   while( c3 )
00413   {
00414     c2 = new ListNode< gul::polyline< point2<T> > >;
00415     C2.Append( c2 );
00416 
00417     c2->el.n = c3->el.n;
00418     c2->el.P.reserve_pool( c3->el.n );
00419    
00420     for( i = 0; i < c3->el.n; i++ )
00421     {
00422       v3[0] = c3->el.P[i].x;
00423       v3[1] = c3->el.P[i].y;
00424       v3[2] = c3->el.P[i].z;
00425       v3[3] = (T)1;
00426 
00427       VMProduct(4,4,v3,Ti,v2);
00428 
00429       c2->el.P[i].x = v2[0];
00430       c2->el.P[i].y = v2[1];
00431     }
00432 
00433     c3 = c3->next;
00434   }
00435 }
00436 // template instantiation
00437 template void Polygon3dTo2d(
00438             const List< ListNode< gul::polyline< point<float> > > >& C3, 
00439             const Ptr< Ptr< float > >& Ti,
00440             List< ListNode< gul::polyline< point2<float> > > >& C2 );
00441 template void Polygon3dTo2d(
00442             const List< ListNode< gul::polyline< point<double> > > >& C3, 
00443             const Ptr< Ptr< double > >& Ti,
00444             List< ListNode< gul::polyline< point2<double> > > >& C2 );
00445 
00446 /*------------------------------------------------------------------------
00447   Triangulate a polygon with 3d vertices, normals, and texture coordinates
00448 -------------------------------------------------------------------------*/
00449 
00450 template< class T >
00451 GULAPI void TriangulatePolygon3d(
00452             const List< ListNode< gul::polyline< point<T> > > >& C3,
00453             const List< ListNode< gul::polyline< point<T> > > >& N3,
00454             const List< ListNode< gul::polyline< point<T> > > >& T3,
00455             const Ptr< Ptr< T > >& Ti,
00456             Ptr< point2<T> >& D,
00457             Ptr< point<T> >& F,
00458             Ptr< point<T> >& N,
00459             Ptr< point<T> >& Tx,
00460             int *nTri,
00461             Ptr<itriangle>& Tri )
00462 {
00463   T minx,maxx,miny,maxy;
00464   T dx,dy,scale,scalei;
00465   ListNode< gugr::polyline > *pn,*inc;
00466   ListNode< gul::polyline< point<T> > > *inF,*inN,*inT;
00467   List< ListNode< gul::polyline< point2<T> > > > C2;
00468   ListNode< gul::polyline< point2<T> > > *c2;
00469   List< ListNode<polyline> > Pl;
00470   List< ListNode<segment> > segs,outsegs;
00471   ListNode<segment> *seg;
00472   graph_edge_list E;
00473   graph_vertex_list V;
00474   rational far_minx,far_maxx,far_miny,far_maxy;
00475   unsigned long *cbuf = 
00476     (unsigned long *)alloca(gul::rtr<T>::mantissa_length());
00477   int nv,i,nt;
00478   Ptr< point<T> > &sumF = F, &sumN = N, &sumT = Tx;
00479   Ptr<T> sumW;
00480   graph_vertex *vn;
00481   graph_edge *e;
00482   ListNode<graph_edge *> *en;
00483   Interval iu,iv;
00484   T u,v,u1,u2,v1,v2,su,sv,alpha,w,wi,giant;
00485   point<T> fB,nB,fE,nE,tB,tE,f,n,t;
00486   bool end;
00487   triangle_list tri;
00488   triangle *tr;
00489 
00490   if( C3.nElems == 0 ) return;
00491 
00492   giant = gul::rtr<T>::giant();
00493 
00494   Polygon3dTo2d( C3, Ti, C2 );
00495 
00496   c2 = C2.First();
00497   CalcBoundingBoxE( c2->el.n, c2->el.P, minx, maxx, miny, maxy );
00498   c2 = c2->next;
00499 
00500   while( c2 )
00501   {
00502     UpdateBoundingBoxE( c2->el.n, c2->el.P, minx, maxx, miny, maxy );
00503     c2 = c2->next;
00504   }
00505 
00506   dx = maxx - minx;
00507   dy = maxy - miny;
00508   scale = dx > dy ? dx : dy;
00509   minx -= scale;
00510   miny -= scale;
00511   scalei = (T)1.0/scale;
00512 
00513   c2 = C2.First();
00514   while( c2 )
00515   {
00516     pn = new ListNode<gugr::polyline>();
00517     Pl.Append( pn );
00518     pn->el.init( c2->el.n, c2->el.P, minx, miny, scalei ); 
00519     c2 = c2->next;
00520   }
00521 
00522   inc = Pl.First();
00523   inF = C3.First();
00524   inN = N3.First();
00525   inT = T3.First();
00526 
00527   while( inc )
00528   {
00529     AppendContourFNT( &inc->el, inF->el.P, inN->el.P, inT->el.P, 0, 0, segs );
00530     inc = inc->next;
00531     inF = inF->next;
00532     inN = inN->next;
00533     inT = inT->next;
00534   }
00535 
00536   IntersectSegments( segs, &E, &V, true );
00537 
00538   far_miny = far_minx = rational( guar::ULong(0x100000), -1 );
00539   far_maxy = far_maxx = rational( coord2int((T)2,cbuf),cbuf) +
00540                                       rational( guar::ULong(0x100000) );
00541 
00542   RemoveUnnecessaryEdges( E, V, far_maxx, far_maxy, 1, 0, outsegs );
00543     
00544   ISDeleteBackpointers(E); // the backpointers were used to remove edge entries
00545                            // from 'segs' in 'RemoveUnnecessaryEdges'
00546   outsegs.DeleteElems();
00547 
00548   // if the contours intersect each other 3d points and normals must be
00549   // calculated at the intersections  
00550 
00551   nv = V.nElems;
00552   D.reserve_pool(nv);
00553   sumF.reserve_pool(nv);
00554   sumN.reserve_pool(nv);
00555   sumT.reserve_pool(nv);
00556   sumW.reserve_pool(nv);
00557 
00558   i = 0;
00559   vn = V.First();
00560   while( vn )
00561   {
00562     vn->v.m_rep->reserved.i = i;  // enumber vertices
00563 
00564     iu = vn->v.v().x.get_bounds();
00565     iv = vn->v.v().y.get_bounds();
00566     u = (T)((iu.m_low+iu.m_high)/2.0);
00567     v = (T)((iv.m_low+iv.m_high)/2.0);
00568     u = gugr::cnv2coord(u)*scale + minx; 
00569     v = gugr::cnv2coord(v)*scale + miny; 
00570 
00571     D[i].x = u;
00572     D[i].y = v;
00573     set( sumF[i], (T)0 );
00574     set( sumN[i], (T)0 );
00575     sumW[i] = (T)0;
00576 
00577     i++;    
00578     vn = vn->next;
00579   }
00580 
00581   for( seg = segs.First(); seg != 0; seg = seg->next )
00582   {
00583     // get function value and normal of start and end point of segment
00584     fB = *((seg_point_info< point<T> > *)seg->el.reserved[0])->f;
00585     nB = *((seg_point_info< point<T> > *)seg->el.reserved[0])->n;
00586     tB = *((seg_point_info< point<T> > *)seg->el.reserved[0])->t;
00587     fE = *((seg_point_info< point<T> > *)seg->el.reserved[1])->f;
00588     nE = *((seg_point_info< point<T> > *)seg->el.reserved[1])->n;
00589     tE = *((seg_point_info< point<T> > *)seg->el.reserved[1])->t;
00590  
00591     // get u,v of segment start point
00592     iu = seg->el.E.x.get_bounds();
00593     iv = seg->el.E.y.get_bounds();
00594     u = (T)((iu.m_low+iu.m_high)/2.0);
00595     v = (T)((iv.m_low+iv.m_high)/2.0);
00596     u2 = cnv2coord(u)*scale + minx; 
00597     v2 = cnv2coord(v)*scale + miny; 
00598 
00599     // get u,v of segment end point
00600     iu = seg->el.B.x.get_bounds();
00601     iv = seg->el.B.y.get_bounds();
00602     u = (T)((iu.m_low+iu.m_high)/2.0);
00603     v = (T)((iv.m_low+iv.m_high)/2.0);
00604     u1 = cnv2coord(u)*scale + minx; 
00605     v1 = cnv2coord(v)*scale + miny; 
00606  
00607     su = u2 - u1;
00608     sv = v2 - v1;
00609 
00610     // travert edges on this segment
00611 
00612     en = seg->el.e.First();
00613     if( !en ) continue;
00614     e = en->el;
00615     if( e->l.IsHorizontal() || (e->l.dx().test() < 0) )
00616       end = 0;
00617     else
00618       end = 1;
00619 
00620     for( ; en != 0; en = en->next )
00621     {
00622       e = en->el;
00623 
00624       /* ---- first point of edge --------------------------- */
00625 
00626       vn = e->v[!end];
00627       i = vn->v.m_rep->reserved.i;
00628       u = D[i].x - u1;
00629       v = D[i].y - v1;
00630     
00631       if( su > sv )
00632         alpha = u/su;
00633       else if( sv > (T)0 )
00634         alpha = v/sv;
00635       else
00636         alpha = (T)0;
00637 
00638       if( (alpha == (T)0) || (alpha >= (T)1) )
00639       {
00640         wi = giant;
00641       }
00642       else 
00643       {
00644         if( alpha > (T)0.5 )
00645         {
00646           u = u2 - D[i].x;
00647           v = v2 - D[i].y;
00648         }
00649         w = u*u + v*v;
00650         if( w > (T)0 ) wi = (T)1.0/w;
00651         else wi = giant;
00652       }
00653 
00654       f = ((T)1.0-alpha)*fB + alpha*fE;
00655       n = ((T)1.0-alpha)*nB + alpha*nE;
00656       t = ((T)1.0-alpha)*tB + alpha*tE;
00657 
00658       if( wi >= giant )
00659       {
00660         if( sumW[i] >= (T)0 )
00661         {
00662           sumW[i] = (T)-1.0;
00663           sumF[i] = -f;
00664           sumN[i] = -n;
00665           sumT[i] = -t;
00666         }
00667         else
00668         {
00669           sumW[i] -= (T)1.0;
00670           sumF[i] -= f;
00671           sumN[i] -= n;
00672           sumT[i] -= t;
00673          }
00674       }
00675       else
00676       {
00677         sumW[i] += wi;
00678         sumF[i] += wi*f;
00679         sumN[i] += wi*n;
00680         sumT[i] += wi*t;
00681       }
00682 
00683       /* ---- second point of edge --------------------------- */
00684 
00685       if( en->next && (en->next->el->v[!end] == e->v[end]) )
00686         continue;    // will be processed with next edge
00687  
00688       vn = e->v[end];
00689       i = vn->v.m_rep->reserved.i;
00690       u = D[i].x - u1;
00691       v = D[i].y - v1;
00692     
00693       if( su > sv )
00694         alpha = u/su;
00695       else if( sv > (T)0 )
00696         alpha = v/sv;
00697       else
00698         alpha = (T)0;
00699 
00700       if( (alpha == (T)0) || (alpha >= (T)1) )
00701       {
00702         wi = giant;
00703       }
00704       else 
00705       {
00706         if( alpha > (T)0.5 )
00707         {
00708           u = u2 - D[i].x;
00709           v = v2 - D[i].y;
00710         }
00711         w = u*u + v*v;
00712         if( w > (T)0 ) wi = (T)1.0/w;
00713         else wi = giant;
00714       }
00715 
00716       f = ((T)1.0-alpha)*fB + alpha*fE;
00717       n = ((T)1.0-alpha)*nB + alpha*nE;
00718       t = ((T)1.0-alpha)*tB + alpha*tE;
00719 
00720       if( wi >= giant )
00721       {
00722         if( sumW[i] >= (T)0 )
00723         {
00724           sumW[i] = (T)-1;
00725           sumF[i] = -f;
00726           sumN[i] = -n;
00727           sumT[i] = -t;
00728          }
00729         else
00730         {
00731           sumW[i] -= (T)1;
00732           sumF[i] -= f;
00733           sumN[i] -= n;
00734           sumT[i] -= t;
00735         }
00736       }
00737       else
00738       {
00739         sumW[i] += wi;
00740         sumF[i] += wi*f;
00741         sumN[i] += wi*n;
00742         sumT[i] += wi*t;
00743       }
00744     }
00745   }
00746 
00747   for( i = 0; i < nv; i++ )
00748   {
00749     wi = (T)1/sumW[i];
00750     sumF[i] *= wi;
00751     sumN[i] *= wi;
00752     sumT[i] *= wi;
00753   }  
00754 
00755   // delete not needed data
00756   segs.DeleteElems();
00757 
00758   /* ---- finally, triangulate the graph ------------------- */
00759 
00760   Regularize( &E, &V );
00761 
00762   Triangulate( &E, &V, far_minx, &tri );
00763 
00764   nt = tri.nElems;
00765   Tri.reserve_pool(nt);
00766   tr = tri.First(); 
00767 
00768   for( i = 0; i < nt; i++ )
00769   {
00770     Tri[i].v[0] = tr->v[0].m_rep->reserved.i;
00771     Tri[i].v[1] = tr->v[1].m_rep->reserved.i;
00772     Tri[i].v[2] = tr->v[2].m_rep->reserved.i;
00773     tr = tr->next;
00774   }
00775   *nTri = nt;
00776 }
00777 // template instantiation
00778 template GULAPI void TriangulatePolygon3d<float>(
00779             const List< ListNode< gul::polyline< point<float> > > >& C3,
00780             const List< ListNode< gul::polyline< point<float> > > >& N3,
00781             const List< ListNode< gul::polyline< point<float> > > >& T3,
00782             const Ptr< Ptr< float > >& Ti,
00783             Ptr< point2<float> >& D,
00784             Ptr< point<float> >& F,
00785             Ptr< point<float> >& N,
00786             Ptr< point<float> >& Tx,
00787             int *nTri,
00788             Ptr<itriangle>& Tri );
00789 
00790 template GULAPI void TriangulatePolygon3d<double>(
00791             const List< ListNode< gul::polyline< point<double> > > >& C3,
00792             const List< ListNode< gul::polyline< point<double> > > >& N3,
00793             const List< ListNode< gul::polyline< point<double> > > >& T3,
00794             const Ptr< Ptr< double > >& Ti,
00795             Ptr< point2<double> >& D,
00796             Ptr< point<double> >& F,
00797             Ptr< point<double> >& N,
00798             Ptr< point<double> >& Tx,
00799             int *nTri,
00800             Ptr<itriangle>& Tri );
00801 
00802 
00803 }

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