32#define MOVEPT(p) ((p).x += dx, (p).y += dy)
34#define GRID(x,s) ((int)ceil((x)/(s)))
36#define CVAL(v,s) ((v) >= 0 ? (v)/(s) : (((v)+1)/(s))-1)
38#define CELL(p,s) ((p).x = CVAL((p).x,s), (p).y = CVAL((p).y,(s)))
62 a =
C * (double)ng - 1;
65 for (
size_t i = 0; i < ng; i++) {
67 W = bb.
UR.
x - bb.
LL.
x + 2 * margin;
68 H = bb.
UR.
y - bb.
LL.
y + 2 * margin;
72 d = b * b - 4.0 * a * c;
74 agerrorf(
"libpack: disc = %f ( < 0)\n", d);
78 l1 = (-b + r) / (2 * a);
79 l2 = (-b - r) / (2 * a);
81 if (root == 0) root = 1;
83 fprintf(stderr,
"Packing: compute grid size\n");
84 fprintf(stderr,
"a %f b %f c %f d %f r %f\n", a, b, c, d, r);
85 fprintf(stderr,
"root %d (%f) %d (%f)\n", root, l1, (
int) l2,
87 fprintf(stderr,
" r1 %f r2 %f\n", a * l1 * l1 + b * l1 + c,
88 a * l2 * l2 + b * l2 + c);
97static int cmpf(
const void *
X,
const void *
Y)
113 return x > 0 ? 1 : -1;
125 int d, x, y, ax, ay, sx, sy,
dx,
dy;
169 int ssize,
bool doS) {
187 for (
size_t j = 0; j <
ED_spl(e)->size; j++) {
204 for (; k < bz.
size; k++) {
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",
258 for (i = 0; i <
info->nc; i++)
259 fprintf(stderr,
" %.0f %.0f cell\n",
info->cells[i].x,
283 unsigned int margin = pinfo->
margin;
319 for (
double x = bb.
LL.
x; x <= bb.
UR.
x; x++)
320 for (
double y = bb.
LL.
y; y <= bb.
UR.
y; y++)
341 for (
double x = LL.
x; x <= UR.
x; x++)
342 for (
double y = LL.
y; y <= UR.
y; y++)
376 for (
double x = LL.
x; x <= UR.
x; x++)
377 for (
double y = LL.
y; y <= UR.
y; y++)
394 fprintf(stderr,
"%s no. cells %d W %d H %d\n",
396 for (i = 0; i <
info->nc; i++)
397 fprintf(stderr,
" %.0f %.0f cell\n",
info->cells[i].x,
409 int step,
boxf *bbs) {
414 for (i = 0; i < n; i++) {
424 place->
x = step * x - LL.
x;
425 place->
y = step * y - LL.
y;
428 for (i = 0; i < n; i++) {
437 fprintf(stderr,
"cc (%d cells) at (%d,%d) (%.0f,%.0f)\n", n, x, y,
455 for (i = 0; i < n; i++) {
460 fprintf(stderr,
"cc (%d cells) at (%.0f,%.0f)\n", n, place->
x,
470 int step,
unsigned int margin,
boxf* bbs) {
476 const int W =
GRID(bb.
UR.
x - bb.
LL.
x + 2 * margin, step);
477 const int H =
GRID(bb.
UR.
y - bb.
LL.
y + 2 * margin, step);
478 if (
fits(-W / 2, -H / 2,
info,
ps, place, step, bbs))
484 const double W = ceil(bb.
UR.
x - bb.
LL.
x);
485 const double H = ceil(bb.
UR.
y - bb.
LL.
y);
487 for (bnd = 1;; bnd++) {
496 for (; x > -bnd; x--)
499 for (; y > -bnd; y--)
507 for (bnd = 1;; bnd++) {
510 for (; y > -bnd; y--)
519 for (; x > -bnd; x--)
533 int i, c_cnt =
info->nc;
535 fprintf(stderr,
"%s\n", pfx);
536 for (i = 0; i < c_cnt; i++) {
537 fprintf(stderr,
"%.0f %.0f box\n", cells[i].x, cells[i].y);
543static int ucmpf(
const void *
X,
const void *
Y,
void *user_values) {
548 const unsigned int dX = userVals[x->
index];
549 const unsigned int dY = userVals[y->
index];
550 if (dX > dY)
return 1;
551 if (dX < dY)
return -1;
562 if (dX < dY)
return 1;
563 if (dX > dY)
return -1;
568 if (m){ c++; if (c == nc) { c = 0; r++; } } \
569 else { r++; if (r == nr) { r = 0; c++; } }
586 nc = (ng + (nr-1))/nr;
590 nc = (ng + (nr-1))/nr;
597 nr = (ng + (nc-1))/nc;
601 nr = (ng + (nc-1))/nc;
606 " columns\n", rowMajor ?
"row major" :
"column major", nr, nc);
607 double *widths =
gv_calloc(nc + 1,
sizeof(
double));
608 double *heights =
gv_calloc(nr + 1,
sizeof(
double));
611 for (
size_t i = 0; i < ng; i++, ip++) {
619 for (
size_t i = 0; i < ng; i++) {
632 for (
size_t i = 0; i < ng; i++, ip++) {
634 widths[c] = fmax(widths[c], ip->
width);
635 heights[r] = fmax(heights[r], ip->
height);
641 for (
size_t i = 0; i <= nc; i++) {
648 for (
size_t i = nr; 0 < i; i--) {
657 for (
size_t i = 0; i < ng; i++, ip++) {
659 const size_t idx = ip->
index;
662 places[idx].
x = widths[c];
664 places[idx].
x = widths[c+1] - (bb.
UR.
x - bb.
LL.
x);
666 places[idx].
x = (widths[c] + widths[c+1] - bb.
UR.
x - bb.
LL.
x)/2.0;
668 places[idx].
y = heights[r] - (bb.
UR.
y - bb.
LL.
y);
670 places[idx].
y = heights[r+1];
672 places[idx].
y = (heights[r] + heights[r+1] - bb.
UR.
y - bb.
LL.
y)/2.0;
690 fprintf(stderr,
"step size = %d\n", stepSize);
696 for (
size_t i = 0; i < ng; i++) {
703 for (
size_t i = 0; i < ng; i++) {
710 for (
size_t i = 0; i < ng; i++)
712 stepSize, pinfo->
margin, gs);
715 for (
size_t i = 0; i < ng; i++)
721 for (
size_t i = 0; i < ng; i++)
722 fprintf(stderr,
"pos[%" PRISIZE_T "] %.0f %.0f\n", i, places[i].x,
757 bool *fixed = pinfo->
fixed;
759 boxf fixed_bb = { {0, 0}, {0, 0} };
766 for (
size_t i = 0; i < ng; i++) {
769 if (fixed && fixed[i]) {
772 fixed_bb.
LL.
x = fmin(bb.
LL.
x, fixed_bb.
LL.
x);
773 fixed_bb.
LL.
y = fmin(bb.
LL.
y, fixed_bb.
LL.
y);
774 fixed_bb.
UR.
x = fmax(bb.
UR.
x, fixed_bb.
UR.
x);
775 fixed_bb.
UR.
y = fmax(bb.
UR.
y, fixed_bb.
UR.
y);
781 fprintf(stderr,
"bb[%s] %.5g %.5g %.5g %.5g\n",
agnameof(g),
789 for (
size_t i = 0; i < ng; i++)
790 bbs[i] =
GD_bb(gs[i]);
793 fprintf(stderr,
"step size = %d\n", stepSize);
805 for (
size_t i = 0; i < ng; i++) {
818 for (
size_t i = 0; i < ng; i++) {
826 for (
size_t i = 0; i < ng; i++) {
830 for (
size_t i = 0; i < ng; i++) {
833 stepSize, pinfo->
margin, bbs);
836 for (
size_t i = 0; i < ng; i++)
838 stepSize, pinfo->
margin, bbs);
842 for (
size_t i = 0; i < ng; i++)
849 for (
size_t i = 0; i < ng; i++)
850 fprintf(stderr,
"pos[%" PRISIZE_T "] %.0f %.0f\n", i, places[i].x,
862 if (ng == 0)
return NULL;
869 for (
size_t i = 0; i < ng; i++) {
878 for (
size_t i = 0; i < ng; i++) {
879 s =
agget (gs[i],
"sortv");
880 if (
s && sscanf(
s,
"%d", &v) > 0 && v >= 0)
896 if (ng == 0)
return NULL;
917 if (ng <= 1)
return 0;
923 for (
size_t i = 0; i < ng; i++) {
950 for (
size_t j = 0; j <
ED_spl(e)->size; j++) {
952 for (
size_t k = 0; k < bz.
size; k++)
1014 for (
size_t i = 0; i < ng; i++) {
1021 const double dx = p.
x;
1022 const double dy = p.
y;
1081 for (
size_t i = 0; i < ng; i++) {
1098 info.doSplines =
true;
1108 if (*p !=
'_')
return p;
1111 while (more && (c = *p)) {
1186 p += strlen(
"array");
1188 if ((sscanf (p,
"%d", &i)>0) && (i > 0))
1192 if (sscanf(p + strlen(
"aspect"),
"%f", &v) > 0 && v > 0)
1196 }
else if (
streq(p,
"cluster")) {
1198 }
else if (
streq(p,
"graph")) {
1200 }
else if (
streq(p,
"node")) {
1206 fprintf (stderr,
"pack info:\n");
1209 fprintf (stderr,
" aspect %f\n", pinfo->
aspect);
1210 fprintf (stderr,
" size %d\n", pinfo->
sz);
1211 fprintf (stderr,
" flags %d\n", pinfo->
flags);
1242 if ((p =
agget(g,
"pack"))) {
1243 if (sscanf(p,
"%d", &i) == 1 && i >= 0)
1245 else if (*p ==
't' || *p ==
'T')
1259 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 mid_pointf(pointf p, pointf q)
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)
void agerrorf(const char *fmt,...)
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 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)