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

gugr_basics.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_BASICS_H
00021 #define GUGR_BASICS_H
00022 
00023 namespace gugr {
00024 
00025 using gul::ndebug;
00026 using gul::Assert;
00027 using gul::InternalError;
00028 using gul::PoolAllocError;
00029 using gul::List;
00030 using gul::List2;
00031 using gul::bounding_box;
00032 using guar::Interval;
00033 using guar::ULong;
00034 using guar::rational;
00035 using gul::point2;
00036 using gul::compare;
00037 using gust::PoolAlloc;
00038 using gust::PoolFree;
00039 
00040 /*------------------------------------------------------------
00041   converts a floating point number lying between 1 and 2 into 
00042   a rational number between 0 and epsilon^-1
00043 -------------------------------------------------------------*/
00044 inline int coord2int( double f, unsigned long *buf )
00045 {
00046   gul::uint64 i;
00047   unsigned long hi,lo;
00048   
00049 //  gul::Assert<gul::InternalError>( ndebug | (1.0 <= f && f <= 2.0) );
00050   if( f < 1.0 ) f = 1.0; 
00051   else if( f > 2.0 ) f = 2.0; 
00052   i = (gul::uint64)(f*gul::rtr<double>::epsilon_inv());
00053   i -= (gul::uint64)gul::rtr<double>::epsilon_inv();
00054   hi = (unsigned long)((i >> 32) & LL(0xffffffff));
00055   lo = (unsigned long)(i & LL(0xffffffff)); 
00056   if( !hi )
00057   {
00058     if( !lo ) return 0;
00059     buf[0] = lo;
00060     return 1;
00061   }
00062   buf[0] = lo;
00063   buf[1] = hi;
00064   return 2; 
00065 }
00066 
00067 inline int coord2int( float f, unsigned long *buf )
00068 {
00069   unsigned long i;
00070   
00071 //  gul::Assert<InternalError>( ndebug | (1.0f <= f && f <= 2.0f) );
00072   if( f < 1.0f ) f = 1.0f; 
00073   else if( f > 2.0f ) f = 2.0f; 
00074   i = (unsigned long)(f * gul::rtr<float>::epsilon_inv());
00075   i -= (unsigned long)gul::rtr<float>::epsilon_inv();
00076   if( !i ) return 0;
00077   buf[0] = i;
00078   return 1;
00079 }
00080 
00081 /*---------------------------------------------------------------
00082   converts a number between 0 and epsilon^-1 into a number
00083   between 1 and 2
00084 ---------------------------------------------------------------*/
00085 template< class T >
00086 T cnv2coord( const T& i )
00087 {
00088   return i * gul::rtr<T>::epsilon() + (T)1.0;
00089 }
00090 
00091 /*---------------------------------------------------------------
00092   converts a rational between 0 and epsilon^-1 into a floating
00093   point number between 1 and 2
00094 ---------------------------------------------------------------*/
00095 template< class T >
00096 inline void cnv2coord_rnd( rational& f, T *ret )
00097 {
00098   rational q,r,rd,h;
00099   T flt;
00100 
00101   f.div_mod(&q,&r);
00102 
00103   rd = r/f.denominator();
00104   h = rational(ULong(1))/rational(ULong(2));
00105 
00106   if( compare(rd,h) >= 0 )
00107     q = q + rational(ULong(1));
00108 
00109   guar::IntTo<T>(q.m->m_na,q.m->m_a,flt);
00110 
00111   *ret = cnv2coord(flt);
00112 }
00113 
00114 struct vertex_rep
00115 {
00116   point2<rational>       v;
00117   int                    m_refcount;
00118   gul::ptr_int_union     reserved;  /* used internally as a pointer to a buffer
00119                                        for conversions */
00120   vertex_rep() 
00121   { 
00122     m_refcount = 1;
00123     reserved.p = 0;
00124     reserved.i = 0;
00125   }
00126 
00127   explicit vertex_rep( const point2<rational> &av ) : v(av) 
00128   { 
00129     m_refcount = 1;
00130     reserved.p = 0;
00131     reserved.i = 0;
00132   }
00133 
00134   ~vertex_rep()
00135   {
00136   }
00137   
00138   void *operator new( size_t s )
00139   {
00140     size_t dummy;
00141     void *p = PoolAlloc( s, &dummy );
00142     if( p == NULL ) throw PoolAllocError();
00143     return(p);
00144   }
00145   void operator delete( void *p, size_t s )
00146   {
00147     PoolFree( p, s );
00148   }
00149 };
00150 
00151 struct vertex
00152 {
00153   friend bool operator==( const vertex& a, const vertex& b );
00154   
00155   vertex_rep *m_rep;
00156   
00157   vertex() 
00158   { 
00159     m_rep = NULL;
00160   }
00161 
00162   explicit vertex( const vertex &other )
00163   {
00164     if( other.m_rep ) other.m_rep->m_refcount++;
00165     m_rep = other.m_rep;
00166   }
00167 
00168   explicit vertex( const point2<rational> &av )
00169   {
00170     m_rep = new vertex_rep( av );
00171   }
00172 
00173   ~vertex() 
00174   { 
00175     if( (m_rep != NULL) && (--m_rep->m_refcount == 0) ) delete m_rep;
00176   }
00177 
00178   vertex& operator=( const vertex& other )  {
00179     if( other.m_rep ) other.m_rep->m_refcount++;
00180     if( (m_rep != NULL) && (--m_rep->m_refcount == 0) ) {
00181       delete m_rep;
00182     }
00183     m_rep = other.m_rep;
00184     return( *this );    
00185   }
00186 
00187   point2<rational>& v() const { return(m_rep->v); }
00188 };
00189 
00190 inline bool operator==( const vertex& a, const vertex& b )
00191 {
00192   return( a.m_rep == b.m_rep );
00193 }
00194 
00195 struct line_rep
00196 {
00197   point2<rational>     v;
00198   rational    dx;
00199   rational    dy;
00200   int             m_refcount;
00201 
00202   line_rep() { m_refcount = 1; }
00203 
00204   line_rep( const point2<rational> &av, const rational& adx,
00205             const rational &ady ) : v(av), dx(adx), dy(ady)
00206   { m_refcount = 1; }
00207 
00208   void *operator new( size_t s )
00209   {
00210     size_t dummy;
00211     void *p = PoolAlloc( s, &dummy );
00212     if( p == NULL ) throw PoolAllocError();
00213     return(p);
00214   }
00215   
00216   void operator delete( void *p, size_t s )
00217   {
00218     PoolFree( p, s );
00219   }
00220 };
00221 
00222 struct line
00223 {
00224   line_rep *m_rep;
00225 
00226   line() { m_rep = NULL; }
00227 
00228   explicit line( const line &other )
00229   {
00230     if( other.m_rep ) other.m_rep->m_refcount++;
00231     m_rep = other.m_rep;
00232   }
00233 
00234   ~line() { if( (m_rep != NULL)&&(--m_rep->m_refcount == 0) ) delete m_rep; }
00235 
00236 
00237   explicit line( const point2<rational> &av, const rational& adx,
00238                  const rational &ady )
00239   {
00240     m_rep = new line_rep( av, adx, ady );
00241   }
00242   GULAPI explicit line( const point2<rational>& a, const point2<rational>& b );
00243 
00244   line& operator=( const line& other ) {
00245     if( other.m_rep ) other.m_rep->m_refcount++;
00246     if( (m_rep != NULL) && (--m_rep->m_refcount == 0) ) {
00247       m_rep->~line_rep();
00248       PoolFree( m_rep, sizeof(line_rep) );      
00249     }
00250     m_rep = other.m_rep;
00251     return( *this ); }
00252   point2<rational>& v() const { return(m_rep->v); }
00253   rational& dx() const { return(m_rep->dx); }
00254   rational& dy() const { return(m_rep->dy); }
00255   bool IsNULL( void ) const { return(m_rep == NULL); }
00256   bool IsHorizontal(void) const { return m_rep->dy.is_zero(); }
00257   bool IsVertical(void) const { return m_rep->dx.is_zero(); }
00258 };
00259 
00260 inline bool parallel( const line& a, const line& b )
00261 {
00262   if( a.IsHorizontal() )
00263     return b.IsHorizontal();
00264   else if( a.IsVertical() )
00265     return b.IsVertical();
00266 
00267   if( b.IsHorizontal() || b.IsVertical() )
00268     return false;
00269 
00270   return compare( a.dy(), b.dy() ) == 0;
00271 }
00272 
00273 bool intersect_nonvert( const line& a, const line& b, point2<rational>& I );
00274 bool intersect_vert( const rational& x0, const line& b, point2<rational>& I );
00275 bool intersect_horiz( const rational& y0, const line& b, point2<rational>& I );
00276 bool intersect( const line& a, const line& b, point2<rational>& I );
00277 
00278 
00279 struct graph_edge;
00280 
00281 struct graph_vertex
00282 {
00283   vertex                 v;
00284   graph_edge            *e;
00285   
00286   gul::ptr_int_union     reserved[2];
00287 
00288   graph_vertex          *next;
00289   graph_vertex          *prev;
00290 
00291   graph_vertex() 
00292   {
00293   }
00294   explicit graph_vertex( const point2<rational>& av, graph_edge *ae ) : v(av) 
00295   { 
00296     e = ae;
00297   }
00298   explicit graph_vertex( const vertex& av, graph_edge *ae ) 
00299   { 
00300     v = av; e = ae;
00301   }
00302                      /* sets the reserved[1] field, only for internal use! */
00303   explicit graph_vertex( const vertex& av, graph_edge *ae, int code ) 
00304   { 
00305     v = av; e = ae; reserved[1].set_i(code);
00306   }
00307 
00308                      /* sets the reserved[1] field, only for internal use! */
00309   explicit graph_vertex( const vertex& av, graph_edge *ae, gul::ptr_int_union pi ) 
00310   { 
00311     v = av; e = ae; reserved[1] = pi;
00312   }
00313 
00314 
00315   ~graph_vertex()
00316   {
00317   }
00318 
00319   void *operator new( size_t s )
00320   {
00321     size_t dummy;
00322     void *p = PoolAlloc( s, &dummy );
00323     if( p == NULL ) throw PoolAllocError();
00324     return(p);
00325   }
00326   void operator delete( void *p, size_t s )
00327   {
00328     PoolFree( p, s );
00329   }
00330 };
00331 
00332 typedef List<graph_vertex> graph_vertex_list;
00333 typedef List2<graph_vertex> graph_vertex_list2;
00334 
00335 struct graph_edge
00336 {
00337   struct graph_vertex   *v[2];
00338   struct graph_edge     *e[2];
00339   gul::ptr_int_union     f[2];
00340 
00341   line                   l;
00342   
00343   gul::ptr_int_union     reserved[3];
00344 
00345   struct  graph_edge    *next;
00346   struct  graph_edge    *prev;
00347  
00348   graph_edge() { };
00349 
00350   explicit graph_edge( graph_vertex *v0, graph_vertex *v1 )
00351   { 
00352     v[0] = v0; v[1] = v1;
00353   }
00354 
00355   bool IsHorizontal(void)
00356   { 
00357     if( l.IsNULL() ) CalcLine();
00358     return( l.dy().is_zero() );
00359   }
00360     
00361   void CalcLine( void )   // Calculates the line on which a graph edge lies
00362   {
00363     l = line( v[0]->v.v(), v[1]->v.v() );
00364   }
00365 
00366 //  graph_edge( graph_vertex *v1, graph_vertex *v2 ) { v[0] = v1; v[1] = v2; }
00367 
00368   void *operator new( size_t s )
00369   {
00370     size_t dummy;
00371     void *p = PoolAlloc( s, &dummy );
00372     if( p == NULL ) throw PoolAllocError();
00373     return(p);
00374   }
00375   
00376   void operator delete( void *p, size_t s )
00377   {
00378     PoolFree( p, s );
00379   }
00380 };
00381 
00382 
00383 typedef List<graph_edge> graph_edge_list;
00384 
00385 typedef struct _cut_record
00386 {
00387   graph_edge            *e;
00388   rational         val;
00389   graph_vertex          *v;
00390   
00391   struct _cut_record    *next;
00392   struct _cut_record    *prev;
00393 
00394   void *operator new( size_t s )
00395   {
00396     size_t dummy;
00397     void *p = PoolAlloc( s, &dummy );
00398     if( p == NULL ) throw PoolAllocError();
00399     return(p);
00400   }  
00401   void operator delete( void *p, size_t s )
00402   {
00403     PoolFree( p, s );
00404   }
00405 }
00406 cut_record;
00407 
00408 typedef List<cut_record> cut_record_list;
00409 
00410 typedef struct _cut_info
00411 {
00412   rational        val;
00413   cut_record_list       R;
00414   graph_edge_list       E;
00415   graph_vertex_list     V;
00416 }
00417 cut_info;
00418 
00419 struct triangle
00420 {
00421   vertex v[3];
00422   int code0 : 2;  
00423   int code1 : 2;  
00424   int code2 : 2;  
00425 
00426   struct triangle    *next;
00427   struct triangle    *prev;
00428 
00429   void *operator new( size_t s )
00430   {
00431     size_t dummy;
00432     void *p = PoolAlloc( s, &dummy );
00433     if( p == NULL ) throw PoolAllocError();
00434     return(p);
00435   }
00436   void operator delete( void *p, size_t s )
00437   {
00438     PoolFree( p, s );
00439   }
00440 };
00441 
00442 typedef List<triangle> triangle_list;
00443 
00444 struct monpoly_info
00445 {
00446   graph_vertex_list2 Vl;
00447   graph_vertex_list2 Vr;
00448   graph_edge_list    E;
00449 
00450   /* ------------------------------------------------------------------------
00451     Appends a edge to the left chain of a monotone polygon. If this closes
00452     the polygon the function returns true
00453   ------------------------------------------------------------------------ */
00454   bool AppendLeft( const graph_vertex& v1, const graph_vertex& v2 );
00455 
00456   /* ------------------------------------------------------------------------
00457     Appends a vertex to the right chain of a monotone polygon. If this closes
00458     the polygon the function returns true
00459   -------------------------------------------------------------------------- */
00460   bool AppendRight( const graph_vertex& v1, const graph_vertex& v2 );
00461 };
00462 
00463 /* ----------------------------------------------------------------
00464    gets the edges incident to vertex 'v'
00465 ------------------------------------------------------------------ */
00466 int IncidentEdges( const graph_vertex *v, graph_edge **A );
00467 
00468 /* ----------------------------------------------------------------
00469    gets the edges incident to edge 'e' at vertex 'v'
00470 ------------------------------------------------------------------ */
00471 int EdgeCycle( graph_edge *e, graph_vertex *v, graph_edge **A );
00472 
00473 /* --------------------------------------------------------------------
00474   Orient edge, so that y2 > y1 or x2 < x1 if y2 = y1
00475 --------------------------------------------------------------------- */
00476 void OrientEdge( graph_edge *e );
00477 
00478 /* --------------------------------------------------------------------
00479   Orient edges, so that y2 > y1 or x2 < x1 if y2 = y1
00480 --------------------------------------------------------------------- */
00481 void OrientEdges( graph_edge *E );
00482 
00483 /* ------------------------------------------------------------------------
00484   Determine on which side of AB the point C is
00485 -------------------------------------------------------------------------- */
00486 int DetermineOrientation( const point2<rational>& A, const point2<rational>& B, 
00487                           const point2<rational>& C );
00488 int DetermineOrientationPV( const point2<rational>& A, const point2<rational>& AB, 
00489                             const point2<rational>& C );
00490 
00491 /* --------------------------------------------------------------------
00492   Compares angle(AB,AC) to angle(AB,AD)
00493 
00494   Remarks:
00495 
00496   code_x = 3 if X is to the left of AB
00497            2 if X is on AB
00498            1 if X is to the right of AB
00499            0 if it was not necessary to calculate the cross-product
00500   match = 1 if C lies on AB
00501         = 2 if D lies on AB
00502         = 0 if both C and D are not on AB             
00503 ---------------------------------------------------------------------- */
00504 int CompareAngles(
00505   const point2<rational>& A, const point2<rational>& B,
00506   const point2<rational>& C, const point2<rational>& D,
00507   int *match, int *code_c, int *code_d );
00508  
00509 /* --------------------------------------------------------------------
00510   Find the insertion positon for a oriented line segment in an edge 
00511   cycle of a DCEL 
00512 
00513   Remarks:
00514 
00515   code_edge = 3 if angle(ab,edge) < 180
00516             = 2 if angle(ab,edge) = 0 or 180
00517             = 1 if angle(ab,edge) > 180
00518   match = 1 if ab and left are colinear 
00519         = 2 if ab and right are colinear
00520         = 0 if none of both edges lies on ab         
00521 ---------------------------------------------------------------------*/ 
00522 int EdgeInsertPosition(
00523          const vertex& a, const vertex& b,
00524          int nE, graph_edge **E,
00525          int *eleft, int *eright,
00526          int *code_left, int *code_right );
00527 
00528 /* ----------------------------------------------------------------------
00529   Connects a edge at its ends into a graph
00530 -----------------------------------------------------------------------*/
00531 void ConnectEdge( graph_edge *e, int maxE );
00532 
00533 /* ----------------------------------------------------------------------
00534   Disconnect the ends of an edge from a graph. Bit 1/2 of the result
00535   indicate that v[0/1] of the edge are isolated afterwards 
00536 -----------------------------------------------------------------------*/
00537 int DisconnectEdge( graph_edge *e, int maxE );
00538 
00539 /*-------------------------------------------------------------------------
00540   Converts simple polygon to a DCEL (doubly connected edge list, winged edge
00541   list)
00542 --------------------------------------------------------------------------*/
00543 template< class T >
00544 void PolygonToGraph( 
00545       const int n, gul::Ptr< gul::point2<T> > P,
00546       const T orgx, const T orgy,
00547       const T scalex, const T scaley,
00548       int fleft, int fright,
00549       graph_edge_list *E, graph_vertex_list *V );
00550 
00551 template< class T >
00552 inline void PolygonToGraphNV( 
00553       const int n, gul::Ptr< gul::point2<T> > P,
00554       const T orgx, const T orgy,
00555       const T scalex, const T scaley,
00556       int fleft, int fright,
00557       graph_edge_list *E, graph_vertex_list *V );
00558 
00559 
00560 }
00561 
00562 
00563 #endif

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