00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #define USE_QHULL
00028
00029 #include <stdlib.h>
00030 #include <stdio.h>
00031 #include <assert.h>
00032 #include <math.h>
00033 #include <string.h>
00034 #include <limits.h>
00035 #include <float.h>
00036 #ifdef USE_QHULL
00037 #include <qhull/qhull_a.h>
00038 #else
00039 #include "triangle.h"
00040 #endif
00041 #include "istack.h"
00042 #include "nan.h"
00043 #include "delaunay.h"
00044
00045 int circle_build( circle* c, point* p0, point* p1, point* p2 );
00046 int circle_contains( circle* c, point* p );
00047
00048 #ifdef USE_QHULL
00049 static int cw( delaunay *d, triangle *t );
00050 #endif
00051
00052 #ifndef USE_QHULL
00053 static void tio_init( struct triangulateio* tio )
00054 {
00055 tio->pointlist = NULL;
00056 tio->pointattributelist = NULL;
00057 tio->pointmarkerlist = NULL;
00058 tio->numberofpoints = 0;
00059 tio->numberofpointattributes = 0;
00060 tio->trianglelist = NULL;
00061 tio->triangleattributelist = NULL;
00062 tio->trianglearealist = NULL;
00063 tio->neighborlist = NULL;
00064 tio->numberoftriangles = 0;
00065 tio->numberofcorners = 0;
00066 tio->numberoftriangleattributes = 0;
00067 tio->segmentlist = 0;
00068 tio->segmentmarkerlist = NULL;
00069 tio->numberofsegments = 0;
00070 tio->holelist = NULL;
00071 tio->numberofholes = 0;
00072 tio->regionlist = NULL;
00073 tio->numberofregions = 0;
00074 tio->edgelist = NULL;
00075 tio->edgemarkerlist = NULL;
00076 tio->normlist = NULL;
00077 tio->numberofedges = 0;
00078 }
00079
00080 static void tio_destroy( struct triangulateio* tio )
00081 {
00082 if ( tio->pointlist != NULL )
00083 free( tio->pointlist );
00084 if ( tio->pointattributelist != NULL )
00085 free( tio->pointattributelist );
00086 if ( tio->pointmarkerlist != NULL )
00087 free( tio->pointmarkerlist );
00088 if ( tio->trianglelist != NULL )
00089 free( tio->trianglelist );
00090 if ( tio->triangleattributelist != NULL )
00091 free( tio->triangleattributelist );
00092 if ( tio->trianglearealist != NULL )
00093 free( tio->trianglearealist );
00094 if ( tio->neighborlist != NULL )
00095 free( tio->neighborlist );
00096 if ( tio->segmentlist != NULL )
00097 free( tio->segmentlist );
00098 if ( tio->segmentmarkerlist != NULL )
00099 free( tio->segmentmarkerlist );
00100 if ( tio->holelist != NULL )
00101 free( tio->holelist );
00102 if ( tio->regionlist != NULL )
00103 free( tio->regionlist );
00104 if ( tio->edgelist != NULL )
00105 free( tio->edgelist );
00106 if ( tio->edgemarkerlist != NULL )
00107 free( tio->edgemarkerlist );
00108 if ( tio->normlist != NULL )
00109 free( tio->normlist );
00110 }
00111
00112 static delaunay* delaunay_create()
00113 {
00114 delaunay* d = malloc( sizeof ( delaunay ) );
00115
00116 d->npoints = 0;
00117 d->points = NULL;
00118 d->xmin = DBL_MAX;
00119 d->xmax = -DBL_MAX;
00120 d->ymin = DBL_MAX;
00121 d->ymax = -DBL_MAX;
00122 d->ntriangles = 0;
00123 d->triangles = NULL;
00124 d->circles = NULL;
00125 d->neighbours = NULL;
00126 d->n_point_triangles = NULL;
00127 d->point_triangles = NULL;
00128 d->nedges = 0;
00129 d->edges = NULL;
00130 d->flags = NULL;
00131 d->first_id = -1;
00132 d->t_in = NULL;
00133 d->t_out = NULL;
00134
00135 return d;
00136 }
00137
00138 static void tio2delaunay( struct triangulateio* tio_out, delaunay* d )
00139 {
00140 int i, j;
00141
00142
00143
00144
00145
00146
00147
00148 assert( tio_out->numberofpoints == d->npoints );
00149 assert( tio_out->pointlist[2 * d->npoints - 2] == d->points[d->npoints - 1].x && tio_out->pointlist[2 * d->npoints - 1] == d->points[d->npoints - 1].y );
00150
00151 for ( i = 0, j = 0; i < d->npoints; ++i )
00152 {
00153 point* p = &d->points[i];
00154
00155 if ( p->x < d->xmin )
00156 d->xmin = p->x;
00157 if ( p->x > d->xmax )
00158 d->xmax = p->x;
00159 if ( p->y < d->ymin )
00160 d->ymin = p->y;
00161 if ( p->y > d->ymax )
00162 d->ymax = p->y;
00163 }
00164 if ( nn_verbose )
00165 {
00166 fprintf( stderr, "input:\n" );
00167 for ( i = 0, j = 0; i < d->npoints; ++i )
00168 {
00169 point* p = &d->points[i];
00170
00171 fprintf( stderr, " %d: %15.7g %15.7g %15.7g\n", i, p->x, p->y, p->z );
00172 }
00173 }
00174
00175 d->ntriangles = tio_out->numberoftriangles;
00176 if ( d->ntriangles > 0 )
00177 {
00178 d->triangles = malloc( d->ntriangles * sizeof ( triangle ) );
00179 d->neighbours = malloc( d->ntriangles * sizeof ( triangle_neighbours ) );
00180 d->circles = malloc( d->ntriangles * sizeof ( circle ) );
00181 d->n_point_triangles = calloc( d->npoints, sizeof ( int ) );
00182 d->point_triangles = malloc( d->npoints * sizeof ( int* ) );
00183 d->flags = calloc( d->ntriangles, sizeof ( int ) );
00184 }
00185
00186 if ( nn_verbose )
00187 fprintf( stderr, "triangles:\n" );
00188 for ( i = 0; i < d->ntriangles; ++i )
00189 {
00190 int offset = i * 3;
00191 triangle * t = &d->triangles[i];
00192 triangle_neighbours* n = &d->neighbours[i];
00193 circle * c = &d->circles[i];
00194
00195 t->vids[0] = tio_out->trianglelist[offset];
00196 t->vids[1] = tio_out->trianglelist[offset + 1];
00197 t->vids[2] = tio_out->trianglelist[offset + 2];
00198
00199 n->tids[0] = tio_out->neighborlist[offset];
00200 n->tids[1] = tio_out->neighborlist[offset + 1];
00201 n->tids[2] = tio_out->neighborlist[offset + 2];
00202
00203 circle_build( c, &d->points[t->vids[0]], &d->points[t->vids[1]], &d->points[t->vids[2]] );
00204
00205 if ( nn_verbose )
00206 fprintf( stderr, " %d: (%d,%d,%d)\n", i, t->vids[0], t->vids[1], t->vids[2] );
00207 }
00208
00209 for ( i = 0; i < d->ntriangles; ++i )
00210 {
00211 triangle* t = &d->triangles[i];
00212
00213 for ( j = 0; j < 3; ++j )
00214 d->n_point_triangles[t->vids[j]]++;
00215 }
00216 if ( d->ntriangles > 0 )
00217 {
00218 for ( i = 0; i < d->npoints; ++i )
00219 {
00220 if ( d->n_point_triangles[i] > 0 )
00221 d->point_triangles[i] = malloc( d->n_point_triangles[i] * sizeof ( int ) );
00222 else
00223 d->point_triangles[i] = NULL;
00224 d->n_point_triangles[i] = 0;
00225 }
00226 }
00227 for ( i = 0; i < d->ntriangles; ++i )
00228 {
00229 triangle* t = &d->triangles[i];
00230
00231 for ( j = 0; j < 3; ++j )
00232 {
00233 int vid = t->vids[j];
00234
00235 d->point_triangles[vid][d->n_point_triangles[vid]] = i;
00236 d->n_point_triangles[vid]++;
00237 }
00238 }
00239
00240 if ( tio_out->edgelist != NULL )
00241 {
00242 d->nedges = tio_out->numberofedges;
00243 d->edges = malloc( d->nedges * 2 * sizeof ( int ) );
00244 memcpy( d->edges, tio_out->edgelist, d->nedges * 2 * sizeof ( int ) );
00245 }
00246 }
00247 #endif
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259 delaunay* delaunay_build( int np, point points[], int ns, int segments[], int nh, double holes[] )
00260 #ifndef USE_QHULL
00261 {
00262 delaunay * d = delaunay_create();
00263 struct triangulateio tio_in;
00264 struct triangulateio tio_out;
00265 char cmd[64] = "eznC";
00266 int i, j;
00267
00268 assert( sizeof ( REAL ) == sizeof ( double ) );
00269
00270 tio_init( &tio_in );
00271
00272 if ( np == 0 )
00273 {
00274 free( d );
00275 return NULL;
00276 }
00277
00278 tio_in.pointlist = malloc( np * 2 * sizeof ( double ) );
00279 tio_in.numberofpoints = np;
00280 for ( i = 0, j = 0; i < np; ++i )
00281 {
00282 tio_in.pointlist[j++] = points[i].x;
00283 tio_in.pointlist[j++] = points[i].y;
00284 }
00285
00286 if ( ns > 0 )
00287 {
00288 tio_in.segmentlist = malloc( ns * 2 * sizeof ( int ) );
00289 tio_in.numberofsegments = ns;
00290 memcpy( tio_in.segmentlist, segments, ns * 2 * sizeof ( int ) );
00291 }
00292
00293 if ( nh > 0 )
00294 {
00295 tio_in.holelist = malloc( nh * 2 * sizeof ( double ) );
00296 tio_in.numberofholes = nh;
00297 memcpy( tio_in.holelist, holes, nh * 2 * sizeof ( double ) );
00298 }
00299
00300 tio_init( &tio_out );
00301
00302 if ( !nn_verbose )
00303 strcat( cmd, "Q" );
00304 else if ( nn_verbose > 1 )
00305 strcat( cmd, "VV" );
00306 if ( ns != 0 )
00307 strcat( cmd, "p" );
00308
00309 if ( nn_verbose )
00310 fflush( stderr );
00311
00312
00313
00314
00315 triangulate( cmd, &tio_in, &tio_out, NULL );
00316
00317 if ( nn_verbose )
00318 fflush( stderr );
00319
00320 d->npoints = np;
00321 d->points = points;
00322
00323 tio2delaunay( &tio_out, d );
00324
00325 tio_destroy( &tio_in );
00326 tio_destroy( &tio_out );
00327
00328 return d;
00329 }
00330 #else // USE_QHULL
00331 {
00332 delaunay* d = malloc( sizeof ( delaunay ) );
00333
00334 coordT *qpoints;
00335 boolT ismalloc = False;
00336 char flags[64] = "qhull d Qbb Qt";
00337 facetT *facet, *neighbor, **neighborp;
00338 vertexT *vertex, **vertexp;
00339
00340 int curlong, totlong;
00341 FILE *outfile = stdout;
00342 FILE *errfile = stderr;
00343
00344 int i, j;
00345 int exitcode;
00346 int dim, ntriangles;
00347 int numfacets, numsimplicial, numridges, totneighbors, numcoplanars, numtricoplanars;
00348
00349 dim = 2;
00350
00351 assert( sizeof ( realT ) == sizeof ( double ) );
00352
00353 if ( np == 0 || ns > 0 || nh > 0 )
00354 {
00355 fprintf( stderr, "segments=%d holes=%d\n, aborting Qhull implementation, use 'triangle' instead.\n", ns, nh );
00356 free( d );
00357 return NULL;
00358 }
00359
00360 qpoints = (coordT *) malloc( np * ( dim + 1 ) * sizeof ( coordT ) );
00361
00362 for ( i = 0; i < np; i++ )
00363 {
00364 qpoints[i * dim] = points[i].x;
00365 qpoints[i * dim + 1] = points[i].y;
00366 }
00367
00368 if ( !nn_verbose )
00369 outfile = NULL;
00370 if ( nn_verbose )
00371 strcat( flags, " s" );
00372 if ( nn_verbose > 1 )
00373 strcat( flags, " Ts" );
00374
00375 if ( nn_verbose )
00376 fflush( stderr );
00377
00378
00379
00380
00381
00382 exitcode = qh_new_qhull( dim, np, qpoints, ismalloc,
00383 flags, outfile, errfile );
00384
00385 if ( !exitcode )
00386 {
00387 if ( nn_verbose )
00388 fflush( stderr );
00389
00390 d->xmin = DBL_MAX;
00391 d->xmax = -DBL_MAX;
00392 d->ymin = DBL_MAX;
00393 d->ymax = -DBL_MAX;
00394
00395 d->npoints = np;
00396 d->points = malloc( np * sizeof ( point ) );
00397 for ( i = 0; i < np; ++i )
00398 {
00399 point* p = &d->points[i];
00400
00401 p->x = points[i].x;
00402 p->y = points[i].y;
00403 p->z = points[i].z;
00404
00405 if ( p->x < d->xmin )
00406 d->xmin = p->x;
00407 if ( p->x > d->xmax )
00408 d->xmax = p->x;
00409 if ( p->y < d->ymin )
00410 d->ymin = p->y;
00411 if ( p->y > d->ymax )
00412 d->ymax = p->y;
00413 }
00414
00415 if ( nn_verbose )
00416 {
00417 fprintf( stderr, "input:\n" );
00418 for ( i = 0; i < np; ++i )
00419 {
00420 point* p = &d->points[i];
00421
00422 fprintf( stderr, " %d: %15.7g %15.7g %15.7g\n",
00423 i, p->x, p->y, p->z );
00424 }
00425 }
00426
00427 qh_findgood_all( qh facet_list );
00428 qh_countfacets( qh facet_list, NULL, !qh_ALL, &numfacets,
00429 &numsimplicial, &totneighbors, &numridges,
00430 &numcoplanars, &numtricoplanars );
00431
00432 ntriangles = 0;
00433 FORALLfacets {
00434 if ( !facet->upperdelaunay && facet->simplicial )
00435 ntriangles++;
00436 }
00437
00438 d->ntriangles = ntriangles;
00439 d->triangles = malloc( d->ntriangles * sizeof ( triangle ) );
00440 d->neighbours = malloc( d->ntriangles * sizeof ( triangle_neighbours ) );
00441 d->circles = malloc( d->ntriangles * sizeof ( circle ) );
00442
00443 if ( nn_verbose )
00444 fprintf( stderr, "triangles:\tneighbors:\n" );
00445
00446 i = 0;
00447 FORALLfacets {
00448 if ( !facet->upperdelaunay && facet->simplicial )
00449 {
00450 triangle * t = &d->triangles[i];
00451 triangle_neighbours* n = &d->neighbours[i];
00452 circle * c = &d->circles[i];
00453
00454 j = 0;
00455 FOREACHvertex_( facet->vertices )
00456 t->vids[j++] = qh_pointid( vertex->point );
00457
00458 j = 0;
00459 FOREACHneighbor_( facet )
00460 n->tids[j++] = neighbor->visitid ? neighbor->visitid - 1 : -1;
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473 if ( cw( d, t ) )
00474 {
00475 int tmp = t->vids[1];
00476 t->vids[1] = t->vids[2];
00477 t->vids[2] = tmp;
00478
00479 tmp = n->tids[1];
00480 n->tids[1] = n->tids[2];
00481 n->tids[2] = tmp;
00482 }
00483
00484 circle_build( c, &d->points[t->vids[0]], &d->points[t->vids[1]],
00485 &d->points[t->vids[2]] );
00486
00487 if ( nn_verbose )
00488 fprintf( stderr, " %d: (%d,%d,%d)\t(%d,%d,%d)\n",
00489 i, t->vids[0], t->vids[1], t->vids[2], n->tids[0],
00490 n->tids[1], n->tids[2] );
00491
00492 i++;
00493 }
00494 }
00495
00496 d->flags = calloc( d->ntriangles, sizeof ( int ) );
00497
00498 d->n_point_triangles = calloc( d->npoints, sizeof ( int ) );
00499 for ( i = 0; i < d->ntriangles; ++i )
00500 {
00501 triangle* t = &d->triangles[i];
00502
00503 for ( j = 0; j < 3; ++j )
00504 d->n_point_triangles[t->vids[j]]++;
00505 }
00506 d->point_triangles = malloc( d->npoints * sizeof ( int* ) );
00507 for ( i = 0; i < d->npoints; ++i )
00508 {
00509 if ( d->n_point_triangles[i] > 0 )
00510 d->point_triangles[i] = malloc( d->n_point_triangles[i] * sizeof ( int ) );
00511 else
00512 d->point_triangles[i] = NULL;
00513 d->n_point_triangles[i] = 0;
00514 }
00515 for ( i = 0; i < d->ntriangles; ++i )
00516 {
00517 triangle* t = &d->triangles[i];
00518
00519 for ( j = 0; j < 3; ++j )
00520 {
00521 int vid = t->vids[j];
00522
00523 d->point_triangles[vid][d->n_point_triangles[vid]] = i;
00524 d->n_point_triangles[vid]++;
00525 }
00526 }
00527
00528 d->nedges = 0;
00529 d->edges = NULL;
00530
00531 d->t_in = NULL;
00532 d->t_out = NULL;
00533 d->first_id = -1;
00534 }
00535 else
00536 {
00537 free( d );
00538 d = NULL;
00539 }
00540
00541 free( qpoints );
00542 qh_freeqhull( !qh_ALL );
00543 qh_memfreeshort( &curlong, &totlong );
00544 if ( curlong || totlong )
00545 fprintf( errfile,
00546 "qhull: did not free %d bytes of long memory (%d pieces)\n",
00547 totlong, curlong );
00548
00549 return d;
00550 }
00551
00552
00553 static int cw( delaunay *d, triangle *t )
00554 {
00555 point* pa = &d->points[t->vids[0]];
00556 point* pb = &d->points[t->vids[1]];
00557 point* pc = &d->points[t->vids[2]];
00558
00559 return ( ( pb->x - pa->x ) * ( pc->y - pa->y ) <
00560 ( pc->x - pa->x ) * ( pb->y - pa->y ) );
00561 }
00562
00563 #endif
00564
00565
00566
00567
00568
00569 void delaunay_destroy( delaunay* d )
00570 {
00571 if ( d == NULL )
00572 return;
00573
00574 if ( d->point_triangles != NULL )
00575 {
00576 int i;
00577
00578 for ( i = 0; i < d->npoints; ++i )
00579 if ( d->point_triangles[i] != NULL )
00580 free( d->point_triangles[i] );
00581 free( d->point_triangles );
00582 }
00583 if ( d->nedges > 0 )
00584 free( d->edges );
00585 #ifdef USE_QHULL
00586
00587
00588 if ( d->points != NULL )
00589 free( d->points );
00590 #endif
00591 if ( d->n_point_triangles != NULL )
00592 free( d->n_point_triangles );
00593 if ( d->flags != NULL )
00594 free( d->flags );
00595 if ( d->circles != NULL )
00596 free( d->circles );
00597 if ( d->neighbours != NULL )
00598 free( d->neighbours );
00599 if ( d->triangles != NULL )
00600 free( d->triangles );
00601 if ( d->t_in != NULL )
00602 istack_destroy( d->t_in );
00603 if ( d->t_out != NULL )
00604 istack_destroy( d->t_out );
00605 free( d );
00606 }
00607
00608
00609
00610 static int on_right_side( point* p, point* p0, point* p1 )
00611 {
00612 return ( p1->x - p->x ) * ( p0->y - p->y ) > ( p0->x - p->x ) * ( p1->y - p->y );
00613 }
00614
00615
00616
00617
00618
00619
00620
00621
00622 int delaunay_xytoi( delaunay* d, point* p, int id )
00623 {
00624 triangle* t;
00625 int i;
00626
00627 if ( p->x < d->xmin || p->x > d->xmax || p->y < d->ymin || p->y > d->ymax )
00628 return -1;
00629
00630 if ( id < 0 || id > d->ntriangles )
00631 id = 0;
00632 t = &d->triangles[id];
00633 do
00634 {
00635 for ( i = 0; i < 3; ++i )
00636 {
00637 int i1 = ( i + 1 ) % 3;
00638
00639 if ( on_right_side( p, &d->points[t->vids[i]], &d->points[t->vids[i1]] ) )
00640 {
00641 id = d->neighbours[id].tids[( i + 2 ) % 3];
00642 if ( id < 0 )
00643 return id;
00644 t = &d->triangles[id];
00645 break;
00646 }
00647 }
00648 } while ( i < 3 );
00649
00650 return id;
00651 }
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672 void delaunay_circles_find( delaunay* d, point* p, int* n, int** out )
00673 {
00674 int i;
00675
00676 if ( d->t_in == NULL )
00677 {
00678 d->t_in = istack_create();
00679 d->t_out = istack_create();
00680 }
00681
00682
00683
00684
00685
00686
00687
00688
00689 if ( d->first_id < 0 || !circle_contains( &d->circles[d->first_id], p ) )
00690 {
00691
00692
00693
00694 d->first_id = delaunay_xytoi( d, p, d->first_id );
00695
00696
00697
00698
00699
00700 if ( d->first_id < 0 )
00701 {
00702 int nn = d->t_out->n;
00703 int tid = -1;
00704
00705
00706
00707
00708 for ( i = 0; i < nn; ++i )
00709 {
00710 tid = d->t_out->v[i];
00711 if ( circle_contains( &d->circles[tid], p ) )
00712 break;
00713 }
00714
00715
00716
00717 if ( tid < 0 || i == nn )
00718 {
00719 double nt = d->ntriangles;
00720
00721 for ( tid = 0; tid < nt; ++tid )
00722 {
00723 if ( circle_contains( &d->circles[tid], p ) )
00724 break;
00725 }
00726 if ( tid == nt )
00727 {
00728 istack_reset( d->t_out );
00729 *n = 0;
00730 *out = NULL;
00731 return;
00732 }
00733 }
00734 d->first_id = tid;
00735 }
00736 }
00737
00738 istack_reset( d->t_in );
00739 istack_reset( d->t_out );
00740
00741 istack_push( d->t_in, d->first_id );
00742 d->flags[d->first_id] = 1;
00743
00744
00745
00746
00747 while ( d->t_in->n > 0 )
00748 {
00749 int tid = istack_pop( d->t_in );
00750 triangle* t = &d->triangles[tid];
00751
00752 if ( circle_contains( &d->circles[tid], p ) )
00753 {
00754 istack_push( d->t_out, tid );
00755 for ( i = 0; i < 3; ++i )
00756 {
00757 int vid = t->vids[i];
00758 int nt = d->n_point_triangles[vid];
00759 int j;
00760
00761 for ( j = 0; j < nt; ++j )
00762 {
00763 int ntid = d->point_triangles[vid][j];
00764
00765 if ( d->flags[ntid] == 0 )
00766 {
00767 istack_push( d->t_in, ntid );
00768 d->flags[ntid] = 1;
00769 }
00770 }
00771 }
00772 }
00773 }
00774
00775 *n = d->t_out->n;
00776 *out = d->t_out->v;
00777 }