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

gugr_planesweep.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_error.h"
00026 #include "guar_exact.h"
00027 #include "guma_sorting.h"
00028 #include "gugr_basics.h"
00029 #include "gugr_planesweep.h"
00030 #include "gul_io.h"
00031 #include "gul_std.h"
00032 #include "gugr_io.h"
00033 
00034 namespace gugr {
00035 
00036 using gul::ndebug;
00037 /* using gul::Assert; */
00038 using guar::rational;
00039 using gul::ListNodeInfo;
00040 using std::cout;
00041 
00042 // #ifndef NDEBUG
00043 #ifdef __BORLANDC__
00044   template float DumpPS<float>::orgx;
00045   template float DumpPS<float>::orgy;
00046   template float DumpPS<float>::scalex;
00047   template float DumpPS<float>::scaley;
00048   template double DumpPS<double>::orgx;
00049   template double DumpPS<double>::orgy;
00050   template double DumpPS<double>::scalex;
00051   template double DumpPS<double>::scaley;
00052 #else
00053   GULAPI float DumpPS<float>::orgx;
00054   GULAPI float DumpPS<float>::orgy;
00055   GULAPI float DumpPS<float>::scalex;
00056   GULAPI float DumpPS<float>::scaley;
00057   GULAPI double DumpPS<double>::orgx;
00058   GULAPI double DumpPS<double>::orgy;
00059   GULAPI double DumpPS<double>::scalex;
00060   GULAPI double DumpPS<double>::scaley;
00061 #endif
00062 // #endif
00063 
00064 int compare_point_to_linerec( point2<rational> *P, linerec *L )
00065 {
00066   return DetermineOrientation( L->B, L->E, *P );
00067 }
00068 int compare_linerec_to_linerec( linerec *L1, linerec *L2 )
00069 {
00070   int sign = DetermineOrientation(L2->B, L2->E, L1->B );
00071   if( sign == 0 )
00072     sign = DetermineOrientation(L2->B, L2->E, L1->E );
00073   return sign;
00074 }
00075 int compare_point_to_eventrec( point2<rational> *C, eventrec *E )
00076 {
00077   int sign = compare( C->x, E->key.x );
00078   if( sign == 0 ) sign = compare( C->y, E->key.y );
00079   return sign;
00080 }
00081 int compare_segment_to_linerec( segment *S, linerec *L )
00082 {
00083   int sign = DetermineOrientation( L->B, L->E, S->B );
00084   if( sign == 0 ) sign = DetermineOrientation( L->B, L->E, S->E );
00085   return sign;
00086 }
00087 int hcompare_point_to_intersection( point2<rational> *C, intersection *R )
00088 {
00089   return compare( C->x, R->I.x );
00090 }
00091 int vcompare_point_to_intersection( point2<rational> *C, intersection *R )
00092 {
00093   return compare( C->y, R->I.y );
00094 }
00095 int compare_pointer_to_pointer( void *p1, void *p2 )
00096 {
00097   if( p1 < p2 ) return -1;
00098   else if( p1 == p2 ) return 0;
00099   return 1;
00100 }
00101 
00102 
00103 
00104 /*---------------------------------------------------------------------
00105   Calculates the intersection of two linerecs (not vertical) equal to or right
00106   from 'xleft'. If one exists, a reference to this intersection is added to
00107   both linerecs. Furthermore a new intersection event is added to the
00108   event queue (if intersecion x !=xleft) and a new intersection record is
00109   added to the list of intersections if the intersection was not recorded before
00110 ----------------------------------------------------------------------*/
00111 
00112 intersection *intersect( Map<linerec>::Node L1, Map<linerec>::Node L2, 
00113                          const rational& xleft, Map<eventrec> *EvQ,
00114                          List<intersection> *Ipts )
00115 {
00116   const rational& x0 = L1.key()->l.v().x;
00117   const rational& y0 = L1.key()->l.v().y;
00118   const rational& dy = L1.key()->l.dy();
00119   const rational& e  = L1.key()->E.x;
00120   const rational& X0 = L2.key()->l.v().x;
00121   const rational& Y0 = L2.key()->l.v().y;
00122   const rational& DY = L2.key()->l.dy();
00123   const rational& E  = L2.key()->E.x;
00124   rational d;
00125   point2<rational> I;
00126   int sign,bsign,side1,side2;
00127   RefMap<intersection>::Node irnode1, irnode2, irnode;
00128   intersection *i;
00129   int side;
00130   Map<eventrec>::Node enode,enode1;
00131     
00132   d = DY - dy;
00133   sign = d.test();
00134   if( sign == 0 ) return 0;
00135   
00136   I.x = (y0 - Y0 + X0*DY - x0*dy) / d;
00137 
00138   bsign = compare( I.x, xleft );
00139   if( bsign < 0 ) return 0;
00140   sign = compare( I.x, e );
00141   if( sign > 0 ) return 0;
00142   sign = compare( I.x, E );
00143   if( sign > 0 ) return 0;
00144 
00145   I.y = y0 + (I.x-x0)*dy;
00146 
00147   side1 = L1.key()->I.SearchNode(
00148                              &I, hcompare_point_to_intersection, &irnode1 );
00149   side2 = L2.key()->I.SearchNode( 
00150                              &I, hcompare_point_to_intersection, &irnode2 );
00151   if( side1 == 0 ) 
00152     i = irnode1.key();
00153   else if( side2 == 0 )
00154     i = irnode2.key();
00155   else
00156   {
00157     i = new intersection( I );
00158     Ipts->Append(i);
00159   }
00160 
00161   if( side1 != 0 )
00162   {
00163     irnode = L1.key()->I.NewNode(i);
00164     L1.key()->I.InsertNode( irnode, irnode1, side1 );
00165   }
00166   if( side2 != 0 )
00167   {
00168     irnode = L2.key()->I.NewNode(i);
00169     L2.key()->I.InsertNode( irnode, irnode2, side2 );
00170   }
00171 
00172   if( bsign == 0 ) return i;
00173 
00174   side = EvQ->SearchNode( &I, compare_point_to_eventrec, &enode );
00175   if( side != 0 )
00176   {
00177     enode1 = EvQ->NewNode( I );
00178     EvQ->InsertNode( enode1, enode, side ); 
00179     enode = enode1;
00180   }
00181   enode.key()->I.Append( new ListNode<linepair>( linepair(L1,L2) ) );    
00182 
00183   return i;
00184 }
00185 
00186 
00187 intersection *intersect_vert( linerec *vL, Map<linerec>::Node L,
00188                               List<intersection> *Ipts )
00189 {
00190   const rational& X0 = L.key()->l.v().x;
00191   const rational& Y0 = L.key()->l.v().y;
00192   const rational& DY = L.key()->l.dy();
00193   const rational& yleft = vL->B.y;
00194   const rational& yright = vL->E.y;
00195   const rational& x0 = vL->l.v().x;
00196 
00197   point2<rational> I;
00198   int sign,side1,side2;
00199   RefMap<intersection>::Node irnode1, irnode2, irnode;
00200   intersection *i;
00201     
00202   I.y = Y0 + (x0 - X0)*DY;
00203   
00204   sign = compare( I.y, yleft );
00205   if( sign < 0 ) return 0;
00206   sign = compare( I.y, yright );
00207   if( sign > 0 ) return 0;
00208  
00209   I.x = x0;
00210   
00211   side1 = vL->I.SearchNode(
00212                              &I, vcompare_point_to_intersection, &irnode1 );
00213   side2 = L.key()->I.SearchNode( 
00214                              &I, hcompare_point_to_intersection, &irnode2 );
00215   if( side1 == 0 ) 
00216     i = irnode1.key();
00217   else if( side2 == 0 )
00218     i = irnode2.key();
00219   else
00220   {
00221     i = new intersection( I );
00222     Ipts->Append(i);
00223   }
00224 
00225   if( side1 != 0 )
00226   {
00227     irnode = vL->I.NewNode(i);
00228     vL->I.InsertNode( irnode, irnode1, side1 );
00229   }
00230   if( side2 != 0 )
00231   {
00232     irnode = L.key()->I.NewNode(i);
00233     L.key()->I.InsertNode( irnode, irnode2, side2 );
00234   }
00235 
00236   return i;
00237 }
00238 
00239 /* --------------------------------------------------------------------
00240   finally process a (not vertical) linerec. The intersections between
00241   the segments on this line are calculated. These interesctions and
00242   intersections with other linerecs are added as vertices and edges
00243   to a graph and are also logged in lists containing all intersections 
00244 ----------------------------------------------------------------------*/
00245 
00246 void finish_line( linerec *L, graph_edge_list *E, graph_vertex_list *V, 
00247                   int maxE, List<intersection> *Ipts, 
00248                   List<intersectionseg> *Isegs )
00249 {
00250   ListNode<segment *> *segref = L->S.First();
00251   segment *seg;
00252   int side;
00253   intersection *i,*i1,*i2;
00254   intersectionseg *is;
00255   RefMap<intersection>::Node irnode,irnode1;
00256   Ptr<intersection *> I;
00257   int nI,j;
00258   segtree SegTr;
00259   int left,right,mid,iB,iE,sign,nLf;
00260   Ptr<segnode *> Lf;
00261   segnode *snode;
00262   RefMap<segment>::Node segnod;
00263   graph_edge *e;
00264   RefMap<void>::Node leftowner,rightowner,leftowner1,rightowner1;
00265   RefMap<void> *leftowners,*rightowners;
00266   List< ListNode< ListNodeInfo< ListNode<graph_edge *> > > > *ownerrecs;
00267   ListNode< ListNodeInfo< ListNode<graph_edge *> > > *orec;
00268   ListNode<graph_edge *> *erec;
00269 
00270   while( segref != 0 )
00271   {
00272     seg = segref->el;
00273 
00274     /* --- add segment endpoints as intersections --- */
00275 
00276     side = L->I.SearchNode( &seg->B, hcompare_point_to_intersection, 
00277                             &irnode );
00278     if( side != 0 )
00279     {
00280       i = new intersection( seg->B );
00281       Ipts->Append(i);
00282 
00283       irnode1 = L->I.NewNode(i);
00284       L->I.InsertNode( irnode1, irnode, side );
00285     }
00286 
00287     side = L->I.SearchNode( &seg->E, hcompare_point_to_intersection, 
00288                             &irnode );
00289     if( side != 0 )
00290     {
00291       i = new intersection( seg->E );
00292       Ipts->Append(i);
00293 
00294       irnode1 = L->I.NewNode(i);
00295       L->I.InsertNode( irnode1, irnode, side );
00296     }    
00297 
00298     segref = segref->next;
00299   }
00300 
00301   nI = L->I.ConvertToArray( &I );
00302 
00303   SegTr.init( nI, I );
00304 
00305   segref = L->S.First();
00306 
00307   while( segref != 0 )
00308   {
00309     seg = segref->el;
00310 
00311     left = 0;
00312     right = nI;
00313     mid = (left+right)/2;
00314 
00315     for(;;)
00316     {  
00317       sign = compare( seg->B.x, I[mid]->I.x );
00318       if( sign == 0 )
00319         break;
00320       else if( sign < 0 )
00321       {
00322         right = mid;
00323         mid = (left+right)/2;
00324       }
00325       else
00326       {
00327         left = mid;
00328         mid = (left+right)/2;
00329       }
00330     }
00331     iB = mid;
00332 
00333     left = 0;
00334     right = nI;
00335     mid = (left+right)/2;
00336 
00337     for(;;)
00338     {  
00339       sign = compare( seg->E.x, I[mid]->I.x );
00340       if( sign == 0 )
00341         break;
00342       else if( sign < 0 )
00343       {
00344         right = mid;
00345         mid = (left+right)/2;
00346       }
00347       else
00348       {
00349         left = mid;
00350         mid = (left+right)/2;
00351       }
00352     }
00353     iE = mid;
00354 
00355     SegTr.insert( iB, iE, seg );
00356 
00357     segref = segref->next;
00358   }
00359 
00360   nLf = SegTr.leaves_to_array( &Lf );
00361 
00362   for( j = 0; j < nLf; j++ )
00363   {
00364     e = new graph_edge;
00365     E->Append(e);
00366     
00367     i1 = SegTr.m_absz[Lf[j]->m_il];
00368     if( i1->v == 0 )
00369     {
00370       i1->v = new graph_vertex( i1->I, 0 );
00371       V->Append(i1->v);
00372     }
00373     i2 = SegTr.m_absz[Lf[j]->m_ir];
00374     if( i2->v == 0 )
00375     {
00376       i2->v = new graph_vertex( i2->I, 0 );
00377       V->Append(i2->v);
00378     }
00379     e->v[0] = i1->v;
00380     e->v[1] = i2->v;
00381     e->l = L->l; 
00382 
00383     /* --- set owner lists of intersections --- */
00384 
00385     is = new intersectionseg(e);
00386     Isegs->Append(is);
00387 
00388     /* initialize sets of owners of left and right side of the edge */
00389 
00390     leftowners = new RefMap<void>;
00391     rightowners = new RefMap<void>;
00392     e->f[0].p = leftowners;
00393     e->f[1].p = rightowners;
00394     e->reserved[0].set_i(0);
00395     ownerrecs = new List< ListNode< ListNodeInfo< ListNode<graph_edge *> > > >;
00396     e->reserved[1].p = ownerrecs;
00397 
00398     snode = Lf[j];
00399     while( snode )
00400     {
00401       segnod = snode->m_segs.First();
00402  
00403       while( !segnod.IsEmpty() )
00404       {
00405         // increment number of owners by the multiplicity of the segments
00406         // which contain the edge
00407 
00408         e->reserved[0].i += segnod.key()->m;
00409 
00410         /* add owner to the set of owners of the left side of the edge */
00411 
00412         side = leftowners->SearchNode( (void *)segnod.key()->f[0].p,
00413                                      compare_pointer_to_pointer, &leftowner );
00414         if( side != 0 )
00415         {
00416           leftowner1 = leftowners->NewNode((void *)segnod.key()->f[0].p);
00417           leftowners->InsertNode( leftowner1, leftowner, side );
00418         }
00419 
00420         /* add owner to the set of owners of the right side of the edge */
00421 
00422         side = rightowners->SearchNode( (void *)segnod.key()->f[1].p,
00423                                      compare_pointer_to_pointer, &rightowner );
00424         if( side != 0 )
00425         {
00426           rightowner1 = rightowners->NewNode((void *)segnod.key()->f[1].p);
00427           rightowners->InsertNode( rightowner1, rightowner, side );
00428         }
00429 
00430         /* add edge to the list of edges for the original input segment */
00431 
00432         erec = new ListNode<graph_edge *>(e);
00433         segnod.key()->e.Append( erec );
00434 
00435         /* add a backpointer to the corresponding edge record in the edge
00436            list of the input segment; this makes it later possible to remove
00437            all references to an edge from all input segments */
00438 
00439         orec = new ListNode< ListNodeInfo< ListNode<graph_edge *> > >(
00440                ListNodeInfo< ListNode<graph_edge *> >(&segnod.key()->e, erec) );
00441         ownerrecs->Append(orec);
00442 
00443         /* the owner lists of the intersection records are only for debugging */
00444         /*
00445         owner = new ListNode<segment *>(segnod.key());
00446         i1->S.Append(owner);
00447         owner = new ListNode<segment *>(segnod.key());
00448         is->S.Append(owner);
00449         */
00450         segnod = snode->m_segs.Successor(segnod);
00451       }
00452       snode = snode->m_parent;
00453     }  
00454     
00455     OrientEdge( e );
00456     ConnectEdge( e, maxE );
00457   }
00458 
00459   /* --- set owner list of endpoint - intersection --- */
00460   /*
00461   if( (j=nLf-1) >= 0 )
00462   {
00463     snode = Lf[j];
00464     while( snode )
00465     {
00466       segnod = snode->m_segs.First();
00467       while( !segnod.IsEmpty() )
00468       {
00469         owner = new ListNode<segment *>(segnod.key());
00470         i2->S.Append(owner);
00471         segnod = snode->m_segs.Successor(segnod);
00472       }
00473       snode = snode->m_parent;
00474     }
00475   }
00476   */
00477 }
00478 
00479 
00480 /* --------------------------------------------------------------------
00481   finally process a (vertical) linerec. The intersections between
00482   the segments on this line are calculated. These interesctions and
00483   intersections with other linerecs are added as vertices and edges
00484   to a graph and are also logged in lists containing all intersections 
00485   (special version for vertical linerecs, almost the same as the above
00486   function)
00487 ----------------------------------------------------------------------*/
00488 
00489 void finish_vertline( linerec *L, graph_edge_list *E, graph_vertex_list *V, 
00490                   int maxE, List<intersection> *Ipts, 
00491                   List<intersectionseg> *Isegs )
00492 {
00493   ListNode<segment *> *segref = L->S.First();
00494   segment *seg;
00495   int side;
00496   intersection *i,*i1,*i2;
00497   intersectionseg *is;
00498   RefMap<intersection>::Node irnode,irnode1;
00499   Ptr<intersection *> I;
00500   int nI,j;
00501   segtree SegTr;
00502   int left,right,mid,iB,iE,sign,nLf;
00503   Ptr<segnode *> Lf;
00504   segnode *snode;
00505   RefMap<segment>::Node segnod;
00506   graph_edge *e;
00507   RefMap<void>::Node leftowner,rightowner,leftowner1,rightowner1;
00508   RefMap<void> *leftowners,*rightowners;
00509   List< ListNode< ListNodeInfo< ListNode<graph_edge *> > > > *ownerrecs;
00510   ListNode< ListNodeInfo< ListNode<graph_edge *> > > *orec;
00511   ListNode<graph_edge *> *erec;
00512  
00513   while( segref != 0 )
00514   {
00515     seg = segref->el;
00516 
00517     /* --- add segment endpoints as intersections --- */
00518 
00519     side = L->I.SearchNode( &seg->B, vcompare_point_to_intersection, 
00520                             &irnode );
00521     if( side != 0 )
00522     {
00523       i = new intersection( seg->B );
00524       Ipts->Append(i);
00525 
00526       irnode1 = L->I.NewNode(i);
00527       L->I.InsertNode( irnode1, irnode, side );
00528     }
00529 
00530     side = L->I.SearchNode( &seg->E, vcompare_point_to_intersection, 
00531                             &irnode );
00532     if( side != 0 )
00533     {
00534       i = new intersection( seg->E );
00535       Ipts->Append(i);
00536 
00537       irnode1 = L->I.NewNode(i);
00538       L->I.InsertNode( irnode1, irnode, side );
00539     }    
00540 
00541     segref = segref->next;
00542   }
00543 
00544   nI = L->I.ConvertToArray( &I );
00545 
00546   SegTr.init( nI, I );
00547 
00548   segref = L->S.First();
00549 
00550   while( segref != 0 )
00551   {
00552     seg = segref->el;
00553 
00554     left = 0;
00555     right = nI;
00556     mid = (left+right)/2;
00557 
00558     for(;;)
00559     {  
00560       sign = compare( seg->B.y, I[mid]->I.y );
00561       if( sign == 0 )
00562         break;
00563       else if( sign < 0 )
00564       {
00565         right = mid;
00566         mid = (left+right)/2;
00567       }
00568       else
00569       {
00570         left = mid;
00571         mid = (left+right)/2;
00572       }
00573     }
00574     iB = mid;
00575 
00576     left = 0;
00577     right = nI;
00578     mid = (left+right)/2;
00579 
00580     for(;;)
00581     {  
00582       sign = compare( seg->E.y, I[mid]->I.y );
00583       if( sign == 0 )
00584         break;
00585       else if( sign < 0 )
00586       {
00587         right = mid;
00588         mid = (left+right)/2;
00589       }
00590       else
00591       {
00592         left = mid;
00593         mid = (left+right)/2;
00594       }
00595     }
00596     iE = mid;
00597 
00598     SegTr.insert( iB, iE, seg );
00599 
00600     segref = segref->next;
00601   }
00602 
00603   nLf = SegTr.leaves_to_array( &Lf );
00604 
00605   for( j = 0; j < nLf; j++ )
00606   {
00607     e = new graph_edge;
00608     E->Append(e);
00609     
00610     i1 = SegTr.m_absz[Lf[j]->m_il];
00611     if( i1->v == 0 )
00612     {
00613       i1->v = new graph_vertex( i1->I, 0 );
00614       V->Append(i1->v);
00615     }
00616     i2 = SegTr.m_absz[Lf[j]->m_ir];
00617     if( i2->v == 0 )
00618     {
00619       i2->v = new graph_vertex( i2->I, 0 );
00620       V->Append(i2->v);
00621     }
00622     e->v[0] = i1->v;
00623     e->v[1] = i2->v;
00624     e->l = L->l; 
00625 
00626     /* --- set owner lists of intersections --- */
00627 
00628     is = new intersectionseg(e);
00629     Isegs->Append(is);
00630 
00631     /* initialize sets of owners of left and right side of the edge */
00632 
00633     leftowners = new RefMap<void>;
00634     rightowners = new RefMap<void>;
00635     e->f[0].p = leftowners;
00636     e->f[1].p = rightowners;
00637     e->reserved[0].set_i(0);
00638     ownerrecs = new List< ListNode< ListNodeInfo< ListNode<graph_edge *> > > >;
00639     e->reserved[1].p = ownerrecs;
00640 
00641     snode = Lf[j];
00642     while( snode )
00643     {
00644       segnod = snode->m_segs.First();
00645 
00646       while( !segnod.IsEmpty() )
00647       {
00648         // increment number of owners by the multiplicity of the segments
00649         // which contain the edge
00650 
00651         e->reserved[0].i += segnod.key()->m;
00652 
00653         /* add owner to the set of owners of the left side of the edge */
00654 
00655         side = leftowners->SearchNode( (void *)segnod.key()->f[0].p,
00656                                      compare_pointer_to_pointer, &leftowner );
00657         if( side != 0 )
00658         {
00659           leftowner1 = leftowners->NewNode((void *)segnod.key()->f[0].p );
00660           leftowners->InsertNode( leftowner1, leftowner, side );
00661         }
00662 
00663         /* add owner to the set of owners of the right side of the edge */
00664 
00665         side = rightowners->SearchNode( (void *)segnod.key()->f[1].p,
00666                                      compare_pointer_to_pointer, &rightowner );
00667         if( side != 0 )
00668         {
00669           rightowner1 = rightowners->NewNode((void *)segnod.key()->f[1].p);
00670           rightowners->InsertNode( rightowner1, rightowner, side );
00671         }
00672 
00673         /* add edge to the list of edges for the original input segment */
00674 
00675         erec = new ListNode<graph_edge *>(e);
00676         segnod.key()->e.Append( erec );
00677 
00678         /* add a backpointer to the corresponding edge record in the edge
00679            list of the input segment; this makes it later possible to remove
00680            all references to an edge from all input segments */
00681 
00682         orec = new ListNode< ListNodeInfo< ListNode<graph_edge *> > >(
00683                ListNodeInfo< ListNode<graph_edge *> >(&segnod.key()->e, erec) );
00684         ownerrecs->Append(orec);
00685 
00686         /* the owner lists of the intersection records are only for debugging */
00687         /*
00688         owner = new ListNode<segment *>(segnod.key());
00689         i1->S.Append(owner);
00690         owner = new ListNode<segment *>(segnod.key());
00691         is->S.Append(owner);
00692         */
00693 
00694         segnod = snode->m_segs.Successor(segnod);
00695       }
00696       snode = snode->m_parent;
00697     }  
00698     
00699     OrientEdge( e );
00700     ConnectEdge( e, maxE );
00701   }
00702 
00703   /* --- set owner list of endpoint - intersection --- */
00704   /*
00705   if( (j=nLf-1) >= 0 )
00706   {
00707    snode = Lf[j];
00708     while( snode )
00709     {
00710       segnod = snode->m_segs.First();
00711       while( !segnod.IsEmpty() )
00712       {
00713         owner = new ListNode<segment *>(segnod.key());
00714         i2->S.Append(owner);
00715         segnod = snode->m_segs.Successor(segnod);
00716       }
00717       snode = snode->m_parent;
00718     }
00719   }
00720   */
00721 }
00722 
00723 /*---------------------------------------------------------------------
00724   Determine all intersections of a set of line segments
00725 
00726   This function creates a graph with intersections (points and segments) only
00727   inserted once.
00728 
00729   For both sides of each created edge a set is calculated, which is the union
00730   of the segment/side owners ("segment.f[0/1]") of all input segments which
00731   contain this output edge. These sets are stored in the f[0/1] fields of
00732   the output edges (and the sum of the multiplicities of input segments which 
00733   contain this edge is stored in the reserved[0] field of the edge)
00734   The edges of the output graph which form an input segment are stored in
00735   the "segment.e" list of each input segment.
00736 
00737   So the following data structures are filled in by this function:
00738   
00739   segment.e        // list of created edges for this segment
00740   edge.f[0]        // set of owners of the left side of the edge
00741   edge.f[1]        // set of owners of the right side of the edge
00742   edge.reserved[0] // sum of multiplicities of input segments which contain this
00743                    // edge (used for odd/even winding rule for polygon filling)
00744   edge.reserved[1] // list of backpointers to the edge records of the input
00745                    // segments which refer to this edge
00746 
00747   (The pointers to the owner sets in edge.f[0] and edge.f[1] and the
00748   backpointer list in edge.reserved[1] are casted to int's, so they are not
00749   automatically freed in the destructor, the caller must do this manually 
00750   afterwards !!!!!)
00751 ----------------------------------------------------------------------*/
00752 
00753 
00754 void DoIntersectSegments( int nsegs, Map<eventrec>& EvQ, 
00755                         gugr::graph_edge_list *E, gugr::graph_vertex_list *V )
00756 {
00757   
00758   Map<eventrec>::Node enode,evnode,evnode1;
00759   int side,sign;
00760   ListNode<segment *> *begseg;
00761   Map<linerec> SwS;
00762   segment *seg;
00763   ListNode<Map<linerec>::Node> *lrefnode,*lstnode;
00764   Map<linerec>::Node lnode,lnodelo,lnodehi,lnode1,lnode2;
00765   linerec *vlin = 0, *lin;
00766   bool addvend,iflag,iexflag,checkneighbors;
00767   RefMap<intersection>::Node irnode, irnode1;
00768   intersection *irec;
00769   ListNode<linepair> *lpnode;
00770   linepair            lpair;
00771   List<intersection>     Ipts;
00772   List<intersectionseg>  Isegs;
00773   int maxE;
00774   
00775   maxE = nsegs*4;
00776 
00777   /*--- loop until event queue empty ---*/
00778 
00779   for(;;)
00780   {
00781     enode = EvQ.First();
00782     if( enode.IsEmpty() ) break;   // queue empty
00783     
00784     /*--- process starting vertical segments ---*/
00785  
00786     while( enode.key()->BV.nElems > 0 )
00787     {
00788       begseg = enode.key()->BV.First(); 
00789       enode.key()->BV.Remove( begseg );
00790       
00791       /*
00792       cout << "[processing starting vertical line segment]: ";
00793       DumpPS<float>::dump_segment( begseg->el );
00794       */
00795 
00796       addvend = false;
00797       if( vlin == 0 ) 
00798       {
00799         vlin = new linerec( begseg->el );
00800         delete begseg;
00801         addvend = true;
00802       }
00803       else
00804       {
00805         vlin->S.Append( begseg );  // add line-segment (using ex. list node)
00806 
00807         sign = compare( begseg->el->E.y, vlin->E.y );
00808         if( sign > 0 ) 
00809         {
00810           vlin->E = begseg->el->E;
00811 
00812           /* remove old vertical-line-end event */
00813 
00814           vlin->endev.key()->EV = 0;
00815 
00816           if( (vlin->endev.key()->IsEmpty()) && 
00817               (vlin->endev.key() != enode.key()) )
00818           {
00819             EvQ.RemoveNode( vlin->endev );
00820             EvQ.FreeNode( vlin->endev );
00821           }
00822           
00823           addvend = true;
00824         }
00825       }
00826       if( addvend )
00827       {
00828         /* add new vertical-line-end event */
00829 
00830         side = EvQ.SearchNode( &vlin->E, compare_point_to_eventrec, &evnode );
00831         if( side != 0 )
00832         {
00833           evnode1 = EvQ.NewNode( vlin->E );
00834           EvQ.InsertNode( evnode1, evnode, side );
00835           evnode = evnode1;
00836         }
00837         evnode.key()->EV = vlin;    
00838         vlin->endev = evnode;
00839       }
00840     }
00841 
00842     /* check if current event point is a intersection point */
00843 
00844     if( enode.key()->I.nElems > 0 )
00845       iexflag = true;
00846     else
00847       iexflag = false;
00848 
00849     if( iexflag ||
00850         ((vlin != 0) && (enode.key()->B.nElems > 0)) ||
00851         ((vlin != 0) && (!enode.key()->E.IsEmpty())) ||
00852         ((enode.key()->B.nElems > 0) && (!enode.key()->E.IsEmpty())) )
00853     {
00854       iflag = true;
00855       if( iexflag )
00856       {
00857         /* get the intersection record from one of two intersecting lines */
00858 
00859         lin = enode.key()->I.First()->el.L1.key();
00860         side = lin->I.SearchNode( &enode.key()->key, 
00861                            hcompare_point_to_intersection, &irnode );
00862         gul::Assert<InternalError>( ndebug || (side == 0) );
00863 
00864         irec = irnode.key();
00865       }
00866       else
00867       {
00868         /* create a new intersection record */
00869 
00870         irec = new intersection( enode.key()->key );
00871         Ipts.Append(irec);
00872       }
00873     }
00874     else
00875       iflag = false;
00876 
00877     /* --- add intersection to vertical line --- */
00878       
00879     if( vlin && iflag )
00880     {
00881       side = vlin->I.SearchNode(
00882                       &irec->I, vcompare_point_to_intersection, &irnode1 );
00883       if( side != 0 )
00884       {
00885         irnode = vlin->I.NewNode(irec);
00886         vlin->I.InsertNode( irnode, irnode1, side );
00887       }
00888     }
00889 
00890     /*--- process ending lines ---*/
00891 
00892     lrefnode = enode.key()->E.First(); 
00893     while( lrefnode != 0 )
00894     {
00895       /* first element in list of lines ending in current event point */
00896 
00897       lnode = lrefnode->el;
00898       lrefnode = lrefnode->next;
00899 
00900       if( iflag )
00901       {
00902         /* add intersection record (if not already existing) */
00903 
00904         side = lnode.key()->I.SearchNode( &irec->I, 
00905                                  hcompare_point_to_intersection, &irnode );
00906         if( side != 0 )
00907         {
00908           irnode1 = lnode.key()->I.NewNode(irec);
00909           lnode.key()->I.InsertNode( irnode1, irnode, side );
00910         }
00911       }
00912 
00913       lnodelo = SwS.Predecessor( lnode );  /* get neighbors in symetric order */
00914       lnodehi = SwS.Successor( lnode );
00915     
00916       SwS.RemoveNode( lnode );     /* remove ending line from symmetric order */
00917 
00918       /* intersect neighbors */ 
00919 
00920       if( !lnodelo.IsEmpty() && !lnodehi.IsEmpty() )
00921         intersect( lnodelo, lnodehi, enode.key()->key.x, &EvQ, &Ipts );
00922     }
00923 
00924     /* process intersecting lines */
00925 
00926     while( enode.key()->I.nElems > 0 )
00927     {
00928       lpnode = enode.key()->I.First(); 
00929       enode.key()->I.Remove( lpnode );
00930       lpair = lpnode->el;
00931       delete lpnode;       // free list node
00932 
00933       lnode1 = lpair.L1;
00934       lnode2 = lpair.L2;   
00935       
00936       if( !SwS.IsRemoved(lnode1) && !SwS.IsRemoved(lnode2) )
00937       {
00938         SwS.RemoveNode( lnode1 );
00939         SwS.RemoveNode( lnode2 );
00940 
00941         lnode1.key()->B = enode.key()->key;
00942         lnode2.key()->B = enode.key()->key;
00943 
00944         side = SwS.SearchNode( lnode1.key(), compare_linerec_to_linerec, 
00945                                &lnode ); 
00946         gul::Assert<InternalError>(ndebug | (side!=0) );
00947 
00948         SwS.InsertNode(lnode1,lnode,side);  // reinsert
00949 
00950         lnodelo = SwS.Predecessor( lnode1 );  /* get neighbors in order */
00951         lnodehi = SwS.Successor( lnode1 );
00952 
00953         if( !lnodelo.IsEmpty() )
00954           intersect( lnodelo, lnode1, enode.key()->key.x, &EvQ, &Ipts );
00955         if( !lnodehi.IsEmpty() )
00956           intersect( lnodehi, lnode1, enode.key()->key.x, &EvQ, &Ipts );
00957 
00958         side = SwS.SearchNode( lnode2.key(), compare_linerec_to_linerec, 
00959                                &lnode ); 
00960         gul::Assert<InternalError>(ndebug | (side!=0) );
00961 
00962         SwS.InsertNode(lnode2,lnode,side); // reinsert
00963 
00964         lnodelo = SwS.Predecessor( lnode2 );  /* get neighbors in order */
00965         lnodehi = SwS.Successor( lnode2 );
00966 
00967         if( !lnodelo.IsEmpty() )
00968           intersect( lnodelo, lnode2, enode.key()->key.x, &EvQ, &Ipts );
00969         if( !lnodehi.IsEmpty() )
00970           intersect( lnodehi, lnode2, enode.key()->key.x, &EvQ, &Ipts );
00971       }
00972     }
00973 
00974     /* process beginning lines */
00975     
00976     while( enode.key()->B.nElems > 0 )
00977     {
00978       begseg = enode.key()->B.First(); 
00979       enode.key()->B.Remove( begseg );
00980       seg = begseg->el;      
00981  
00982       side = SwS.SearchNode( seg, compare_segment_to_linerec, &lnode ); 
00983       if( side == 0 )  // colinear with existing line
00984       {
00985         lnode.key()->S.Append( begseg );  // add line-segment (using list node)
00986 
00987         sign = compare( begseg->el->E.x, lnode.key()->E.x );
00988         if( sign > 0 ) 
00989         {
00990           lnode.key()->E = begseg->el->E;
00991           
00992           /* remove old line-end event */
00993 
00994           lnode.key()->endev.key()->E.Remove( lnode.key()->endev_node );
00995           delete lnode.key()->endev_node;  // delete line-end lstnode
00996 
00997           if( lnode.key()->endev.key()->IsEmpty() )
00998           {
00999             EvQ.RemoveNode( lnode.key()->endev );
01000             EvQ.FreeNode( lnode.key()->endev );
01001           }
01002           
01003           checkneighbors = true;
01004         }
01005         else
01006         {
01007           checkneighbors = false;
01008         }
01009       }
01010       else
01011       {
01012         delete begseg; // delete list node;
01013         
01014         lnode1 = SwS.NewNode( seg );
01015         SwS.InsertNode( lnode1, lnode, side );
01016         lnode = lnode1;
01017 
01018         checkneighbors = true;
01019       }  
01020 
01021       if( checkneighbors )
01022       {      
01023         lnodelo = SwS.Predecessor( lnode );  /* get neighbors in order */
01024         lnodehi = SwS.Successor( lnode );
01025 
01026         lstnode = new ListNode< Map<linerec>::Node >(lnode);
01027         
01028         side = EvQ.SearchNode( &seg->E, compare_point_to_eventrec, &evnode ); 
01029         if( side != 0 )
01030         {
01031           evnode1 = EvQ.NewNode( seg->E );
01032           EvQ.InsertNode( evnode1, evnode, side );
01033           evnode = evnode1;
01034         }
01035 
01036         evnode.key()->E.Append( lstnode );
01037 
01038         lnode.key()->endev = evnode;
01039         lnode.key()->endev_node = lstnode;
01040 
01041         if( !lnodelo.IsEmpty() )
01042           intersect( lnodelo, lnode, enode.key()->key.x, &EvQ, &Ipts );
01043         if( !lnodehi.IsEmpty() )
01044           intersect( lnodehi, lnode, enode.key()->key.x, &EvQ, &Ipts );
01045       }
01046 
01047       if( iflag )
01048       {
01049         /* add intersection record (if not already existing) */
01050 
01051         side = lnode.key()->I.SearchNode( &irec->I, 
01052                                  hcompare_point_to_intersection, &irnode );
01053         if( side != 0 )
01054         {
01055           irnode1 = lnode.key()->I.NewNode(irec);
01056           lnode.key()->I.InsertNode( irnode1, irnode, side );
01057         }
01058       }
01059     }
01060 
01061     /* --- process end of vertical line --- */
01062     
01063     if( enode.key()->EV != 0 )
01064     {
01065       /* find linerecs passing between start and end of vertical line */
01066 
01067       if( !SwS.IsEmpty() )
01068       {
01069         side = SwS.SearchNode( &enode.key()->EV->B, compare_point_to_linerec, 
01070                              &lnode );
01071         if( side > 0 )
01072           lnode = SwS.Successor( lnode );
01073 
01074         do
01075         {
01076           if( !lnode.IsEmpty() )
01077           {
01078             irec = intersect_vert( vlin, lnode, &Ipts );
01079             lnode = SwS.Successor( lnode );
01080           }
01081         }
01082         while( !lnode.IsEmpty() && (irec != 0) );
01083       }
01084       
01085       // cout << "[before finish_vertline]: ";
01086       // DumpPS<float>::dump_linerec( enode.key()->EV );
01087 
01088       finish_vertline( vlin, E, V, maxE, &Ipts, &Isegs );
01089 
01090       delete vlin;       
01091       vlin = 0;
01092     }
01093 
01094     /* --- process finished lines --- */
01095 
01096     while( (lrefnode = enode.key()->E.First()) != 0 )
01097     {
01098       enode.key()->E.Remove( lrefnode );
01099       lnode = lrefnode->el;
01100       delete lrefnode;
01101 
01102       /*
01103       cout << "[before finish_line]: ";
01104       DumpPS<float>::dump_linerec( lnode.key() );
01105       */
01106       
01107       finish_line( lnode.key(), E, V, maxE, &Ipts, &Isegs );
01108       SwS.FreeNode(lnode);  // already removed, see above
01109     }
01110 
01111     EvQ.RemoveNode( enode );
01112     EvQ.FreeNode(enode);
01113   }
01114 
01115   /*
01116   gugr::Dump<float>::dump_vertices( V.head );
01117   gugr::Dump<float>::dump_edges( E.head );
01118   */
01119 
01120   /*  
01121   cout << "\nINTERSECTIONS\n";
01122   cout << "=============\n";
01123   DumpPS<float>::dump_intersections( Ipts );
01124   cout << "\n";
01125   DumpPS<float>::dump_intersectionsegs( Isegs );
01126   */
01127 
01128   Ipts.DeleteElems();
01129   Isegs.DeleteElems();
01130 }
01131 
01132 }

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