• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

delaunay.c

Go to the documentation of this file.
00001 //--------------------------------------------------------------------------
00002 //
00003 // File:           delaunay.c
00004 //
00005 // Created:        04/08/2000
00006 //
00007 // Author:         Pavel Sakov
00008 //                 CSIRO Marine Research
00009 //
00010 // Purpose:        Delaunay triangulation - a wrapper to triangulate()
00011 //
00012 // Description:    None
00013 //
00014 // Revisions:      10/06/2003 PS: delaunay_build(); delaunay_destroy();
00015 //                 struct delaunay: from now on, only shallow copy of the
00016 //                 input data is contained in struct delaunay. This saves
00017 //                 memory and is consistent with libcsa.
00018 //
00019 // Modified:       Joao Cardoso, 4/2/2003
00020 //                 Adapted for use with Qhull instead of "triangle".
00021 //                 Andrew Ross 20/10/2008
00022 //                 Fix bug in delaunay_circles_find() when checking
00023 //                 whether a circle has been found.
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     // I assume that all input points appear in tio_out in the same order as
00144     // they were written to tio_in. I have seen no exceptions so far, even
00145     // if duplicate points were presented. Just in case, let us make a couple
00146     // of checks.
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 // Builds Delaunay triangulation of the given array of points.
00250 //
00251 // @param np Number of points
00252 // @param points Array of points [np] (input)
00253 // @param ns Number of forced segments
00254 // @param segments Array of (forced) segment endpoint indices [2*ns]
00255 // @param nh Number of holes
00256 // @param holes Array of hole (x,y) coordinates [2*nh]
00257 // @return Delaunay triangulation structure with triangulation results
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     // climax
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;                       // array of coordinates for each point
00335     boolT   ismalloc  = False;              // True if qhull should free points
00336     char    flags[64] = "qhull d Qbb Qt";   // option flags for qhull
00337     facetT  *facet, *neighbor, **neighborp; // variables to walk through facets
00338     vertexT *vertex, **vertexp;             // variables to walk through vertex
00339 
00340     int     curlong, totlong;               // memory remaining after qh_memfreeshort
00341     FILE    *outfile = stdout;
00342     FILE    *errfile = stderr;              // error messages from qhull code
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 ) ); // Qhull was compiled with doubles?
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     // climax
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                 // Put triangle vertices in counterclockwise order, as
00463                 // 'triangle' do.
00464                 // The same needs to be done with the neighbors.
00465                 //
00466                 // The following works, i.e., it seems that Qhull maintains a
00467                 // relationship between the vertices and the neighbors
00468                 // triangles, but that is not said anywhere, so if this stop
00469                 // working in a future Qhull release, you know what you have
00470                 // to do, reorder the neighbors.
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 );               // free long memory
00543     qh_memfreeshort( &curlong, &totlong ); // free short memory and memory allocator
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 // returns 1 if a,b,c are clockwise ordered
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 // Releases memory engaged in the Delaunay triangulation structure.
00566 //
00567 // @param d Structure to be destroyed
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     // This is a shallow copy if we're not using qhull so we don't
00587     // need to free it
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 // Returns whether the point p is on the right side of the vector (p0, p1).
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 // Finds triangle specified point belongs to (if any).
00616 //
00617 // @param d Delaunay triangulation
00618 // @param p Point to be mapped
00619 // @param seed Triangle index to start with
00620 // @return Triangle id if successful, -1 otherwhile
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 // Finds all tricircles specified point belongs to.
00654 //
00655 // @param d Delaunay triangulation
00656 // @param p Point to be mapped
00657 // @param n Pointer to the number of tricircles within `d' containing `p'
00658 //          (output)
00659 // @param out Pointer to an array of indices of the corresponding triangles
00660 //            [n] (output)
00661 //
00662 // There is a standard search procedure involving search through triangle
00663 // neighbours (not through vertex neighbours). It must be a bit faster due to
00664 // the smaller number of triangle neighbours (3 per triangle) but can fail
00665 // for a point outside convex hall.
00666 //
00667 // We may wish to modify this procedure in future: first check if the point
00668 // is inside the convex hall, and depending on that use one of the two
00669 // search algorithms. It not 100% clear though whether this will lead to a
00670 // substantial speed gains because of the check on convex hall involved.
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     // It is important to have a reasonable seed here. If the last search
00684     // was successful -- start with the last found tricircle, otherwhile (i)
00685     // try to find a triangle containing (x,y); if fails then (ii) check
00686     // tricircles from the last search; if fails then (iii) make linear
00687     // search through all tricircles
00688     //
00689     if ( d->first_id < 0 || !circle_contains( &d->circles[d->first_id], p ) )
00690     {
00691         //
00692         // if any triangle contains (x,y) -- start with this triangle
00693         //
00694         d->first_id = delaunay_xytoi( d, p, d->first_id );
00695 
00696         //
00697         // if no triangle contains (x,y), there still is a chance that it is
00698         // inside some of circumcircles
00699         //
00700         if ( d->first_id < 0 )
00701         {
00702             int nn  = d->t_out->n;
00703             int tid = -1;
00704 
00705             //
00706             // first check results of the last search
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             // if unsuccessful, search through all circles
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;     // failed
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     // main cycle
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 }

Generated on Wed Oct 12 2011 20:42:21 for PLplot by  doxygen 1.7.1