32 #define ABS(a) ((a) >= 0 ? (a) : -(a))
39 #define prerror(msg) \
40 fprintf (stderr, "libpath/%s:%d: %s\n", __FILE__, __LINE__, (msg))
42 #define DISTSQ(a, b) ( \
43 (((a).x - (b).x) * ((a).x - (b).x)) + (((a).y - (b).y) * ((a).y - (b).y)) \
46 #define POINTSIZE sizeof (Ppoint_t)
48 #define LT(pa, pbp) ((pa.y > pbp->y) || ((pa.y == pbp->y) && (pa.x < pbp->x)))
49 #define GT(pa, pbp) ((pa.y < pbp->y) || ((pa.y == pbp->y) && (pa.x > pbp->x)))
75 static int reallyroutespline(
Pedge_t *,
int,
83 static void points2coeff(
double,
double,
double,
double,
double *);
84 static void addroot(
double,
double *,
int *);
88 static void growops(
int);
95 static double B0(
double t);
96 static double B1(
double t);
97 static double B2(
double t);
98 static double B3(
double t);
99 static double B01(
double t);
100 static double B23(
double t);
102 static int cmpp2efunc(
const void *,
const void *);
104 static void listdelete(
Pedge_t *);
134 if (!(p2es = (
p2e_t *) malloc(
sizeof(
p2e_t) * (p2en = edgen * 2)))) {
138 for (ei = 0, p2ei = 0; ei < edgen; ei++) {
139 if (edges[ei].a.x == edges[ei].
b.
x
140 && edges[ei].
a.
y == edges[ei].
b.
y)
142 p2es[p2ei].
pp = &edges[ei].
a;
143 p2es[p2ei++].
ep = &edges[ei];
144 p2es[p2ei].
pp = &edges[ei].
b;
145 p2es[p2ei++].
ep = &edges[ei];
148 qsort(p2es, p2en,
sizeof(
p2e_t), cmpp2efunc);
150 for (p2ei = 0; p2ei < p2en; p2ei += 2) {
153 fprintf(stderr,
"point: %d %lf %lf\n", p2ei, pp->
x, pp->
y);
156 e1p = p2es[p2ei + 1].
ep;
157 p0 = (&e0p->
a == p2es[p2ei].
pp) ? e0p->
b : e0p->
a;
158 p1 = (&e0p->
a == p2es[p2ei + 1].
pp) ? e1p->
b : e1p->
a;
159 if (
LT(p0, pp) &&
LT(p1, pp)) {
160 listdelete(e0p), listdelete(e1p);
161 }
else if (
GT(p0, pp) &&
GT(p1, pp)) {
162 listinsert(e0p, *pp), listinsert(e1p, *pp);
165 listreplace(e0p, e1p);
167 listreplace(e1p, e0p);
175 evs[0] = normv(evs[0]);
176 evs[1] = normv(evs[1]);
179 ops[opl++] = inps[0];
180 if (reallyroutespline(edges, edgen, inps, inpn, evs[0], evs[1]) == -1)
186 fprintf(stderr,
"edge\na\nb\n");
187 fprintf(stderr,
"points\n%d\n", inpn);
188 for (ipi = 0; ipi < inpn; ipi++)
189 fprintf(stderr,
"%f %f\n", inps[ipi].x, inps[ipi].y);
190 fprintf(stderr,
"splpoints\n%d\n", opl);
191 for (opi = 0; opi < opl; opi++)
192 fprintf(stderr,
"%f %f\n", ops[opi].x, ops[opi].y);
198 static int reallyroutespline(
Pedge_t * edges,
int edgen,
203 Pvector_t v1, v2, splitv, splitv1, splitv2;
212 if (!(tnas = malloc(
sizeof(
tna_t) * inpn)))
215 if (!(tnas = realloc(tnas,
sizeof(
tna_t) * inpn)))
221 for (i = 1; i < inpn; i++)
222 tnas[i].t = tnas[i - 1].t +
dist(inps[i], inps[i - 1]);
223 for (i = 1; i < inpn; i++)
224 tnas[i].t /= tnas[inpn - 1].t;
225 for (i = 0; i < inpn; i++) {
226 tnas[i].
a[0] = scale(ev0, B1(tnas[i].t));
227 tnas[i].
a[1] = scale(ev1, B2(tnas[i].t));
229 if (mkspline(inps, inpn, tnas, ev0, ev1, &p1, &v1, &p2, &v2) == -1)
231 if (splinefits(edges, edgen, p1, v1, p2, v2, inps, inpn))
233 cp1 = add(p1, scale(v1, 1 / 3.0));
234 cp2 =
sub(p2, scale(v2, 1 / 3.0));
235 for (maxd = -1, maxi = -1, i = 1; i < inpn - 1; i++) {
237 p.
x = B0(t) * p1.
x + B1(t) * cp1.
x + B2(t) * cp2.
x + B3(t) * p2.
x;
238 p.
y = B0(t) * p1.
y + B1(t) * cp1.
y + B2(t) * cp2.
y + B3(t) * p2.
y;
239 if ((d =
dist(p, inps[i])) > maxd)
243 splitv1 = normv(
sub(inps[spliti], inps[spliti - 1]));
244 splitv2 = normv(
sub(inps[spliti + 1], inps[spliti]));
245 splitv = normv(add(splitv1, splitv2));
246 reallyroutespline(edges, edgen, inps, spliti + 1, ev0, splitv);
247 reallyroutespline(edges, edgen, &inps[spliti], inpn - spliti, splitv,
257 double c[2][2], x[2], det01, det0X, detX1;
258 double d01, scale0, scale3;
261 scale0 = scale3 = 0.0;
262 c[0][0] = c[0][1] = c[1][0] = c[1][1] = 0.0;
264 for (i = 0; i < inpn; i++) {
265 c[0][0] +=
dot(tnas[i].a[0], tnas[i].a[0]);
266 c[0][1] +=
dot(tnas[i].a[0], tnas[i].a[1]);
268 c[1][1] +=
dot(tnas[i].a[1], tnas[i].a[1]);
269 tmp =
sub(inps[i], add(scale(inps[0], B01(tnas[i].t)),
270 scale(inps[inpn - 1], B23(tnas[i].t))));
271 x[0] +=
dot(tnas[i].a[0], tmp);
272 x[1] +=
dot(tnas[i].a[1], tmp);
274 det01 = c[0][0] * c[1][1] - c[1][0] * c[0][1];
275 det0X = c[0][0] * x[1] - c[0][1] * x[0];
276 detX1 = x[0] * c[1][1] - x[1] * c[0][1];
277 if (
ABS(det01) >= 1e-6) {
278 scale0 = detX1 / det01;
279 scale3 = det0X / det01;
281 if (
ABS(det01) < 1e-6 || scale0 <= 0.0 || scale3 <= 0.0) {
282 d01 =
dist(inps[0], inps[inpn - 1]) / 3.0;
287 *sv0 = scale(ev0, scale0);
288 *sp1 = inps[inpn - 1];
289 *sv1 = scale(ev1, scale3);
293 static double dist_n(
Ppoint_t * p,
int n)
299 for (i = 1; i < n; i++) {
301 sqrt((p[i].x - p[i - 1].x) * (p[i].x - p[i - 1].x) +
302 (p[i].y - p[i - 1].y) * (p[i].y - p[i - 1].y));
320 forceflag = (inpn == 2 ? 1 : 0);
323 d = sqrt((pb.
x - pa.
x) * (pb.
x - pa.
x) +
324 (pb.
y - pa.
y) * (pb.
y - pa.
y));
332 sps[1].
x = pa.
x + a * va.
x / 3.0;
333 sps[1].
y = pa.
y + a * va.
y / 3.0;
334 sps[2].
x = pb.
x - b * vb.
x / 3.0;
335 sps[2].
y = pb.
y - b * vb.
y / 3.0;
347 if (first && (dist_n(sps, 4) < (dist_n(inps, inpn) -
EPSILON1)))
351 if (splineisinside(edges, edgen, &sps[0])) {
353 for (pi = 1; pi < 4; pi++)
354 ops[opl].x = sps[pi].x, ops[opl++].y = sps[pi].y;
355 #if defined(DEBUG) && DEBUG >= 1
356 fprintf(stderr,
"success: %f %f\n", a, b);
360 if (a == 0 && b == 0) {
363 for (pi = 1; pi < 4; pi++)
364 ops[opl].x = sps[pi].x, ops[opl++].y = sps[pi].y;
365 #if defined(DEBUG) && DEBUG >= 1
366 fprintf(stderr,
"forced straight line: %f %f\n", a, b);
377 #if defined(DEBUG) && DEBUG >= 1
378 fprintf(stderr,
"failure\n");
389 double t, ta, tb, tc, td;
391 for (ei = 0; ei < edgen; ei++) {
392 lps[0] = edges[ei].
a, lps[1] = edges[ei].
b;
395 if ((rootn = splineintersectsline(sps, lps, roots)) == 4)
397 for (rooti = 0; rooti < rootn; rooti++) {
402 tc = 3 * t * t * (1 - t);
403 tb = 3 * t * (1 - t) * (1 - t);
404 ta = (1 - t) * (1 - t) * (1 - t);
405 ip.
x = ta * sps[0].
x + tb * sps[1].
x +
406 tc * sps[2].
x + td * sps[3].
x;
407 ip.
y = ta * sps[0].
y + tb * sps[1].
y +
408 tc * sps[2].
y + td * sps[3].
y;
421 double scoeff[4], xcoeff[2], ycoeff[2];
422 double xroots[3], yroots[3], tv, sv, rat;
423 int rootn, xrootn, yrootn, i, j;
425 xcoeff[0] = lps[0].
x;
426 xcoeff[1] = lps[1].
x - lps[0].
x;
427 ycoeff[0] = lps[0].
y;
428 ycoeff[1] = lps[1].
y - lps[0].
y;
430 if (xcoeff[1] == 0) {
431 if (ycoeff[1] == 0) {
432 points2coeff(sps[0].x, sps[1].x, sps[2].x, sps[3].x, scoeff);
433 scoeff[0] -= xcoeff[0];
434 xrootn =
solve3(scoeff, xroots);
435 points2coeff(sps[0].y, sps[1].y, sps[2].y, sps[3].y, scoeff);
436 scoeff[0] -= ycoeff[0];
437 yrootn =
solve3(scoeff, yroots);
442 for (j = 0; j < yrootn; j++)
443 addroot(yroots[j], roots, &rootn);
444 else if (yrootn == 4)
445 for (i = 0; i < xrootn; i++)
446 addroot(xroots[i], roots, &rootn);
448 for (i = 0; i < xrootn; i++)
449 for (j = 0; j < yrootn; j++)
450 if (xroots[i] == yroots[j])
451 addroot(xroots[i], roots, &rootn);
454 points2coeff(sps[0].x, sps[1].x, sps[2].x, sps[3].x, scoeff);
455 scoeff[0] -= xcoeff[0];
456 xrootn =
solve3(scoeff, xroots);
459 for (i = 0; i < xrootn; i++) {
461 if (tv >= 0 && tv <= 1) {
462 points2coeff(sps[0].y, sps[1].y, sps[2].y, sps[3].y,
464 sv = scoeff[0] + tv * (scoeff[1] + tv *
465 (scoeff[2] + tv * scoeff[3]));
466 sv = (sv - ycoeff[0]) / ycoeff[1];
467 if ((0 <= sv) && (sv <= 1))
468 addroot(tv, roots, &rootn);
474 rat = ycoeff[1] / xcoeff[1];
475 points2coeff(sps[0].y - rat * sps[0].x, sps[1].y - rat * sps[1].x,
476 sps[2].y - rat * sps[2].x, sps[3].y - rat * sps[3].x,
478 scoeff[0] += rat * xcoeff[0] - ycoeff[0];
479 xrootn =
solve3(scoeff, xroots);
482 for (i = 0; i < xrootn; i++) {
484 if (tv >= 0 && tv <= 1) {
485 points2coeff(sps[0].x, sps[1].x, sps[2].x, sps[3].x,
487 sv = scoeff[0] + tv * (scoeff[1] +
488 tv * (scoeff[2] + tv * scoeff[3]));
489 sv = (sv - xcoeff[0]) / xcoeff[1];
490 if ((0 <= sv) && (sv <= 1))
491 addroot(tv, roots, &rootn);
498 static void points2coeff(
double v0,
double v1,
double v2,
double v3,
501 coeff[3] = v3 + 3 * v1 - (v0 + 3 * v2);
502 coeff[2] = 3 * v0 + 3 * v2 - 6 * v1;
503 coeff[1] = 3 * (v1 - v0);
507 static void addroot(
double root,
double *roots,
int *rootnp)
509 if (root >= 0 && root <= 1)
510 roots[*rootnp] = root, (*rootnp)++;
517 d = v.
x * v.
x + v.
y * v.
y;
525 static void growops(
int newopn)
535 if (!(ops = (
Ppoint_t *) realloc((
void *) ops,
546 p1.
x += p2.
x, p1.
y += p2.
y;
552 p1.
x -= p2.
x, p1.
y -= p2.
y;
560 dx = p2.
x - p1.
x, dy = p2.
y - p1.
y;
561 return sqrt(dx * dx + dy * dy);
572 return p1.
x * p2.
x + p1.
y * p2.
y;
575 static double B0(
double t)
577 double tmp = 1.0 - t;
578 return tmp * tmp * tmp;
581 static double B1(
double t)
583 double tmp = 1.0 - t;
584 return 3 * t * tmp * tmp;
587 static double B2(
double t)
589 double tmp = 1.0 - t;
590 return 3 * t * t * tmp;
593 static double B3(
double t)
598 static double B01(
double t)
600 double tmp = 1.0 - t;
601 return tmp * tmp * (tmp + 3 * t);
604 static double B23(
double t)
606 double tmp = 1.0 - t;
607 return t * t * (3 * tmp + t);
611 static int cmpp2efunc(
const void *v0p,
const void *v1p)
613 p2e_t *p2e0p, *p2e1p;
617 if (p2e0p->
pp->
y > p2e1p->
pp->
y)
619 else if (p2e0p->
pp->
y < p2e1p->
pp->
y)
621 if (p2e0p->
pp->
x < p2e1p->
pp->
x)
623 else if (p2e0p->
pp->
x > p2e1p->
pp->
x)
625 x0 = (p2e0p->
pp == &p2e0p->
ep->
a) ? p2e0p->
ep->
b.
x : p2e0p->
ep->
a.
x;
626 x1 = (p2e1p->
pp == &p2e1p->
ep->
a) ? p2e1p->
ep->
b.
x : p2e1p->
ep->
a.
x;
638 for (lp = elist; lp; lp = lp->
next) {
651 prerror(
"cannot find list element to delete");
660 for (lp = elist; lp; lp = lp->
next) {
667 prerror(
"cannot find list element to replace");
678 prerror(
"cannot malloc newlp");
687 for (lp = elist; lp; lp = lp->
next) {
703 lastlp->
next = newlp;
704 newlp->
prev = lastlp;
int solve3(double *coeff, double *roots)
int Proutespline(Pedge_t *barriers, int n_barriers, Ppolyline_t input_route, Pvector_t endpoint_slopes[2], Ppolyline_t *output_route)
double dist(Site *s, Site *t)