|
Graphviz
2.29.20120523.0446
|
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
1.7.5