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

gugr_regularize.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 #include "gul_types.h"
00024 #include "guar_exact.h"
00025 #include "gugr_basics.h"
00026 #include "guma_sorting.h"
00027 #include "gugr_regularize.h"
00028 
00029 
00030 namespace gugr {
00031 
00032 using gul::AllocError;
00033 using guma::BBTNode;
00034 using guma::PtrHeapSort;
00035 using guma::InitBBT;
00036 using guma::InsertElementIntoBBT;
00037 using guma::DeleteElementFromBBT;
00038 using guma::SearchElementInBBT;
00039 using guma::DumpBBTTree;
00040 using std::cout;
00041 
00042 /* --------------------------------------------------------------------
00043   Sort vertices. (V2 > V1, if y2 > y1 or x2 < x1 if y2 = y1)
00044 --------------------------------------------------------------------- */
00045 
00046 int compare_vertices( void *p1, void *p2, void *data )
00047 {
00048   const graph_vertex& v1 = *((graph_vertex *)p1);
00049   const graph_vertex& v2 = *((graph_vertex *)p2);
00050   int sign;
00051   
00052   sign = compare( v1.v.v().y, v2.v.v().y );
00053   if( !sign ) sign = -compare( v1.v.v().x, v2.v.v().x );
00054 
00055   return(sign);
00056 }
00057 
00058 graph_vertex *SortVertices( graph_vertex_list *V )
00059 {
00060   graph_vertex **tmpV,*v;
00061   int i,j;
00062   
00063   tmpV = (graph_vertex **)alloca( sizeof(graph_vertex *)*V->nElems );
00064   if( !tmpV ) throw AllocError();
00065   
00066   v = V->head;
00067   for( i = 0; i < V->nElems; i++ )
00068   {
00069     tmpV[i] = v;
00070     v = v->next;
00071   }
00072   
00073   PtrHeapSort( V->nElems, (void **)tmpV, compare_vertices, NULL );
00074 
00075   V->head = tmpV[0];
00076   tmpV[0]->prev = NULL;
00077   for( j = 1; j < V->nElems; j++ )
00078   {
00079     tmpV[j-1]->next = tmpV[j];
00080     tmpV[j]->prev = tmpV[j-1];
00081   }
00082   tmpV[V->nElems-1]->next = NULL;
00083 
00084   return(tmpV[V->nElems-1]); /* return last vertex in list */
00085 }
00086 
00087 typedef struct
00088 {
00089   graph_edge   *l,*r;
00090   graph_vertex *v;
00091 }
00092 edge_interval;
00093 
00094 const graph_edge NegInf(0, (graph_vertex *)(-1));
00095 const graph_edge PosInf(0, (graph_vertex *)(+1));
00096 #define EDGE_NEG_INF ((graph_edge *)&NegInf)
00097 #define EDGE_POS_INF ((graph_edge *)&PosInf)
00098 
00099 #define IS_INF(e) ( (e).v[0] == NULL )
00100 #define INF_SIGN(e) (((e).v[1] == (graph_vertex *)(-1)) ? -1 : 1)
00101 
00102 struct edge_interval_tree
00103 {
00104   BBTNode root;
00105   // int icnt,ncnt;
00106 
00107   edge_interval_tree()
00108   {
00109     InitBBT(&root);
00110     // icnt = ncnt = 0;
00111   }
00112 
00113   BBTNode *NewNode( void )
00114   {
00115     BBTNode *node;
00116     size_t dummy;
00117     
00118     node = (BBTNode *)PoolAlloc( sizeof(BBTNode), &dummy );
00119     if( node == NULL ) throw PoolAllocError();
00120     node->key = PoolAlloc( sizeof(edge_interval), &dummy );
00121     if( node->key == NULL ) throw PoolAllocError();
00122 
00123     return(node);
00124   }
00125 
00126   BBTNode *Head( void ) { return(root.right); }
00127 
00128   void FreeNode( BBTNode *node )
00129   {
00130     PoolFree( node->key, sizeof(edge_interval) );
00131     PoolFree( node, sizeof(BBTNode) );   
00132   }
00133 
00134   void InsertNode( BBTNode *element, BBTNode *where, int side )
00135   {
00136     InsertElementIntoBBT( element, where, side, &root );
00137   }
00138 
00139   void RemoveNode( BBTNode *element )
00140   {
00141     DeleteElementFromBBT( element, &root );
00142   }
00143 
00144   int SearchNode( void *key, int compare( void *, void * ),
00145                   BBTNode **element )
00146   {
00147     return( SearchElementInBBT(&root, key, compare, element) );
00148   }
00149 
00150   static void dump_edge_interval( void *p  )
00151   {
00152      edge_interval *ei = (edge_interval *)p;
00153      cout << "key = {l=" << (void *)ei->l << ", r=" << (void *)ei->r <<
00154           ", v=" << (void *)ei->v << "}";
00155   }
00156   /* 
00157   void Dump()
00158   {
00159     std::cout << "EDGE INTERVALLS (" << icnt << ")\n";
00160     std::cout << "================================\n";
00161     DumpBBTTree( Head(), 0, dump_edge_interval );
00162     std::cout << "\n";
00163     std::cout.flush();
00164     icnt++;
00165   }
00166   void DumpNodes()
00167   {
00168     std::cout << "TREE NODES (" << ncnt << ")\n";
00169     std::cout << "===========================\n";
00170     DumpBBTNode( Head(), 0 );
00171     std::cout << "\n";
00172     std::cout.flush();
00173     ncnt++;
00174   }
00175   */
00176 };
00177 
00178 
00179 int CompareEdgesBU( const graph_edge *A, const graph_edge *B )
00180 {
00181   int sign;
00182   
00183   if( A == B ) return(0);
00184   
00185   if( IS_INF(*A) )
00186     return( INF_SIGN(*A) );
00187   if( IS_INF(*B) )
00188     return( -INF_SIGN(*B) );
00189   
00190   if( A->v[0] != B->v[0] ) {
00191     sign = DetermineOrientation( B->v[0]->v.v(), B->v[1]->v.v(),
00192                                  A->v[0]->v.v() );
00193   } else {
00194     sign = DetermineOrientation( B->v[0]->v.v(), B->v[1]->v.v(),
00195                                  A->v[1]->v.v() );
00196   }
00197   return(-sign);
00198 }
00199 int CompareEdgesTD( const graph_edge *A, const graph_edge *B )
00200 {
00201   int sign;
00202   
00203   if( A == B ) return(0);
00204   
00205   if( IS_INF(*A) )
00206     return( INF_SIGN(*A) );
00207   if( IS_INF(*B) )
00208     return( -INF_SIGN(*B) );
00209   
00210   if( A->v[1] != B->v[1] ) {
00211     sign = DetermineOrientation( B->v[0]->v.v(), B->v[1]->v.v(),
00212                                  A->v[1]->v.v() );
00213   } else {
00214     sign = DetermineOrientation( B->v[0]->v.v(), B->v[1]->v.v(),
00215                                  A->v[0]->v.v() );
00216   }
00217   return(-sign);
00218 }
00219 
00220 int compare_edge_to_intervalBU( void *p1, void *p2 )
00221 {
00222  graph_edge *e = (graph_edge *)p1; 
00223  edge_interval *ei = (edge_interval *)p2;
00224 
00225  if( CompareEdgesBU( e, ei->l ) <= 0 )
00226    return(-1);
00227  if( CompareEdgesBU( e, ei->r ) < 0 )
00228    return(0);
00229 
00230   return(1);
00231 }
00232 int compare_edge_to_intervalTD( void *p1, void *p2 )
00233 {
00234  graph_edge *e = (graph_edge *)p1; 
00235  edge_interval *ei = (edge_interval *)p2;
00236 
00237  if( CompareEdgesTD( e, ei->l ) <= 0 )
00238    return(-1);
00239  if( CompareEdgesTD( e, ei->r ) < 0 )
00240    return(0);
00241 
00242   return(1);
00243 }
00244 
00245 void EdgeInsert( graph_edge *e, int maxE )
00246 {
00247   graph_edge *left, *right, **E;
00248   graph_vertex *v0 = e->v[0], *v1 = e->v[1];
00249   int ileft, iright, codel, coder, nE;
00250  
00251   E = (graph_edge **)alloca( sizeof(graph_edge *) * maxE );
00252   if( E == NULL ) throw AllocError();
00253  
00254   nE = IncidentEdges( v0, E );
00255   EdgeInsertPosition( v0->v, v1->v, nE, E, &ileft, &iright,
00256                       &codel, &coder );
00257   left = E[ileft];  right = E[iright];
00258 
00259   if( left->v[0] == v0 )
00260     left->e[0] = e;
00261   else
00262     left->e[1] = e;
00263 
00264   e->e[0] = right; 
00265 
00266   if( left->v[0] == v0 )
00267     e->f[1] = left->f[0];
00268   else
00269     e->f[1] = left->f[1];
00270 
00271   if( right->v[0] == v0 )
00272     e->f[0] = right->f[1];
00273   else
00274     e->f[0] = right->f[0];
00275 
00276   nE = IncidentEdges( v1, E );
00277 
00278   EdgeInsertPosition( v1->v, v0->v, nE, E, &ileft, &iright,
00279                       &coder, &codel );
00280   left = E[ileft];  right = E[iright];
00281 
00282   if( left->v[0] == v1 )
00283     left->e[0] = e;
00284   else
00285     left->e[1] = e;
00286 
00287   e->e[1] = right; 
00288 }
00289 
00290 void Regularize( graph_edge_list *E, graph_vertex_list *V )
00291 {
00292   edge_interval_tree Status;
00293   BBTNode *node,*node1,*node2;
00294   edge_interval *I;
00295   graph_edge **TE, *edge,*a,*r;
00296   graph_vertex *v0,*vmax,*vmin,*v;
00297   int nTE,sign,regular,j,side;
00298  
00299   TE = (graph_edge **)alloca( sizeof(graph_edge *)*(3*E->nElems) );
00300   if( !TE ) throw AllocError();
00301 
00302   vmax = SortVertices( V );
00303   vmin = V->head;
00304 
00305 /*--- tree of intervalls bounded by two edges for status info -------------*/ 
00306 
00307   node = Status.NewNode();
00308   
00309   I = (edge_interval *)node->key;
00310   I->l = EDGE_NEG_INF;
00311   I->r = EDGE_POS_INF;
00312   I->v = NULL;
00313   
00314   Status.InsertNode( node, &Status.root, 1 );
00315   // Status.Dump(); Status.DumpNodes();
00316   
00317 /****************** Top-Down Sweep **********************************/
00318 
00319   v0 = vmax;
00320   while( v0 != NULL )
00321   {
00322     nTE = IncidentEdges( v0, TE );
00323 
00324     regular = 0;
00325     for( j = 0; j < nTE; j++ )
00326     {
00327       a = TE[j];
00328       if( a->v[0] == v0 )  /* edge starts in v0 (then v0 cannot be maximum */
00329       {                    /* of graph) */
00330         regular = 1;
00331     
00332         sign = compare( a->v[1]->v.v().y, v0->v.v().y );
00333         if( sign == 0 ) continue; /* nothing to do for horizontal edges */
00334 
00335                         /* replace the two intervalls [l,a],[a,r] with [l,r] */
00336         node1 = (BBTNode *)a->reserved[0].p;
00337         node2 = (BBTNode *)a->reserved[1].p;        
00338 
00339         edge = ((edge_interval *)(node2->key))->r;
00340         edge->reserved[0].p = (void *)node1;
00341 
00342         ((edge_interval *)(node1->key))->r = edge;        
00343         ((edge_interval *)(node1->key))->v = v0;
00344         
00345         Status.RemoveNode( node2 );
00346         Status.FreeNode( node2 );
00347         // Status.Dump(); Status.DumpNodes();
00348 
00349       }
00350     }
00351 
00352     if( (!regular) && (v0 != vmax) )
00353     {
00354       side = Status.SearchNode( (void *)(v0->e), compare_edge_to_intervalTD, 
00355                                 &node );
00356       if( side != 0 ) throw InternalError();
00357 
00358       v = ((edge_interval *)node->key)->v;
00359 
00360       edge = new graph_edge();
00361       E->Append(edge);
00362             
00363       edge->v[1] = v;
00364       edge->v[0] = v0;
00365 
00366       EdgeInsert( edge, E->nElems );
00367     }
00368 
00369     for( j = 0; j < nTE; j++ )
00370     {
00371       a = TE[j];
00372       if( a->v[1] == v0 )  /* edge ends in v0 */
00373       {         
00374         side = Status.SearchNode( (void *)a, compare_edge_to_intervalTD, 
00375                                 &node1 );
00376         if( side != 0 ) throw InternalError();
00377 
00378         sign = compare( a->v[0]->v.v().y, v0->v.v().y );
00379         if( sign == 0 )             /*special case: horizontal edge */
00380         {
00381           ((edge_interval *)(node1->key))->v = a->v[0];
00382         }
00383         else
00384         {
00385           r = ((edge_interval *)node1->key)->r;
00386           ((edge_interval *)node1->key)->r = a;
00387           ((edge_interval *)node1->key)->v = v0;
00388           a->reserved[0].p = (void *)node1;
00389  
00390           node2 = Status.NewNode();
00391 
00392           ((edge_interval *)node2->key)->l = a;
00393           ((edge_interval *)node2->key)->r = r;
00394           ((edge_interval *)node2->key)->v = v0;
00395           a->reserved[1].p = (void *)node2;
00396           r->reserved[0].p = (void *)node2;
00397           
00398           side = Status.SearchNode( (void *)a, compare_edge_to_intervalTD, 
00399                                     &node );
00400           if( side == 0 ) throw InternalError();
00401 
00402           Status.InsertNode( node2, node, side );
00403           // Status.Dump(); Status.DumpNodes();
00404 
00405         }
00406       }
00407     }
00408 
00409     v0 = v0->prev;
00410   }
00411 
00412 
00413 /********* Bottom Up Sweep ****************************************/
00414 
00415   node = Status.Head();
00416   
00417   I = (edge_interval *)node->key;
00418   I->v = NULL;
00419 
00420   gul::Assert<InternalError>( ndebug || 
00421                         ((node->left == NULL) || (node->right == NULL) ||
00422                          (I->l == EDGE_NEG_INF) || (I->r == EDGE_POS_INF)) );
00423   v0 = vmin;
00424   while( v0 != NULL )
00425   {
00426     nTE = IncidentEdges( v0, TE );
00427 
00428     regular = 0;
00429     for( j = 0; j < nTE; j++ )
00430     {
00431       a = TE[j];
00432       if( a->v[1] == v0 )    /* edge ends in v0 (then v0 cannot be minimum */
00433       {                      /* of graph) */
00434         regular = 1;
00435     
00436         sign = compare( a->v[0]->v.v().y, v0->v.v().y );
00437         if( sign == 0 ) continue; /* nothing to do for horizontal edges */
00438 
00439                         /* replace the two intervalls [l,a],[a,r] with [l,r] */
00440         node1 = (BBTNode *)a->reserved[0].p;
00441         node2 = (BBTNode *)a->reserved[1].p;        
00442 
00443         edge = ((edge_interval *)(node2->key))->r;
00444         edge->reserved[0].p = (void *)node1;
00445 
00446         ((edge_interval *)(node1->key))->r = edge;        
00447         ((edge_interval *)(node1->key))->v = v0;
00448         
00449         Status.RemoveNode( node2 );
00450         Status.FreeNode( node2 );
00451       }
00452     }
00453 
00454     if( (!regular) && (v0 != vmin) )
00455     {
00456       side = Status.SearchNode( (void *)(v0->e), compare_edge_to_intervalBU, 
00457                                 &node );
00458       if( side != 0 ) throw InternalError();
00459 
00460       v = ((edge_interval *)node->key)->v;
00461 
00462       edge = new graph_edge();
00463       E->Append(edge);
00464       
00465       edge->v[1] = v0;
00466       edge->v[0] = v;
00467 
00468       EdgeInsert( edge, E->nElems );
00469     }
00470 
00471     for( j = 0; j < nTE; j++ )
00472     {
00473       a = TE[j];
00474       if( a->v[0] == v0 )  /* edge starts in v0 */
00475       {         
00476         side = Status.SearchNode( (void *)a, compare_edge_to_intervalBU, 
00477                                 &node1 );
00478         if( side != 0 ) throw InternalError();
00479 
00480         sign = compare( a->v[1]->v.v().y, v0->v.v().y );
00481         if( sign == 0 )  /*special case: horizontal edge */
00482         {
00483           ((edge_interval *)(node1->key))->v = a->v[1];
00484         }
00485         else
00486         {
00487           r = ((edge_interval *)node1->key)->r;
00488           ((edge_interval *)node1->key)->r = a;
00489           ((edge_interval *)node1->key)->v = v0;
00490           a->reserved[0].p = (void *)node1;
00491  
00492           node2 = Status.NewNode();
00493  
00494           ((edge_interval *)node2->key)->l = a;
00495           ((edge_interval *)node2->key)->r = r;
00496           ((edge_interval *)node2->key)->v = v0;
00497           a->reserved[1].p = (void *)node2;
00498           r->reserved[0].p = (void *)node2;
00499           
00500           side = Status.SearchNode( (void *)a, compare_edge_to_intervalBU, 
00501                                     &node );
00502           if( side == 0 ) throw InternalError();
00503 
00504           Status.InsertNode( node2, node, side );
00505         }
00506       }
00507     }
00508 
00509     v0 = v0->next;
00510   }
00511 
00512   node = Status.Head();
00513   
00514   I = (edge_interval *)node->key;
00515   gul::Assert<InternalError>( ndebug || 
00516                         ((node->left == NULL) || (node->right == NULL) ||
00517                          (I->l == EDGE_NEG_INF) || (I->r == EDGE_POS_INF)) );
00518 
00519   Status.RemoveNode( node );
00520   Status.FreeNode( node );
00521 }
00522 
00523 }

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