34#define MOVEPT(p) ((p).x += dx, (p).y += dy)
37static int GRID(
double x,
int s) {
38 const double required = ceil(x /
s);
44#define CVAL(v, s) ((v) >= 0 ? (v) / (s) : (((v) + 1) / (s)) - 1)
47#define CELL(p, s) ((p).x = CVAL((p).x, s), (p).y = CVAL((p).y, (s)))
71 a =
C * (double)ng - 1;
74 for (
size_t i = 0; i < ng; i++) {
76 W = bb.
UR.
x - bb.
LL.
x + 2 * margin;
77 H = bb.
UR.
y - bb.
LL.
y + 2 * margin;
81 d = b * b - 4.0 * a * c;
84 l1 = (-b + r) / (2 * a);
85 l2 = (-b - r) / (2 * a);
90 fprintf(stderr,
"Packing: compute grid size\n");
91 fprintf(stderr,
"a %f b %f c %f d %f r %f\n", a, b, c, d, r);
92 fprintf(stderr,
"root %d (%f) %d (%f)\n", root, l1, (
int)l2, l2);
93 fprintf(stderr,
" r1 %f r2 %f\n", a * l1 * l1 + b * l1 + c,
94 a * l2 * l2 + b * l2 + c);
103static int cmpf(
const void *
X,
const void *
Y) {
117static int sgn(
int x) {
return x > 0 ? 1 : -1; }
127 int d, x, y, ax, ay, sx, sy,
dx,
dy;
171 int ssize,
bool doS) {
189 for (
size_t j = 0; j <
ED_spl(e)->size; j++) {
206 for (; k < bz.
size; k++) {
234 const boxf bb = {.
LL = {.
x = round(bb0.
LL.
x), .y = round(bb0.
LL.
y)},
235 .UR = {.x = round(bb0.
UR.
x), .y = round(bb0.
UR.
y)}};
243 LL = (
pointf){.
x = round(LL.
x), .y = round(LL.
y)};
245 UR = (
pointf){.
x = round(UR.
x), .y = round(UR.
y)};
247 for (x = LL.
x; x <= UR.
x; x++)
248 for (y = LL.
y; y <= UR.
y; y++)
253 W =
GRID(bb0.
UR.
x - bb0.
LL.
x + 2 * margin, ssize);
254 H =
GRID(bb0.
UR.
y - bb0.
LL.
y + 2 * margin, ssize);
259 fprintf(stderr,
"%s no. cells %d W %d H %d\n",
s,
info->nc, W, H);
260 for (i = 0; i <
info->nc; i++)
261 fprintf(stderr,
" %.0f %.0f cell\n",
info->cells[i].x,
info->cells[i].y);
284 unsigned int margin = pinfo->
margin;
310 .
LL = {.
x = round(
GD_bb(subg).LL.x), .y = round(
GD_bb(subg).LL.y)},
311 .UR = {.x = round(
GD_bb(subg).UR.x), .y = round(
GD_bb(subg).UR.y)}};
324 for (
double x = bb.
LL.
x; x <= bb.
UR.
x; x++)
325 for (
double y = bb.
LL.
y; y <= bb.
UR.
y; y++)
337 pointf pt = {.
x = round(ptf.
x), .y = round(ptf.
y)};
341 .y = round(margin +
ND_ysize(n) / 2)};
345 LL = (
pointf){.
x = round(LL.
x), .y = round(LL.
y)};
347 UR = (
pointf){.
x = round(UR.
x), .y = round(UR.
y)};
349 for (
double x = LL.
x; x <= UR.
x; x++)
350 for (
double y = LL.
y; y <= UR.
y; y++)
354 pt = (
pointf){.
x = round(pt.
x), .y = round(pt.
y)};
360 pt = (
pointf){.
x = round(pt.
x), .y = round(pt.
y)};
378 pointf pt = {.
x = round(ptf.
x), .y = round(ptf.
y)};
381 .y = round(margin +
ND_ysize(n) / 2)};
385 LL = (
pointf){.
x = round(LL.
x), .y = round(LL.
y)};
387 UR = (
pointf){.
x = round(UR.
x), .y = round(UR.
y)};
389 for (
double x = LL.
x; x <= UR.
x; x++)
390 for (
double y = LL.
y; y <= UR.
y; y++)
394 pt = (
pointf){.
x = round(pt.
x), .y = round(pt.
y)};
408 fprintf(stderr,
"%s no. cells %d W %d H %d\n",
agnameof(g),
info->nc, W, H);
409 for (i = 0; i <
info->nc; i++)
410 fprintf(stderr,
" %.0f %.0f cell\n",
info->cells[i].x,
info->cells[i].y);
421 int step,
const boxf *bbs) {
426 for (i = 0; i < n; i++) {
436 .y = round(bbs[
info->index].
LL.
y)};
437 place->
x = step * x - LL.
x;
438 place->
y = step * y - LL.
y;
441 for (i = 0; i < n; i++) {
450 fprintf(stderr,
"cc (%d cells) at (%d,%d) (%.0f,%.0f)\n", n, x, y, place->
x,
468 for (i = 0; i < n; i++) {
473 fprintf(stderr,
"cc (%d cells) at (%.0f,%.0f)\n", n, place->
x, place->
y);
482 int step,
unsigned int margin,
const boxf *bbs) {
488 const int W =
GRID(bb.
UR.
x - bb.
LL.
x + 2 * margin, step);
489 const int H =
GRID(bb.
UR.
y - bb.
LL.
y + 2 * margin, step);
490 if (
fits(-W / 2, -H / 2,
info, ps, place, step, bbs))
494 if (
fits(0, 0,
info, ps, place, step, bbs))
496 const double W = ceil(bb.
UR.
x - bb.
LL.
x);
497 const double H = ceil(bb.
UR.
y - bb.
LL.
y);
499 for (bnd = 1;; bnd++) {
503 if (
fits(x, y,
info, ps, place, step, bbs))
506 if (
fits(x, y,
info, ps, place, step, bbs))
508 for (; x > -bnd; x--)
509 if (
fits(x, y,
info, ps, place, step, bbs))
511 for (; y > -bnd; y--)
512 if (
fits(x, y,
info, ps, place, step, bbs))
515 if (
fits(x, y,
info, ps, place, step, bbs))
519 for (bnd = 1;; bnd++) {
522 for (; y > -bnd; y--)
523 if (
fits(x, y,
info, ps, place, step, bbs))
526 if (
fits(x, y,
info, ps, place, step, bbs))
529 if (
fits(x, y,
info, ps, place, step, bbs))
531 for (; x > -bnd; x--)
532 if (
fits(x, y,
info, ps, place, step, bbs))
535 if (
fits(x, y,
info, ps, place, step, bbs))
544 int i, c_cnt =
info->nc;
546 fprintf(stderr,
"%s\n", pfx);
547 for (i = 0; i < c_cnt; i++) {
548 fprintf(stderr,
"%.0f %.0f box\n", cells[i].x, cells[i].y);
554static int ucmpf(
const void *
X,
const void *
Y,
void *user_values) {
559 const unsigned int dX = userVals[x->
index];
560 const unsigned int dY = userVals[y->
index];
569static int acmpf(
const void *
X,
const void *
Y) {
588static void INC(
bool m,
size_t *c,
size_t *r,
size_t nc,
size_t nr) {
620 nc = (ng + (nr - 1)) / nr;
623 nc = (ng + (nr - 1)) / nr;
629 nr = (ng + (nc - 1)) / nc;
632 nr = (ng + (nc - 1)) / nc;
638 rowMajor ?
"row major" :
"column major", nr, nc);
639 double *widths =
gv_calloc(nc + 1,
sizeof(
double));
640 double *heights =
gv_calloc(nr + 1,
sizeof(
double));
643 for (
size_t i = 0; i < ng; i++, ip++) {
651 for (
size_t i = 0; i < ng; i++) {
663 for (
size_t i = 0; i < ng; i++, ip++) {
665 widths[c] = fmax(widths[c], ip->
width);
666 heights[r] = fmax(heights[r], ip->
height);
667 INC(rowMajor, &c, &r, nc, nr);
672 for (
size_t i = 0; i <= nc; i++) {
679 for (
size_t i = nr; 0 < i; i--) {
688 for (
size_t i = 0; i < ng; i++, ip++) {
690 const size_t idx = ip->
index;
693 places[idx].
x = round(widths[c]);
695 places[idx].
x = round(widths[c + 1] - (bb.
UR.
x - bb.
LL.
x));
698 round((widths[c] + widths[c + 1] - bb.
UR.
x - bb.
LL.
x) / 2.0);
700 places[idx].
y = round(heights[r] - (bb.
UR.
y - bb.
LL.
y));
702 places[idx].
y = round(heights[r + 1]);
705 round((heights[r] + heights[r + 1] - bb.
UR.
y - bb.
LL.
y) / 2.0);
706 INC(rowMajor, &c, &r, nc, nr);
723 fprintf(stderr,
"step size = %d\n", stepSize);
729 for (
size_t i = 0; i < ng; i++) {
736 for (
size_t i = 0; i < ng; i++) {
743 for (
size_t i = 0; i < ng; i++)
748 for (
size_t i = 0; i < ng; i++)
754 for (
size_t i = 0; i < ng; i++)
755 fprintf(stderr,
"pos[%" PRISIZE_T "] %.0f %.0f\n", i, places[i].x,
790 bool *fixed = pinfo->
fixed;
792 boxf fixed_bb = {{0, 0}, {0, 0}};
799 for (
size_t i = 0; i < ng; i++) {
802 if (fixed && fixed[i]) {
804 .
LL = {.
x = round(
GD_bb(g).LL.x), .y = round(
GD_bb(g).LL.y)},
805 .UR = {.x = round(
GD_bb(g).UR.x), .y = round(
GD_bb(g).UR.y)}};
807 fixed_bb.
LL.
x = fmin(bb.
LL.
x, fixed_bb.
LL.
x);
808 fixed_bb.
LL.
y = fmin(bb.
LL.
y, fixed_bb.
LL.
y);
809 fixed_bb.
UR.
x = fmax(bb.
UR.
x, fixed_bb.
UR.
x);
810 fixed_bb.
UR.
y = fmax(bb.
UR.
y, fixed_bb.
UR.
y);
816 fprintf(stderr,
"bb[%s] %.5g %.5g %.5g %.5g\n",
agnameof(g),
823 for (
size_t i = 0; i < ng; i++)
824 bbs[i] =
GD_bb(gs[i]);
827 fprintf(stderr,
"step size = %d\n", stepSize);
840 for (
size_t i = 0; i < ng; i++) {
853 for (
size_t i = 0; i < ng; i++) {
861 for (
size_t i = 0; i < ng; i++) {
865 for (
size_t i = 0; i < ng; i++) {
871 for (
size_t i = 0; i < ng; i++)
877 for (
size_t i = 0; i < ng; i++)
884 for (
size_t i = 0; i < ng; i++)
885 fprintf(stderr,
"pos[%" PRISIZE_T "] %.0f %.0f\n", i, places[i].x,
905 for (
size_t i = 0; i < ng; i++) {
914 for (
size_t i = 0; i < ng; i++) {
915 s =
agget(gs[i],
"sortv");
916 if (
s && sscanf(
s,
"%d", &v) > 0 && v >= 0)
961 for (
size_t i = 0; i < ng; i++) {
987 for (
size_t j = 0; j <
ED_spl(e)->size; j++) {
989 for (
size_t k = 0; k < bz.
size; k++)
1051 for (
size_t i = 0; i < ng; i++) {
1058 const double dx = p.
x;
1059 const double dy = p.
y;
1118 for (
size_t i = 0; i < ng; i++) {
1135 info.doSplines =
true;
1150 while (more && (c = *p)) {
1223 p += strlen(
"array");
1225 if (sscanf(p,
"%d", &i) > 0 && i > 0)
1229 if (sscanf(p + strlen(
"aspect"),
"%f", &v) > 0 && v > 0)
1233 }
else if (
streq(p,
"cluster")) {
1235 }
else if (
streq(p,
"graph")) {
1237 }
else if (
streq(p,
"node")) {
1243 fprintf(stderr,
"pack info:\n");
1246 fprintf(stderr,
" aspect %f\n", pinfo->
aspect);
1247 fprintf(stderr,
" size %d\n", pinfo->
sz);
1248 fprintf(stderr,
" flags %d\n", pinfo->
flags);
1274 if ((p =
agget(g,
"pack"))) {
1275 if (sscanf(p,
"%d", &i) == 1 && i >= 0)
1277 else if (*p ==
't' || *p ==
'T')
1290 fprintf(stderr,
" margin %u\n", pinfo->
margin);
Memory allocation wrappers that exit on failure.
static void * gv_calloc(size_t nmemb, size_t size)
void compute_bb(graph_t *g)
#define X(prefix, name, str, type, subtype,...)
#define PS2INCH(a_points)
geometric functions (e.g. on points and boxes)
static WUR pointf sub_pointf(pointf p, pointf q)
static WUR pointf add_pointf(pointf p, pointf q)
int agnnodes(Agraph_t *g)
char * agget(void *obj, char *name)
Agedge_t * agfstout(Agraph_t *g, Agnode_t *n)
Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)
Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
Agnode_t * agfstnode(Agraph_t *g)
char * agnameof(void *)
returns a string descriptor for the object.
static int genPoly(Agraph_t *root, Agraph_t *g, ginfo *info, int ssize, pack_info *pinfo, pointf center)
pack_mode getPackModeInfo(Agraph_t *g, pack_mode dflt, pack_info *pinfo)
pack_mode parsePackModeInfo(const char *p, pack_mode dflt, pack_info *pinfo)
static int computeStep(size_t ng, const boxf *bbs, unsigned int margin)
static const char * chkFlags(const char *p, pack_info *pinfo)
static pointf * arrayRects(size_t ng, const boxf *gs, pack_info *pinfo)
static int ucmpf(const void *X, const void *Y, void *user_values)
Sort by user values.
static int sgn(int x)
sgn, as defined in Graphics Gems I, §11.8, pp. 99
pack_mode getPackMode(Agraph_t *g, pack_mode dflt)
static const char * mode2Str(pack_mode m)
static int cmpf(const void *X, const void *Y)
static void shiftGraph(Agraph_t *g, double dx, double dy)
pointf * putRects(size_t ng, boxf *bbs, pack_info *pinfo)
int packSubgraphs(size_t ng, Agraph_t **gs, Agraph_t *root, pack_info *info)
int pack_graph(size_t ng, Agraph_t **gs, Agraph_t *root, bool *fixed)
Pack subgraphs followed by postprocessing.
int getPack(Agraph_t *g, int not_def, int dflt)
static int fits(int x, int y, ginfo *info, PointSet *ps, pointf *place, int step, const boxf *bbs)
int packRects(size_t ng, boxf *bbs, pack_info *pinfo)
static void placeFixed(ginfo *info, PointSet *ps, pointf *place, pointf center)
int packGraphs(size_t ng, Agraph_t **gs, Agraph_t *root, pack_info *info)
static pointf * polyRects(size_t ng, const boxf *gs, pack_info *pinfo)
static int GRID(double x, int s)
given cell size s, how many cells are required by size x?
static void fillLine(pointf p, pointf q, PointSet *ps)
static int acmpf(const void *X, const void *Y)
Sort by height + width.
static pointf * polyGraphs(size_t ng, Agraph_t **gs, Agraph_t *root, pack_info *pinfo)
static void fillEdge(Agedge_t *e, pointf p, PointSet *ps, double dx, double dy, int ssize, bool doS)
int shiftGraphs(size_t ng, Agraph_t **gs, pointf *pp, Agraph_t *root, bool doSplines)
pack_mode getPackInfo(Agraph_t *g, pack_mode dflt, int dfltMargin, pack_info *pinfo)
static void placeGraph(size_t i, ginfo *info, PointSet *ps, pointf *place, int step, unsigned int margin, const boxf *bbs)
static void genBox(boxf bb0, ginfo *info, int ssize, unsigned int margin, pointf center, char *s)
pointf * putGraphs(size_t ng, Agraph_t **gs, Agraph_t *root, pack_info *pinfo)
static void shiftEdge(Agedge_t *e, double dx, double dy)
Translate all of the edge components by the given offset.
support for connected components
void addPS(PointSet *ps, double x, double y)
void insertPS(PointSet *ps, pointf pt)
void freePS(PointSet *ps)
pointf * pointsOf(PointSet *ps)
int inPS(PointSet *ps, pointf pt)
point containers PointSet and PointMap
void dotneato_postprocess(Agraph_t *g)
qsort with carried along context
static void gv_sort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *, void *), void *arg)
qsort with an extra state parameter, ala qsort_r
static bool startswith(const char *s, const char *prefix)
does the string s begin with the string prefix?
static bool streq(const char *a, const char *b)
are a and b equal?
size_t index
index in original array
result of partitioning available space, part of maze
size_t index
index in original array
pointf * cells
cells in covering polyomino
bool doSplines
use splines in constructing graph shape
static point center(point vertex[], size_t n)