00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
00042
00043
00044 inline int coord2int( double f, unsigned long *buf )
00045 {
00046 gul::uint64 i;
00047 unsigned long hi,lo;
00048
00049
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
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
00083
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
00093
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;
00119
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
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
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 )
00362 {
00363 l = line( v[0]->v.v(), v[1]->v.v() );
00364 }
00365
00366
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
00452
00453
00454 bool AppendLeft( const graph_vertex& v1, const graph_vertex& v2 );
00455
00456
00457
00458
00459
00460 bool AppendRight( const graph_vertex& v1, const graph_vertex& v2 );
00461 };
00462
00463
00464
00465
00466 int IncidentEdges( const graph_vertex *v, graph_edge **A );
00467
00468
00469
00470
00471 int EdgeCycle( graph_edge *e, graph_vertex *v, graph_edge **A );
00472
00473
00474
00475
00476 void OrientEdge( graph_edge *e );
00477
00478
00479
00480
00481 void OrientEdges( graph_edge *E );
00482
00483
00484
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
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
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
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
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
00530
00531 void ConnectEdge( graph_edge *e, int maxE );
00532
00533
00534
00535
00536
00537 int DisconnectEdge( graph_edge *e, int maxE );
00538
00539
00540
00541
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