26static int triangle_is_hole(
void *
triangle,
void *ignored) {
30 GtsEdge *e1, *e2, *e3;
31 GtsVertex *v1, *v2, *v3;
33 gts_triangle_vertices_edges(t,
NULL, &v1, &v2, &v3, &e1, &e2, &e3);
35 if ((GTS_IS_CONSTRAINT(e1) && GTS_SEGMENT(e1)->v1 != v1) ||
36 (GTS_IS_CONSTRAINT(e2) && GTS_SEGMENT(e2)->v1 != v2) ||
37 (GTS_IS_CONSTRAINT(e3) && GTS_SEGMENT(e3)->v1 != v3))
43static unsigned delaunay_remove_holes(GtsSurface *surface) {
44 return gts_surface_foreach_face_remove(surface, triangle_is_hole,
NULL);
58 GtsVertexClass parent_class;
61static GVertexClass *g_vertex_class(
void)
63 static GVertexClass *klass =
NULL;
66 GtsObjectClassInfo vertex_info = {
70 (GtsObjectClassInitFunc)
NULL,
71 (GtsObjectInitFunc)
NULL,
75 klass = gts_object_class_new(GTS_OBJECT_CLASS(gts_vertex_class()),
88 GtsFaceClass parent_class;
91static GFaceClass *g_face_class(
void)
93 static GFaceClass *klass =
NULL;
96 GtsObjectClassInfo face_info = {
100 (GtsObjectClassInitFunc)
NULL,
101 (GtsObjectInitFunc)
NULL,
102 (GtsArgSetFunc)
NULL,
105 klass = gts_object_class_new(GTS_OBJECT_CLASS(gts_face_class()),
116destroy (GtsVertex* v)
122 GSList * next = i->next;
123 gts_object_destroy (i->data);
126 g_assert (v->segments ==
NULL);
127 gts_object_destroy(GTS_OBJECT(v));
142tri(
double *x,
double *y,
int npt,
int *segs,
int nsegs,
int sepArr)
146 GVertex **vertices =
gv_calloc(npt,
sizeof(GVertex *));
147 GtsEdge **edges =
gv_calloc(nsegs,
sizeof(GtsEdge *));
149 GtsVertex *v1, *v2, *v3;
151 GtsVertexClass *vcl = (GtsVertexClass *) g_vertex_class();
152 GtsEdgeClass *ecl = GTS_EDGE_CLASS (gts_constraint_class ());
155 for (i = 0; i < npt; i++) {
156 GVertex *p = (GVertex *) gts_vertex_new(vcl, x[i], y[i], 0);
162 for (i = 0; i < npt; i++) {
163 GVertex *p = (GVertex *) gts_vertex_new(vcl, x[2*i], x[2*i+1], 0);
173 for (i = 0; i < nsegs; i++) {
174 edges[i] = gts_edge_new(ecl,
175 (GtsVertex *)vertices[segs[2 * i]],
176 (GtsVertex *)vertices[segs[2 * i + 1]]);
179 for (i = 0; i < npt; i++)
180 list = g_slist_prepend(list, vertices[i]);
181 t = gts_triangle_enclosing(gts_triangle_class(), list, 100.);
184 gts_triangle_vertices(t, &v1, &v2, &v3);
186 surface = gts_surface_new(gts_surface_class(),
187 (GtsFaceClass *) g_face_class(),
190 gts_surface_add_face(surface, gts_face_new(gts_face_class(),
191 t->e1, t->e2, t->e3));
193 for (i = 0; i < npt; i++) {
194 GtsVertex *v4 = (GtsVertex *)vertices[i];
195 GtsVertex *v = gts_delaunay_add_vertex(surface, v4,
NULL);
201 gts_vertex_replace(v4, v);
205 for (i = 0; i < nsegs; i++) {
206 gts_delaunay_add_constraint(surface,GTS_CONSTRAINT(edges[i]));
210 gts_allow_floating_vertices = TRUE;
211 gts_allow_floating_edges = TRUE;
215 gts_allow_floating_edges = FALSE;
216 gts_allow_floating_vertices = FALSE;
219 delaunay_remove_holes(surface);
231static int cnt_edge(
void *
edge,
void *stats) {
232 GtsSegment *e =
edge;
237 sp->delaunay[((GVertex*)e->v1)->idx].
nedges++;
238 sp->delaunay[((GVertex*)e->v2)->idx].nedges++;
245edgeStats (GtsSurface*
s, estats* sp)
247 gts_surface_foreach_edge(
s, cnt_edge, sp);
251 GtsSegment *e =
edge;
254 int source = ((GVertex*)e->v1)->idx;
255 int dest = ((GVertex*)e->v2)->idx;
257 delaunay[source].
edges[delaunay[source].
nedges++] = dest;
258 delaunay[dest].
edges[delaunay[dest].
nedges++] = source;
264 GtsSurface*
s =
tri(x, y, n,
NULL, 0, 1);
272 for (i = 0; i < n; i++) {
278 stats.delaunay = delaunay;
279 edgeStats (
s, &stats);
283 for (i = 0; i < n; i++) {
284 delaunay[i].
edges = edges;
285 edges += delaunay[i].
nedges;
286 delaunay[i].
edges[0] = i;
289 gts_surface_foreach_edge(
s,
add_edge, delaunay);
291 gts_object_destroy (GTS_OBJECT (
s));
302 GtsSegment *e =
edge;
305 int source = ((GVertex*)e->v1)->idx;
306 int dest = ((GVertex*)e->v2)->idx;
308 es->
edges[2 * es->n] = source;
309 es->edges[2 * es->n + 1] = dest;
315static int vcmp(
const void *x,
const void *y,
void *values) {
318 const double *_vals = values;
319 double va = _vals[*a];
320 double vb = _vals[*b];
322 if (va < vb)
return -1;
323 if (va > vb)
return 1;
339int *
delaunay_tri(
double *x,
double *y,
int n,
int* pnedges)
341 GtsSurface*
s =
tri(x, y, n,
NULL, 0, 1);
350 stats.delaunay =
NULL;
351 edgeStats (
s, &stats);
352 *pnedges =
nedges = stats.n;
358 gts_surface_foreach_edge(
s,
addEdge, &state);
368 for (i = 0; i < n; i++)
371 gv_sort(vs, n,
sizeof(
int), vcmp, x[0] == x[1] ? y : x);
374 for (i = 1; i < n; i++) {
384 gts_object_destroy (GTS_OBJECT (
s));
389static int cntFace(
void *face,
void *
data) {
410static int addNeighbor(
void *face,
void *ni) {
414 es->neigh[es->nneigh] = f->idx;
420static int addFace(
void *face,
void *state) {
424 int i, myid = f->idx;
425 int* ip = es->faces + 3*myid;
426 int* neigh = es->neigh + 3*myid;
428 GtsVertex *v1, *v2, *v3;
430 gts_triangle_vertices (&f->v.triangle, &v1, &v2, &v3);
431 *ip++ = ((GVertex*)v1)->idx;
432 *ip++ = ((GVertex*)v2)->idx;
433 *ip++ = ((GVertex*)v3)->idx;
437 gts_face_foreach_neighbor((GtsFace*)f, 0, addNeighbor, &ni);
438 for (i = ni.nneigh; i < 3; i++)
444static int addTri(
void *face,
void *state) {
449 int* ip = es->faces + 3*myid;
450 GtsVertex *v1, *v2, *v3;
452 gts_triangle_vertices (&f->v.triangle, &v1, &v2, &v3);
453 *ip++ = ((GVertex*)v1)->idx;
454 *ip++ = ((GVertex*)v2)->idx;
455 *ip++ = ((GVertex*)v3)->idx;
468mkSurface (
double *x,
double *y,
int n,
int* segs,
int nsegs)
470 GtsSurface*
s =
tri(x, y, n, segs, nsegs, 1);
480 stats.delaunay =
NULL;
481 edgeStats (
s, &stats);
483 segs =
gv_calloc(2 * nsegs,
sizeof(
int));
487 gts_surface_foreach_edge(
s,
addEdge, &state);
489 gts_surface_foreach_face(
s, cntFace, &nfaces);
491 int *faces =
gv_calloc(3 * nfaces,
sizeof(
int));
492 int *neigh =
gv_calloc(3 * nfaces,
sizeof(
int));
496 gts_surface_foreach_face(
s, addFace, &statf);
504 gts_object_destroy (GTS_OBJECT (
s));
523 if (n <= 2)
return NULL;
528 gts_surface_foreach_face(
s, cntFace, &nfaces);
529 statf.faces =
gv_calloc(3 * nfaces,
sizeof(
int));
530 gts_surface_foreach_face(
s,
addTri, &statf);
532 gts_object_destroy (GTS_OBJECT (
s));
546#elif defined(HAVE_TRIANGLE)
555 struct triangulateio mid, vorout;
558 if (n <= 2)
return NULL;
560 struct triangulateio in = {.numberofpoints = n};
561 in.pointlist =
gv_calloc(in.numberofpoints * 2,
sizeof(
REAL));
563 for (i = 0; i < n; i++){
564 in.pointlist[i*2] = x[i*2];
565 in.pointlist[i*2 + 1] = x[i*2 + 1];
567 mid.pointlist =
NULL;
568 mid.pointattributelist =
NULL;
569 mid.pointmarkerlist =
NULL;
570 mid.trianglelist =
NULL;
571 mid.triangleattributelist =
NULL;
572 mid.neighborlist =
NULL;
573 mid.segmentlist =
NULL;
574 mid.segmentmarkerlist =
NULL;
576 mid.edgemarkerlist =
NULL;
577 vorout.pointlist =
NULL;
578 vorout.pointattributelist =
NULL;
579 vorout.edgelist =
NULL;
580 vorout.normlist =
NULL;
589 assert (mid.numberofcorners == 3);
591 *
tris = mid.numberoftriangles;
594 free(in.pointattributelist);
595 free(in.pointmarkerlist);
598 free(mid.pointattributelist);
599 free(mid.pointmarkerlist);
600 free(mid.triangleattributelist);
601 free(mid.neighborlist);
602 free(mid.segmentlist);
603 free(mid.segmentmarkerlist);
605 free(mid.edgemarkerlist);
606 free(vorout.pointlist);
607 free(vorout.pointattributelist);
608 free(vorout.edgelist);
609 free(vorout.normlist);
611 return mid.trianglelist;
620 struct triangulateio in = {
624 for (i = 0; i < n; i++) {
625 in.pointlist[2 * i] = x[i];
626 in.pointlist[2 * i + 1] = y[i];
629 struct triangleio
out = {.numberofpoints = n};
635 free (in.pointattributelist);
636 free (in.pointmarkerlist);
637 free (in.trianglearealist);
638 free (in.triangleattributelist);
639 free (in.neighborlist);
640 free (in.segmentlist);
641 free (in.segmentmarkerlist);
643 free (in.regionlist);
644 free (in.edgemarkerlist);
649 free (
out.triangleattributelist);
669 for (i = 0; i < n; i++) {
674 for (i = 0; i < 2 *
nedges; i++)
677 for (i = 0; i < n; i++) {
678 delaunay[i].
edges = edges;
679 edges += delaunay[i].
nedges;
680 delaunay[i].
edges[0] = i;
683 for (i = 0; i <
nedges; i++) {
686 delaunay[source].
edges[delaunay[source].
nedges++] = dest;
687 delaunay[dest].
edges[delaunay[dest].
nedges++] = source;
695mkSurface (
double *x,
double *y,
int n,
int* segs,
int nsegs)
697 agerrorf(
"mkSurface not yet implemented using Triangle library\n");
704 agerrorf(
"freeSurface not yet implemented using Triangle library\n");
708static char*
err =
"Graphviz built without any triangulation library\n";
724mkSurface (
double *x,
double *y,
int n,
int* segs,
int nsegs)
739 for (i = 1; i <
graph[source].nedges; i++) {
740 if (
graph[source].edges[i] == dest) {
750 double dist_ij, dist_ik, dist_jk, x_i, y_i, x_j, y_j;
751 int j, k, neighbor_j, neighbor_k;
757 delaunay[0].
edges = edges;
759 delaunay[0].
edges[0] = 0;
760 delaunay[0].
edges[1] = 1;
761 delaunay[1].
edges = edges + 2;
764 delaunay[1].
edges[0] = 1;
765 delaunay[1].
edges[1] = 0;
771 delaunay[0].
edges = edges;
773 delaunay[0].
edges[0] = 0;
780 for (i = 0; i < n; i++) {
783 for (j = 1; j < delaunay[i].
nedges;) {
784 neighbor_j = delaunay[i].
edges[j];
787 dist_ij = (x_j - x_i) * (x_j - x_i) + (y_j - y_i) * (y_j - y_i);
790 bool removed =
false;
791 for (k = 1; k < delaunay[i].
nedges && !removed; k++) {
792 neighbor_k = delaunay[i].
edges[k];
793 dist_ik = (x[neighbor_k] - x_i) * (x[neighbor_k] - x_i) +
794 (y[neighbor_k] - y_i) * (y[neighbor_k] - y_i);
795 if (dist_ik < dist_ij) {
796 dist_jk = (x[neighbor_k] - x_j) * (x[neighbor_k] - x_j) +
797 (y[neighbor_k] - y_j) * (y[neighbor_k] - y_j);
798 if (dist_jk < dist_ij) {
static void out(agerrlevel_t level, const char *fmt, va_list args)
Report messages using a user-supplied or default write function.
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
static int triangulate(pointnlink_t **, size_t)
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