00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
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]);
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
00106
00107 edge_interval_tree()
00108 {
00109 InitBBT(&root);
00110
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
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
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
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
00316
00317
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 )
00329 {
00330 regular = 1;
00331
00332 sign = compare( a->v[1]->v.v().y, v0->v.v().y );
00333 if( sign == 0 ) continue;
00334
00335
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
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 )
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 )
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
00404
00405 }
00406 }
00407 }
00408
00409 v0 = v0->prev;
00410 }
00411
00412
00413
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 )
00433 {
00434 regular = 1;
00435
00436 sign = compare( a->v[0]->v.v().y, v0->v.v().y );
00437 if( sign == 0 ) continue;
00438
00439
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 )
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 )
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 }