return cvt2pt(pf);
}
-point pointof(int x, int y)
-{
- point rv;
- rv.x = x, rv.y = y;
- return rv;
-}
-
-point cvt2pt(pointf p)
-{
- point rv;
- rv.x = POINTS(p.x);
- rv.y = POINTS(p.y);
- return rv;
-}
-
-pointf cvt2ptf(point p)
-{
- pointf rv;
- rv.x = PS2INCH(p.x);
- rv.y = PS2INCH(p.y);
- return rv;
-}
-
-box boxof(int llx, int lly, int urx, int ury)
-{
- box b;
-
- b.LL.x = llx, b.LL.y = lly;
- b.UR.x = urx, b.UR.y = ury;
- return b;
-}
-
-boxf boxfof(double llx, double lly, double urx, double ury)
-{
- boxf b;
-
- b.LL.x = llx, b.LL.y = lly;
- b.UR.x = urx, b.UR.y = ury;
- return b;
-}
-
-box mkbox(point p0, point p1)
-{
- box rv;
-
- if (p0.x < p1.x) {
- rv.LL.x = p0.x;
- rv.UR.x = p1.x;
- } else {
- rv.LL.x = p1.x;
- rv.UR.x = p0.x;
- }
- if (p0.y < p1.y) {
- rv.LL.y = p0.y;
- rv.UR.y = p1.y;
- } else {
- rv.LL.y = p1.y;
- rv.UR.y = p0.y;
- }
- return rv;
-}
-
-boxf mkboxf(pointf p0, pointf p1)
-{
- boxf rv;
-
- if (p0.x < p1.x) {
- rv.LL.x = p0.x;
- rv.UR.x = p1.x;
- } else {
- rv.LL.x = p1.x;
- rv.UR.x = p0.x;
- }
- if (p0.y < p1.y) {
- rv.LL.y = p0.y;
- rv.UR.y = p1.y;
- } else {
- rv.LL.y = p1.y;
- rv.UR.y = p0.y;
- }
- return rv;
-}
-
-point add_points(point p0, point p1)
-{
- p0.x += p1.x;
- p0.y += p1.y;
- return p0;
-}
-
-point sub_points(point p0, point p1)
-{
- p0.x -= p1.x;
- p0.y -= p1.y;
- return p0;
-}
-
-pointf add_pointfs(pointf p0, pointf p1)
-{
- p0.x += p1.x;
- p0.y += p1.y;
- return p0;
-}
-
-pointf sub_pointfs(pointf p0, pointf p1)
-{
- p0.x -= p1.x;
- p0.y -= p1.y;
- return p0;
-}
-
-point exch_xy(point p)
-{
- int t;
- t = p.x;
- p.x = p.y;
- p.y = t;
- return p;
-}
-
-pointf exch_xyf(pointf p)
-{
- double t;
- t = p.x;
- p.x = p.y;
- p.y = t;
- return p;
-}
-
-/* from Glassner's Graphics Gems */
-#define W_DEGREE 5
-
-/*
- * Bezier :
- * Evaluate a Bezier curve at a particular parameter value
- * Fill in control points for resulting sub-curves if "Left" and
- * "Right" are non-null.
- *
- */
-pointf Bezier(pointf * V, int degree, double t, pointf * Left,
- pointf * Right)
-{
- int i, j; /* Index variables */
- pointf Vtemp[W_DEGREE + 1][W_DEGREE + 1];
-
- /* Copy control points */
- for (j = 0; j <= degree; j++) {
- Vtemp[0][j] = V[j];
- }
-
- /* Triangle computation */
- for (i = 1; i <= degree; i++) {
- for (j = 0; j <= degree - i; j++) {
- Vtemp[i][j].x =
- (1.0 - t) * Vtemp[i - 1][j].x + t * Vtemp[i - 1][j + 1].x;
- Vtemp[i][j].y =
- (1.0 - t) * Vtemp[i - 1][j].y + t * Vtemp[i - 1][j + 1].y;
- }
- }
-
- if (Left != NULL)
- for (j = 0; j <= degree; j++)
- Left[j] = Vtemp[j][0];
- if (Right != NULL)
- for (j = 0; j <= degree; j++)
- Right[j] = Vtemp[degree - j][j];
-
- return (Vtemp[degree][0]);
-}
-
#ifdef DEBUG
edge_t *debug_getedge(graph_t * g, char *s0, char *s1)
{
}
}
-box box_bb(box b0, box b1)
-{
- box b;
-
- b.LL.x = MIN(b0.LL.x, b1.LL.x);
- b.LL.y = MIN(b0.LL.y, b1.LL.y);
- b.UR.x = MAX(b0.UR.x, b1.UR.x);
- b.UR.y = MAX(b0.UR.y, b1.UR.y);
-
- return b;
-}
-
-boxf boxf_bb(boxf b0, boxf b1)
-{
- boxf b;
-
- b.LL.x = MIN(b0.LL.x, b1.LL.x);
- b.LL.y = MIN(b0.LL.y, b1.LL.y);
- b.UR.x = MAX(b0.UR.x, b1.UR.x);
- b.UR.y = MAX(b0.UR.y, b1.UR.y);
-
- return b;
-}
-
-box box_intersect(box b0, box b1)
-{
- box b;
-
- b.LL.x = MAX(b0.LL.x, b1.LL.x);
- b.LL.y = MAX(b0.LL.y, b1.LL.y);
- b.UR.x = MIN(b0.UR.x, b1.UR.x);
- b.UR.y = MIN(b0.UR.y, b1.UR.y);
-
- return b;
-}
-
-boxf boxf_intersect(boxf b0, boxf b1)
-{
- boxf b;
-
- b.LL.x = MAX(b0.LL.x, b1.LL.x);
- b.LL.y = MAX(b0.LL.y, b1.LL.y);
- b.UR.x = MIN(b0.UR.x, b1.UR.x);
- b.UR.y = MIN(b0.UR.y, b1.UR.y);
-
- return b;
-}
-
-boolean box_overlap(box b0, box b1)
-{
- return OVERLAP(b0, b1);
-}
-
-boolean boxf_overlap(boxf b0, boxf b1)
-{
- return OVERLAP(b0, b1);
-}
-
-boolean box_contains(box b0, box b1)
-{
- return CONTAINS(b0, b1);
-}
-
-boolean boxf_contains(boxf b0, boxf b1)
-{
- return CONTAINS(b0, b1);
-}
-
int maptoken(char *p, char **name, int *val)
{
int i;
return atoi(p);
}
-static double dist2(pointf p, pointf q) /* return square of dist between p and q */
-{
- double d0, d1;
-
- d0 = p.x - q.x;
- d1 = p.y - q.y;
- return (d0 * d0 + d1 * d1);
-}
-
-point dotneato_closest(splines * spl, point p)
-{
- int i, j, k, besti, bestj;
- double bestdist2, d2, dlow2, dhigh2; /* squares of distances */
- double low, high, t;
- pointf c[4], pt2, pt;
- point rv;
- bezier bz;
-
- besti = bestj = -1;
- bestdist2 = 1e+38;
- P2PF(p, pt);
- for (i = 0; i < spl->size; i++) {
- bz = spl->list[i];
- for (j = 0; j < bz.size; j++) {
- pointf b;
-
- b.x = bz.list[j].x;
- b.y = bz.list[j].y;
- d2 = dist2(b, pt);
- if ((bestj == -1) || (d2 < bestdist2)) {
- besti = i;
- bestj = j;
- bestdist2 = d2;
- }
- }
- }
-
- bz = spl->list[besti];
- j = bestj / 3;
- if (j >= spl->size)
- j--;
- for (k = 0; k < 4; k++) {
- c[k].x = bz.list[j + k].x;
- c[k].y = bz.list[j + k].y;
- }
- low = 0.0;
- high = 1.0;
- dlow2 = dist2(c[0], pt);
- dhigh2 = dist2(c[3], pt);
- do {
- t = (low + high) / 2.0;
- pt2 = Bezier(c, 3, t, NULL, NULL);
- if (fabs(dlow2 - dhigh2) < 1.0)
- break;
- if (fabs(high - low) < .00001)
- break;
- if (dlow2 < dhigh2) {
- high = t;
- dhigh2 = dist2(pt2, pt);
- } else {
- low = t;
- dlow2 = dist2(pt2, pt);
- }
- } while (1);
- PF2P(pt2, rv);
- return rv;
-}
-
-point spline_at_y(splines * spl, int y)
-{
- int i, j;
- double low, high, d, t;
- pointf c[4], pt2;
- point pt;
- static bezier bz;
-
-/* this caching seems to prevent pt.x from getting set from bz.list[0].x
- - optimizer problem ? */
-
-#if 0
- static splines *mem = NULL;
-
- if (mem != spl) {
- mem = spl;
-#endif
- for (i = 0; i < spl->size; i++) {
- bz = spl->list[i];
- if (BETWEEN(bz.list[bz.size - 1].y, y, bz.list[0].y))
- break;
- }
-#if 0
- }
-#endif
- if (y > bz.list[0].y)
- pt = bz.list[0];
- else if (y < bz.list[bz.size - 1].y)
- pt = bz.list[bz.size - 1];
- else {
- for (i = 0; i < bz.size; i += 3) {
- for (j = 0; j < 3; j++) {
- if ((bz.list[i + j].y <= y) && (y <= bz.list[i + j + 1].y))
- break;
- if ((bz.list[i + j].y >= y) && (y >= bz.list[i + j + 1].y))
- break;
- }
- if (j < 3)
- break;
- }
- assert(i < bz.size);
- for (j = 0; j < 4; j++) {
- c[j].x = bz.list[i + j].x;
- c[j].y = bz.list[i + j].y;
- /* make the spline be monotonic in Y, awful but it works for now */
- if ((j > 0) && (c[j].y > c[j - 1].y))
- c[j].y = c[j - 1].y;
- }
- low = 0.0;
- high = 1.0;
- do {
- t = (low + high) / 2.0;
- pt2 = Bezier(c, 3, t, NULL, NULL);
- d = pt2.y - y;
- if (ABS(d) <= 1)
- break;
- if (d < 0)
- high = t;
- else
- low = t;
- } while (1);
- pt.x = pt2.x;
- pt.y = pt2.y;
- }
- pt.y = y;
- return pt;
-}
-
-point neato_closest(splines * spl, point p)
-{
-/* this is a stub so that we can share a common emit.c between dot and neato */
-
- return spline_at_y(spl, p.y);
-}
-
static int Tflag;
void toggle(int s)
{
return r;
}
-/* flip_ptf:
- * Transform point =>
- * LR - rotate ccw by 90
- * BT - reflect across x axis
- * RL - TB o LR
- */
-point flip_pt(point p, int rankdir)
-{
- int x = p.x, y = p.y;
- switch (rankdir) {
- case RANKDIR_TB:
- break;
- case RANKDIR_LR:
- p.x = -y;
- p.y = x;
- break;
- case RANKDIR_BT:
- p.x = x;
- p.y = -y;
- break;
- case RANKDIR_RL:
- p.x = y;
- p.y = x;
- break;
- }
- return p;
-}
-
-/* flip_ptf:
- * flip_pt for pointf type.
- */
-pointf flip_ptf(pointf p, int rankdir)
-{
- double x = p.x, y = p.y;
- switch (rankdir) {
- case RANKDIR_TB:
- break;
- case RANKDIR_LR:
- p.x = -y;
- p.y = x;
- break;
- case RANKDIR_BT:
- p.x = x;
- p.y = -y;
- break;
- case RANKDIR_RL:
- p.x = y;
- p.y = x;
- break;
- }
- return p;
-}
-
-/* invflip_pt:
- * Transform point =>
- * LR - rotate cw by 90
- * BT - reflect across x axis
- * RL - TB o LR
- * Note that flip and invflip only differ on LR
- */
-point invflip_pt(point p, int rankdir)
-{
- int x = p.x, y = p.y;
- switch (rankdir) {
- case RANKDIR_TB:
- break;
- case RANKDIR_LR:
- p.x = y;
- p.y = -x;
- break;
- case RANKDIR_BT:
- p.x = x;
- p.y = -y;
- break;
- case RANKDIR_RL:
- p.x = y;
- p.y = x;
- break;
- }
- return p;
-}
-
-box flip_rec_box(box b, point p)
-{
- box rv;
- /* flip box */
- rv.UR.x = b.UR.y;
- rv.UR.y = b.UR.x;
- rv.LL.x = b.LL.y;
- rv.LL.y = b.LL.x;
- /* move box */
- rv.LL.x += p.x;
- rv.LL.y += p.y;
- rv.UR.x += p.x;
- rv.UR.y += p.y;
- return rv;
-}
-
/* addLabelBB:
*/
static box addLabelBB(box bb, textlabel_t * lp, boolean flipxy)
b.LL = sub_points(pt, s2);
b.UR = add_points(pt, s2);
- bb.LL.x = MIN(bb.LL.x, b.LL.x);
- bb.LL.y = MIN(bb.LL.y, b.LL.y);
- bb.UR.x = MAX(bb.UR.x, b.UR.x);
- bb.UR.y = MAX(bb.UR.y, b.UR.y);
+ EXPANDBB(b,b);
for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
if (ED_spl(e) == 0)
continue;
for (i = 0; i < ED_spl(e)->size; i++) {
for (j = 0; j < ED_spl(e)->list[i].size; j++) {
pt = ED_spl(e)->list[i].list[j];
- if (bb.LL.x > pt.x)
- bb.LL.x = pt.x;
- if (bb.LL.y > pt.y)
- bb.LL.y = pt.y;
- if (bb.UR.x < pt.x)
- bb.UR.x = pt.x;
- if (bb.UR.y < pt.y)
- bb.UR.y = pt.y;
+ EXPANDBP(bb,pt);
}
}
if (ED_label(e) && ED_label(e)->set)
}
for (i = 1; i <= GD_n_cluster(g); i++) {
- bb.LL.x = MIN(bb.LL.x, GD_clust(g)[i]->u.bb.LL.x);
- bb.LL.y = MIN(bb.LL.y, GD_clust(g)[i]->u.bb.LL.y);
- bb.UR.x = MAX(bb.UR.x, GD_clust(g)[i]->u.bb.UR.x);
- bb.UR.y = MAX(bb.UR.y, GD_clust(g)[i]->u.bb.UR.y);
+ EXPANDBB(bb,GD_clust(g)[i]->u.bb);
}
GD_bb(g) = bb;
return ns;
}
-/*
- *--------------------------------------------------------------
- *
- * lineToBox --
- *
- * Determine whether a line lies entirely inside, entirely
- * outside, or overlapping a given rectangular area.
- *
- * Results:
- * -1 is returned if the line given by p1 and p2
- * is entirely outside the rectangle given by b.
- * 0 is returned if the polygon overlaps the rectangle, and
- * 1 is returned if the polygon is entirely inside the rectangle.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------
- */
-
-/* This code steals liberally from algorithms in tk/generic/tkTrig.c -- jce */
-
-static int lineToBox(pointf p1, pointf p2, boxf b)
-{
- int inside1, inside2;
-
- /*
- * First check the two points individually to see whether they
- * are inside the rectangle or not.
- */
-
- inside1 = (p1.x >= b.LL.x) && (p1.x <= b.UR.x)
- && (p1.y >= b.LL.y) && (p1.y <= b.UR.y);
- inside2 = (p2.x >= b.LL.x) && (p2.x <= b.UR.x)
- && (p2.y >= b.LL.y) && (p2.y <= b.UR.y);
- if (inside1 != inside2) {
- return 0;
- }
- if (inside1 & inside2) {
- return 1;
- }
-
- /*
- * Both points are outside the rectangle, but still need to check
- * for intersections between the line and the rectangle. Horizontal
- * and vertical lines are particularly easy, so handle them
- * separately.
- */
-
- if (p1.x == p2.x) {
- /*
- * Vertical line.
- */
-
- if (((p1.y >= b.LL.y) ^ (p2.y >= b.LL.y))
- && (p1.x >= b.LL.x)
- && (p1.x <= b.UR.x)) {
- return 0;
- }
- } else if (p1.y == p2.y) {
- /*
- * Horizontal line.
- */
- if (((p1.x >= b.LL.x) ^ (p2.x >= b.LL.x))
- && (p1.y >= b.LL.y)
- && (p1.y <= b.UR.y)) {
- return 0;
- }
- } else {
- double m, x, y, low, high;
-
- /*
- * Diagonal line. Compute slope of line and use
- * for intersection checks against each of the
- * sides of the rectangle: left, right, bottom, top.
- */
-
- m = (p2.y - p1.y)/(p2.x - p1.x);
- if (p1.x < p2.x) {
- low = p1.x; high = p2.x;
- } else {
- low = p2.x; high = p1.x;
- }
-
- /*
- * Left edge.
- */
-
- y = p1.y + (b.LL.x - p1.x)*m;
- if ((b.LL.x >= low) && (b.LL.x <= high)
- && (y >= b.LL.y) && (y <= b.UR.y)) {
- return 0;
- }
-
- /*
- * Right edge.
- */
-
- y += (b.UR.x - b.LL.x)*m;
- if ((y >= b.LL.y) && (y <= b.UR.y)
- && (b.UR.x >= low) && (b.UR.x <= high)) {
- return 0;
- }
-
- /*
- * Bottom edge.
- */
-
- if (p1.y < p2.y) {
- low = p1.y; high = p2.y;
- } else {
- low = p2.y; high = p1.y;
- }
- x = p1.x + (b.LL.y - p1.y)/m;
- if ((x >= b.LL.x) && (x <= b.UR.x)
- && (b.LL.y >= low) && (b.LL.y <= high)) {
- return 0;
- }
-
- /*
- * Top edge.
- */
-
- x += (b.UR.y - b.LL.y)/m;
- if ((x >= b.LL.x) && (x <= b.UR.x)
- && (b.UR.y >= low) && (b.UR.y <= high)) {
- return 0;
- }
- }
- return -1;
-}
-
boolean overlap_node(node_t *n, boxf b)
{
boxf bb;
#include "config.h"
#endif
+#include "geom.h"
+
#ifndef HAVE_STRCASECMP
extern int strcasecmp(const char *s1, const char *s2);
#endif
extern void UF_singleton(Agnode_t *);
extern void UF_setname(Agnode_t *, Agnode_t *);
- extern point pointof(int, int);
- extern pointf cvt2ptf(point);
- extern point cvt2pt(pointf);
- extern point add_points(point, point);
- extern pointf add_pointfs(pointf, pointf);
- extern point sub_points(point, point);
- extern pointf sub_pointfs(pointf, pointf);
- extern point exch_xy(point p);
- extern pointf exch_xyf(pointf p);
- extern point flip_pt(point p, int rankdir);
- extern pointf flip_ptf(pointf p, int rankdir);
- extern point invflip_pt(point p, int rankdir);
-
- extern box boxof(int llx, int lly, int urx, int ury);
- extern boxf boxfof(double llx, double lly, double urx, double ury);
- extern box mkbox(point, point);
- extern boxf mkboxf(pointf, pointf);
- extern box box_bb(box, box);
- extern boxf boxf_bb(boxf, boxf);
- extern box box_intersect(box, box);
- extern boxf boxf_intersect(boxf, boxf);
- extern boolean box_overlap(box, box);
- extern boolean boxf_overlap(boxf, boxf);
- extern boolean box_contains(box, box);
- extern boolean boxf_contains(boxf, boxf);
- extern box flip_rec_box(box b, point p);
-
- extern pointf Bezier(pointf *, int, double, pointf *, pointf *);
- extern point dotneato_closest(splines * spl, point p);
- extern point neato_closest(splines * spl, point p);
- extern point spline_at_y(splines * spl, int y);
-
extern char *username(void);
extern char *safefile(char *shapefilename);
extern void cat_libfile(FILE *, char **, char **);