27 #define strneq(a,b,n) (!strncmp(a,b,n))
31 #define MOVEPT(p) ((p).x += dx, (p).y += dy)
33 #define GRID(x,s) ((int)ceil((x)/(s)))
35 #define CVAL(v,s) ((v) >= 0 ? (v)/(s) : (((v)+1)/(s))-1)
37 #define CELL(p,s) ((p).x = CVAL((p).x,s), (p).y = CVAL((p).y,(s)))
56 static int computeStep(
int ng,
boxf* bbs,
int margin)
66 for (i = 0; i < ng; i++) {
68 W = bb.
UR.
x - bb.
LL.
x + 2 * margin;
69 H = bb.
UR.
y - bb.
LL.
y + 2 * margin;
73 d = b * b - 4.0 * a * c;
75 agerr(
AGERR,
"libpack: disc = %f ( < 0)\n", d);
79 l1 = (-b + r) / (2 * a);
80 l2 = (-b - r) / (2 * a);
82 if (root == 0) root = 1;
84 fprintf(stderr,
"Packing: compute grid size\n");
85 fprintf(stderr,
"a %f b %f c %f d %f r %f\n", a, b, c, d, r);
86 fprintf(stderr,
"root %d (%f) %d (%f)\n", root, l1, (
int) l2,
88 fprintf(stderr,
" r1 %f r2 %f\n", a * l1 * l1 + b * l1 + c,
89 a * l2 * l2 + b * l2 + c);
99 static int cmpf(
const void *X,
const void *Y)
118 int d, x, y, ax, ay, sx, sy, dx, dy;
186 for (j = 0; j <
ED_spl(e)->size; j++) {
203 for (; k < bz.
size; k++) {
238 LL.
x = center.
x - margin;
239 LL.
y = center.
y - margin;
240 UR.
x = center.
x + bb.
UR.
x - bb.
LL.
x + margin;
241 UR.
y = center.
y + bb.
UR.
y - bb.
LL.
y + margin;
245 for (x = LL.
x; x <= UR.
x; x++)
246 for (y = LL.
y; y <= UR.
y; y++)
251 W =
GRID(bb0.
UR.
x - bb0.
LL.
x + 2 * margin, ssize);
252 H =
GRID(bb0.
UR.
y - bb0.
LL.
y + 2 * margin, ssize);
257 fprintf(stderr,
"%s no. cells %d W %d H %d\n",
259 for (i = 0; i < info->
nc; i++)
260 fprintf(stderr,
" %d %d cell\n", info->
cells[i].
x,
292 int margin = pinfo->
margin;
330 for (x = bb.
LL.
x; x <= bb.
UR.
x; x++)
331 for (y = bb.
LL.
y; y <= bb.
UR.
y; y++)
348 LL = sub_point(pt, s2);
349 UR = add_point(pt, s2);
353 for (x = LL.
x; x <= UR.
x; x++)
354 for (y = LL.
y; y <= UR.
y; y++)
359 fillEdge(e, pt, ps, dx, dy, ssize, doSplines);
366 fillEdge(e, pt, ps, dx, dy, ssize, doSplines);
384 LL = sub_point(pt, s2);
385 UR = add_point(pt, s2);
389 for (x = LL.
x; x <= UR.
x; x++)
390 for (y = LL.
y; y <= UR.
y; y++)
395 fillEdge(e, pt, ps, dx, dy, ssize, doSplines);
407 fprintf(stderr,
"%s no. cells %d W %d H %d\n",
409 for (i = 0; i < info->
nc; i++)
410 fprintf(stderr,
" %d %d cell\n", info->
cells[i].
x,
431 for (i = 0; i < n; i++) {
441 place->
x = step * x - LL.
x;
442 place->
y = step * y - LL.
y;
445 for (i = 0; i < n; i++) {
454 fprintf(stderr,
"cc (%d cells) at (%d,%d) (%d,%d)\n", n, x, y,
471 place->
x = -center.
x;
472 place->
y = -center.
y;
474 for (i = 0; i < n; i++) {
479 fprintf(stderr,
"cc (%d cells) at (%d,%d)\n", n, place->
x,
491 int margin,
boxf* bbs)
499 W =
GRID(bb.
UR.
x - bb.
LL.
x + 2 * margin, step);
500 H =
GRID(bb.
UR.
y - bb.
LL.
y + 2 * margin, step);
501 if (fits(-W / 2, -H / 2, info, ps, place, step, bbs))
505 if (fits(0, 0, info, ps, place, step, bbs))
507 W = ceil(bb.
UR.
x - bb.
LL.
x);
508 H = ceil(bb.
UR.
y - bb.
LL.
y);
510 for (bnd = 1;; bnd++) {
514 if (fits(x, y, info, ps, place, step, bbs))
517 if (fits(x, y, info, ps, place, step, bbs))
519 for (; x > -bnd; x--)
520 if (fits(x, y, info, ps, place, step, bbs))
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))
530 for (bnd = 1;; bnd++) {
533 for (; y > -bnd; y--)
534 if (fits(x, y, info, ps, place, step, bbs))
537 if (fits(x, y, info, ps, place, step, bbs))
540 if (fits(x, y, info, ps, place, step, bbs))
542 for (; x > -bnd; x--)
543 if (fits(x, y, info, ps, place, step, bbs))
546 if (fits(x, y, info, ps, place, step, bbs))
553 void dumpp(
ginfo * info,
char *pfx)
556 int i, c_cnt = info->
nc;
558 fprintf(stderr,
"%s\n", pfx);
559 for (i = 0; i < c_cnt; i++) {
560 fprintf(stderr,
"%d %d box\n", cells[i].x, cells[i].y);
570 static int ucmpf(
const void *X,
const void *Y)
575 int dX = userVals[x->
index];
576 int dY = userVals[y->
index];
577 if (dX > dY)
return 1;
578 else if (dX < dY)
return -1;
585 static int acmpf(
const void *X,
const void *Y)
598 if (dX < dY)
return 1;
599 else if (dX > dY)
return -1;
604 if (m){ c++; if (c == nc) { c = 0; r++; } } \
605 else { r++; if (r == nr) { r = 0; c++; } }
631 nc = (ng + (nr-1))/nr;
635 nc = (ng + (nr-1))/nr;
642 nr = (ng + (nc-1))/nc;
646 nr = (ng + (nc-1))/nc;
650 fprintf (stderr,
"array packing: %s %d rows %d columns\n", (rowMajor?
"row major":
"column major"), nr, nc);
651 widths =
N_NEW(nc+1,
double);
652 heights =
N_NEW(nr+1,
double);
655 for (i = 0; i < ng; i++, ip++) {
663 for (i = 0; i < ng; i++) {
668 userVals = pinfo->
vals;
669 qsort(sinfo, ng,
sizeof(
ainfo *), ucmpf);
672 qsort(sinfo, ng,
sizeof(
ainfo *), acmpf);
677 for (i = 0; i < ng; i++, ip++) {
679 widths[c] =
MAX(widths[c],ip->
width);
686 for (i = 0; i <= nc; i++) {
693 for (i = nr; 0 < i; i--) {
702 for (i = 0; i < ng; i++, ip++) {
708 places[idx].
x = widths[c];
710 places[idx].
x = widths[c+1] - (bb.
UR.
x - bb.
LL.
x);
712 places[idx].
x = (widths[c] + widths[c+1] - bb.
UR.
x - bb.
LL.
x)/2.0;
714 places[idx].
y = heights[r] - (bb.
UR.
y - bb.
LL.
y);
716 places[idx].
y = heights[r+1];
718 places[idx].
y = (heights[r] + heights[r+1] - bb.
UR.
y - bb.
LL.
y)/2.0;
741 stepSize = computeStep(ng, gs, pinfo->
margin);
743 fprintf(stderr,
"step size = %d\n", stepSize);
748 center.
x = center.
y = 0;
750 for (i = 0; i < ng; i++) {
752 genBox(gs[i], info + i, stepSize, pinfo->
margin, center,
"");
757 for (i = 0; i < ng; i++) {
760 qsort(sinfo, ng,
sizeof(
ginfo *), cmpf);
764 for (i = 0; i < ng; i++)
765 placeGraph(i, sinfo[i], ps, places + (sinfo[i]->index),
766 stepSize, pinfo->
margin, gs);
769 for (i = 0; i < ng; i++)
775 for (i = 0; i < ng; i++)
776 fprintf(stderr,
"pos[%d] %d %d\n", i, places[i].x,
816 boolean *fixed = pinfo->
fixed;
818 box bb, fixed_bb = { {0, 0}, {0, 0} };
827 for (i = 0; i < ng; i++) {
830 if (fixed && fixed[i]) {
842 fprintf(stderr,
"bb[%s] %.5g %.5g %.5g %.5g\n",
agnameof(g),
850 for (i = 0; i < ng; i++)
851 bbs[i] =
GD_bb(gs[i]);
852 stepSize = computeStep(ng, bbs, pinfo->
margin);
854 fprintf(stderr,
"step size = %d\n", stepSize);
860 center.
x = (fixed_bb.
LL.
x + fixed_bb.
UR.
x) / 2;
861 center.
y = (fixed_bb.
LL.
y + fixed_bb.
UR.
y) / 2;
863 center.
x = center.
y = 0;
865 for (i = 0; i < ng; i++) {
870 else if (genPoly(root, gs[i], info + i, stepSize, pinfo, center)) {
877 for (i = 0; i < ng; i++) {
880 qsort(sinfo, ng,
sizeof(
ginfo *), cmpf);
885 for (i = 0; i < ng; i++) {
887 placeFixed(sinfo[i], ps, places + (sinfo[i]->index),
890 for (i = 0; i < ng; i++) {
892 placeGraph(i, sinfo[i], ps, places + (sinfo[i]->index),
893 stepSize, pinfo->
margin, bbs);
896 for (i = 0; i < ng; i++)
897 placeGraph(i, sinfo[i], ps, places + (sinfo[i]->index),
898 stepSize, pinfo->
margin, bbs);
902 for (i = 0; i < ng; i++)
909 for (i = 0; i < ng; i++)
910 fprintf(stderr,
"pos[%d] %d %d\n", i, places[i].x,
925 if (ng <= 0)
return NULL;
928 return polyGraphs (ng, gs, root, pinfo);
932 for (i = 0; i < ng; i++) {
941 for (i = 0; i < ng; i++) {
942 s =
agget (gs[i],
"sortv");
943 if (s && (sscanf (s,
"%d", &v) > 0) && (v >= 0))
948 pts = arrayRects (ng, bbs, pinfo);
961 if (ng <= 0)
return NULL;
964 return polyRects (ng, bbs, pinfo);
966 return arrayRects (ng, bbs, pinfo);
989 if (ng < 0)
return -1;
990 if (ng <= 1)
return 0;
996 for (i = 0; i < ng; i++) {
1012 static void shiftEdge(
Agedge_t * e,
int dx,
int dy)
1029 for (j = 0; j <
ED_spl(e)->size; j++) {
1031 for (k = 0; k < bz.
size; k++)
1042 static void shiftGraph(
Agraph_t * g,
int dx,
int dy)
1060 shiftGraph(subg, dx, dy);
1103 for (i = 0; i < ng; i++) {
1124 shiftEdge(e, dx, dy);
1127 shiftGraph(g, dx, dy);
1175 for (i = 0; i < ng; i++) {
1203 #define ARRAY "array"
1204 #define ASPECT "aspect"
1205 #define SLEN(s) (sizeof(s)/sizeof(char) - 1)
1212 if (*p !=
'_')
return p;
1215 while (more && (c = *p)) {
1303 p = chkFlags (p, pinfo);
1304 if ((sscanf (p,
"%d", &i)>0) && (i > 0))
1309 if ((sscanf (p +
SLEN(
ARRAY),
"%f", &v)>0) && (v > 0))
1315 #ifdef NOT_IMPLEMENTED
1317 if (
streq(p,
"bisect"))
1318 pinfo->
mode = l_bisect;
1322 if (
streq(p,
"cluster"))
1326 if (
streq(p,
"graph"))
1329 #ifdef NOT_IMPLEMENTED
1331 if (
streq(p,
"hull"))
1332 pinfo->
mode = l_hull;
1336 if (
streq(p,
"node"))
1339 #ifdef NOT_IMPLEMENTED
1341 if (
streq(p,
"tile"))
1342 pinfo->
mode = l_tile;
1349 fprintf (stderr,
"pack info:\n");
1350 fprintf (stderr,
" mode %s\n", mode2Str(pinfo->
mode));
1352 fprintf (stderr,
" aspect %f\n", pinfo->
aspect);
1353 fprintf (stderr,
" size %d\n", pinfo->
sz);
1354 fprintf (stderr,
" flags %d\n", pinfo->
flags);
1387 if ((p =
agget(g,
"pack"))) {
1388 if ((sscanf(p,
"%d", &i) == 1) && (i >= 0))
1390 else if ((*p ==
't') || (*p ==
'T'))
1404 fprintf (stderr,
" margin %d\n", pinfo->
margin);
void dotneato_postprocess(Agraph_t *g)
void freePS(PointSet *ps)
void insertPS(PointSet *ps, point pt)
int packRects(int ng, boxf *bbs, pack_info *pinfo)
int agerr(agerrlevel_t level, const char *fmt,...)
pack_mode getPackInfo(Agraph_t *g, pack_mode dflt, int dfltMargin, pack_info *pinfo)
int packGraphs(int ng, Agraph_t **gs, Agraph_t *root, pack_info *info)
CGRAPH_API Agedge_t * agfstout(Agraph_t *g, Agnode_t *n)
void fillLine(pointf p, pointf q, PointSet *ps)
int shiftGraphs(int ng, Agraph_t **gs, point *pp, Agraph_t *root, int doSplines)
#define PS2INCH(a_points)
char * agget(void *obj, char *name)
CGRAPH_API Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
CGRAPH_API Agnode_t * aghead(Agedge_t *e)
pack_mode getPackMode(Agraph_t *g, pack_mode dflt)
pack_mode getPackModeInfo(Agraph_t *g, pack_mode dflt, pack_info *pinfo)
CGRAPH_API char * agnameof(void *)
int pack_graph(int ng, Agraph_t **gs, Agraph_t *root, boolean *fixed)
point * pointsOf(PointSet *ps)
void compute_bb(graph_t *g)
point * putRects(int ng, boxf *bbs, pack_info *pinfo)
CGRAPH_API Agnode_t * agfstnode(Agraph_t *g)
int packSubgraphs(int ng, Agraph_t **gs, Agraph_t *root, pack_info *info)
void addPS(PointSet *ps, int x, int y)
int getPack(Agraph_t *g, int not_def, int dflt)
EXTERN unsigned char Verbose
CGRAPH_API int agnnodes(Agraph_t *g)
int inPS(PointSet *ps, point pt)
point * putGraphs(int ng, Agraph_t **gs, Agraph_t *root, pack_info *pinfo)
pack_mode parsePackModeInfo(char *p, pack_mode dflt, pack_info *pinfo)
CGRAPH_API Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)