27static int triangle_is_hole(
void *
triangle,
void *ignored) {
31 GtsEdge *e1, *e2, *e3;
32 GtsVertex *v1, *v2, *v3;
34 gts_triangle_vertices_edges(t,
NULL, &v1, &v2, &v3, &e1, &e2, &e3);
36 if ((GTS_IS_CONSTRAINT(e1) && GTS_SEGMENT(e1)->v1 != v1) ||
37 (GTS_IS_CONSTRAINT(e2) && GTS_SEGMENT(e2)->v1 != v2) ||
38 (GTS_IS_CONSTRAINT(e3) && GTS_SEGMENT(e3)->v1 != v3))
44static unsigned delaunay_remove_holes(GtsSurface *surface) {
45 return gts_surface_foreach_face_remove(surface, triangle_is_hole,
NULL);
59static GVertex *downcast(GtsVertex *base) {
60 return (GVertex *)((
char *)base - offsetof(GVertex, v));
64static GtsVertex *upcast(GVertex *derived) {
69 GtsVertexClass parent_class;
72static GtsVertexClass *g_vertex_class(
void) {
73 static GVertexClass *klass =
NULL;
76 GtsObjectClassInfo vertex_info = {
78 .object_size =
sizeof(GVertex),
79 .class_size =
sizeof(GVertexClass),
81 klass = gts_object_class_new(GTS_OBJECT_CLASS(gts_vertex_class()),
85 return &klass->parent_class;
94 GtsFaceClass parent_class;
97static GtsFaceClass *g_face_class(
void) {
98 static GFaceClass *klass =
NULL;
101 GtsObjectClassInfo face_info = {
103 .object_size =
sizeof(GFace),
104 .class_size =
sizeof(GFaceClass),
106 klass = gts_object_class_new(GTS_OBJECT_CLASS(gts_face_class()),
110 return &klass->parent_class;
115destroy (GtsVertex* v)
121 GSList * next = i->next;
122 gts_object_destroy (i->data);
125 g_assert (v->segments ==
NULL);
126 gts_object_destroy(GTS_OBJECT(v));
140tri(
double *x,
double *y,
int npt,
int *segs,
int nsegs,
int sepArr)
144 GVertex **vertices =
gv_calloc(npt,
sizeof(GVertex *));
145 GtsEdge **edges =
gv_calloc(nsegs,
sizeof(GtsEdge *));
147 GtsVertex *v1, *v2, *v3;
149 GtsVertexClass *vcl = g_vertex_class();
150 GtsEdgeClass *ecl = GTS_EDGE_CLASS (gts_constraint_class ());
153 for (i = 0; i < npt; i++) {
154 GVertex *p = downcast(gts_vertex_new(vcl, x[i], y[i], 0));
160 for (i = 0; i < npt; i++) {
161 GVertex *p = downcast(gts_vertex_new(vcl, x[2*i], x[2*i+1], 0));
171 for (i = 0; i < nsegs; i++) {
172 edges[i] = gts_edge_new(ecl,
173 upcast(vertices[segs[2 * i]]),
174 upcast(vertices[segs[2 * i + 1]]));
177 for (i = 0; i < npt; i++)
178 list = g_slist_prepend(list, vertices[i]);
179 t = gts_triangle_enclosing(gts_triangle_class(), list, 100.);
182 gts_triangle_vertices(t, &v1, &v2, &v3);
184 surface = gts_surface_new(gts_surface_class(), g_face_class(),
185 gts_edge_class(), gts_vertex_class());
186 gts_surface_add_face(surface, gts_face_new(gts_face_class(),
187 t->e1, t->e2, t->e3));
189 for (i = 0; i < npt; i++) {
190 GtsVertex *v4 = upcast(vertices[i]);
191 GtsVertex *v = gts_delaunay_add_vertex(surface, v4,
NULL);
197 gts_vertex_replace(v4, v);
201 for (i = 0; i < nsegs; i++) {
202 gts_delaunay_add_constraint(surface,GTS_CONSTRAINT(edges[i]));
206 gts_allow_floating_vertices = TRUE;
207 gts_allow_floating_edges = TRUE;
211 gts_allow_floating_edges = FALSE;
212 gts_allow_floating_vertices = FALSE;
215 delaunay_remove_holes(surface);
227static int cnt_edge(
void *
edge,
void *stats) {
228 GtsSegment *e =
edge;
233 sp->delaunay[downcast(e->v1)->idx].
nedges++;
234 sp->delaunay[downcast(e->v2)->idx].nedges++;
241edgeStats (GtsSurface*
s, estats* sp)
243 gts_surface_foreach_edge(
s, cnt_edge, sp);
247 GtsSegment *e =
edge;
250 int source = downcast(e->v1)->idx;
251 int dest = downcast(e->v2)->idx;
253 delaunay[source].
edges[delaunay[source].
nedges++] = dest;
254 delaunay[dest].
edges[delaunay[dest].
nedges++] = source;
260 GtsSurface*
s =
tri(x, y, n,
NULL, 0, 1);
268 for (i = 0; i < n; i++) {
274 stats.delaunay = delaunay;
275 edgeStats (
s, &stats);
279 for (i = 0; i < n; i++) {
280 delaunay[i].
edges = edges;
281 edges += delaunay[i].
nedges;
282 delaunay[i].
edges[0] = i;
285 gts_surface_foreach_edge(
s,
add_edge, delaunay);
287 gts_object_destroy (GTS_OBJECT (
s));
298 GtsSegment *e =
edge;
301 int source = downcast(e->v1)->idx;
302 int dest = downcast(e->v2)->idx;
304 es->
edges[2 * es->n] = source;
305 es->edges[2 * es->n + 1] = dest;
311static int vcmp(
const void *x,
const void *y,
void *values) {
314 const double *_vals = values;
315 double va = _vals[*a];
316 double vb = _vals[*b];
318 if (va < vb)
return -1;
319 if (va > vb)
return 1;
334int *
delaunay_tri(
double *x,
double *y,
int n,
int* pnedges)
336 GtsSurface*
s =
tri(x, y, n,
NULL, 0, 1);
342 edgeStats (
s, &stats);
343 int nedges = *pnedges = stats.n;
347 gts_surface_foreach_edge(
s,
addEdge, &(estate){.edges = edges});
355 for (
int i = 0; i < n; i++)
358 gv_sort(vs, n,
sizeof(
int), vcmp, x[0] == x[1] ? y : x);
361 for (
int i = 1; i < n; i++) {
362 const int hd = vs[i];
371 gts_object_destroy (GTS_OBJECT (
s));
376static int cntFace(
void *face,
void *data) {
397static int addNeighbor(
void *face,
void *ni) {
401 es->neigh[es->nneigh] = f->idx;
407static int addFace(
void *face,
void *state) {
411 int i, myid = f->idx;
412 int* ip = es->faces + 3*myid;
413 int* neigh = es->neigh + 3*myid;
415 GtsVertex *v1, *v2, *v3;
417 gts_triangle_vertices (&f->v.triangle, &v1, &v2, &v3);
418 *ip++ = downcast(v1)->idx;
419 *ip++ = downcast(v2)->idx;
420 *ip++ = downcast(v3)->idx;
424 gts_face_foreach_neighbor((GtsFace*)f, 0, addNeighbor, &ni);
425 for (i = ni.nneigh; i < 3; i++)
431static int addTri(
void *face,
void *state) {
436 int* ip = es->faces + 3*myid;
437 GtsVertex *v1, *v2, *v3;
439 gts_triangle_vertices (&f->v.triangle, &v1, &v2, &v3);
440 *ip++ = downcast(v1)->idx;
441 *ip++ = downcast(v2)->idx;
442 *ip++ = downcast(v3)->idx;
454mkSurface (
double *x,
double *y,
int n,
int* segs,
int nsegs)
456 GtsSurface*
s =
tri(x, y, n, segs, nsegs, 1);
466 stats.delaunay =
NULL;
467 edgeStats (
s, &stats);
469 segs =
gv_calloc(2 * nsegs,
sizeof(
int));
473 gts_surface_foreach_edge(
s,
addEdge, &state);
475 gts_surface_foreach_face(
s, cntFace, &nfaces);
477 int *faces =
gv_calloc(3 * nfaces,
sizeof(
int));
478 int *neigh =
gv_calloc(3 * nfaces,
sizeof(
int));
482 gts_surface_foreach_face(
s, addFace, &statf);
490 gts_object_destroy (GTS_OBJECT (
s));
508 if (n <= 2)
return NULL;
513 gts_surface_foreach_face(
s, cntFace, &nfaces);
514 statf.faces =
gv_calloc(3 * nfaces,
sizeof(
int));
515 gts_surface_foreach_face(
s,
addTri, &statf);
517 gts_object_destroy (GTS_OBJECT (
s));
532static char*
err =
"Graphviz built without any triangulation library\n";
561mkSurface (
double *x,
double *y,
int n,
int* segs,
int nsegs)
584 for (i = 1; i <
graph[source].nedges; i++) {
585 if (
graph[source].edges[i] == dest) {
595 double dist_ij, dist_ik, dist_jk, x_i, y_i, x_j, y_j;
596 int j, k, neighbor_j, neighbor_k;
602 delaunay[0].
edges = edges;
604 delaunay[0].
edges[0] = 0;
605 delaunay[0].
edges[1] = 1;
606 delaunay[1].
edges = edges + 2;
609 delaunay[1].
edges[0] = 1;
610 delaunay[1].
edges[1] = 0;
616 delaunay[0].
edges = edges;
618 delaunay[0].
edges[0] = 0;
625 for (i = 0; i < n; i++) {
628 for (j = 1; j < delaunay[i].
nedges;) {
629 neighbor_j = delaunay[i].
edges[j];
632 dist_ij = (x_j - x_i) * (x_j - x_i) + (y_j - y_i) * (y_j - y_i);
635 bool removed =
false;
636 for (k = 1; k < delaunay[i].
nedges && !removed; k++) {
637 neighbor_k = delaunay[i].
edges[k];
638 dist_ik = (x[neighbor_k] - x_i) * (x[neighbor_k] - x_i) +
639 (y[neighbor_k] - y_i) * (y[neighbor_k] - y_i);
640 if (dist_ik < dist_ij) {
641 dist_jk = (x[neighbor_k] - x_j) * (x[neighbor_k] - x_j) +
642 (y[neighbor_k] - y_j) * (y[neighbor_k] - y_j);
643 if (dist_jk < dist_ij) {
Memory allocation wrappers that exit on failure.
static void * gv_calloc(size_t nmemb, size_t size)
static void * gv_alloc(size_t size)
abstract graph C library, Cgraph API
int * get_triangles(double *x, int n, int *tris)
void freeGraph(v_data *graph)
v_data * UG_graph(double *x, double *y, int n)
void freeGraphData(vtx_data *graph)
static v_data * delaunay_triangulation(double *x, double *y, int n)
surface_t * mkSurface(double *x, double *y, int n, int *segs, int nsegs)
static void remove_edge(v_data *graph, int source, int dest)
int * delaunay_tri(double *x, double *y, int n, int *nedges)
void freeSurface(surface_t *s)
void add_edge(edgelist *list, Agedge_t *e)
void agerrorf(const char *fmt,...)
Agraph_t * graph(char *name)
static void addEdge(edge_t *de, edge_t *e)
static tri * addTri(int i, int j, tri *oldp)
static int nedges
total no. of edges used in routing
qsort with carried along context
static void gv_sort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *, void *), void *arg)
qsort with an extra state parameter, ala qsort_r