41 #define prerror(msg) \
42 fprintf (stderr, "libpath/%s:%d: %s\n", __FILE__, __LINE__, (msg))
44 #define POINTSIZE sizeof (Ppoint_t)
51 #define POINTNLINKSIZE sizeof (pointnlink_t)
52 #define POINTNLINKPSIZE sizeof (pointnlink_t *)
66 #define TRIANGLESIZE sizeof (triangle_t)
75 static int pnln, pnll;
78 static int trin, tril;
88 static void connecttris(
int,
int);
89 static int marktripath(
int,
int);
92 static void splitdq(
int,
int);
98 static int pointintri(
int,
Ppoint_t *);
100 static void growpnls(
int);
101 static void growtris(
int);
102 static void growdq(
int);
103 static void growops(
int);
115 int trii, trij, ftrii, ltrii;
130 growdq(polyp->
pn * 2);
134 for (pi = 0, minx = HUGE_VAL, minpi = -1; pi < polyp->
pn; pi++) {
135 if (minx > polyp->
ps[pi].
x)
136 minx = polyp->
ps[pi].
x, minpi = pi;
138 p2 = polyp->
ps[minpi];
139 p1 = polyp->
ps[((minpi == 0) ? polyp->
pn - 1 : minpi - 1)];
140 p3 = polyp->
ps[((minpi == polyp->
pn - 1) ? 0 : minpi + 1)];
141 if (((p1.
x == p2.
x && p2.
x == p3.
x) && (p3.
y > p2.
y)) ||
142 ccw(&p1, &p2, &p3) !=
ISCCW) {
143 for (pi = polyp->
pn - 1; pi >= 0; pi--) {
144 if (pi < polyp->pn - 1
145 && polyp->
ps[pi].
x == polyp->
ps[pi + 1].
x
146 && polyp->
ps[pi].
y == polyp->
ps[pi + 1].
y)
148 pnls[pnll].
pp = &polyp->
ps[pi];
149 pnls[pnll].
link = &pnls[pnll % polyp->
pn];
150 pnlps[pnll] = &pnls[pnll];
154 for (pi = 0; pi < polyp->
pn; pi++) {
155 if (pi > 0 && polyp->
ps[pi].
x == polyp->
ps[pi - 1].
x &&
156 polyp->
ps[pi].
y == polyp->
ps[pi - 1].
y)
158 pnls[pnll].
pp = &polyp->
ps[pi];
159 pnls[pnll].
link = &pnls[pnll % polyp->
pn];
160 pnlps[pnll] = &pnls[pnll];
165 #if defined(DEBUG) && DEBUG >= 1
166 fprintf(stderr,
"points\n%d\n", pnll);
167 for (pnli = 0; pnli < pnll; pnli++)
168 fprintf(stderr,
"%f %f\n", pnls[pnli].pp->x, pnls[pnli].
pp->
y);
172 triangulate(pnlps, pnll);
174 #if defined(DEBUG) && DEBUG >= 2
175 fprintf(stderr,
"triangles\n%d\n", tril);
176 for (trii = 0; trii < tril; trii++)
177 for (ei = 0; ei < 3; ei++)
178 fprintf(stderr,
"%f %f\n", tris[trii].e[ei].pnl0p->pp->x,
183 for (trii = 0; trii < tril; trii++)
184 for (trij = trii + 1; trij < tril; trij++)
185 connecttris(trii, trij);
188 for (trii = 0; trii < tril; trii++)
189 if (pointintri(trii, &eps[0]))
192 prerror(
"source point not in any triangle");
196 for (trii = 0; trii < tril; trii++)
197 if (pointintri(trii, &eps[1]))
200 prerror(
"destination point not in any triangle");
206 if (!marktripath(ftrii, ltrii)) {
207 prerror(
"cannot find triangle path");
211 ops[0] = eps[0], ops[1] = eps[1];
217 if (ftrii == ltrii) {
220 ops[0] = eps[0], ops[1] = eps[1];
236 for (ei = 0; ei < 3; ei++)
246 pnlp = trip->
e[(ei + 1) % 3].pnl1p;
262 splitindex = finddqsplit(rpnlp);
266 if (splitindex > dq.
apex)
267 dq.
apex = splitindex;
270 splitindex = finddqsplit(lpnlp);
274 if (splitindex < dq.
apex)
275 dq.
apex = splitindex;
279 for (ei = 0; ei < 3; ei++)
281 trii = trip->
e[ei].
rtp - tris;
286 #if defined(DEBUG) && DEBUG >= 1
287 fprintf(stderr,
"polypath");
288 for (pnlp = &epnls[1]; pnlp; pnlp = pnlp->
link)
289 fprintf(stderr,
" %f %f", pnlp->
pp->
x, pnlp->
pp->
y);
290 fprintf(stderr,
"\n");
293 for (pi = 0, pnlp = &epnls[1]; pnlp; pnlp = pnlp->
link)
297 for (pi = pi - 1, pnlp = &epnls[1]; pnlp; pi--, pnlp = pnlp->
link)
305 static void triangulate(
pointnlink_t ** pnlps,
int pnln)
307 int pnli, pnlip1, pnlip2;
311 for (pnli = 0; pnli < pnln; pnli++)
313 pnlip1 = (pnli + 1) % pnln;
314 pnlip2 = (pnli + 2) % pnln;
315 if (isdiagonal(pnli, pnlip2, pnlps, pnln))
317 loadtriangle(pnlps[pnli], pnlps[pnlip1], pnlps[pnlip2]);
318 for (pnli = pnlip1; pnli < pnln - 1; pnli++)
319 pnlps[pnli] = pnlps[pnli + 1];
320 triangulate(pnlps, pnln - 1);
324 prerror(
"triangulation failed");
327 loadtriangle(pnlps[0], pnlps[1], pnlps[2]);
331 static int isdiagonal(
int pnli,
int pnlip2,
pointnlink_t ** pnlps,
334 int pnlip1, pnlim1, pnlj, pnljp1, res;
337 pnlip1 = (pnli + 1) % pnln;
338 pnlim1 = (pnli + pnln - 1) % pnln;
340 if (ccw(pnlps[pnlim1]->pp, pnlps[pnli]->pp, pnlps[pnlip1]->pp) ==
343 (ccw(pnlps[pnli]->pp, pnlps[pnlip2]->pp, pnlps[pnlim1]->pp) ==
345 && (ccw(pnlps[pnlip2]->pp, pnlps[pnli]->pp, pnlps[pnlip1]->pp)
349 res = (ccw(pnlps[pnli]->pp, pnlps[pnlip2]->pp,
350 pnlps[pnlip1]->pp) ==
ISCW);
355 for (pnlj = 0; pnlj < pnln; pnlj++) {
356 pnljp1 = (pnlj + 1) % pnln;
357 if (!((pnlj == pnli) || (pnljp1 == pnli) ||
358 (pnlj == pnlip2) || (pnljp1 == pnlip2)))
359 if (intersects(pnlps[pnli]->pp, pnlps[pnlip2]->pp,
360 pnlps[pnlj]->pp, pnlps[pnljp1]->pp))
375 trip = &tris[tril++];
383 for (ei = 0; ei < 3; ei++)
384 trip->
e[ei].
ltp = trip;
388 static void connecttris(
int tri1,
int tri2)
393 for (ei = 0; ei < 3; ei++) {
394 for (ej = 0; ej < 3; ej++) {
395 tri1p = &tris[tri1], tri2p = &tris[tri2];
396 if ((tri1p->
e[ei].
pnl0p->
pp == tri2p->e[ej].pnl0p->pp &&
397 tri1p->
e[ei].
pnl1p->
pp == tri2p->e[ej].pnl1p->pp) ||
398 (tri1p->
e[ei].
pnl0p->
pp == tri2p->e[ej].pnl1p->pp &&
399 tri1p->
e[ei].
pnl1p->
pp == tri2p->e[ej].pnl0p->pp))
400 tri1p->
e[ei].
rtp = tri2p, tri2p->
e[ej].
rtp = tri1p;
406 static int marktripath(
int trii,
int trij)
415 for (ei = 0; ei < 3; ei++)
416 if (tris[trii].e[ei].rtp &&
417 marktripath(tris[trii].e[ei].rtp - tris, trij))
439 static void splitdq(
int side,
int index)
451 for (index = dq.
fpnlpi; index < dq.
apex; index++)
455 for (index = dq.
lpnlpi; index > dq.
apex; index--)
467 d = ((p1p->
y - p2p->
y) * (p3p->
x - p2p->
x)) -
468 ((p3p->
y - p2p->
y) * (p1p->
x - p2p->
x));
476 int ccw1, ccw2, ccw3, ccw4;
478 if (ccw(pap, pbp, pcp) ==
ISON || ccw(pap, pbp, pdp) ==
ISON ||
479 ccw(pcp, pdp, pap) ==
ISON || ccw(pcp, pdp, pbp) ==
ISON) {
480 if (between(pap, pbp, pcp) || between(pap, pbp, pdp) ||
481 between(pcp, pdp, pap) || between(pcp, pdp, pbp))
484 ccw1 = (ccw(pap, pbp, pcp) ==
ISCCW) ? 1 : 0;
485 ccw2 = (ccw(pap, pbp, pdp) ==
ISCCW) ? 1 : 0;
486 ccw3 = (ccw(pcp, pdp, pap) ==
ISCCW) ? 1 : 0;
487 ccw4 = (ccw(pcp, pdp, pbp) ==
ISCCW) ? 1 : 0;
488 return (ccw1 ^ ccw2) && (ccw3 ^ ccw4);
498 p1.
x = pbp->
x - pap->
x, p1.
y = pbp->
y - pap->
y;
499 p2.
x = pcp->
x - pap->
x, p2.
y = pcp->
y - pap->
y;
500 if (ccw(pap, pbp, pcp) !=
ISON)
502 return (p2.
x * p1.
x + p2.
y * p1.
y >= 0) &&
503 (p2.
x * p2.
x + p2.
y * p2.
y <= p1.
x * p1.
x + p1.
y * p1.
y);
506 static int pointintri(
int trii,
Ppoint_t * pp)
510 for (ei = 0, sum = 0; ei < 3; ei++)
511 if (ccw(tris[trii].e[ei].pnl0p->pp,
514 return (sum == 3 || sum == 0);
517 static void growpnls(
int newpnln)
527 prerror(
"cannot malloc pnlps");
533 prerror(
"cannot realloc pnls");
539 prerror(
"cannot realloc pnlps");
546 static void growtris(
int newtrin)
556 if (!(tris = (
triangle_t *) realloc((
void *) tris,
558 prerror(
"cannot realloc tris");
565 static void growdq(
int newdqn)
567 if (newdqn <= dq.
pnlpn)
573 prerror(
"cannot malloc dq.pnls");
580 prerror(
"cannot realloc dq.pnls");
587 static void growops(
int newopn)
597 if (!(ops = (
Ppoint_t *) realloc((
void *) ops,
struct triangle_t triangle_t
struct pointnlink_t * link
struct pointnlink_t pointnlink_t
int Pshortestpath(Ppoly_t *boundary, Ppoint_t endpoints[2], Ppolyline_t *output_route)