31#define MOVEPT(p) ((p).x += dx, (p).y += dy)
34static int GRID(
double x,
int s) {
35 const double required = ceil(x /
s);
41#define CVAL(v, s) ((v) >= 0 ? (v) / (s) : (((v) + 1) / (s)) - 1)
44#define CELL(p, s) ((p).x = CVAL((p).x, s), (p).y = CVAL((p).y, (s)))
68 a =
C * (double)ng - 1;
71 for (
size_t i = 0; i < ng; i++) {
73 W = bb.
UR.
x - bb.
LL.
x + 2 * margin;
74 H = bb.
UR.
y - bb.
LL.
y + 2 * margin;
78 d = b * b - 4.0 * a * c;
81 l1 = (-b + r) / (2 * a);
82 l2 = (-b - r) / (2 * a);
87 fprintf(stderr,
"Packing: compute grid size\n");
88 fprintf(stderr,
"a %f b %f c %f d %f r %f\n", a, b, c, d, r);
89 fprintf(stderr,
"root %d (%f) %d (%f)\n", root, l1, (
int)l2, l2);
90 fprintf(stderr,
" r1 %f r2 %f\n", a * l1 * l1 + b * l1 + c,
91 a * l2 * l2 + b * l2 + c);
100static int cmpf(
const void *
X,
const void *
Y) {
114static int sgn(
int x) {
return x > 0 ? 1 : -1; }
124 int d, x, y, ax, ay, sx, sy,
dx,
dy;
168 int ssize,
bool doS) {
186 for (
size_t j = 0; j <
ED_spl(e)->size; j++) {
203 for (; k < bz.
size; k++) {
231 const boxf bb = {.
LL = {.
x = round(bb0.
LL.
x), .y = round(bb0.
LL.
y)},
232 .UR = {.x = round(bb0.
UR.
x), .y = round(bb0.
UR.
y)}};
240 LL = (
pointf){.
x = round(LL.
x), .y = round(LL.
y)};
242 UR = (
pointf){.
x = round(UR.
x), .y = round(UR.
y)};
244 for (x = LL.
x; x <= UR.
x; x++)
245 for (y = LL.
y; y <= UR.
y; y++)
250 W =
GRID(bb0.
UR.
x - bb0.
LL.
x + 2 * margin, ssize);
251 H =
GRID(bb0.
UR.
y - bb0.
LL.
y + 2 * margin, ssize);
256 fprintf(stderr,
"%s no. cells %d W %d H %d\n",
s,
info->nc, W, H);
257 for (i = 0; i <
info->nc; i++)
258 fprintf(stderr,
" %.0f %.0f cell\n",
info->cells[i].x,
info->cells[i].y);
281 unsigned int margin = pinfo->
margin;
307 .
LL = {.
x = round(
GD_bb(subg).LL.x), .y = round(
GD_bb(subg).LL.y)},
308 .UR = {.x = round(
GD_bb(subg).UR.x), .y = round(
GD_bb(subg).UR.y)}};
321 for (
double x = bb.
LL.
x; x <= bb.
UR.
x; x++)
322 for (
double y = bb.
LL.
y; y <= bb.
UR.
y; y++)
334 pointf pt = {.
x = round(ptf.
x), .y = round(ptf.
y)};
338 .y = round(margin +
ND_ysize(n) / 2)};
342 LL = (
pointf){.
x = round(LL.
x), .y = round(LL.
y)};
344 UR = (
pointf){.
x = round(UR.
x), .y = round(UR.
y)};
346 for (
double x = LL.
x; x <= UR.
x; x++)
347 for (
double y = LL.
y; y <= UR.
y; y++)
351 pt = (
pointf){.
x = round(pt.
x), .y = round(pt.
y)};
357 pt = (
pointf){.
x = round(pt.
x), .y = round(pt.
y)};
375 pointf pt = {.
x = round(ptf.
x), .y = round(ptf.
y)};
378 .y = round(margin +
ND_ysize(n) / 2)};
382 LL = (
pointf){.
x = round(LL.
x), .y = round(LL.
y)};
384 UR = (
pointf){.
x = round(UR.
x), .y = round(UR.
y)};
386 for (
double x = LL.
x; x <= UR.
x; x++)
387 for (
double y = LL.
y; y <= UR.
y; y++)
391 pt = (
pointf){.
x = round(pt.
x), .y = round(pt.
y)};
405 fprintf(stderr,
"%s no. cells %d W %d H %d\n",
agnameof(g),
info->nc, W, H);
406 for (i = 0; i <
info->nc; i++)
407 fprintf(stderr,
" %.0f %.0f cell\n",
info->cells[i].x,
info->cells[i].y);
418 int step,
boxf *bbs) {
423 for (i = 0; i < n; i++) {
433 .y = round(bbs[
info->index].
LL.
y)};
434 place->
x = step * x - LL.
x;
435 place->
y = step * y - LL.
y;
438 for (i = 0; i < n; i++) {
447 fprintf(stderr,
"cc (%d cells) at (%d,%d) (%.0f,%.0f)\n", n, x, y, place->
x,
465 for (i = 0; i < n; i++) {
470 fprintf(stderr,
"cc (%d cells) at (%.0f,%.0f)\n", n, place->
x, place->
y);
479 int step,
unsigned int margin,
boxf *bbs) {
485 const int W =
GRID(bb.
UR.
x - bb.
LL.
x + 2 * margin, step);
486 const int H =
GRID(bb.
UR.
y - bb.
LL.
y + 2 * margin, step);
487 if (
fits(-W / 2, -H / 2,
info,
ps, place, step, bbs))
493 const double W = ceil(bb.
UR.
x - bb.
LL.
x);
494 const double H = ceil(bb.
UR.
y - bb.
LL.
y);
496 for (bnd = 1;; bnd++) {
505 for (; x > -bnd; x--)
508 for (; y > -bnd; y--)
516 for (bnd = 1;; bnd++) {
519 for (; y > -bnd; y--)
528 for (; x > -bnd; x--)
541 int i, c_cnt =
info->nc;
543 fprintf(stderr,
"%s\n", pfx);
544 for (i = 0; i < c_cnt; i++) {
545 fprintf(stderr,
"%.0f %.0f box\n", cells[i].x, cells[i].y);
551static int ucmpf(
const void *
X,
const void *
Y,
void *user_values) {
556 const unsigned int dX = userVals[x->
index];
557 const unsigned int dY = userVals[y->
index];
566static int acmpf(
const void *
X,
const void *
Y) {
585static void INC(
bool m,
size_t *c,
size_t *r,
size_t nc,
size_t nr) {
617 nc = (ng + (nr - 1)) / nr;
620 nc = (ng + (nr - 1)) / nr;
626 nr = (ng + (nc - 1)) / nc;
629 nr = (ng + (nc - 1)) / nc;
635 rowMajor ?
"row major" :
"column major", nr, nc);
636 double *widths =
gv_calloc(nc + 1,
sizeof(
double));
637 double *heights =
gv_calloc(nr + 1,
sizeof(
double));
640 for (
size_t i = 0; i < ng; i++, ip++) {
648 for (
size_t i = 0; i < ng; i++) {
660 for (
size_t i = 0; i < ng; i++, ip++) {
662 widths[c] = fmax(widths[c], ip->
width);
663 heights[r] = fmax(heights[r], ip->
height);
664 INC(rowMajor, &c, &r, nc, nr);
669 for (
size_t i = 0; i <= nc; i++) {
676 for (
size_t i = nr; 0 < i; i--) {
685 for (
size_t i = 0; i < ng; i++, ip++) {
687 const size_t idx = ip->
index;
690 places[idx].
x = round(widths[c]);
692 places[idx].
x = round(widths[c + 1] - (bb.
UR.
x - bb.
LL.
x));
695 round((widths[c] + widths[c + 1] - bb.
UR.
x - bb.
LL.
x) / 2.0);
697 places[idx].
y = round(heights[r] - (bb.
UR.
y - bb.
LL.
y));
699 places[idx].
y = round(heights[r + 1]);
702 round((heights[r] + heights[r + 1] - bb.
UR.
y - bb.
LL.
y) / 2.0);
703 INC(rowMajor, &c, &r, nc, nr);
720 fprintf(stderr,
"step size = %d\n", stepSize);
726 for (
size_t i = 0; i < ng; i++) {
733 for (
size_t i = 0; i < ng; i++) {
740 for (
size_t i = 0; i < ng; i++)
745 for (
size_t i = 0; i < ng; i++)
751 for (
size_t i = 0; i < ng; i++)
752 fprintf(stderr,
"pos[%" PRISIZE_T "] %.0f %.0f\n", i, places[i].x,
787 bool *fixed = pinfo->
fixed;
789 boxf fixed_bb = {{0, 0}, {0, 0}};
796 for (
size_t i = 0; i < ng; i++) {
799 if (fixed && fixed[i]) {
801 .
LL = {.
x = round(
GD_bb(g).LL.x), .y = round(
GD_bb(g).LL.y)},
802 .UR = {.x = round(
GD_bb(g).UR.x), .y = round(
GD_bb(g).UR.y)}};
804 fixed_bb.
LL.
x = fmin(bb.
LL.
x, fixed_bb.
LL.
x);
805 fixed_bb.
LL.
y = fmin(bb.
LL.
y, fixed_bb.
LL.
y);
806 fixed_bb.
UR.
x = fmax(bb.
UR.
x, fixed_bb.
UR.
x);
807 fixed_bb.
UR.
y = fmax(bb.
UR.
y, fixed_bb.
UR.
y);
813 fprintf(stderr,
"bb[%s] %.5g %.5g %.5g %.5g\n",
agnameof(g),
820 for (
size_t i = 0; i < ng; i++)
821 bbs[i] =
GD_bb(gs[i]);
824 fprintf(stderr,
"step size = %d\n", stepSize);
837 for (
size_t i = 0; i < ng; i++) {
850 for (
size_t i = 0; i < ng; i++) {
858 for (
size_t i = 0; i < ng; i++) {
862 for (
size_t i = 0; i < ng; i++) {
868 for (
size_t i = 0; i < ng; i++)
874 for (
size_t i = 0; i < ng; i++)
881 for (
size_t i = 0; i < ng; i++)
882 fprintf(stderr,
"pos[%" PRISIZE_T "] %.0f %.0f\n", i, places[i].x,
902 for (
size_t i = 0; i < ng; i++) {
911 for (
size_t i = 0; i < ng; i++) {
912 s =
agget(gs[i],
"sortv");
913 if (
s && sscanf(
s,
"%d", &v) > 0 && v >= 0)
958 for (
size_t i = 0; i < ng; i++) {
984 for (
size_t j = 0; j <
ED_spl(e)->size; j++) {
986 for (
size_t k = 0; k < bz.
size; k++)
1048 for (
size_t i = 0; i < ng; i++) {
1055 const double dx = p.
x;
1056 const double dy = p.
y;
1115 for (
size_t i = 0; i < ng; i++) {
1132 info.doSplines =
true;
1147 while (more && (c = *p)) {
1220 p += strlen(
"array");
1222 if (sscanf(p,
"%d", &i) > 0 && i > 0)
1226 if (sscanf(p + strlen(
"aspect"),
"%f", &v) > 0 && v > 0)
1230 }
else if (
streq(p,
"cluster")) {
1232 }
else if (
streq(p,
"graph")) {
1234 }
else if (
streq(p,
"node")) {
1240 fprintf(stderr,
"pack info:\n");
1243 fprintf(stderr,
" aspect %f\n", pinfo->
aspect);
1244 fprintf(stderr,
" size %d\n", pinfo->
sz);
1245 fprintf(stderr,
" flags %d\n", pinfo->
flags);
1271 if ((p =
agget(g,
"pack"))) {
1272 if (sscanf(p,
"%d", &i) == 1 && i >= 0)
1274 else if (*p ==
't' || *p ==
'T')
1287 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)
static pointf add_pointf(pointf p, pointf q)
static pointf sub_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 pointf * arrayRects(size_t ng, boxf *gs, pack_info *pinfo)
static int fits(int x, int y, ginfo *info, PointSet *ps, pointf *place, int step, boxf *bbs)
static const char * chkFlags(const char *p, 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 pointf * polyRects(size_t ng, boxf *gs, pack_info *pinfo)
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)
static void placeGraph(size_t i, ginfo *info, PointSet *ps, pointf *place, int step, unsigned int margin, boxf *bbs)
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)
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 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 computeStep(size_t ng, boxf *bbs, unsigned int margin)
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 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)
#define PRISIZE_T
PRIu64 alike for printing size_t
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)