#endif
static int nedges, nboxes; /* total no. of edges and boxes used in routing */
-static jmp_buf jbuf;
static int routeinit;
/* static data used across multiple edges */
static Pedge_t *edges; /* polygon edges passed to Proutespline */
static int edgen; /* size of edges[] */
-static void checkpath(int, boxf*, path*);
+static int checkpath(int, boxf*, path*);
static int mkspacep(int size);
static void printpath(path * pp);
#ifdef DEBUG
#define INIT_DELTA 10
#define LOOP_TRIES 15 /* number of times to try to limiting boxes to regain space, using smaller divisions */
+/* routesplines:
+ * Route a path using the path info in pp. This includes start and end points
+ * plus a collection of contiguous boxes contain the terminal points. The boxes
+ * are converted into a containing polygon. A shortest path is constructed within
+ * the polygon from between the terminal points. If polyline is true, this path
+ * is converted to a spline representation. Otherwise, we call the path planner to
+ * convert the polyline into a smooth spline staying within the polygon. In both
+ * cases, the function returns an array of the computed control points. The number
+ * of these points is given in npoints.
+ *
+ * Note that the returned points are stored in a single array, so the points must be
+ * used before another call to this function.
+ *
+ * During cleanup, the function determines the x-extent of the spline in the box, so
+ * the box can be shrunk to the minimum width. The extra space can then be used by other
+ * edges.
+ *
+ * If a catastrophic error, return NULL.
+ */
static pointf *_routesplines(path * pp, int *npoints, int polyline)
{
Ppoly_t poly;
realedge = ED_to_orig(realedge));
if (!realedge) {
agerr(AGERR, "in routesplines, cannot find NORMAL edge\n");
- longjmp (jbuf, 1);
+ return NULL;
}
boxes = pp->boxes;
boxn = pp->nbox;
- checkpath(boxn, boxes, pp);
+ if (checkpath(boxn, boxes, pp))
+ return NULL;
#ifdef DEBUG
if (debugleveln(realedge, 1))
else {
if (!(prev == -1 && next == -1)) {
agerr(AGERR, "in routesplines, illegal values of prev %d and next %d, line %d\n", prev, next, __LINE__);
- longjmp (jbuf, 1);
+ return NULL;
}
}
}
if (!(prev == -1 && next == -1)) {
/* it went badly, e.g. degenerate box in boxlist */
agerr(AGERR, "in routesplines, illegal values of prev %d and next %d, line %d\n", prev, next, __LINE__);
- longjmp (jbuf, 1); /* for correctness sake, it's best to just stop */
- return ps; /* could also be reported as a lost edge (no spline) */
+ return NULL; /* for correctness sake, it's best to just stop */
}
polypoints[pi].x = boxes[bi].UR.x;
polypoints[pi++].y = boxes[bi].LL.y;
}
else {
agerr(AGERR, "in routesplines, edge is a loop at %s\n", agnameof(aghead(realedge)));
- longjmp (jbuf, 1);
+ return NULL;
}
if (flip) {
eps[1].x = pp->end.p.x, eps[1].y = pp->end.p.y;
if (Pshortestpath(&poly, eps, &pl) < 0) {
agerr(AGERR, "in routesplines, Pshortestpath failed\n");
- longjmp (jbuf, 1);
+ return NULL;
}
#ifdef DEBUG
if (debugleveln(realedge, 3)) {
if (Proutespline(edges, poly.pn, pl, evs, &spl) < 0) {
agerr(AGERR, "in routesplines, Proutespline failed\n");
- longjmp (jbuf, 1);
+ return NULL;
}
#ifdef DEBUG
if (debugleveln(realedge, 3)) {
#endif
}
if (mkspacep(spl.pn))
- longjmp (jbuf, 1); /* Bailout if no memory left */
+ return NULL; /* Bailout if no memory left */
for (bi = 0; bi < boxn; bi++) {
boxes[bi].LL.x = INT_MAX;
* loop and we can see the bad edge, and even use the showboxes scaffolding.
*/
Ppolyline_t polyspl;
- agerr(AGWARN, "Unable to reclaim box space in spline routing. Something is probably seriously wrong.\n");
+ agerr(AGWARN, "Unable to reclaim box space in spline routing for edge \"%s\" -> \"%s\". Something is probably seriously wrong.\n", agnameof(agtail(realedge)), agnameof(aghead(realedge)));
make_polyline (pl, &polyspl);
limitBoxes (boxes, boxn, polyspl.ps, polyspl.pn, INIT_DELTA);
free (polyspl.ps);
pointf *routesplines(path * pp, int *npoints)
{
- if (setjmp (jbuf)) {
- *npoints = 0;
- return NULL;
- }
return _routesplines (pp, npoints, 0);
}
pointf *routepolylines(path * pp, int *npoints)
{
- if (setjmp (jbuf)) {
- *npoints = 0;
- return NULL;
- }
return _routesplines (pp, npoints, 1);
}
* audit process in the 5E control program - if you've given up on
* fixing all the bugs, at least try to engineer around them!
* in postmodern CS, we could call this "self-healing code."
+ *
+ * Return 1 on failure; 0 on success.
*/
-static void checkpath(int boxn, boxf* boxes, path* thepath)
+static int checkpath(int boxn, boxf* boxes, path* thepath)
{
boxf *ba, *bb;
int bi, i, errs, l, r, d, u;
if (ba->LL.x > ba->UR.x || ba->LL.y > ba->UR.y) {
agerr(AGERR, "in checkpath, box 0 has LL coord > UR coord\n");
printpath(thepath);
- longjmp (jbuf, 1);
+ return 1;
}
for (bi = 0; bi < boxn - 1; bi++) {
ba = &boxes[bi], bb = &boxes[bi + 1];
agerr(AGERR, "in checkpath, box %d has LL coord > UR coord\n",
bi + 1);
printpath(thepath);
- longjmp (jbuf, 1);
+ return 1;
}
l = (ba->UR.x < bb->LL.x) ? 1 : 0;
r = (ba->LL.x > bb->UR.x) ? 1 : 0;
abort();
#endif
}
+ return 0;
}
static int mkspacep(int size)