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

gugr_contour.h

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 #ifndef GUGR_CONTOUR_H
00021 #define GUGR_CONTOUR_H
00022 
00023 #ifndef NDEBUG
00024   #include <iostream>   // for debug dump functions
00025 #endif
00026 
00027 namespace gugr {
00028 
00029 using gul::Ptr;
00030 using guar::rational;
00031 using gul::point2;
00032 using gul::rtr;
00033 using gul::RefMap;
00034 
00035 struct polyline
00036 {
00037   Ptr<point2<rational> >  verts;
00038   int                     nVerts;
00039 
00040   Ptr<line>               lines;
00041 
00042   template< class T >
00043   bool init( int nP, const Ptr< point2<T> >& P, T minx, T miny, T scalei )
00044   {
00045     T x,y;
00046     int i,j;
00047     rational vx,vy;
00048     unsigned long *cbuf = 
00049       (unsigned long *)alloca(gul::rtr<T>::mantissa_length());
00050 
00051     verts.reserve_pool(nP);
00052     lines.reserve_pool(nP);
00053 
00054     x = (P[0].x - minx)*scalei;
00055     y = (P[0].y - miny)*scalei;
00056     verts[0].x = rational(coord2int(x,cbuf),cbuf);
00057     verts[0].y = rational(coord2int(y,cbuf),cbuf);
00058     j = 0;
00059     i = 1;
00060 
00061     for( ;; )
00062     {
00063       while( i < nP )
00064       {
00065         x = (P[i].x - minx)*scalei;
00066         y = (P[i].y - miny)*scalei;
00067         vx = rational(coord2int(x,cbuf),cbuf);
00068         vy = rational(coord2int(y,cbuf),cbuf);
00069 
00070         if( (compare(vx,verts[j].x)!=0) ||
00071             (compare(vy,verts[j].y)!=0) )
00072           break;
00073 
00074         i++;
00075       }
00076 
00077       if( i == nP ) break;
00078 
00079       j++;
00080 
00081       verts[j].x = vx;
00082       verts[j].y = vy;
00083       lines[j-1] = line( verts[j-1], verts[j] );
00084     }
00085 
00086     nVerts = j+1;
00087     if( (compare(verts[nVerts-1].x,verts[0].x)==0) &&
00088         (compare(verts[nVerts-1].y,verts[0].y)==0) )
00089       nVerts--;
00090 
00091     if( nVerts < 2 ) return false;
00092 
00093     lines[nVerts-1] = line( verts[nVerts-1], verts[0] );
00094     return true;
00095   }
00096 
00097   template<>
00098   bool init( int nP, const Ptr< point2<rational> >& P )
00099   {
00100     int i,j;
00101 
00102     verts.reserve_pool(nP);
00103     lines.reserve_pool(nP);
00104 
00105     verts[0] = P[0];
00106     j = 0;
00107     i = 1;
00108 
00109     for(;;)
00110     {
00111       while( (i < nP) &&
00112              (compare(P[i].x,verts[j].x)==0) && 
00113              (compare(P[i].y,verts[j].y)==0) )
00114         i++;
00115 
00116       if( i == nP ) break;
00117 
00118       j++;
00119       verts[j] = P[i];
00120       lines[j-1] = line( verts[j-1], verts[j] );
00121 
00122     }
00123 
00124     nVerts = j+1;
00125     if( (compare(verts[nVerts-1].x,verts[0].x)==0) &&
00126         (compare(verts[nVerts-1].y,verts[0].y)==0) )
00127       nVerts--;
00128 
00129     if( nVerts < 2 ) return false;
00130 
00131     lines[nVerts-1] = line( verts[nVerts-1], verts[0] );
00132     return true;
00133   }
00134 };
00135 
00136 struct contour_node
00137 {
00138   int         nVerts;
00139   Ptr<vertex> verts;
00140 
00141   Ptr<line>   lines;
00142 
00143   int         nOwners;
00144   Ptr<void*>  owners;
00145 
00146   bool        side;
00147   bool        hole;
00148 
00149   contour_node *parent;
00150   RefMap<void> childs;
00151 
00152   segment      *hseg;
00153   segment      *seg;
00154 
00155   bool hseg_firstref; // needed later when cleaning up, has a bit of a hack
00156 
00157   contour_node *next;
00158   contour_node *prev;
00159 
00160   contour_node(bool aside) 
00161   { 
00162     parent = 0; 
00163     side = aside; 
00164     nOwners = 0; }
00165 
00166   bool hasOwner( void *o )
00167   {
00168     int i;
00169 
00170     for( i=0; i < nOwners; i++ )
00171     {
00172       if( owners[i] == o )
00173         return true;
00174     }
00175     return false;
00176   }
00177 
00178   void get_polyline( gul::polyline<gul::point2<guar::rational> >& pl )
00179   {
00180     int i;
00181 
00182     pl.P.reserve_pool(nVerts);
00183     pl.n = nVerts;
00184 
00185     for( i = 0; i < nVerts; i++ )
00186       pl.P[i] = verts[i].v();
00187   }
00188 
00189   void get_polyline_joined( gul::polyline<gul::point2<guar::rational> >& pl )
00190   {
00191     int i,j,i1,iend;
00192 
00193     pl.P.reserve_pool(nVerts);
00194     pl.n = nVerts;
00195 
00196     // find a point which is not in the midst of a series of
00197     // colinear points
00198     i1 = nVerts-1;
00199     for( i = 0; i < nVerts; i++ )
00200     {
00201       if( (compare(lines[i].dx(),lines[i1].dx())!=0) ||
00202           (compare(lines[i].dy(),lines[i1].dy())!=0) )
00203         break;
00204       i1 = i;
00205     }
00206     if( i == nVerts ) // not found
00207     {
00208       pl.n = 0;  // everything is colinear, so whole contour is unnecessary
00209       return;    
00210     }
00211 
00212     pl.P[0] = verts[i].v();
00213     // DumpPS<float>::dump_point(pl.P[0]);
00214 
00215     i1 = iend = i;
00216     i++; 
00217     if( i >= nVerts ) i = 0;
00218     j = 1;
00219 
00220     for(;;)
00221     {
00222       // search next point which is not colinear
00223       while( i != iend )
00224       {
00225         if( (compare(lines[i].dx(),lines[i1].dx())!=0) ||
00226             (compare(lines[i].dy(),lines[i1].dy())!=0) )
00227           break;
00228 
00229         i++;
00230         if( i >= nVerts ) i = 0; // wrap around
00231       }
00232 
00233       // start point of contour reached again
00234       if( i == iend )
00235         break;
00236 
00237       pl.P[j] = verts[i].v();
00238       // DumpPS<float>::dump_point(pl.P[j]);
00239 
00240       i1 = i;
00241       i++;
00242       if( i >= nVerts ) i = 0; // wrap around
00243       j++;
00244     }
00245 
00246     pl.n = j;
00247   }
00248 
00249   void Insert( contour_node *achild )
00250   {
00251     int side;
00252     RefMap<void>::Node pos,child;
00253 
00254     side = childs.SearchNode( (void *)achild, compare_pointer_to_pointer,
00255                                &pos );
00256     if( side != 0 )
00257     {
00258       child = childs.NewNode((void *)achild);
00259       achild->parent = this;
00260       childs.InsertNode( child, pos, side );
00261     }
00262   }
00263 
00264   // #ifndef NDEBUG
00265   void dump( int indent )
00266   {
00267     RefMap<void>::Node mn;
00268     int i;
00269 
00270     for( i = 0; i < indent; i++ ) std::cout << " ";
00271     std::cout << "contour " << (void *)this << "\n";
00272     for( i = 0; i < indent; i++ ) std::cout << " ";
00273     std::cout << "parent = " << (void *)parent << "\n";
00274     for( i = 0; i < indent; i++ ) std::cout << " ";
00275     std::cout << "childs = (\n";
00276 
00277     mn = childs.First();
00278     while( !mn.IsEmpty() )
00279     {
00280       for( i = 0; i < indent; i++ ) std::cout << " ";
00281       std::cout << "  " << mn.key() << "\n";
00282       mn = childs.Successor( mn );
00283     }
00284     for( i = 0; i < indent; i++ ) std::cout << " ";
00285     std::cout << ")\n\n";
00286 
00287     // recursion, dump childs
00288     mn = childs.First();
00289     while( !mn.IsEmpty() )
00290     {
00291       ((contour_node *)mn.key())->dump(indent+4);
00292       mn = childs.Successor( mn );
00293     }
00294   }
00295   // #endif
00296 };
00297 
00298 void AppendContour( polyline *c, int keyleft, int keyright,
00299                     List< ListNode<segment> >& segs );
00300 
00301 template< class EP >
00302 struct seg_point_info
00303 {
00304   EP  *f;
00305   EP  *n;
00306   EP  *t;
00307 
00308   void *operator new( size_t s )
00309   {
00310     size_t dummy;
00311     void *p = PoolAlloc( s, &dummy );
00312     if( p == NULL ) throw PoolAllocError();
00313     return(p);
00314   }
00315   void operator delete( void *p, size_t s )
00316   {
00317     if( p != 0 ) PoolFree( p, s );
00318   }
00319 };
00320 
00321 template< class EP >
00322 void AppendContourFNT( polyline *c, Ptr<EP>& F, Ptr<EP>& N, Ptr<EP>& T,
00323                  int keyleft, int keyright, List< ListNode<segment> >& segs );
00324 
00325 
00326 void LeftSideContour( graph_edge *e, graph_edge_list& E, contour_node *cn );
00327 void RightSideContour( graph_edge *e, graph_edge_list& E, contour_node *cn );
00328 
00329 
00330 /*------------------------------------------------------------------
00331   Finds all contours in a graph. It also constructs a help line for
00332   each contour, which can be used to apply the odd even rule,
00333   or to build a containment tree 
00334 ------------------------------------------------------------------*/
00335 void FindContours( 
00336         graph_edge_list& E, graph_vertex_list& V,
00337         const rational& far_maxx, const rational& far_maxy,
00338         List< ListNode<segment> >& outsegs,
00339         List<contour_node>& contours );
00340 
00341 /*------------------------------------------------------------------
00342   Removes unnecessary edges by applying the odd/even winding rule
00343 ------------------------------------------------------------------*/
00344 void RemoveUnnecessaryEdges( 
00345         graph_edge_list& E, graph_vertex_list& V,
00346         const rational& far_maxx, const rational& far_maxy,
00347         int key_inside, int key_outside,
00348         List< ListNode<segment> >& outsegs );
00349 
00350 /*------------------------------------------------------------------
00351   Forms a graph from a couple of contours, and removes  unnecessary 
00352   edges in this graph by applying the odd/even winding rule
00353 ------------------------------------------------------------------*/
00354 GULAPI void OddEvenRule( 
00355         List< ListNode<polyline> >& inC, 
00356         const rational& far_maxx, const rational& far_maxy,
00357         int key_inside, int key_outside,
00358         graph_edge_list& E, graph_vertex_list& V, 
00359         List< ListNode<segment> >& outsegs );
00360 
00361 }
00362 
00363 #endif
00364 
00365 

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