39static void printboxes(
size_t boxn,
boxf *boxes) {
42 for (
size_t bi = 0; bi < boxn; bi++) {
43 ll = boxes[bi].
LL, ur = boxes[bi].
UR;
45 agxbprint(&buf,
"%.0f %.0f %.0f %.0f pathbox", ll.
x, ll.
y, ur.
x, ur.
y);
51static void psprintpolypts(
Ppoint_t * p,
int sz)
55 fprintf(stderr,
"%%!\n");
56 fprintf(stderr,
"%% constraint poly\n");
57 fprintf(stderr,
"newpath\n");
58 for (i = 0; i < sz; i++)
59 fprintf(stderr,
"%f %f %s\n", p[i].x, p[i].y, i == 0 ?
"moveto" :
"lineto");
60 fprintf(stderr,
"closepath stroke\n");
62static void psprintpoint(
point p)
64 fprintf(stderr,
"gsave\n");
66 "newpath %d %d moveto %d %d 2 0 360 arc closepath fill stroke\n",
68 fprintf(stderr,
"/Times-Roman findfont 4 scalefont setfont\n");
69 fprintf(stderr,
"%d %d moveto (\\(%d,%d\\)) show\n", p.
x + 5, p.
y + 5,
71 fprintf(stderr,
"grestore\n");
73static void psprintpointf(
pointf p)
75 fprintf(stderr,
"gsave\n");
77 "newpath %.5g %.5g moveto %.5g %.5g 2 0 360 arc closepath fill stroke\n",
79 fprintf(stderr,
"/Times-Roman findfont 4 scalefont setfont\n");
80 fprintf(stderr,
"%.5g %.5g moveto (\\(%.5g,%.5g\\)) show\n", p.
x + 5, p.
y + 5,
82 fprintf(stderr,
"grestore\n");
91 for (
size_t i = 0; i < spl.
pn; i++) {
94 i == 0 ?
"moveto" : (i % 3 == 0 ?
"curveto" :
""));
105 for (
size_t i = 0; i < pl.
pn; i++) {
108 i == 0 ?
"moveto" :
"lineto");
114static void psprintpoly(
Ppoly_t p)
120 for (
size_t bi = 0; bi < p.
pn; bi++) {
123 if (fabs(tail.x -
head.x) < 1 && fabs(tail.y -
head.y) < 1) pfx =
"%%";
126 agxbprint(&buf,
"%s%.0f %.0f %.0f %.0f makevec", pfx, tail.x, tail.y,
head.x,
133static void psprintboxes(
size_t boxn,
boxf *boxes) {
138 for (
size_t bi = 0; bi < boxn; bi++) {
139 ll = boxes[bi].
LL, ur = boxes[bi].
UR;
141 agxbprint(&buf,
"newpath\n%.0f %.0f moveto", ll.
x, ll.
y);
154static void psprintinit (
int begin)
162static bool debugleveln(
edge_t* realedge,
int i)
191 for (
size_t i = 0; i <
poly.pn; i++) {
192 edges[i].
a =
poly.ps[i];
195 evs[0].
x = evs[0].
y = 0;
196 evs[1].
x = evs[1].
y = 0;
209 for (
size_t i = 0; i < spl.
pn; i++) {
238 "routesplines: %d edges, %" PRISIZE_T " boxes %.2f sec\n",
246 const double num_div =
delta * (double)boxn;
248 for (
size_t splinepi = 0; splinepi + 3 < pn; splinepi += 3) {
249 for (
double si = 0; si <= num_div; si++) {
251 sp[0] = pps[splinepi];
252 sp[1] = pps[splinepi + 1];
253 sp[2] = pps[splinepi + 2];
254 sp[3] = pps[splinepi + 3];
255 sp[0].
x += t * (sp[1].
x - sp[0].
x);
256 sp[0].
y += t * (sp[1].
y - sp[0].
y);
257 sp[1].
x += t * (sp[2].
x - sp[1].
x);
258 sp[1].
y += t * (sp[2].
y - sp[1].
y);
259 sp[2].
x += t * (sp[3].
x - sp[2].
x);
260 sp[2].
y += t * (sp[3].
y - sp[2].
y);
261 sp[0].
x += t * (sp[1].
x - sp[0].
x);
262 sp[0].
y += t * (sp[1].
y - sp[0].
y);
263 sp[1].
x += t * (sp[2].
x - sp[1].
x);
264 sp[1].
y += t * (sp[2].
y - sp[1].
y);
265 sp[0].
x += t * (sp[1].
x - sp[0].
x);
266 sp[0].
y += t * (sp[1].
y - sp[0].
y);
267 for (
size_t bi = 0; bi < boxn; bi++) {
271 if (sp[0].y <= boxes[bi].UR.y+
FUDGE && sp[0].
y >= boxes[bi].
LL.
y-
FUDGE) {
272 boxes[bi].
LL.
x = fmin(boxes[bi].LL.x, sp[0].
x);
273 boxes[bi].
UR.
x = fmax(boxes[bi].UR.x, sp[0].
x);
317 for (realedge = pp->
data;
321 agerrorf(
"in routesplines, cannot find NORMAL edge\n");
326 const size_t boxn = pp->
nbox;
332 if (debugleveln(realedge, 1))
333 printboxes(boxn, boxes);
334 if (debugleveln(realedge, 3)) {
336 psprintboxes(boxn, boxes);
343 if (boxn > 1 && boxes[0].LL.y > boxes[1].
LL.
y) {
345 for (
size_t bi = 0; bi < boxn; bi++) {
346 double v = boxes[bi].
UR.
y;
347 boxes[bi].
UR.
y = -1*boxes[bi].
LL.
y;
358 for (bi = 0, pi = 0; bi < boxn; bi++) {
361 prev = boxes[bi].
LL.
y > boxes[bi - 1].
LL.
y ? -1 : 1;
363 next = boxes[bi + 1].
LL.
y > boxes[bi].
LL.
y ? 1 : -1;
365 if (next == -1 ||
prev == 1) {
366 polypoints[pi].
x = boxes[bi].
LL.
x;
367 polypoints[pi++].
y = boxes[bi].
UR.
y;
368 polypoints[pi].
x = boxes[bi].
LL.
x;
369 polypoints[pi++].
y = boxes[bi].
LL.
y;
371 polypoints[pi].
x = boxes[bi].
UR.
x;
372 polypoints[pi++].
y = boxes[bi].
LL.
y;
373 polypoints[pi].
x = boxes[bi].
UR.
x;
374 polypoints[pi++].
y = boxes[bi].
UR.
y;
377 else if (
prev == 0) {
378 polypoints[pi].
x = boxes[bi].
LL.
x;
379 polypoints[pi++].
y = boxes[bi].
UR.
y;
380 polypoints[pi].
x = boxes[bi].
LL.
x;
381 polypoints[pi++].
y = boxes[bi].
LL.
y;
384 if (!(
prev == -1 && next == -1)) {
386 agerrorf(
"in routesplines, illegal values of prev %d and next %d, line %d\n",
prev, next, __LINE__);
391 for (bi = boxn - 1; bi !=
SIZE_MAX; bi--) {
394 prev = boxes[bi].
LL.
y > boxes[bi + 1].
LL.
y ? -1 : 1;
396 next = boxes[bi - 1].
LL.
y > boxes[bi].
LL.
y ? 1 : -1;
398 if (next == -1 ||
prev == 1 ) {
399 polypoints[pi].
x = boxes[bi].
LL.
x;
400 polypoints[pi++].
y = boxes[bi].
UR.
y;
401 polypoints[pi].
x = boxes[bi].
LL.
x;
402 polypoints[pi++].
y = boxes[bi].
LL.
y;
404 polypoints[pi].
x = boxes[bi].
UR.
x;
405 polypoints[pi++].
y = boxes[bi].
LL.
y;
406 polypoints[pi].
x = boxes[bi].
UR.
x;
407 polypoints[pi++].
y = boxes[bi].
UR.
y;
410 else if (
prev == 0) {
411 polypoints[pi].
x = boxes[bi].
UR.
x;
412 polypoints[pi++].
y = boxes[bi].
LL.
y;
413 polypoints[pi].
x = boxes[bi].
UR.
x;
414 polypoints[pi++].
y = boxes[bi].
UR.
y;
417 if (!(
prev == -1 && next == -1)) {
420 agerrorf(
"in routesplines, illegal values of prev %d and next %d, line %d\n",
prev, next, __LINE__);
423 polypoints[pi].
x = boxes[bi].
UR.
x;
424 polypoints[pi++].
y = boxes[bi].
LL.
y;
425 polypoints[pi].
x = boxes[bi].
UR.
x;
426 polypoints[pi++].
y = boxes[bi].
UR.
y;
427 polypoints[pi].
x = boxes[bi].
LL.
x;
428 polypoints[pi++].
y = boxes[bi].
UR.
y;
429 polypoints[pi].
x = boxes[bi].
LL.
x;
430 polypoints[pi++].
y = boxes[bi].
LL.
y;
441 for (
size_t bi = 0; bi < boxn; bi++) {
442 double v = boxes[bi].
UR.
y;
443 boxes[bi].
UR.
y = -1*boxes[bi].
LL.
y;
446 for (
size_t i = 0; i < pi; i++)
447 polypoints[i].y *= -1;
450 static const double INITIAL_LLX = DBL_MAX;
451 static const double INITIAL_URX = -DBL_MAX;
452 for (
size_t bi = 0; bi < boxn; bi++) {
453 boxes[bi].
LL.
x = INITIAL_LLX;
454 boxes[bi].
UR.
x = INITIAL_URX;
461 agerrorf(
"in routesplines, Pshortestpath failed\n");
465 if (debugleveln(realedge, 3)) {
476 for (
size_t edgei = 0; edgei <
poly.pn; edgei++) {
477 edges[edgei].
a = polypoints[edgei];
478 edges[edgei].
b = polypoints[(edgei + 1) %
poly.pn];
484 evs[0].
x = evs[0].
y = 0;
489 evs[1].
x = evs[1].
y = 0;
494 agerrorf(
"in routesplines, Proutespline failed\n");
499 if (debugleveln(realedge, 3)) {
513 for (
size_t splinepi = 0; splinepi < spl.
pn; splinepi++) {
514 ps[splinepi] = spl.
ps[splinepi];
518 for (loopcnt = 0; unbounded && loopcnt <
LOOP_TRIES; loopcnt++) {
527 for (bi = 0; bi < boxn; bi++) {
559 printboxes(boxn, boxes);
574static double overlap(
double i0,
double i1,
double j0,
double j1) {
581 if (i0 <= j0 && i1 >= j1)
584 if (j0 <= i0 && j1 >= i1)
587 if (j0 <= i0 && i0 <= j1)
589 assert(j0 <= i1 && i1 <= j1);
605 int errs, l, r, d, u;
609 for (
size_t bi = 0; bi < boxn; bi++) {
610 if (fabs(boxes[bi].LL.y - boxes[bi].
UR.
y) < .01)
612 if (fabs(boxes[bi].LL.x - boxes[bi].
UR.
x) < .01)
614 boxes[i] = boxes[bi];
621 agerrorf(
"in checkpath, box 0 has LL coord > UR coord\n");
625 for (
size_t bi = 0; bi + 1 < boxn; bi++) {
626 ba = &boxes[bi], bb = &boxes[bi + 1];
627 if (bb->LL.x > bb->UR.x || bb->LL.y > bb->UR.y) {
633 l = ba->
UR.
x < bb->LL.x ? 1 : 0;
634 r = ba->
LL.
x > bb->UR.x ? 1 : 0;
635 d = ba->
UR.
y < bb->LL.y ? 1 : 0;
636 u = ba->
LL.
y > bb->UR.y ? 1 : 0;
637 errs = l + r + d + u;
640 " don't touch\n", bi, bi + 1);
647 xy = ba->
UR.
x, ba->
UR.
x = bb->LL.x, bb->LL.x = xy, l = 0;
649 xy = ba->
LL.
x, ba->
LL.
x = bb->UR.x, bb->UR.x = xy, r = 0;
651 xy = ba->
UR.
y, ba->
UR.
y = bb->LL.y, bb->LL.y = xy, d = 0;
653 xy = ba->
LL.
y, ba->
LL.
y = bb->UR.y, bb->UR.y = xy, u = 0;
654 for (
int j = 0; j < errs - 1; j++) {
656 xy = (ba->
UR.
x + bb->LL.x) / 2.0 + 0.5, ba->
UR.
x =
657 bb->LL.x = xy, l = 0;
659 xy = (ba->
LL.
x + bb->UR.x) / 2.0 + 0.5, ba->
LL.
x =
660 bb->UR.x = xy, r = 0;
662 xy = (ba->
UR.
y + bb->LL.y) / 2.0 + 0.5, ba->
UR.
y =
663 bb->LL.y = xy, d = 0;
665 xy = (ba->
LL.
y + bb->UR.y) / 2.0 + 0.5, ba->
LL.
y =
666 bb->UR.y = xy, u = 0;
670 double xoverlap =
overlap(ba->
LL.
x, ba->
UR.
x, bb->LL.x, bb->UR.x);
671 double yoverlap =
overlap(ba->
LL.
y, ba->
UR.
y, bb->LL.y, bb->UR.y);
672 if (xoverlap > 0 && yoverlap > 0) {
673 if (xoverlap < yoverlap) {
674 if (ba->
UR.
x - ba->
LL.
x > bb->UR.x - bb->LL.x) {
676 if (ba->
UR.
x < bb->UR.x)
682 if (ba->
UR.
x < bb->UR.x)
688 if (ba->
UR.
y - ba->
LL.
y > bb->UR.y - bb->LL.y) {
690 if (ba->
UR.
y < bb->UR.y)
696 if (ba->
UR.
y < bb->UR.y)
710 fprintf(stderr,
"in checkpath, start port not in first box\n");
718 if (thepath->
end.
p.
x < boxes[boxn - 1].
LL.
x
719 || thepath->
end.
p.
x > boxes[boxn - 1].
UR.
x
720 || thepath->
end.
p.
y < boxes[boxn - 1].
LL.
y
721 || thepath->
end.
p.
y > boxes[boxn - 1].
UR.
y) {
723 fprintf(stderr,
"in checkpath, end port not in last box\n");
726 thepath->
end.
p.
x = fmax(thepath->
end.
p.
x, boxes[boxn - 1].
LL.
x);
727 thepath->
end.
p.
x = fmin(thepath->
end.
p.
x, boxes[boxn - 1].
UR.
x);
728 thepath->
end.
p.
y = fmax(thepath->
end.
p.
y, boxes[boxn - 1].
LL.
y);
729 thepath->
end.
p.
y = fmin(thepath->
end.
p.
y, boxes[boxn - 1].
UR.
y);
737 for (
size_t bi = 0; bi < pp->
nbox; bi++)
738 fprintf(stderr,
"%" PRISIZE_T " (%.5g, %.5g), (%.5g, %.5g)\n", bi,
741 fprintf(stderr,
"start port: (%.5g, %.5g), tangent angle: %.5g, %s\n",
744 fprintf(stderr,
"end port: (%.5g, %.5g), tangent angle: %.5g, %s\n",
773 const size_t cycle_len = nodes_size(cycle);
775 for (
size_t i=0; i < cycle_len; ++i) {
776 const node_t *c_start = nodes_get(cycle, i == 0 ? cycle_len - 1 : i - 1);
777 const node_t *c_end = nodes_get(cycle, i);
779 if (c_start == start && c_end == end)
790 const size_t cycle_len = nodes_size(cycle);
793 bool all_items_match;
795 for (
size_t c = 0; c < cycles_size(cycles); ++c) {
796 nodes_t *cur_cycle = cycles_get(cycles, c);
797 const size_t cur_cycle_len = nodes_size(cur_cycle);
800 if (cur_cycle_len == cycle_len) {
801 all_items_match =
true;
802 for (i=0; i < cur_cycle_len; ++i) {
803 node_t *cur_cycle_item = nodes_get(cur_cycle, i);
804 if (!nodes_contains(cycle, cur_cycle_item,
eq)) {
805 all_items_match =
false;
822 if (nodes_contains(visited, search,
eq)) {
825 nodes_t *cycle =
gv_alloc(
sizeof(nodes_t));
826 *cycle = nodes_copy(visited);
827 cycles_append(cycles, cycle);
831 nodes_append(visited, search);
834 dfs(g, n, visited, end, cycles);
836 if (!nodes_is_empty(visited)) {
837 (void)nodes_pop_back(visited);
847 cycles_t alloced_cycles = {0};
848 cycles_t cycles = {0};
851 nodes_t *cycle =
gv_alloc(
sizeof(nodes_t));
853 cycles_append(&alloced_cycles, cycle);
855 dfs(g, n, cycle, n, &cycles);
858 cycles_free(&alloced_cycles);
864 nodes_t *shortest =
NULL;
866 for (
size_t c = 0; c < cycles_size(cycles); ++c) {
867 nodes_t *cycle = cycles_get(cycles, c);
868 size_t cycle_len = nodes_size(cycle);
870 if (cycle_len < min_size)
873 if (shortest ==
NULL || nodes_size(shortest) > cycle_len) {
892 cycles_free(&cycles);
897 for (
size_t idx = 0; idx < nodes_size(cycle); ++idx) {
898 node_t *n = nodes_get(cycle, idx);
904 cycles_free(&cycles);
920 double vX = centroid.
x - midpt.
x;
921 double vY = centroid.
y - midpt.
y;
922 double magV = hypot(vX, vY);
923 if (magV == 0)
return;
924 a.
x = midpt.
x - vX / magV * r;
925 a.
y = midpt.
y - vY / magV * r;
928 spl[1].
x = spl[2].
x = a.
x;
929 spl[1].
y = spl[2].
y = a.
y;
944 for (
size_t i = 0; i < e_cnt; i++) {
948 assert(e_cnt <= INT_MAX);
980 .
x = dumb[0].
y - dumb[3].
y,
981 .y = dumb[3].
x - dumb[0].
x
985 assert(e_cnt - 1 <= INT_MAX);
986 int dx = xstep * (int)(e_cnt - 1) / 2;
987 dumb[1].
x = dumb[0].
x +
dx *
perp.
x / l_perp;
988 dumb[1].
y = dumb[0].
y +
dx *
perp.
y / l_perp;
989 dumb[2].
x = dumb[3].
x +
dx *
perp.
x / l_perp;
990 dumb[2].
y = dumb[3].
y +
dx *
perp.
y / l_perp;
995 for (
size_t i = 0; i < e_cnt; i++) {
996 edge_t *e0 = edge_list[i];
999 for (
size_t j = 0; j < 4; j++) {
1000 dumber[j] = dumb[j];
1003 for (
size_t j = 0; j < 4; j++) {
1004 dumber[3 - j] = dumb[j];
1008 Ppoint_t pts[] = {dumber[0], dumber[1], dumber[2], dumber[3]};
static int agxbprint(agxbuf *xb, const char *fmt,...)
Printf-style output to an agxbuf.
static char * agxbdisown(agxbuf *xb)
Memory allocation wrappers that exit on failure.
static char * gv_strdup(const char *original)
static void * gv_calloc(size_t nmemb, size_t size)
static void * gv_alloc(size_t size)
static void del(Dict_t *d, Dtlink_t **set, Agedge_t *e)
static double dist(int dim, double *x, double *y)
#define APPROXEQPT(p, q, tol)
geometric functions (e.g. on points and boxes)
static pointf mid_pointf(pointf p, pointf q)
static pointf add_pointf(pointf p, pointf q)
static pointf perp(pointf p)
static int cnt(Dict_t *d, Dtlink_t **set)
Agedge_t * agfstout(Agraph_t *g, Agnode_t *n)
Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)
void agwarningf(const char *fmt,...)
void agerrorf(const char *fmt,...)
Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
Agnode_t * agfstnode(Agraph_t *g)
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?
#define DEFINE_LIST_WITH_DTOR(name, type, dtor)
#define DEFINE_LIST(name, type)
finds and smooths shortest paths
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)
#define PRISIZE_T
PRIu64 alike for printing size_t
void clip_and_install(edge_t *fe, node_t *hn, pointf *ps, size_t pn, splineInfo *info)
void addEdgeLabels(edge_t *e)
static bool is_cycle_unique(cycles_t *cycles, nodes_t *cycle)
static void printpath(path *pp)
static pointf get_centroid(Agraph_t *g)
static void dfs(graph_t *g, node_t *search, nodes_t *visited, node_t *end, cycles_t *cycles)
int routesplinesinit(void)
static int nedges
total no. of edges used in routing
static void nodes_delete(nodes_t *pvec)
pointf * simpleSplineRoute(pointf tp, pointf hp, Ppoly_t poly, size_t *n_spl_pts, int polyline)
Given a simple (ccw) polygon, route an edge from tp to hp.
static nodes_t * find_shortest_cycle_with_edge(cycles_t *cycles, edge_t *edge, size_t min_size)
static bool eq(const node_t *a, const node_t *b)
static bool cycle_contains_edge(nodes_t *cycle, edge_t *edge)
static cycles_t find_all_cycles(graph_t *g)
static size_t nboxes
total no. of boxes used in routing
static void limitBoxes(boxf *boxes, size_t boxn, const pointf *pps, size_t pn, double delta)
static int checkpath(size_t, boxf *, path *)
static pointf get_cycle_centroid(graph_t *g, edge_t *edge)
static double overlap(double i0, double i1, double j0, double j1)
void routesplinesterm(void)
void makeStraightEdges(graph_t *g, edge_t **edge_list, size_t e_cnt, int et, splineInfo *sinfo)
void makeStraightEdge(graph_t *g, edge_t *e, int et, splineInfo *sinfo)
pointf * routesplines(path *pp, size_t *npoints)
pointf * routepolylines(path *pp, size_t *npoints)
static pointf * routesplines_(path *pp, size_t *npoints, int polyline)
Agraph_t * root
subgraphs - ancestors
size_t nbox
number of subdivisions