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

gugr_triangulate.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 "guar_exact.h"
00026 #include "gugr_basics.h"
00027 #include "gugr_regularize.h"
00028 #include "gugr_triangulate.h"
00029 #include "gul_io.h"
00030 #include "gul_std.h"
00031 #include "gugr_planesweep.h"
00032 #include "gugr_io.h"
00033 
00034 namespace gugr {
00035 
00036 using gul::AllocError;
00037 using gul::InternalError;
00038 
00039 
00040 /* ------------------------------------------------------------------------
00041   Triangulates the regions of a graph. E must be regularized, and V
00042   sorted. For this purpose the graph is divided into monotone chains.
00043   Between two monontone chains lies a monotone polygone.
00044   Only those triangles are calculated, whose edges have a positive face
00045   index on the inward side 
00046 ------------------------------------------------------------------------- */
00047 
00048 void Triangulate( graph_edge_list *E, graph_vertex_list *V,
00049                   const rational& far_left, triangle_list *T )
00050 {
00051   vertex farleft;
00052   graph_edge *e, *eb, *ea,*left,*right,**tmpE;
00053   graph_vertex *v;
00054   int ileft,iright,codel,coder,nE,Win,Wout,ie,iea,ieb;
00055   int nP,i;
00056   graph_edge *e1;
00057   monpoly_info *P,*tmpP;
00058   int li,ri;
00059   
00060   tmpE = (graph_edge **)alloca( sizeof(graph_edge *)*(E->nElems) );
00061   if( !tmpE ) throw AllocError();
00062 
00063   if( V->head != NULL ) v = V->head->next;       /* second smallest vertex */
00064   else return;
00065   if( v->next == NULL ) return;
00066 
00067   e = E->head;
00068   while( e != NULL )                            /* initialize weights to 1 */
00069   { e->reserved[0].set_i(1); e = e->next; } 
00070   
00071 /* ---------- weight balancing, first pass ----------------------------- */
00072 
00073   while( v->next != NULL )
00074   {
00075     nE = IncidentEdges( v, tmpE );
00076 
00077     farleft = vertex( point2<rational>(far_left,v->v.v().y) );    
00078     EdgeInsertPosition( v->v, farleft, nE, tmpE, &ileft, &iright,
00079                         &codel, &coder );
00080     left = tmpE[ileft];  right = tmpE[iright];
00081 
00082     if( right->v[0] == v )         /* => leftwards oriented horizontal edge */ 
00083       e = eb = right->e[0];
00084     else
00085       e = eb = right;              /* eb = leftmost incoming edge */
00086 
00087     Win = 0;                       /* sum of weights of incoming edges of v */
00088     while( e->v[1] == v )
00089     {
00090       Win += e->reserved[0].i;
00091       e = e->e[1];
00092     }
00093     Wout = 1;                      /* sum of weights of outgoing edges of v */
00094     while( e->e[0] != eb )
00095     {
00096       Wout++;
00097       e = e->e[0];
00098     }
00099     ea = e;                        /* ea = leftmost outgoing edge */
00100     
00101     if( Win > Wout )
00102       ea->reserved[0].set_i(Win-Wout+1);
00103 
00104     v = v->next;
00105   }
00106 
00107 /***** second pass, combined with extraction of monotone polygons *********/
00108 
00109   /* ------- initialize polygon slots at the maximum vertex -------- */
00110 
00111   nP = 0;                         
00112 
00113   nE = IncidentEdges( v, tmpE ); /* edges adjacent to maximum of graph */
00114 
00115   farleft = vertex( point2<rational>(far_left,v->v.v().y) );    
00116   EdgeInsertPosition( v->v, farleft, nE, tmpE, &ileft, &iright,
00117                       &codel, &coder );
00118   e1 = right = tmpE[iright];
00119 
00120   do 
00121   {
00122     e1->reserved[1].set_i(nP);   /* store index of the polygon on the right*/
00123     nP += e1->reserved[0].i;     /* side of this edge                      */
00124     e1 = e1->e[1];
00125   }
00126   while( e1 != right );
00127   nP--;
00128 
00129   P = tmpP = (monpoly_info *)alloca( sizeof(monpoly_info) * nP );
00130   if( P == NULL ) throw AllocError();
00131   // new(P) monpoly_info[nP];
00132   for( i = 0; i < nP; i++ ) new(tmpP++) monpoly_info;
00133 
00134   /*
00135   std::cout << "number of monotone polygons = " << nP << "\n";
00136   */
00137 
00138   /* ------- second pass of weight balancing -------- */
00139 
00140   v = v->prev;                  /* v = second largest vertex */
00141 
00142   while( v->prev != NULL )
00143   {
00144     nE = IncidentEdges( v, tmpE );
00145 
00146     farleft = vertex( point2<rational>(far_left,v->v.v().y) );    
00147     EdgeInsertPosition( v->v, farleft, nE, tmpE, &ileft, &iright,
00148                         &codel, &coder );
00149     if( tmpE[iright]->v[0] == v ) /* => leftwards oriented horizontal edge */
00150       ie = iea = iright;
00151     else  
00152       ie = iea = ileft;           /* iea = index of leftmost outgoing edge */
00153 
00154     Wout = 0;                       /* sum of weights of outgoing edges of v */
00155     do
00156     {
00157       Wout += tmpE[ie]->reserved[0].i;
00158 
00159    /* ----- add edge to involved polygons ---------------- */ 
00160 
00161       li = tmpE[ie]->reserved[1].i-1;
00162       if( (li >= 0) && (tmpE[ie]->f[0].i > 0) )
00163       {
00164         /*
00165         std::cout << "adding edge " << (void *)tmpE[ie] << " to polygon " << 
00166                   li+1 << ", right chain\n";
00167         */
00168 
00169         if( P[li].AppendRight(*v, *tmpE[ie]->v[1]) )
00170         {
00171           /*
00172           std::cout << "triangulating monotone polygon #" << li+1 << "\n";
00173           */
00174           
00175           TriangulateMonotonePolygon( &P[li].Vl, &P[li].Vr, &P[li].E, T ); 
00176         }
00177       }
00178       ri = li + tmpE[ie]->reserved[0].i;
00179       if( (ri < nP) && (tmpE[ie]->f[1].i > 0) )
00180       {     
00181         /*
00182         std::cout << "adding edge " << (void *)tmpE[ie] << " to polygon " << 
00183                   ri+1 << ", left chain\n";
00184         */
00185         
00186         if( P[ri].AppendLeft(*v, *tmpE[ie]->v[1]) )
00187         {
00188           /*
00189           std::cout << "triangulating monotone polygon #" << ri+1 << "\n";
00190           */
00191 
00192           TriangulateMonotonePolygon( &P[ri].Vl, &P[ri].Vr, &P[ri].E, T ); 
00193         }
00194       }
00195            
00196    /* ---------------------------------------------------- */
00197 
00198       ie--; if(ie < 0) ie = nE-1;
00199     }
00200     while( tmpE[ie]->v[0] == v );
00201 
00202     Win = 0;                      /* sum of weights of incoming edges of v */
00203     while( tmpE[ie] != tmpE[iea] )
00204     {
00205       Win += tmpE[ie]->reserved[0].i;
00206       ie--; if(ie < 0) ie = nE-1;
00207     }
00208     ieb = iea+1;                   /* ieb = index of leftmost incoming edge */
00209     if( ieb == nE ) ieb = 0;
00210 
00211     if( Wout > Win ) 
00212       tmpE[ieb]->reserved[0].i += (Wout-Win);
00213 
00214   /* -------- set polygon indices for incoming edges -------------------- */ 
00215 
00216     i = tmpE[iea]->reserved[1].i; /* index of polygon to the right of */
00217     e = tmpE[ieb];                   /* leftmost  edges */
00218     e->reserved[1].set_i(i);  /* give leftmost incoming edge this index */
00219     i += e->reserved[0].i;    /* add multiplicity of edge */
00220     e = e->e[1];                 /* next edge */
00221     
00222     while( e->v[1] == v )        /* is next incoming edge */
00223     {
00224       e->reserved[1].set_i(i);
00225       i += e->reserved[0].i;
00226       e = e->e[1];               /* next edge */
00227     }
00228   /* -------------------------------------------------------------------- */
00229 
00230     v = v->prev;
00231   }
00232 
00233   /* process smallest vertex */
00234 
00235   nE = IncidentEdges( v, tmpE );  /* incident edges to smallest vertex */
00236 
00237   farleft = vertex( point2<rational>(far_left,v->v.v().y) );    
00238   EdgeInsertPosition( v->v, farleft, nE, tmpE, &ileft, &iright,
00239                      &codel, &coder );
00240   if( tmpE[iright]->IsHorizontal() )  /* => leftwards orient horizontal edge */
00241     ie = iea = iright;
00242   else  
00243     ie = iea = ileft;               /* iea = index of leftmost outgoing edge */
00244 
00245   do    /* add edges to involved polygons */
00246   {
00247     li = tmpE[ie]->reserved[1].i-1;
00248     if( (li >= 0) && (tmpE[ie]->f[0].i > 0) )
00249     {
00250       /*
00251       std::cout << "adding edge " << (void *)tmpE[ie] << " to polygon " << 
00252                 li+1 << ", right chain\n";
00253       */
00254 
00255       if( P[li].AppendRight(*v, *tmpE[ie]->v[1]) )
00256       {
00257         /*
00258         std::cout << "triangulating monotone polygon #" << li+1 << "\n";
00259         */
00260 
00261         TriangulateMonotonePolygon( &P[li].Vl, &P[li].Vr, &P[li].E, T ); 
00262       }
00263     }
00264     ri = li + tmpE[ie]->reserved[0].i;
00265     if( (ri < nP) && (tmpE[ie]->f[1].i > 0) )
00266     {     
00267       /*
00268       std::cout << "adding edge " << (void *)tmpE[ie] << " to polygon " << 
00269                 ri+1 << ", left chain\n";
00270       */
00271 
00272       if( P[ri].AppendLeft(*v, *tmpE[ie]->v[1]) )
00273       {
00274         /*
00275         std::cout << "triangulating monotone polygon #" << ri+1 << "\n";
00276         */
00277 
00278         TriangulateMonotonePolygon( &P[ri].Vl, &P[ri].Vr, &P[ri].E, T ); 
00279       }
00280     }
00281 
00282     ie--; if(ie < 0) ie = nE-1;
00283   }
00284   while( ie != iea );
00285 
00286   for( i = 0; i < nP; i++ )
00287   {
00288     P[i].Vl.DeleteElems();
00289     P[i].Vr.DeleteElems();
00290     P[i].E.DeleteElems();
00291   }
00292 }
00293 
00294 
00295 
00296 /* ------------------------------------------------------------------------
00297   Triangulates a monotone polygon
00298 
00299   The vertices in V1 and V2, and the edges in E are deleted
00300   in this function! 
00301 -------------------------------------------------------------------------- */
00302 
00303 void TriangulateMonotonePolygon(
00304               graph_vertex_list2 *V1, graph_vertex_list2 *V2,
00305               graph_edge_list *E, triangle_list *T )
00306       
00307 {
00308   graph_vertex_list2 Vq, S;
00309   graph_vertex *vh,*v1,*v2,*vi,*vi_1,*vs,*vt,*v,*vh1,*vh2;
00310   graph_edge *e;
00311   triangle *tri;
00312   int sign;
00313   graph_vertex_list V;
00314 
00315   /*
00316   cout << "Triangulation of montone polygon\n";
00317   cout << "********************************\n";
00318   cout << "Vertices of left chain\n";
00319   cout << "======================\n";
00320   gugr::Dump<float>::dump_vertices( V1->head );
00321   cout << "Vertices of right chain\n";
00322   cout << "======================\n";
00323   gugr::Dump<float>::dump_vertices( V2->head );
00324   cout << "Edges (of both chains)\n";
00325   cout << "======================\n";
00326   gugr::Dump<float>::dump_edges( E->head );
00327   */
00328 
00329 /* ----- merge together the vertices of both monotone chains ------------ */
00330   
00331   vh1 = V1->Last();            /* first vertex of chain 1 */
00332   V1->Remove(vh1);
00333   V.Append(vh1);
00334 
00335   vh2 = V2->Last();            /* first vertex of chain 2 */
00336   V2->Remove(vh2);
00337   V.Append(vh2);
00338 
00339   v1 = V1->Last();
00340   V1->Remove(v1);
00341   v1->reserved[0].set_i(-1);        /* element of left chain */
00342  
00343   v2 = V2->Last();
00344   V2->Remove(v2);
00345   v2->reserved[0].set_i(+1);        /* element of right chain */
00346 
00347   if( (V1->Last() == NULL) && (V2->Last() == NULL) )  /* ready, no triangles */
00348   {
00349     delete v1; delete v2;
00350     V1->DeleteElems();
00351     V2->DeleteElems();
00352     V.DeleteElems();
00353     E->DeleteElems();
00354     return;
00355   }
00356                     /* make first vertex of both chains have the same address */
00357   vh = new graph_vertex( vh2->v, NULL, vh2->reserved[1].i );                                              
00358   Vq.AppendRight(vh);
00359   vh->reserved[0].set_i(0);
00360 
00361   e = new graph_edge();
00362   E->Append(e);
00363   e->l = v1->e->l;
00364   e->v[0] = v1;
00365   e->v[1] = vh;
00366   v1->e = e;
00367 
00368   e = new graph_edge();
00369   E->Append(e);
00370   e->l = v2->e->l;
00371   e->v[0] = v2;
00372   e->v[1] = vh;
00373   v2->e = e;
00374 
00375   while( (v1 != NULL) || (v2 != NULL) )
00376   {
00377     if( v1 != NULL )
00378     {
00379       if( v2 != NULL )
00380         sign = compare( v1->v.v().y, v2->v.v().y );
00381       else 
00382         sign = +1;
00383     }
00384     else sign = -1;
00385     
00386     if( sign >= 0 )
00387     {
00388       if( v1->e->IsHorizontal() )  /* compress together horizontal edges */
00389       {
00390         vs = v1;
00391         vt = V1->Last();
00392         while( (vt != NULL) && (vt->e->IsHorizontal()) )
00393         {
00394           V1->Remove(vt);
00395           delete v1;
00396           v1 = vt;
00397           vt = V1->Last();
00398         }
00399         if( v1 != vs )
00400         {
00401           e = new graph_edge();
00402           E->Append(e);
00403           e->l = v1->e->l;
00404           e->v[0] = v1;
00405           e->v[1] = vh;
00406           v1->e = e;
00407         }
00408       }      
00409       v1->reserved[0].set_i(-1);
00410       Vq.AppendRight(v1);
00411       vh = v1;
00412       v1 = V1->Last();
00413       if( v1 != NULL ) V1->Remove(v1);
00414     }
00415     else
00416     {
00417       if( v2->e->IsHorizontal() )  /* compress together horizontal edges */
00418       {
00419         vs = v2;
00420         vt = V2->Last();
00421         while( (vt != NULL) && (vt->e->IsHorizontal()) )
00422         {
00423           V2->Remove(vt);
00424           delete v2;
00425           v2 = vt;
00426           vt = V2->Last();
00427         }
00428         if( v2 != vs )
00429         {
00430           e = new graph_edge();
00431           E->Append(e);
00432           e->l = v2->e->l;
00433           e->v[0] = v2;
00434           e->v[1] = vh;
00435           v2->e = e;
00436         }
00437       }
00438 
00439       v2->reserved[0].set_i(+1);
00440       Vq.AppendRight(v2);
00441       vh = v2;
00442       v2 = V2->Last();
00443       if( v2 != NULL ) V2->Remove(v2);
00444     }
00445   }
00446 
00447   vh->prev->reserved[0].set_i(0);    /* this is the last vertex */
00448   Vq.Remove(vh);              
00449   delete vh;
00450   
00451 /* ---- construct the triangles ------------------------------------------- */
00452 
00453   v = Vq.First();     /* put first two vertices on stack */
00454   Vq.Remove(v);
00455   S.AppendRight(v);
00456 
00457   v = Vq.First();
00458   Vq.Remove(v);
00459   S.AppendRight(v);
00460 
00461   v = Vq.First();
00462   Vq.Remove(v);
00463 
00464   while( v->reserved[0].i != 0 )     /* not the last vertex */
00465   {
00466     vi = S.Last();
00467     v1 = S.First();
00468     
00469     e = v->e;
00470     
00471     if( e->v[1] == vi )  /* adjacent to top of stack */
00472     {
00473       vi_1 = vi->prev;
00474 
00475       sign = DetermineOrientation(v->v.v(),vi->v.v(),vi_1->v.v());
00476       sign *= v->reserved[0].i;
00477 
00478       if( (sign == 0) && (v->e->IsHorizontal()) ) /* special case */
00479       {
00480         S.Remove(vi);
00481         V.Append(vi);
00482         S.AppendRight(v);
00483       }
00484       else
00485       {
00486         while( (sign > 0) && (S.nElems > 1) )
00487         {
00488           tri = new triangle();
00489           if( vi->reserved[0].i == +1 )
00490           {
00491             tri->v[0] = v->v;    tri->code0 = v->reserved[1].i;
00492             tri->v[1] = vi->v;   tri->code1 = vi->reserved[1].i;
00493             tri->v[2] = vi_1->v; tri->code2 = vi_1->reserved[1].i;
00494             /*
00495             cout << "TRIANGLE\n";
00496             Dump<float>::dump_vertice(v);
00497             Dump<float>::dump_vertice(vi);
00498             Dump<float>::dump_vertice(vi_1);
00499             */
00500           }
00501           else     
00502           {
00503             tri->v[0] = v->v;    tri->code0 = v->reserved[1].i;
00504             tri->v[1] = vi_1->v; tri->code1 = vi_1->reserved[1].i;
00505             tri->v[2] = vi->v;   tri->code2 = vi->reserved[1].i;
00506             /*
00507             cout << "TRIANGLE\n";
00508             Dump<float>::dump_vertice(v);
00509             Dump<float>::dump_vertice(vi_1);
00510             Dump<float>::dump_vertice(vi);
00511             */
00512           }
00513           T->Append(tri);
00514 
00515           S.Remove(vi);
00516           V.Append(vi);
00517           if( S.nElems > 1 )
00518           {
00519             vi = vi_1;
00520             vi_1 = vi->prev;
00521             sign = DetermineOrientation(v->v.v(),vi->v.v(),vi_1->v.v());
00522             sign *= v->reserved[0].i;
00523           }
00524         }
00525         S.AppendRight(v);
00526       }
00527     } 
00528     else                  /* adjacent to bottom of stack */
00529     {
00530       gul::Assert<gul::InternalError>( ndebug || (e->v[1] == v1) );
00531      
00532       if( v->e->IsHorizontal() )  /* special case */
00533       {
00534         gul::Assert<gul::InternalError>( ndebug || (S.nElems == 2) );
00535         S.Remove(v1);
00536         V.Append(v1);
00537         S.AppendRight(v);
00538       }
00539       else
00540       {
00541         v2 = v1->next;
00542         do
00543         {
00544           tri = new triangle();
00545           if( v2->reserved[0].i == +1 )
00546           {
00547             tri->v[0] = v->v;   tri->code0 = v->reserved[1].i;
00548             tri->v[1] = v2->v;  tri->code1 = v2->reserved[1].i;
00549             tri->v[2] = v1->v;  tri->code2 = v1->reserved[1].i;
00550             /*
00551             cout << "TRIANGLE\n";
00552             Dump<float>::dump_vertice(v);
00553             Dump<float>::dump_vertice(v2);
00554             Dump<float>::dump_vertice(v1);
00555             */
00556           }
00557           else
00558           {
00559             tri->v[0] = v->v;   tri->code0 = v->reserved[1].i;
00560             tri->v[1] = v1->v;  tri->code1 = v1->reserved[1].i;
00561             tri->v[2] = v2->v;  tri->code2 = v2->reserved[1].i;
00562             /*
00563             cout << "TRIANGLE\n";
00564             Dump<float>::dump_vertice(v);
00565             Dump<float>::dump_vertice(v1);
00566             Dump<float>::dump_vertice(v2);
00567             */
00568           }
00569           T->Append(tri);
00570     
00571           S.Remove(v1);
00572           V.Append(v1);
00573           v1 = v2;
00574           v2 = v1->next;            
00575         }
00576         while( v2 != NULL );
00577     
00578         S.AppendRight(v);   
00579       }
00580     }
00581 
00582     v = Vq.First();
00583     Vq.Remove(v);
00584   }
00585 
00586   /* last vertex */
00587 
00588   v1 = S.First();
00589   do
00590   {
00591     v2 = v1->next;
00592 
00593     tri = new triangle();
00594     if( (int)v2->reserved[0].i == +1 )
00595     {
00596       tri->v[0] = v->v;   tri->code0 = v->reserved[1].i;
00597       tri->v[1] = v2->v;  tri->code1 = v2->reserved[1].i;
00598       tri->v[2] = v1->v;  tri->code2 = v1->reserved[1].i;
00599       /*
00600       cout << "TRIANGLE\n";
00601       Dump<float>::dump_vertice(v);
00602       Dump<float>::dump_vertice(v2);
00603       Dump<float>::dump_vertice(v1);
00604       */
00605     }
00606     else
00607     {
00608       tri->v[0] = v->v;   tri->code0 = v->reserved[1].i;
00609       tri->v[1] = v1->v;  tri->code1 = v1->reserved[1].i;
00610       tri->v[2] = v2->v;  tri->code2 = v2->reserved[1].i;
00611       /*
00612       cout << "TRIANGLE\n";
00613       Dump<float>::dump_vertice(v);
00614       Dump<float>::dump_vertice(v1);
00615       Dump<float>::dump_vertice(v2);
00616       */
00617     }
00618     T->Append(tri);
00619 
00620     S.Remove(v1);
00621     V.Append(v1);
00622     v1 = v2;
00623     v2 = v1->next;
00624   }
00625   while( v2 != NULL );
00626   S.Remove(v1);
00627   V.Append(v1);
00628 
00629   delete v;
00630 
00631   gul::Assert<gul::InternalError>( ndebug || 
00632     ((S.nElems == 0) && (Vq.nElems == 0) &&
00633      (V1->nElems == 0) && (V2->nElems == 0)) );
00634 
00635 //  S.DeleteElems();
00636 //  Vq.DeleteElems();
00637 //  V1->DeleteElems();
00638 //  V2->DeleteElems();
00639   V.DeleteElems();
00640   E->DeleteElems();
00641 }
00642 
00643 }

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