return p;
}
-boxf arrow_bb(GVJ_t * job, pointf p, pointf u, double scale, int flag)
+boxf arrow_bb(pointf p, pointf u, double scale, int flag)
{
double s;
boxf bb;
return rv;
}
-static void init_bb_node(node_t *n)
-{
- ND_bb(n).LL.x = ND_coord_i(n).x - ND_lw_i(n);
- ND_bb(n).LL.y = ND_coord_i(n).y - ND_ht_i(n) / 2.;
- ND_bb(n).UR.x = ND_coord_i(n).x + ND_rw_i(n);
- ND_bb(n).UR.y = ND_coord_i(n).y + ND_ht_i(n) / 2.;
-}
-
-static box bezier_bb(bezier bz)
+static boxf bezier_bb(bezier bz)
{
int i;
+ point p;
box bb;
+ boxf bbf;
assert(bz.size > 0);
bb.LL = bb.UR = bz.list[0];
for (i = 1; i < bz.size; i++) {
- bb.LL.x = MIN(bb.LL.x, bz.list[i].x);
- bb.LL.y = MIN(bb.LL.y, bz.list[i].y);
- bb.UR.x = MAX(bb.UR.x, bz.list[i].x);
- bb.UR.y = MAX(bb.UR.y, bz.list[i].y);
+ p=bz.list[i];
+ EXPANDBP(bb,p);
}
- return bb;
+ B2BF(bb, bbf);
+ return bbf;
}
static void init_splines_bb(splines *spl)
{
int i;
- box bb, b;
+ bezier bz;
+ boxf bb, b;
+ pointf p, u;
assert(spl->size > 0);
- bb = bezier_bb(spl->list[0]);
- for (i = 1; i < spl->size; i++) {
- b = bezier_bb(spl->list[0]);
- 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);
+ bz = spl->list[0];
+ bb = bezier_bb(bz);
+ for (i = 0; i < spl->size; i++) {
+ if (i > 0) {
+ bz = spl->list[i];
+ b = bezier_bb(bz);
+ EXPANDBB(bb, b);
+ }
+ if (bz.sflag) {
+ P2PF(bz.sp, p);
+ P2PF(bz.list[0], u);
+ b = arrow_bb(p, u, 1, bz.sflag);
+ EXPANDBB(bb, b);
+ }
+ if (bz.eflag) {
+ P2PF(bz.ep, p);
+ P2PF(bz.list[bz.size - 1], u);
+ b = arrow_bb(p, u, 1, bz.eflag);
+ EXPANDBB(bb, b);
+ }
}
- B2BF(bb,spl->bb);
+ spl->bb = bb;
}
static void init_bb_edge(edge_t *e)
// {}
}
+static void init_bb_node(graph_t *g, node_t *n)
+{
+ edge_t *e;
+
+ ND_bb(n).LL.x = ND_coord_i(n).x - ND_lw_i(n);
+ ND_bb(n).LL.y = ND_coord_i(n).y - ND_ht_i(n) / 2.;
+ ND_bb(n).UR.x = ND_coord_i(n).x + ND_rw_i(n);
+ ND_bb(n).UR.y = ND_coord_i(n).y + ND_ht_i(n) / 2.;
+
+ for (e = agfstout(g, n); e; e = agnxtout(g, e))
+ init_bb_edge(e);
+
+ /* IDEA - could also save in the node the bb of the node and
+ all of its outedges, then the scan time would be proportional
+ to just the number of nodes for many graphs.
+ Wouldn't work so well if the edges are sprawling all over the place
+ but it wouldn't add much to the cost to try before trying individual
+ nodes and edges. */
+}
+
static void init_bb(graph_t *g)
{
node_t *n;
- edge_t *e;
- for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
- init_bb_node(n);
- for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
- init_bb_edge(e);
- }
- }
+ for (n = agfstnode(g); n; n = agnxtnode(g, n))
+ init_bb_node(g, n);
}
void emit_jobs (GVC_t * gvc, graph_t * g)
#undef BETWEEN
#endif
#define BETWEEN(a,b,c) (((a) <= (b)) && ((b) <= (c)))
+
+/* true if point p is inside box b */
#define INSIDE(p,b) (BETWEEN((b).LL.x,(p).x,(b).UR.x) && BETWEEN((b).LL.y,(p).y,(b).UR.y))
+/* true if boxes b0 and b1 overlap */
#define OVERLAP(b0,b1) (((b0).UR.x >= (b1).LL.x) && ((b1).UR.x >= (b0).LL.x) && ((b0).UR.y >= (b1).LL.y) && ((b1).UR.y >= (b0).LL.y))
+/* true if box b0 completely contains b1*/
#define CONTAINS(b0,b1) (((b0).UR.x >= (b1).UR.x) && ((b0).UR.y >= (b1).UR.y) && ((b0).LL.x <= (b1).LL.x) && ((b0).LL.y <= (b1).LL.y))
+/* expand box b as needed to enclose point p */
+#define EXPANDBP(b, p) (b.LL.x = MIN(b.LL.x, p.x), b.LL.y = MIN(b.LL.y, p.y), b.UR.x = MAX(b.UR.x, p.x), b.UR.y = MAX(b.UR.y, p.y))
+/* expand box b0 as needed to enclose box b1 */
+#define EXPANDBB(b0, b1) (b0.LL.x = MIN(b0.LL.x, b1.LL.x), b0.LL.y = MIN(b0.LL.y, b1.LL.y), b0.UR.x = MAX(b0.UR.x, b1.UR.x), b0.UR.y = MAX(b0.UR.y, b1.UR.y))
+
#define ROUND(f) ((f>=0)?(int)(f + .5):(int)(f - .5))
#define RADIANS(deg) ((deg)/180.0 * PI)
#define DEGREES(rad) ((rad)/PI * 180.0)
extern point add_points(point, point);
extern pointf add_pointfs(pointf, pointf);
extern void arrow_flags(Agedge_t * e, int *sflag, int *eflag);
- extern boxf arrow_bb(GVJ_t * job, pointf p, pointf u, double scale,
- int flag);
+ extern boxf arrow_bb(pointf p, pointf u, double scale, int flag);
extern void arrow_gen(GVJ_t * job, point p, point u, double scale,
int flag);
extern double arrow_length(edge_t * e, int flag);
{
return CONTAINS(b0, b1);
}
+
boolean boxf_contains(boxf b0, boxf b1)
{
return CONTAINS(b0, b1);
return OVERLAP(b, bb);
}
+static boolean overlap_arrow(pointf p, pointf u, double scale, int flag, boxf b)
+{
+ boxf bb;
+
+ bb = arrow_bb(p, u, scale, flag);
+ if (OVERLAP(b, bb)) {
+ /* FIXME - check inside arrow shape */
+ return TRUE;
+ }
+ return FALSE;
+}
+
static boolean overlap_bezier(bezier bz, boxf b)
{
int i, j;
+ point pp;
box bb;
boxf bbf;
+ pointf p, u;
for (i = 0; i < bz.size -1; i += 3) {
/* compute a bb for the bezier segment */
bb.LL = bb.UR = bz.list[i];
for (j = i+1; j < i+4; j++) {
- bb.LL.x = MIN(bb.LL.x,bz.list[j].x);
- bb.LL.y = MIN(bb.LL.y,bz.list[j].y);
- bb.UR.x = MAX(bb.UR.x,bz.list[j].x);
- bb.UR.y = MAX(bb.UR.y,bz.list[j].y);
+ pp = bz.list[j];
+ EXPANDBP(bb, pp);
}
B2BF(bb, bbf);
if (OVERLAP(b, bbf)) {
return TRUE;
}
}
+
+ /* check arrows */
+ if (bz.sflag) {
+ P2PF(bz.sp, p);
+ P2PF(bz.list[0], u);
+ if (overlap_arrow(p, u, 1, bz.sflag, b))
+ return TRUE;
+ }
+ if (bz.eflag) {
+ P2PF(bz.ep, p);
+ P2PF(bz.list[bz.size - 1], u);
+ if (overlap_arrow(p, u, 1, bz.eflag, b))
+ return TRUE;
+ }
return FALSE;
}
textlabel_t *lp;
spl = ED_spl(e);
- if (spl && boxf_overlap(spl->bb, b)) {
+ if (spl && boxf_overlap(spl->bb, b))
for (i = 0; i < spl->size; i++)
if (overlap_bezier(spl->list[i], b))
return TRUE;
-// if (inside_arrow(e))
-// return TRUE;
- }
-
lp = ED_label(e);
if (lp && overlap_label(lp, b))
return TRUE;