65static int cmpItem(
void *item1,
void *item2) {
66 const int *p1 = item1;
67 const int *p2 = item2;
68 if (p1[0] < p2[0])
return -1;
69 if (p1[0] > p2[0])
return 1;
70 if (p1[1] < p2[1])
return -1;
71 if (p1[1] > p2[1])
return 1;
80 newp->
a[0] = objp->
a[0];
81 newp->
a[1] = objp->
a[1];
89 .size = 2 *
sizeof(int),
90 .link = offsetof(
item, link),
117 for (i = 0; i < sf->
nfaces; i++) {
153 const int *p1 = pair1;
154 const int *p2 =
pair2;
178 .link = offsetof(
Ipair, link),
202 for (; tp; tp = tp->
nxttri) {
222 theta = atan2(np.
y - cp.
y, np.
x - cp.
x);
223 phi = atan2(pp.
y - cp.
y, pp.
x - cp.
x);
224 return (theta + phi) / 2.0;
230 int wa =
wind(v, w, a);
231 int wb =
wind(v, w, b);
235 return wind(v, b, w) *
wind(v, b, a) >= 0;
237 return wind(v, a, w) *
wind(v, a, b) >= 0;
279 for (
size_t i = 1; i < polys->
pn; i++) {
281 if (w.
x == v.
x && w.
y == v.
y) {
282 assert(i <= INT_MAX);
305 double d, sep, theta, sinTheta, cosTheta;
313 sinTheta = sin(theta);
314 cosTheta = cos(theta);
315 w.
x = v.
x + 100 * cosTheta;
316 w.
y = v.
y + 100 * sinTheta;
321 w.
x = v.
x + 100 * cosTheta;
322 w.
y = v.
y + 100 * sinTheta;
324 }
else if (
wind(
prev, v, w) != -1) {
327 w.
x = v.
x + 100 * cosTheta;
328 w.
y = v.
y + 100 * sinTheta;
331 if (
triPoint(trip, idx, v, w, &q)) {
342 for (i = 0; i < mult; i++) {
343 ps[i].x = v.
x + i * sep * cosTheta;
344 ps[i].y = v.
y + i * sep * sinTheta;
347 for (i = 0; i < mult; i++) {
348 ps[mult - i - 1].x = v.
x + i * sep * cosTheta;
349 ps[mult - i - 1].y = v.
y + i * sep * sinTheta;
397 p.
x = (a.
x + b.
x + c.
x) / 3.0;
398 p.
y = (a.
y + b.
y + c.
y) / 3.0;
415 bb.
LL.
x = bb.
LL.
y = DBL_MAX;
416 bb.
UR.
x = bb.
UR.
y = -DBL_MAX;
418 for (i = 0; i < npoly; i++) {
420 for (
size_t j = 0; j < obs->
pn; j++) {
443 memcpy(tris, sf->
faces, 3 * sf->
nfaces *
sizeof(
int));
457 if (p2 != *(q + 1) && p2 != *(q + 2)) {
460 }
else if (p1 == *(q + 1)) {
461 if (p2 != *q && p2 != *(q + 2)) {
464 }
else if (p1 == *(q + 2)) {
465 if (p2 != *q && p2 != *(q + 1)) {
485 sizeof(g->
edges[0]));
496 sizeof(tp->
edges[0]));
499 sizeof(hp->
edges[0]));
507 for (
size_t i = 0; i < tg->
nnodes; ++i) {
527 for (
int i = 0; i < sf->
nfaces; i++) {
532 for (
int i = 0; i < sf->
nfaces; i++) {
533 int *jp = sf->
neigh + 3 * i;
534 for (
int ne = 0; ne < 3 && (j = *jp++) != -1; ++ne) {
565 int *obsi =
gv_calloc(npoly + 1,
sizeof(
int));
566 int i, ix = 4, six = 0;
568 bb =
bbox(obsp, npoly, &npts);
571 int *segs =
gv_calloc(2 * npts,
sizeof(
int));
580 for (i = 1; i <= 4; i++) {
589 for (i = 0; i < npoly; i++) {
592 for (
size_t j = 1; j <= obs->
pn; j++) {
595 segs[six++] = ix + 1;
597 segs[six++] = obsi[i];
598 pts[ix++] = obs->
ps[j - 1];
604 double *x =
gv_calloc(npts,
sizeof(
double));
605 double *y =
gv_calloc(npts,
sizeof(
double));
606 for (i = 0; i < npts; i++) {
632 for (
size_t j = 0; j < spl.
pn / 2; j++) {
643#define EQPT(p,q) (((p).x==(q).x)&&((p).y==(q).y))
666 prv =
poly.ps[
s - 1];
669 m.
x = (nxt.
x + prv.
x)/2.0 - p.
x;
670 m.
y = (nxt.
y + prv.
y)/2.0 - p.
y;
671 const double d = hypot(m.
x, m.
y);
716 for (
size_t j = 0; j <
poly.pn; j++) {
717 medges[j].
a =
poly.ps[j];
718 medges[j].
b =
poly.ps[(j + 1) %
poly.pn];
733 const size_t pn = 2 * (pl.
pn - 1);
736 for (
size_t i = 0; i + 2 < pl.
pn; i++) {
749 for (
int i = 0; i < mult; i++) {
751 for (
size_t j = 1; j + 1 < pl.
pn; j++) {
752 poly.ps[j] = cpts[j - 1][i];
754 poly.ps[pl.
pn - 1] = eps[1];
755 for (
size_t j = 1; j + 1 < pl.
pn; j++) {
756 poly.ps[pn - j] = cpts[j - 1][i + 1];
769 for (
size_t j = 0; j <
poly.pn; j++) {
770 medges[j].
a =
poly.ps[j];
771 medges[j].
b =
poly.ps[(j + 1) %
poly.pn];
774 const bool failed_routing =
777 if (failed_routing) {
778 agwarningf(
"Could not create control points for multiple spline for edge (%s,%s)\n",
791 for (
size_t i = 0; i + 2 < pl.
pn; i++)
799#define NSMALL -0.0000000001
826 int starti = rtr->
obs[obs_id];
827 int endi = rtr->
obs[obs_id + 1];
882 for (i = starti; i < endi; i++) {
890 if (sides && !
inCone (v0, p, v1, pts[seg.
i]) && !
inCone (v0, p, v1, pts[seg.
j]) && !
raySeg(p,vr,pts[seg.
i],pts[seg.
j]))
894 assert(rtr->
tg.
nodes[v_id].
ne > 0 &&
"no edges were added");
909 for (
size_t k = 0; k < np->
ne; k++) {
911 if (ep->
t == j || ep->
h == j)
926 for (
size_t i = 0; i < trip->
poly.
pn; i++) {
927 for (tp = trip->
triMap[i]; tp; tp = nxt) {
968 for (nxt = dad[t]; nxt !=
s; nxt = dad[nxt]) {
970 assert (nxt != dad[nxt] &&
"infinite loop due to 'nxt' not changing");
979 side1[cnt1++].
v = p.
i;
981 side2[cnt2++].
v = p.
j;
984 for (nxt = dad[t]; nxt >= 0; nxt = dad[nxt]) {
986 if (p.
i == side1[cnt1 - 1].
v) {
988 addTri(side2[cnt2 - 1].v, p.
j, side1[cnt1 - 1].
ts);
990 addTri(side1[cnt1 - 1].v, p.
j, side2[cnt2 - 1].
ts);
992 addTri(side2[cnt2 - 1].v, side1[cnt1 - 1].v,
NULL);
993 side2[cnt2++].
v = p.
j;
994 }
else if (p.
i == side2[cnt2 - 1].
v) {
996 addTri(side2[cnt2 - 1].v, p.
j, side1[cnt1 - 1].
ts);
998 addTri(side1[cnt1 - 1].v, p.
j, side2[cnt2 - 1].
ts);
1000 addTri(side2[cnt2 - 1].v, side1[cnt1 - 1].v,
NULL);
1001 side1[cnt1++].
v = p.
j;
1002 }
else if (p.
j == side1[cnt1 - 1].
v) {
1003 side1[cnt1 - 1].
ts =
1004 addTri(side2[cnt2 - 1].v, p.
i, side1[cnt1 - 1].
ts);
1005 side2[cnt2 - 1].
ts =
1006 addTri(side1[cnt1 - 1].v, p.
i, side2[cnt2 - 1].
ts);
1008 addTri(side2[cnt2 - 1].v, side1[cnt1 - 1].v,
NULL);
1009 side2[cnt2++].
v = p.
i;
1011 side1[cnt1 - 1].
ts =
1012 addTri(side2[cnt2 - 1].v, p.
i, side1[cnt1 - 1].
ts);
1013 side2[cnt2 - 1].
ts =
1014 addTri(side1[cnt1 - 1].v, p.
i, side2[cnt2 - 1].
ts);
1016 addTri(side2[cnt2 - 1].v, side1[cnt1 - 1].v,
NULL);
1017 side1[cnt1++].
v = p.
i;
1021 side1[cnt1 - 1].
ts =
addTri(-2, side2[cnt2 - 1].v, side1[cnt1 - 1].ts);
1022 side2[cnt2 - 1].
ts =
addTri(-2, side1[cnt1 - 1].v, side2[cnt2 - 1].ts);
1034 for (
int i = 0; i < cnt1; i++) {
1035 vmapAdd(vmap, side1[i].v, idx);
1036 *pps++ = rtr->
ps[side1[i].
v];
1037 trim[idx++] = side1[i].
ts;
1041 for (
int i = cnt2 - 1; i >= 0; i--) {
1042 vmapAdd(vmap, side2[i].v, idx);
1043 *pps++ = rtr->
ps[side2[i].
v];
1044 trim[idx++] = side2[i].
ts;
1047 for (
size_t i = 0; i < nt + 4; i++) {
1052 ps->poly.pn = nt + 4;
1065 size_t *original_edge_count) {
1069 for (i = 0; i < ncnt; i++) {
1070 np->
ne = original_edge_count[i];
1076#define PQVTYPE double
1088#define N_VAL(pq,n) ((PPQ*)pq)->vals[n]
1089#define N_IDX(pq,n) ((PPQ*)pq)->idxs[n]
1095#define N_DAD(n) dad[n]
1096#define E_WT(e) (e->dist)
1097#define UNSEEN (-FLT_MAX)
1111 for (i = 0; i <
pq->PQsize; i++)
1125 for (
size_t j = 0; j < np->
ne; j++) {
1140 }
else if (
N_VAL(
pq, adjn) < d) {
1164 int h_id = rtr->
tn + 1;
1172 sizeof(original_edge_count[0]));
1173 for (
size_t i = 0; i < rtr->
tg.
nnodes; ++i)
1174 original_edge_count[i] = rtr->
tg.
nodes[i].
ne;
1197 poly =
mkPoly(rtr, sp, h_id, t_id, h_p, t_p, &idx);
1207 free(original_edge_count);
Memory allocation wrappers that exit on failure.
static void * gv_recalloc(void *ptr, size_t old_nmemb, size_t new_nmemb, size_t size)
static void * gv_calloc(size_t nmemb, size_t size)
static void * gv_alloc(size_t size)
CDT_API int dtclose(Dt_t *)
CDT_API Dtmethod_t * Dtoset
ordered set (self-adjusting tree)
CDT_API Dt_t * dtopen(Dtdisc_t *, Dtmethod_t *)
surface_t * mkSurface(double *x, double *y, int n, int *segs, int nsegs)
void freeSurface(surface_t *s)
void PQupdate(snode *n, int d)
int line_intersect(pointf a, pointf b, pointf c, pointf d, pointf *p)
static WUR pointf add_pointf(pointf p, pointf q)
static int cnt(Dict_t *d, Dtlink_t **set)
void agwarningf(const char *fmt,...)
Agraph_t * agraphof(void *obj)
char * agnameof(void *)
returns a string descriptor for the object.
Arithmetic helper functions.
static bool is_exactly_equal(double a, double b)
are two values precisely the same?
void PQinsert(pq_t *pq, Halfedge *he, Site *v, double offset)
static tripoly_t * mkPoly(router_t *rtr, int *dad, int s, int t, pointf p_s, pointf p_t, int *sx)
static int findMap(Dt_t *map, int a, int b)
static void addMap(Dt_t *map, int a, int b, int t)
static void mapTri(Dt_t *map, tri *tp)
map vertex indices from router_t to tripoly_t coordinates
router_t * mkRouter(Ppoly_t **obsp, int npoly)
static ipair sharedEdge(int *p, int *q)
static void resetGraph(tgraph g, int ncnt, int ecnt, size_t *original_edge_count)
remove edges and nodes added for current edge routing
static int raySegIntersect(pointf v, pointf w, pointf a, pointf b, pointf *p)
static int * mkTriIndices(surface_t *sf)
static bool swap_ends_p(edge_t *e)
static bool spline_merge(node_t *n)
static ipair edgeToSeg(tgraph tg, int i, int j)
void freeRouter(router_t *rtr)
static void addTriEdge(tgraph *g, int t, int h, ipair seg)
static int vMap(Dt_t *map, int i)
static void finishEdge(edge_t *e, Ppoly_t spl, int flip)
static int inCone(pointf a, pointf b, pointf c, pointf q)
returns true iff q is in the convex cone a-b-c
static void * newIpair(void *p, Dtdisc_t *disc)
static int cmpItem(void *item1, void *item2)
int makeMultiSpline(edge_t *e, router_t *rtr, int doPolyline)
static pointf * mkCtrlPts(int s, int mult, pointf prev, pointf v, pointf nxt, tripoly_t *trip)
static void * newItem(void *p, Dtdisc_t *disc)
static tri * addTri(int i, int j, tri *oldp)
static void tweakPath(Ppoly_t poly, size_t t, Ppolyline_t pl)
static int genroute(tripoly_t *trip, int t, edge_t *e, int doPolyline)
static pointf triCenter(pointf *pts, int *idxs)
static Ppoint_t tweakEnd(Ppoly_t poly, size_t s, Ppoint_t q)
static int cmpIpair(void *pair1, void *pair2)
static int raySeg(pointf v, pointf w, pointf a, pointf b)
check if ray v->w intersects segment a–b
static tgraph mkTriGraph(surface_t *sf, pointf *pts)
static Dt_t * mapSegToTri(surface_t *sf)
static Dtdisc_t ipairdisc
static void freeTriGraph(tgraph *tg)
static int triPoint(tripoly_t *trip, int vx, pointf v, pointf w, pointf *ip)
static int ctrlPtIdx(pointf v, Ppoly_t *polys)
static int * triPath(tgraph g, int n, int v0, int v1, PQ *pq)
static boxf bbox(Ppoly_t **obsp, int npoly, int *np)
static void vmapAdd(Dt_t *map, int i, int j)
static void addEndpoint(router_t *rtr, pointf p, node_t *v, int v_id, int sides)
static double bisect(pointf pp, pointf cp, pointf np)
return the angle bisecting the angle pp–cp–np
static void freeTripoly(tripoly_t *trip)
void make_polyline(Ppolyline_t line, Ppolyline_t *sline)
int Proutespline(Pedge_t *barriers, size_t n_barriers, Ppolyline_t input_route, Pvector_t endpoint_slopes[2], Ppolyline_t *output_route)
int Pshortestpath(Ppoly_t *boundary, Ppoint_t endpoints[2], Ppolyline_t *output_route)
PATHUTIL_API int wind(Ppoint_t a, Ppoint_t b, Ppoint_t c)
PATHUTIL_API COORD area2(Ppoint_t, Ppoint_t, Ppoint_t)
void clip_and_install(edge_t *fe, node_t *hn, pointf *ps, size_t pn, splineInfo *info)
void makeStraightEdge(graph_t *g, edge_t *e, int edgetype, splineInfo *info)
void addEdgeLabels(edge_t *e)
bool(* swapEnds)(edge_t *e)