63static int cmpItem(
void *item1,
void *item2) {
64 const int *p1 = item1;
65 const int *p2 = item2;
66 if (p1[0] < p2[0])
return -1;
67 if (p1[0] > p2[0])
return 1;
68 if (p1[1] < p2[1])
return -1;
69 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),
118 for (i = 0; i < sf->
nfaces; i++) {
154 const int *p1 = pair1;
155 const int *p2 =
pair2;
179 .link = offsetof(
Ipair, link),
205 for (; tp; tp = tp->
nxttri) {
229 theta = atan2(np.
y - cp.
y, np.
x - cp.
x);
230 phi = atan2(pp.
y - cp.
y, pp.
x - cp.
x);
231 return (theta + phi) / 2.0;
239 int wa =
wind(v, w, a);
240 int wb =
wind(v, w, b);
244 return wind(v, b, w) *
wind(v, b, a) >= 0;
246 return wind(v, a, w) *
wind(v, a, b) >= 0;
291 for (
size_t i = 1; i < polys->
pn; i++) {
293 if (w.
x == v.
x && w.
y == v.
y) {
294 assert(i <= INT_MAX);
318 double d, sep, theta, sinTheta, cosTheta;
326 sinTheta = sin(theta);
327 cosTheta = cos(theta);
328 w.
x = v.
x + 100 * cosTheta;
329 w.
y = v.
y + 100 * sinTheta;
334 w.
x = v.
x + 100 * cosTheta;
335 w.
y = v.
y + 100 * sinTheta;
337 }
else if (
wind(
prev, v, w) != -1) {
340 w.
x = v.
x + 100 * cosTheta;
341 w.
y = v.
y + 100 * sinTheta;
344 if (
triPoint(trip, idx, v, w, &q)) {
354 for (i = 0; i < mult; i++) {
355 ps[i].x = v.
x + i * sep * cosTheta;
356 ps[i].y = v.
y + i * sep * sinTheta;
359 for (i = 0; i < mult; i++) {
360 ps[mult - i - 1].x = v.
x + i * sep * cosTheta;
361 ps[mult - i - 1].y = v.
y + i * sep * sinTheta;
410 p.
x = (a.
x + b.
x + c.
x) / 3.0;
411 p.
y = (a.
y + b.
y + c.
y) / 3.0;
429 bb.
LL.
x = bb.
LL.
y = DBL_MAX;
430 bb.
UR.
x = bb.
UR.
y = -DBL_MAX;
432 for (i = 0; i < npoly; i++) {
434 for (
size_t j = 0; j < obs->
pn; j++) {
472 if (p2 != *(q + 1) && p2 != *(q + 2)) {
475 }
else if (p1 == *(q + 1)) {
476 if (p2 != *q && p2 != *(q + 2)) {
479 }
else if (p1 == *(q + 2)) {
480 if (p2 != *q && p2 != *(q + 1)) {
501 sizeof(g->
edges[0]));
512 sizeof(tp->
edges[0]));
515 sizeof(hp->
edges[0]));
523 for (
size_t i = 0; i < tg->
nnodes; ++i) {
541 for (i = 0; i < 3 * sf->
nfaces; i++)
542 if (sf->
neigh[i] != -1)
551 for (i = 0; i < sf->
nfaces; i++) {
556 for (i = 0; i < sf->
nfaces; i++) {
558 jp = sf->
neigh + 3 * i;
560 while (ne < 3 && (j = *jp++) != -1) {
592 int *obsi =
gv_calloc(npoly + 1,
sizeof(
int));
593 int i, ix = 4, six = 0;
595 bb =
bbox(obsp, npoly, &npts);
598 int *segs =
gv_calloc(2 * npts,
sizeof(
int));
607 for (i = 1; i <= 4; i++) {
616 for (i = 0; i < npoly; i++) {
619 for (
size_t j = 1; j <= obs->
pn; j++) {
622 segs[six++] = ix + 1;
624 segs[six++] = obsi[i];
625 pts[ix++] = obs->
ps[j - 1];
631 double *x =
gv_calloc(npts,
sizeof(
double));
632 double *y =
gv_calloc(npts,
sizeof(
double));
633 for (i = 0; i < npts; i++) {
660 for (
size_t j = 0; j < spl.
pn / 2; j++) {
671#define EQPT(p,q) (((p).x==(q).x)&&((p).y==(q).y))
695 prv =
poly.ps[
s - 1];
698 m.
x = (nxt.
x + prv.
x)/2.0 - p.
x;
699 m.
y = (nxt.
y + prv.
y)/2.0 - p.
y;
700 const double d = hypot(m.
x, m.
y);
744 evs[0].
x = evs[0].
y = 0;
745 evs[1].
x = evs[1].
y = 0;
750 for (
size_t j = 0; j <
poly.pn; j++) {
751 medges[j].
a =
poly.ps[j];
752 medges[j].
b =
poly.ps[(j + 1) %
poly.pn];
767 const size_t pn = 2 * (pl.
pn - 1);
770 for (
size_t i = 0; i + 2 < pl.
pn; i++) {
783 for (
int i = 0; i < mult; i++) {
785 for (
size_t j = 1; j + 1 < pl.
pn; j++) {
786 poly.ps[j] = cpts[j - 1][i];
788 poly.ps[pl.
pn - 1] = eps[1];
789 for (
size_t j = 1; j + 1 < pl.
pn; j++) {
790 poly.ps[pn - j] = cpts[j - 1][i + 1];
803 for (
size_t j = 0; j <
poly.pn; j++) {
804 medges[j].
a =
poly.ps[j];
805 medges[j].
b =
poly.ps[(j + 1) %
poly.pn];
808 const bool failed_routing =
Proutespline(medges,
poly.pn, mmpl, evs, &spl) < 0;
810 if (failed_routing) {
811 agwarningf(
"Could not create control points for multiple spline for edge (%s,%s)\n",
824 for (
size_t i = 0; i + 2 < pl.
pn; i++)
832#define NSMALL -0.0000000001
862 int starti = rtr->
obs[obs_id];
863 int endi = rtr->
obs[obs_id + 1];
918 for (i = starti; i < endi; i++) {
926 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]))
930 assert(rtr->
tg->
nodes[v_id].
ne > 0 &&
"no edges were added");
947 for (
size_t k = 0; k < np->
ne; k++) {
949 if (ep->
t == j || ep->
h == j)
964 for (
size_t i = 0; i < trip->
poly.
pn; i++) {
965 for (tp = trip->
triMap[i]; tp; tp = nxt) {
1007 for (nxt = dad[t]; nxt !=
s; nxt = dad[nxt]) {
1009 assert (nxt != dad[nxt] &&
"infinite loop due to 'nxt' not changing");
1018 side1[cnt1++].
v = p.
i;
1020 side2[cnt2++].
v = p.
j;
1023 for (nxt = dad[t]; nxt >= 0; nxt = dad[nxt]) {
1025 if (p.
i == side1[cnt1 - 1].
v) {
1026 side1[cnt1 - 1].
ts =
1027 addTri(side2[cnt2 - 1].v, p.
j, side1[cnt1 - 1].
ts);
1028 side2[cnt2 - 1].
ts =
1029 addTri(side1[cnt1 - 1].v, p.
j, side2[cnt2 - 1].
ts);
1031 addTri(side2[cnt2 - 1].v, side1[cnt1 - 1].v,
NULL);
1032 side2[cnt2++].
v = p.
j;
1033 }
else if (p.
i == side2[cnt2 - 1].
v) {
1034 side1[cnt1 - 1].
ts =
1035 addTri(side2[cnt2 - 1].v, p.
j, side1[cnt1 - 1].
ts);
1036 side2[cnt2 - 1].
ts =
1037 addTri(side1[cnt1 - 1].v, p.
j, side2[cnt2 - 1].
ts);
1039 addTri(side2[cnt2 - 1].v, side1[cnt1 - 1].v,
NULL);
1040 side1[cnt1++].
v = p.
j;
1041 }
else if (p.
j == side1[cnt1 - 1].
v) {
1042 side1[cnt1 - 1].
ts =
1043 addTri(side2[cnt2 - 1].v, p.
i, side1[cnt1 - 1].
ts);
1044 side2[cnt2 - 1].
ts =
1045 addTri(side1[cnt1 - 1].v, p.
i, side2[cnt2 - 1].
ts);
1047 addTri(side2[cnt2 - 1].v, side1[cnt1 - 1].v,
NULL);
1048 side2[cnt2++].
v = p.
i;
1050 side1[cnt1 - 1].
ts =
1051 addTri(side2[cnt2 - 1].v, p.
i, side1[cnt1 - 1].
ts);
1052 side2[cnt2 - 1].
ts =
1053 addTri(side1[cnt1 - 1].v, p.
i, side2[cnt2 - 1].
ts);
1055 addTri(side2[cnt2 - 1].v, side1[cnt1 - 1].v,
NULL);
1056 side1[cnt1++].
v = p.
i;
1060 side1[cnt1 - 1].
ts =
addTri(-2, side2[cnt2 - 1].v, side1[cnt1 - 1].ts);
1061 side2[cnt2 - 1].
ts =
addTri(-2, side1[cnt1 - 1].v, side2[cnt2 - 1].ts);
1073 for (
int i = 0; i < cnt1; i++) {
1074 vmapAdd(vmap, side1[i].v, idx);
1075 *pps++ = rtr->
ps[side1[i].
v];
1076 trim[idx++] = side1[i].
ts;
1080 for (
int i = cnt2 - 1; i >= 0; i--) {
1081 vmapAdd(vmap, side2[i].v, idx);
1082 *pps++ = rtr->
ps[side2[i].
v];
1083 trim[idx++] = side2[i].
ts;
1086 for (
size_t i = 0; i < nt + 4; i++) {
1091 ps->poly.pn = nt + 4;
1106 size_t *original_edge_count) {
1110 for (i = 0; i < ncnt; i++) {
1111 np->
ne = original_edge_count[i];
1117#define PQVTYPE float
1129#define N_VAL(pq,n) ((PPQ*)pq)->vals[n]
1130#define N_IDX(pq,n) ((PPQ*)pq)->idxs[n]
1136#define N_DAD(n) dad[n]
1137#define E_WT(e) (e->dist)
1138#define UNSEEN (-FLT_MAX)
1155 for (i = 0; i <
pq->PQsize; i++)
1169 for (
size_t j = 0; j < np->
ne; j++) {
1184 }
else if (
N_VAL(
pq, adjn) < d) {
1209 int h_id = rtr->
tn + 1;
1217 sizeof(original_edge_count[0]));
1218 for (
size_t i = 0; i < rtr->
tg->
nnodes; ++i)
1219 original_edge_count[i] = rtr->
tg->
nodes[i].
ne;
1242 poly =
mkPoly(rtr, sp, h_id, t_id, h_p, t_p, &idx);
1252 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 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.
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 tgraph * mkTriGraph(surface_t *sf, pointf *pts)
static void mapTri(Dt_t *map, tri *tp)
router_t * mkRouter(Ppoly_t **obsp, int npoly)
static ipair sharedEdge(int *p, int *q)
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)
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)
static void * newIpair(void *p, Dtdisc_t *disc)
static int cmpItem(void *item1, void *item2)
static void resetGraph(tgraph *g, int ncnt, int ecnt, size_t *original_edge_count)
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 ipair edgeToSeg(tgraph *tg, int i, int j)
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 * triPath(tgraph *g, int n, int v0, int v1, PQ *pq)
static int cmpIpair(void *pair1, void *pair2)
static int raySeg(pointf v, pointf w, pointf a, pointf b)
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 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)
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)