Graphviz  2.29.20120523.0446
lib/neatogen/delaunay.c
Go to the documentation of this file.
00001 /* $Id$ $Revision$ */
00002 /* vim:set shiftwidth=4 ts=8: */
00003 
00004 /*************************************************************************
00005  * Copyright (c) 2011 AT&T Intellectual Property 
00006  * All rights reserved. This program and the accompanying materials
00007  * are made available under the terms of the Eclipse Public License v1.0
00008  * which accompanies this distribution, and is available at
00009  * http://www.eclipse.org/legal/epl-v10.html
00010  *
00011  * Contributors: See CVS logs. Details at http://www.graphviz.org/
00012  *************************************************************************/
00013 
00014 #ifdef HAVE_CONFIG_H
00015 #include "config.h"
00016 #endif
00017 
00018  /* until we can include cgraph.h or something else */
00019 typedef enum { AGWARN, AGERR, AGMAX, AGPREV } agerrlevel_t;
00020 extern int agerr(agerrlevel_t level, char *fmt, ...);
00021 
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <string.h>
00025 #include <math.h>
00026 #include "delaunay.h"
00027 #include "memory.h"
00028 #include "logic.h"
00029 
00030 #if HAVE_GTS
00031 #include <gts.h>
00032 
00033 static gboolean triangle_is_hole(GtsTriangle * t)
00034 {
00035     GtsEdge *e1, *e2, *e3;
00036     GtsVertex *v1, *v2, *v3;
00037     gboolean ret;
00038 
00039     gts_triangle_vertices_edges(t, NULL, &v1, &v2, &v3, &e1, &e2, &e3);
00040 
00041     if ((GTS_IS_CONSTRAINT(e1) && GTS_SEGMENT(e1)->v1 != v1) ||
00042         (GTS_IS_CONSTRAINT(e2) && GTS_SEGMENT(e2)->v1 != v2) ||
00043         (GTS_IS_CONSTRAINT(e3) && GTS_SEGMENT(e3)->v1 != v3))
00044         ret = TRUE;
00045     else ret = FALSE;
00046     return ret;
00047 }
00048 
00049 static guint delaunay_remove_holes(GtsSurface * surface)
00050 {
00051     return gts_surface_foreach_face_remove(surface,
00052                                     (GtsFunc) triangle_is_hole, NULL);
00053 }
00054 
00055 /* Derived classes for vertices and faces so we can assign integer ids
00056  * to make it easier to identify them. In particular, this allows the
00057  * segments and faces to refer to vertices using the order in which
00058  * they were passed in. 
00059  */
00060 typedef struct {
00061     GtsVertex v;
00062     int idx;
00063 } GVertex;
00064 
00065 typedef struct {
00066     GtsVertexClass parent_class;
00067 } GVertexClass;
00068 
00069 static GVertexClass *g_vertex_class(void)
00070 {
00071     static GVertexClass *klass = NULL;
00072 
00073     if (klass == NULL) {
00074         GtsObjectClassInfo vertex_info = {
00075             "GVertex",
00076             sizeof(GVertex),
00077             sizeof(GVertexClass),
00078             (GtsObjectClassInitFunc) NULL,
00079             (GtsObjectInitFunc) NULL,
00080             (GtsArgSetFunc) NULL,
00081             (GtsArgGetFunc) NULL
00082         };
00083         klass = gts_object_class_new(GTS_OBJECT_CLASS(gts_vertex_class()),
00084                                      &vertex_info);
00085     }
00086 
00087     return klass;
00088 }
00089 
00090 typedef struct {
00091     GtsFace v;
00092     int idx;
00093 } GFace;
00094 
00095 typedef struct {
00096     GtsFaceClass parent_class;
00097 } GFaceClass;
00098 
00099 static GFaceClass *g_face_class(void)
00100 {
00101     static GFaceClass *klass = NULL;
00102 
00103     if (klass == NULL) {
00104         GtsObjectClassInfo face_info = {
00105             "GFace",
00106             sizeof(GFace),
00107             sizeof(GFaceClass),
00108             (GtsObjectClassInitFunc) NULL,
00109             (GtsObjectInitFunc) NULL,
00110             (GtsArgSetFunc) NULL,
00111             (GtsArgGetFunc) NULL
00112         };
00113         klass = gts_object_class_new(GTS_OBJECT_CLASS(gts_face_class()),
00114                                      &face_info);
00115     }
00116 
00117     return klass;
00118 }
00119 
00120 /* destroy:
00121  * Destroy each edge using v, then destroy v
00122  */
00123 static void
00124 destroy (GtsVertex* v)
00125 {
00126     GSList * i;
00127 
00128     i = v->segments;
00129     while (i) {
00130         GSList * next = i->next;
00131         gts_object_destroy (i->data);
00132         i = next;
00133     }
00134     g_assert (v->segments == NULL);
00135     gts_object_destroy(GTS_OBJECT(v));
00136 }
00137 
00138 /* tri:
00139  * Main entry point to using GTS for triangulation.
00140  * Input is npt points with x and y coordinates stored either separately
00141  * in x[] and y[] (sepArr != 0) or consecutively in x[] (sepArr == 0).
00142  * Optionally, the input can include nsegs line segments, whose endpoint
00143  * indices are supplied in segs[2*i] and segs[2*i+1] yielding a constrained
00144  * triangulation.
00145  *
00146  * The return value is the corresponding gts surface, which can be queries for
00147  * the triangles and line segments composing the triangulation.
00148  */
00149 static GtsSurface*
00150 tri(double *x, double *y, int npt, int *segs, int nsegs, int sepArr)
00151 {
00152     int i;
00153     GtsSurface *surface;
00154     GVertex **vertices = N_GNEW(npt, GVertex *);
00155     GtsEdge **edges = N_GNEW(nsegs, GtsEdge*);
00156     GSList *list = NULL;
00157     GtsVertex *v1, *v2, *v3;
00158     GtsTriangle *t;
00159     GtsVertexClass *vcl = (GtsVertexClass *) g_vertex_class();
00160     GtsEdgeClass *ecl = GTS_EDGE_CLASS (gts_constraint_class ());
00161 
00162     if (sepArr) {
00163         for (i = 0; i < npt; i++) {
00164             GVertex *p = (GVertex *) gts_vertex_new(vcl, x[i], y[i], 0);
00165             p->idx = i;
00166             vertices[i] = p;
00167         }
00168     }
00169     else {
00170         for (i = 0; i < npt; i++) {
00171             GVertex *p = (GVertex *) gts_vertex_new(vcl, x[2*i], x[2*i+1], 0);
00172             p->idx = i;
00173             vertices[i] = p;
00174         }
00175     }
00176 
00177     /* N.B. Edges need to be created here, presumably before the
00178      * the vertices are added to the face. In particular, they cannot
00179      * be added created and added vi gts_delaunay_add_constraint() below.
00180      */
00181     for (i = 0; i < nsegs; i++) {
00182         edges[i] = gts_edge_new(ecl,
00183                  (GtsVertex *) (vertices[ segs[ 2 * i]]),
00184                  (GtsVertex *) (vertices[ segs[ 2 * i + 1]]));
00185     }
00186 
00187     for (i = 0; i < npt; i++)
00188         list = g_slist_prepend(list, vertices[i]);
00189     t = gts_triangle_enclosing(gts_triangle_class(), list, 100.);
00190     g_slist_free(list);
00191 
00192     gts_triangle_vertices(t, &v1, &v2, &v3);
00193 
00194     surface = gts_surface_new(gts_surface_class(),
00195                                   (GtsFaceClass *) g_face_class(),
00196                                   gts_edge_class(),
00197                                   gts_vertex_class());
00198     gts_surface_add_face(surface, gts_face_new(gts_face_class(),
00199                                                t->e1, t->e2, t->e3));
00200 
00201     for (i = 0; i < npt; i++) {
00202         GtsVertex *v1 = (GtsVertex *) vertices[i];
00203         GtsVertex *v = gts_delaunay_add_vertex(surface, v1, NULL);
00204 
00205         /* if v != NULL, it is a previously added pt with the same
00206          * coordinates as v1, in which case we replace v1 with v
00207          */
00208         if (v) {
00209             /* agerr (AGWARN, "Duplicate point %d %d\n", i, ((GVertex*)v)->idx); */
00210             gts_vertex_replace (v1, v);
00211         }
00212     }
00213 
00214     for (i = 0; i < nsegs; i++) {
00215         gts_delaunay_add_constraint(surface,GTS_CONSTRAINT(edges[i]));
00216     }
00217 
00218     /* destroy enclosing triangle */
00219     gts_allow_floating_vertices = TRUE;
00220     gts_allow_floating_edges = TRUE;
00221 /*
00222     gts_object_destroy(GTS_OBJECT(v1));
00223     gts_object_destroy(GTS_OBJECT(v2));
00224     gts_object_destroy(GTS_OBJECT(v3));
00225 */
00226     destroy(v1);
00227     destroy(v2);
00228     destroy(v3);
00229     gts_allow_floating_edges = FALSE;
00230     gts_allow_floating_vertices = FALSE;
00231 
00232     if (nsegs)
00233         delaunay_remove_holes(surface);
00234 
00235     free (edges);
00236     free(vertices);
00237     return surface;
00238 }
00239 
00240 typedef struct {
00241     int n;
00242     v_data *delaunay;
00243 } estats;
00244     
00245 static void cnt_edge (GtsSegment * e, estats* sp)
00246 {
00247     sp->n++;
00248     if (sp->delaunay) {
00249         sp->delaunay[((GVertex*)(e->v1))->idx].nedges++;
00250         sp->delaunay[((GVertex*)(e->v2))->idx].nedges++;
00251     }
00252 }
00253 
00254 static void
00255 edgeStats (GtsSurface* s, estats* sp)
00256 {
00257     gts_surface_foreach_edge (s, (GtsFunc) cnt_edge, sp);
00258 }
00259 
00260 static void add_edge (GtsSegment * e, v_data* delaunay)
00261 {
00262     int source = ((GVertex*)(e->v1))->idx;
00263     int dest = ((GVertex*)(e->v2))->idx;
00264 
00265     delaunay[source].edges[delaunay[source].nedges++] = dest;
00266     delaunay[dest].edges[delaunay[dest].nedges++] = source;
00267 }
00268 
00269 v_data *delaunay_triangulation(double *x, double *y, int n)
00270 {
00271     v_data *delaunay;
00272     GtsSurface* s = tri(x, y, n, NULL, 0, 1);
00273     int i, nedges;
00274     int* edges;
00275     estats stats;
00276 
00277     if (!s) return NULL;
00278 
00279     delaunay = N_GNEW(n, v_data);
00280 
00281     for (i = 0; i < n; i++) {
00282         delaunay[i].ewgts = NULL;
00283         delaunay[i].nedges = 1;
00284     }
00285 
00286     stats.n = 0;
00287     stats.delaunay = delaunay;
00288     edgeStats (s, &stats);
00289     nedges = stats.n;
00290     edges = N_GNEW(2 * nedges + n, int);
00291 
00292     for (i = 0; i < n; i++) {
00293         delaunay[i].edges = edges;
00294         edges += delaunay[i].nedges;
00295         delaunay[i].edges[0] = i;
00296         delaunay[i].nedges = 1;
00297     }
00298     gts_surface_foreach_edge (s, (GtsFunc) add_edge, delaunay);
00299 
00300     gts_object_destroy (GTS_OBJECT (s));
00301 
00302     return delaunay;
00303 }
00304 
00305 typedef struct {
00306     int n;
00307     int* edges;
00308 } estate;
00309 
00310 static void addEdge (GtsSegment * e, estate* es)
00311 {
00312     int source = ((GVertex*)(e->v1))->idx;
00313     int dest = ((GVertex*)(e->v2))->idx;
00314 
00315     es->edges[2*(es->n)] = source;
00316     es->edges[2*(es->n)+1] = dest;
00317     es->n += 1;
00318 }
00319 
00320 /* If qsort_r ever becomes standardized, this should be used
00321  * instead of having a global variable.
00322  */
00323 static double* _vals;
00324 typedef int (*qsort_cmpf) (const void *, const void *);
00325 
00326 static int 
00327 vcmp (int* a, int* b)
00328 {
00329     double va = _vals[*a];
00330     double vb = _vals[*b];
00331 
00332     if (va < vb) return -1; 
00333     else if (va > vb) return 1; 
00334     else return 0;
00335 }
00336 
00337 /* delaunay_tri:
00338  * Given n points whose coordinates are in the x[] and y[]
00339  * arrays, compute a Delaunay triangulation of the points.
00340  * The number of edges in the triangulation is returned in pnedges.
00341  * The return value itself is an array e of 2*(*pnedges) integers,
00342  * with edge i having points whose indices are e[2*i] and e[2*i+1].
00343  *
00344  * If the points are collinear, GTS fails with 0 edges.
00345  * In this case, we sort the points by x coordinates (or y coordinates
00346  * if the points form a vertical line). We then return a "triangulation"
00347  * consisting of the n-1 pairs of adjacent points.
00348  */
00349 int *delaunay_tri(double *x, double *y, int n, int* pnedges)
00350 {
00351     GtsSurface* s = tri(x, y, n, NULL, 0, 1);
00352     int nedges;
00353     int* edges;
00354     estats stats;
00355     estate state;
00356 
00357     if (!s) return NULL;
00358 
00359     stats.n = 0;
00360     stats.delaunay = NULL;
00361     edgeStats (s, &stats);
00362     *pnedges = nedges = stats.n;
00363 
00364     if (nedges) {
00365         edges = N_GNEW(2 * nedges, int);
00366         state.n = 0;
00367         state.edges = edges;
00368         gts_surface_foreach_edge (s, (GtsFunc) addEdge, &state);
00369     }
00370     else {
00371         int* vs = N_GNEW(n, int);
00372         int* ip;
00373         int i, hd, tl;
00374 
00375         *pnedges = nedges = n-1;
00376         ip = edges = N_GNEW(2 * nedges, int);
00377 
00378         for (i = 0; i < n; i++)
00379             vs[i] = i;
00380 
00381         if (x[0] == x[1])  /* vertical line */ 
00382             _vals = y;
00383         else              
00384             _vals = x;
00385         qsort (vs, n, sizeof(int), (qsort_cmpf)vcmp);
00386 
00387         tl = vs[0];
00388         for (i = 1; i < n; i++) {
00389             hd = vs[i];
00390             *ip++ = tl;
00391             *ip++ = hd;
00392             tl = hd;
00393         }
00394 
00395         free (vs);
00396     }
00397 
00398     gts_object_destroy (GTS_OBJECT (s));
00399 
00400     return edges;
00401 }
00402 
00403 static void cntFace (GFace* fp, int* ip)
00404 {
00405     fp->idx = *ip;
00406     *ip += 1;
00407 }
00408 
00409 typedef struct {
00410     GtsSurface* s;
00411     int* faces;
00412     int* neigh;
00413 } fstate;
00414 
00415 typedef struct {
00416     int nneigh;
00417     int* neigh;
00418 } ninfo;
00419 
00420 static void addNeighbor (GFace* f, ninfo* es)
00421 {
00422     es->neigh[es->nneigh] = f->idx;
00423     es->nneigh++;
00424 }
00425 
00426 static void addFace (GFace* f, fstate* es)
00427 {
00428     int i, myid = f->idx;
00429     int* ip = es->faces + 3*myid;
00430     int* neigh = es->neigh + 3*myid;
00431     ninfo ni;
00432     GtsVertex *v1, *v2, *v3;
00433 
00434     gts_triangle_vertices (&f->v.triangle, &v1, &v2, &v3);
00435     *ip++ = ((GVertex*)(v1))->idx;
00436     *ip++ = ((GVertex*)(v2))->idx;
00437     *ip++ = ((GVertex*)(v3))->idx;
00438 
00439     ni.nneigh = 0;
00440     ni.neigh = neigh;
00441     gts_face_foreach_neighbor ((GtsFace*)f, 0, (GtsFunc) addNeighbor, &ni);
00442     for (i = ni.nneigh; i < 3; i++)
00443         neigh[i] = -1;
00444 }
00445 
00446 static void addTri (GFace* f, fstate* es)
00447 {
00448     int myid = f->idx;
00449     int* ip = es->faces + 3*myid;
00450     GtsVertex *v1, *v2, *v3;
00451 
00452     gts_triangle_vertices (&f->v.triangle, &v1, &v2, &v3);
00453     *ip++ = ((GVertex*)(v1))->idx;
00454     *ip++ = ((GVertex*)(v2))->idx;
00455     *ip++ = ((GVertex*)(v3))->idx;
00456 }
00457 
00458 /* mkSurface:
00459  * Given n points whose coordinates are in x[] and y[], and nsegs line
00460  * segments whose end point indices are given in segs, return a surface
00461  * corresponding the constrained Delaunay triangulation.
00462  * The surface records the line segments, the triangles, and the neighboring
00463  * triangles.
00464  */
00465 surface_t* 
00466 mkSurface (double *x, double *y, int n, int* segs, int nsegs)
00467 {
00468     GtsSurface* s = tri(x, y, n, segs, nsegs, 1);
00469     estats stats;
00470     estate state;
00471     fstate statf;
00472     surface_t* sf;
00473     int nfaces = 0;
00474     int* faces; 
00475     int* neigh; 
00476 
00477     if (!s) return NULL;
00478 
00479     sf = GNEW(surface_t);
00480     stats.n = 0;
00481     stats.delaunay = NULL;
00482     edgeStats (s, &stats);
00483     nsegs = stats.n;
00484     segs = N_GNEW(2 * nsegs, int);
00485 
00486     state.n = 0;
00487     state.edges = segs;
00488     gts_surface_foreach_edge (s, (GtsFunc) addEdge, &state);
00489 
00490     gts_surface_foreach_face (s, (GtsFunc) cntFace, &nfaces);
00491 
00492     faces = N_GNEW(3 * nfaces, int);
00493     neigh = N_GNEW(3 * nfaces, int);
00494 
00495     statf.faces = faces;
00496     statf.neigh = neigh;
00497     gts_surface_foreach_face (s, (GtsFunc) addFace, &statf);
00498 
00499     sf->nedges = nsegs;
00500     sf->edges = segs;
00501     sf->nfaces = nfaces;
00502     sf->faces = faces;
00503     sf->neigh = neigh;
00504 
00505     gts_object_destroy (GTS_OBJECT (s));
00506 
00507     return sf;
00508 }
00509 
00510 /* get_triangles:
00511  * Given n points whose coordinates are stored as (x[2*i],x[2*i+1]),
00512  * compute a Delaunay triangulation of the points.
00513  * The number of triangles in the triangulation is returned in tris.
00514  * The return value t is an array of 3*(*tris) integers,
00515  * with triangle i having points whose indices are t[3*i], t[3*i+1] and t[3*i+2].
00516  */
00517 int* 
00518 get_triangles (double *x, int n, int* tris)
00519 {
00520     GtsSurface* s;
00521     int nfaces = 0;
00522     fstate statf;
00523 
00524     if (n <= 2) return NULL;
00525 
00526     s = tri(x, NULL, n, NULL, 0, 0);
00527     if (!s) return NULL;
00528 
00529     gts_surface_foreach_face (s, (GtsFunc) cntFace, &nfaces);
00530     statf.faces = N_GNEW(3 * nfaces, int);
00531     gts_surface_foreach_face (s, (GtsFunc) addTri, &statf);
00532 
00533     gts_object_destroy (GTS_OBJECT (s));
00534 
00535     *tris = nfaces;
00536     return statf.faces;
00537 }
00538 
00539 void 
00540 freeSurface (surface_t* s)
00541 {
00542     free (s->edges);
00543     free (s->faces);
00544     free (s->neigh);
00545 }
00546 #elif HAVE_TRIANGLE
00547 #define TRILIBRARY
00548 #include "triangle.c"
00549 #include "assert.h"
00550 #include "general.h"
00551 
00552 int*
00553 get_triangles (double *x, int n, int* tris)
00554 {
00555     struct triangulateio in, mid, vorout;
00556     int i;
00557 
00558     if (n <= 2) return NULL;
00559 
00560     in.numberofpoints = n;
00561     in.numberofpointattributes = 0;
00562     in.pointlist = (REAL *) N_GNEW(in.numberofpoints * 2, REAL);
00563 
00564     for (i = 0; i < n; i++){
00565         in.pointlist[i*2] = x[i*2];
00566         in.pointlist[i*2 + 1] = x[i*2 + 1];
00567     }
00568     in.pointattributelist = NULL;
00569     in.pointmarkerlist = NULL;
00570     in.numberofsegments = 0;
00571     in.numberofholes = 0;
00572     in.numberofregions = 0;
00573     in.regionlist = NULL;
00574     mid.pointlist = (REAL *) NULL;            /* Not needed if -N switch used. */
00575     mid.pointattributelist = (REAL *) NULL;
00576     mid.pointmarkerlist = (int *) NULL; /* Not needed if -N or -B switch used. */
00577     mid.trianglelist = (int *) NULL;          /* Not needed if -E switch used. */
00578     mid.triangleattributelist = (REAL *) NULL;
00579     mid.neighborlist = (int *) NULL;         /* Needed only if -n switch used. */
00580     mid.segmentlist = (int *) NULL;
00581     mid.segmentmarkerlist = (int *) NULL;
00582     mid.edgelist = (int *) NULL;             /* Needed only if -e switch used. */
00583     mid.edgemarkerlist = (int *) NULL;   /* Needed if -e used and -B not used. */
00584     vorout.pointlist = (REAL *) NULL;        /* Needed only if -v switch used. */
00585     vorout.pointattributelist = (REAL *) NULL;
00586     vorout.edgelist = (int *) NULL;          /* Needed only if -v switch used. */
00587     vorout.normlist = (REAL *) NULL;         /* Needed only if -v switch used. */
00588 
00589     /* Triangulate the points.  Switches are chosen to read and write a  */
00590     /*   PSLG (p), preserve the convex hull (c), number everything from  */
00591     /*   zero (z), assign a regional attribute to each element (A), and  */
00592     /*   produce an edge list (e), a Voronoi diagram (v), and a triangle */
00593     /*   neighbor list (n).                                              */
00594 
00595     triangulate("Qenv", &in, &mid, &vorout);
00596     assert (mid.numberofcorners == 3);
00597 
00598     *tris = mid.numberoftriangles;
00599     
00600     FREE(in.pointlist);
00601     FREE(in.pointattributelist);
00602     FREE(in.pointmarkerlist);
00603     FREE(in.regionlist);
00604     FREE(mid.pointlist);
00605     FREE(mid.pointattributelist);
00606     FREE(mid.pointmarkerlist);
00607     FREE(mid.triangleattributelist);
00608     FREE(mid.neighborlist);
00609     FREE(mid.segmentlist);
00610     FREE(mid.segmentmarkerlist);
00611     FREE(mid.edgelist);
00612     FREE(mid.edgemarkerlist);
00613     FREE(vorout.pointlist);
00614     FREE(vorout.pointattributelist);
00615     FREE(vorout.edgelist);
00616     FREE(vorout.normlist);
00617 
00618     return mid.trianglelist;
00619 }
00620 
00621 // maybe it should be replaced by RNG - relative neigborhood graph, or by GG - gabriel graph
00622 int* 
00623 delaunay_tri (double *x, double *y, int n, int* nedges)
00624 {
00625     struct triangulateio in, out;
00626     int i;
00627 
00628     in.pointlist = N_GNEW(2 * n, REAL);
00629     for (i = 0; i < n; i++) {
00630         in.pointlist[2 * i] = x[i];
00631         in.pointlist[2 * i + 1] = y[i];
00632     }
00633 
00634     in.pointattributelist = NULL;
00635     in.pointmarkerlist = NULL;
00636     in.numberofpoints = n;
00637     in.numberofpointattributes = 0;
00638     in.trianglearealist = NULL;
00639     in.triangleattributelist = NULL;
00640     in.numberoftriangleattributes = 0;
00641     in.neighborlist = NULL;
00642     in.segmentlist = NULL;
00643     in.segmentmarkerlist = NULL;
00644     in.holelist = NULL;
00645     in.numberofholes = 0;
00646     in.regionlist = NULL;
00647     in.edgelist = NULL;
00648     in.edgemarkerlist = NULL;
00649     in.normlist = NULL;
00650 
00651     out.pointattributelist = NULL;
00652     out.pointmarkerlist = NULL;
00653     out.numberofpoints = n;
00654     out.numberofpointattributes = 0;
00655     out.trianglearealist = NULL;
00656     out.triangleattributelist = NULL;
00657     out.numberoftriangleattributes = 0;
00658     out.neighborlist = NULL;
00659     out.segmentlist = NULL;
00660     out.segmentmarkerlist = NULL;
00661     out.holelist = NULL;
00662     out.numberofholes = 0;
00663     out.regionlist = NULL;
00664     out.edgelist = NULL;
00665     out.edgemarkerlist = NULL;
00666     out.normlist = NULL;
00667 
00668     triangulate("zQNEeB", &in, &out, NULL);
00669 
00670     *nedges = out.numberofedges;
00671     free (in.pointlist);
00672     free (in.pointattributelist);
00673     free (in.pointmarkerlist);
00674     free (in.trianglearealist);
00675     free (in.triangleattributelist);
00676     free (in.neighborlist);
00677     free (in.segmentlist);
00678     free (in.segmentmarkerlist);
00679     free (in.holelist);
00680     free (in.regionlist);
00681     free (in.edgemarkerlist);
00682     free (in.normlist);
00683     free (out.pointattributelist);
00684     free (out.pointmarkerlist);
00685     free (out.trianglearealist);
00686     free (out.triangleattributelist);
00687     free (out.neighborlist);
00688     free (out.segmentlist);
00689     free (out.segmentmarkerlist);
00690     free (out.holelist);
00691     free (out.regionlist);
00692     free (out.edgemarkerlist);
00693     free (out.normlist);
00694     return out.edgelist;
00695 }
00696 
00697 v_data *delaunay_triangulation(double *x, double *y, int n)
00698 {
00699     v_data *delaunay;
00700     int nedges;
00701     int *edges;
00702     int source, dest;
00703     int* edgelist = delaunay_tri (x, y, n, &nedges);
00704     int i;
00705 
00706     delaunay = N_GNEW(n, v_data);
00707     edges = N_GNEW(2 * nedges + n, int);
00708 
00709     for (i = 0; i < n; i++) {
00710         delaunay[i].ewgts = NULL;
00711         delaunay[i].nedges = 1;
00712     }
00713 
00714     for (i = 0; i < 2 * nedges; i++)
00715         delaunay[edgelist[i]].nedges++;
00716 
00717     for (i = 0; i < n; i++) {
00718         delaunay[i].edges = edges;
00719         edges += delaunay[i].nedges;
00720         delaunay[i].edges[0] = i;
00721         delaunay[i].nedges = 1;
00722     }
00723     for (i = 0; i < nedges; i++) {
00724         source = edgelist[2 * i];
00725         dest = edgelist[2 * i + 1];
00726         delaunay[source].edges[delaunay[source].nedges++] = dest;
00727         delaunay[dest].edges[delaunay[dest].nedges++] = source;
00728     }
00729 
00730     free(edgelist);
00731     return delaunay;
00732 }
00733 
00734 surface_t* 
00735 mkSurface (double *x, double *y, int n, int* segs, int nsegs)
00736 {
00737     agerr (AGERR, "mkSurface not yet implemented using Triangle library\n");
00738     assert (0);
00739     return 0;
00740 }
00741 void 
00742 freeSurface (surface_t* s)
00743 {
00744     agerr (AGERR, "freeSurface not yet implemented using Triangle library\n");
00745     assert (0);
00746 }
00747 #else
00748 static char* err = "Graphviz built without any triangulation library\n";
00749 int* get_triangles (double *x, int n, int* tris)
00750 {
00751     agerr(AGERR, "get_triangles: %s\n", err);
00752     return 0;
00753 }
00754 v_data *delaunay_triangulation(double *x, double *y, int n)
00755 {
00756     agerr(AGERR, "delaunay_triangulation: %s\n", err);
00757     return 0;
00758 }
00759 int *delaunay_tri(double *x, double *y, int n, int* nedges)
00760 {
00761     agerr(AGERR, "delaunay_tri: %s\n", err);
00762     return 0;
00763 }
00764 surface_t* 
00765 mkSurface (double *x, double *y, int n, int* segs, int nsegs)
00766 {
00767     agerr(AGERR, "mkSurface: %s\n", err);
00768     return 0;
00769 }
00770 void 
00771 freeSurface (surface_t* s)
00772 {
00773     agerr (AGERR, "freeSurface: %s\n", err);
00774 }
00775 #endif
00776 
00777 static void remove_edge(v_data * graph, int source, int dest)
00778 {
00779     int i;
00780     for (i = 1; i < graph[source].nedges; i++) {
00781         if (graph[source].edges[i] == dest) {
00782             graph[source].edges[i] =
00783                 graph[source].edges[--graph[source].nedges];
00784             break;
00785         }
00786     }
00787 }
00788 
00789 v_data *UG_graph(double *x, double *y, int n, int accurate_computation)
00790 {
00791     v_data *delaunay;
00792     int i;
00793     double dist_ij, dist_ik, dist_jk, x_i, y_i, x_j, y_j;
00794     int j, k, neighbor_j, neighbor_k;
00795     int removed;
00796 
00797     if (n == 2) {
00798         int *edges = N_GNEW(4, int);
00799         delaunay = N_GNEW(n, v_data);
00800         delaunay[0].ewgts = NULL;
00801         delaunay[0].edges = edges;
00802         delaunay[0].nedges = 2;
00803         delaunay[0].edges[0] = 0;
00804         delaunay[0].edges[1] = 1;
00805         delaunay[1].edges = edges + 2;
00806         delaunay[1].ewgts = NULL;
00807         delaunay[1].nedges = 2;
00808         delaunay[1].edges[0] = 1;
00809         delaunay[1].edges[1] = 0;
00810         return delaunay;
00811     } else if (n == 1) {
00812         int *edges = N_GNEW(1, int);
00813         delaunay = N_GNEW(n, v_data);
00814         delaunay[0].ewgts = NULL;
00815         delaunay[0].edges = edges;
00816         delaunay[0].nedges = 1;
00817         delaunay[0].edges[0] = 0;
00818         return delaunay;
00819     }
00820 
00821     delaunay = delaunay_triangulation(x, y, n);
00822 
00823     if (accurate_computation) {
00824         for (i = 0; i < n; i++) {
00825             x_i = x[i];
00826             y_i = y[i];
00827             for (j = 1; j < delaunay[i].nedges;) {
00828                 neighbor_j = delaunay[i].edges[j];
00829                 if (neighbor_j < i) {
00830                     j++;
00831                     continue;
00832                 }
00833                 x_j = x[neighbor_j];
00834                 y_j = y[neighbor_j];
00835                 dist_ij =
00836                     (x_j - x_i) * (x_j - x_i) + (y_j - y_i) * (y_j - y_i);
00837                 removed = FALSE;
00838                 for (k = 0; k < n && !removed; k++) {
00839                     dist_ik =
00840                         (x[k] - x_i) * (x[k] - x_i) + (y[k] -
00841                                                        y_i) * (y[k] - y_i);
00842                     if (dist_ik < dist_ij) {
00843                         dist_jk =
00844                             (x[k] - x_j) * (x[k] - x_j) + (y[k] -
00845                                                            y_j) * (y[k] -
00846                                                                    y_j);
00847                         if (dist_jk < dist_ij) {
00848                             // remove the edge beteween i and neighbor j
00849                             delaunay[i].edges[j] =
00850                                 delaunay[i].edges[--delaunay[i].nedges];
00851                             remove_edge(delaunay, neighbor_j, i);
00852                             removed = TRUE;
00853                         }
00854                     }
00855                 }
00856                 if (!removed) {
00857                     j++;
00858                 }
00859             }
00860         }
00861     } else {
00862         // remove all edges v-u if there is w, neighbor of u or v, that is closer to both u and v than dist(u,v)
00863         for (i = 0; i < n; i++) {
00864             x_i = x[i];
00865             y_i = y[i];
00866             for (j = 1; j < delaunay[i].nedges;) {
00867                 neighbor_j = delaunay[i].edges[j];
00868                 x_j = x[neighbor_j];
00869                 y_j = y[neighbor_j];
00870                 dist_ij =
00871                     (x_j - x_i) * (x_j - x_i) + (y_j - y_i) * (y_j - y_i);
00872                 // now look at i'th neighbors to see whether there is a node in the "forbidden region"
00873                 // we will also go through neighbor_j's neighbors when we traverse the edge from its other side
00874                 removed = FALSE;
00875                 for (k = 1; k < delaunay[i].nedges && !removed; k++) {
00876                     neighbor_k = delaunay[i].edges[k];
00877                     dist_ik =
00878                         (x[neighbor_k] - x_i) * (x[neighbor_k] - x_i) +
00879                         (y[neighbor_k] - y_i) * (y[neighbor_k] - y_i);
00880                     if (dist_ik < dist_ij) {
00881                         dist_jk =
00882                             (x[neighbor_k] - x_j) * (x[neighbor_k] - x_j) +
00883                             (y[neighbor_k] - y_j) * (y[neighbor_k] - y_j);
00884                         if (dist_jk < dist_ij) {
00885                             // remove the edge beteween i and neighbor j
00886                             delaunay[i].edges[j] =
00887                                 delaunay[i].edges[--delaunay[i].nedges];
00888                             remove_edge(delaunay, neighbor_j, i);
00889                             removed = TRUE;
00890                         }
00891                     }
00892                 }
00893                 if (!removed) {
00894                     j++;
00895                 }
00896             }
00897         }
00898     }
00899     return delaunay;
00900 }
00901 
00902 void freeGraph (v_data * graph)
00903 {
00904     if (graph != NULL) {
00905         if (graph[0].edges != NULL)
00906             free(graph[0].edges);
00907         if (graph[0].ewgts != NULL)
00908             free(graph[0].ewgts);
00909         free(graph);
00910     }
00911 }
00912 
00913 void freeGraphData(vtx_data * graph)
00914 {
00915     if (graph != NULL) {
00916         if (graph[0].edges != NULL)
00917             free(graph[0].edges);
00918         if (graph[0].ewgts != NULL)
00919             free(graph[0].ewgts);
00920 #ifdef USE_STYLES
00921         if (graph[0].styles != NULL)
00922             free(graph[0].styles);
00923 #endif
00924 #ifdef DIGCOLA
00925         if (graph[0].edists != NULL)
00926             free(graph[0].edists);
00927 #endif
00928         free(graph);
00929     }
00930 }
00931