static polygon_t p_Mcircle =
{ TRUE, 1, 1, 0., 0., 0., DIAGONALS | AUXLABELS };
+#define IS_BOX(n) (ND_shape(n)->polygon == &p_box)
+
/*
* every shape has these functions:
*
return angle;
}
-/* would like = 0, but spline router croaks
- * Basically, if the point is actually on a box, the curve fitter
- * may, at some point, compute a curve which lies entirely outside
- * the polygon except at the two endpoints. Thus, by guaranteeing that
- * the point lies in the interior, such bad cases can't happen.
- */
-#define MARGIN 1
-
/* compassPoint:
* Compute compass points for non-trivial shapes.
* It finds where the ray ((0,0),(x,y)) hits the boundary and
if (compass && *compass) {
switch (*compass++) {
case 'e':
- p.x = b.UR.x + MARGIN;
+ p.x = b.UR.x;
theta = 0.0;
constrain = 1;
defined = TRUE;
side = sides & RIGHT;
break;
case 's':
- p.y = b.LL.y - MARGIN;
+ p.y = b.LL.y;
constrain = 1;
clip = FALSE;
- side = sides & BOTTOM;
switch (*compass) {
case '\0':
theta = -PI * 0.5;
defined = TRUE;
+ side = sides & BOTTOM;
break;
case 'e':
theta = -PI * 0.25;
defined = TRUE;
if (ictxt) p = compassPoint (ictxt, -MAXINT, MAXINT);
- else p.x = b.UR.x + MARGIN;
+ else p.x = b.UR.x;
+ side = sides & (BOTTOM | RIGHT);
break;
case 'w':
theta = -PI * 0.75;
defined = TRUE;
if (ictxt) p = compassPoint (ictxt, -MAXINT, -MAXINT);
- else p.x = b.LL.x - MARGIN;
+ else p.x = b.LL.x;
+ side = sides & (BOTTOM | LEFT);
break;
default:
p.y = ctr.y;
}
break;
case 'w':
- p.x = b.LL.x - MARGIN;
+ p.x = b.LL.x;
theta = PI;
constrain = 1;
defined = TRUE;
side = sides & LEFT;
break;
case 'n':
- p.y = b.UR.y + MARGIN;
+ p.y = b.UR.y;
constrain = 1;
clip = FALSE;
- side = sides & TOP;
switch (*compass) {
case '\0':
defined = TRUE;
theta = PI * 0.5;
+ side = sides & TOP;
break;
case 'e':
defined = TRUE;
theta = PI * 0.25;
if (ictxt) p = compassPoint (ictxt, MAXINT, MAXINT);
- else p.x = b.UR.x + MARGIN;
+ else p.x = b.UR.x;
+ side = sides & (TOP | RIGHT);
break;
case 'w':
defined = TRUE;
theta = PI * 0.75;
if (ictxt) p = compassPoint (ictxt, MAXINT, -MAXINT);
- else p.x = b.LL.x - MARGIN;
+ else p.x = b.LL.x;
+ side = sides & (TOP | LEFT);
break;
default:
p.y = ctr.y;
}
}
else {
- inside_t ictxt;
+ inside_t* ictxtp;
+ inside_t ictxt;
- ictxt.s.n = n;
- ictxt.s.bp = NULL;
- if (compassPort(n, NULL, &rv, portname, sides, &ictxt))
+ if (IS_BOX(n)) ictxtp = NULL;
+ else {
+ ictxt.s.n = n;
+ ictxt.s.bp = NULL;
+ ictxtp = &ictxt;
+ }
+ if (compassPort(n, NULL, &rv, portname, sides, ictxtp))
unrecognized(n, portname);
}
* such that the last one ends has the smallest LL.y and its LL.y is above
* the bottom of the rank (rank.ht1).
*
+ * For flat edges, we assume endp->sidemask has been set. For regular
+ * edges, we set this, but it doesn't appear to be needed any more.
+ *
+ * In many cases, we tweak the x or y coordinate of P->start.p by 1.
+ * This is because of a problem in the path routing code. If the starting
+ * point actually lies on the polygon, in some cases, the router gets
+ * confused and routes the path outside the polygon. So, the offset ensures
+ * the starting point is in the polygon.
+ *
* FIX: Creating the initial boxes only really works for rankdir=TB and
* rankdir=LR. For the others, we rely on compassPort flipping the side
* and then assume that the node shape has top-bottom symmetry. Since we
if ((et == REGULAREDGE) && (ND_node_type(n) == NORMAL) && ((side = ED_tail_port(e).side))) {
edge_t* orig;
box b0, b = endp->nb;
- switch (side) {
- case LEFT:
- b.UR.x = P->start.p.x;
- b.LL.y = ND_coord_i(n).y - ND_ht_i(n)/2;
- b.UR.y = P->start.p.y;
- endp->boxes[0] = b;
- endp->boxn = 1;
- break;
- case RIGHT:
- b.LL.x = P->start.p.x;
- b.LL.y = ND_coord_i(n).y - ND_ht_i(n)/2;
- b.UR.y = P->start.p.y;
- endp->boxes[0] = b;
- endp->boxn = 1;
- break;
- case TOP:
- if (ND_coord_i(e->head).x < 2*ND_coord_i(n).x - endp->np.x) {
+ if (side & TOP) {
+ endp->sidemask = TOP;
+ if (P->start.p.x < ND_coord_i(n).x) { /* go left */
b0.LL.x = b.LL.x - 1;
/* b0.LL.y = ND_coord_i(n).y + ND_ht_i(n)/2; */
b0.LL.y = P->start.p.y;
- b0.UR.x = P->start.p.x;
+ b0.UR.x = b.UR.x;
b0.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2 + GD_ranksep(n->graph)/2;
b.UR.x = ND_coord_i(n).x - ND_lw_i(n) - 2;
b.UR.y = b0.LL.y;
endp->boxes[1] = b;
}
else {
- b0.LL.x = P->start.p.x;
+ b0.LL.x = b.LL.x;
b0.LL.y = P->start.p.y;
/* b0.LL.y = ND_coord_i(n).y + ND_ht_i(n)/2; */
b0.UR.x = b.UR.x+1;
endp->boxes[0] = b0;
endp->boxes[1] = b;
}
+ P->start.p.y += 1;
endp->boxn = 2;
- break;
- case BOTTOM:
+ }
+ else if (side & BOTTOM) {
+ endp->sidemask = BOTTOM;
b.UR.y = MAX(b.UR.y,P->start.p.y);
endp->boxes[0] = b;
endp->boxn = 1;
- break;
+ P->start.p.y -= 1;
+ }
+ else if (side & LEFT) {
+ endp->sidemask = LEFT;
+ b.UR.x = P->start.p.x;
+ b.LL.y = ND_coord_i(n).y - ND_ht_i(n)/2;
+ b.UR.y = P->start.p.y;
+ endp->boxes[0] = b;
+ endp->boxn = 1;
+ P->start.p.x -= 1;
+ }
+ else {
+ endp->sidemask = RIGHT;
+ b.LL.x = P->start.p.x;
+ b.LL.y = ND_coord_i(n).y - ND_ht_i(n)/2;
+ b.UR.y = P->start.p.y;
+ endp->boxes[0] = b;
+ endp->boxn = 1;
+ P->start.p.x += 1;
}
for (orig = e; ED_edge_type(orig) != NORMAL; orig = ED_to_orig(orig));
if (n == orig->tail)
ED_tail_port(orig).clip = FALSE;
else
ED_head_port(orig).clip = FALSE;
- endp->sidemask = side;
return;
}
if ((et == FLATEDGE) && ((side = ED_tail_port(e).side))) {
box b0, b = endp->nb;
edge_t* orig;
- switch (side) {
- case LEFT:
+ if (side & TOP) {
+ b.LL.y = MIN(b.LL.y,P->end.p.y);
+ endp->boxes[0] = b;
+ endp->boxn = 1;
+ }
+ else if (side & BOTTOM) {
+ if (endp->sidemask == TOP) {
+ b0.UR.y = ND_coord_i(n).y - ND_ht_i(n)/2;
+ b0.UR.x = b.UR.x+1;
+ b0.LL.x = P->start.p.x;
+ b0.LL.y = b0.UR.y - GD_ranksep(n->graph)/2;
+ b.LL.x = ND_coord_i(n).x + ND_rw_i(n) + 2;
+ b.LL.y = b0.UR.y;
+ b.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2;
+ b.UR.x += 1;
+ endp->boxes[0] = b0;
+ endp->boxes[1] = b;
+ endp->boxn = 2;
+ }
+ else {
+ b.UR.y = MAX(b.UR.y,P->start.p.y);
+ endp->boxes[0] = b;
+ endp->boxn = 1;
+ }
+ }
+ else if (side & LEFT) {
b.UR.x = P->start.p.x+1;
if (endp->sidemask == TOP) {
b.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2;
}
endp->boxes[0] = b;
endp->boxn = 1;
- break;
- case RIGHT:
+ }
+ else {
b.LL.x = P->start.p.x;
if (endp->sidemask == TOP) {
b.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2;
}
endp->boxes[0] = b;
endp->boxn = 1;
- break;
- case TOP:
- b.LL.y = MIN(b.LL.y,P->end.p.y);
- endp->boxes[0] = b;
- endp->boxn = 1;
- break;
- case BOTTOM:
- if (endp->sidemask == TOP) {
- b0.UR.y = ND_coord_i(n).y - ND_ht_i(n)/2;
- b0.UR.x = b.UR.x+1;
- b0.LL.x = P->start.p.x;
- b0.LL.y = b0.UR.y - GD_ranksep(n->graph)/2;
- b.LL.x = ND_coord_i(n).x + ND_rw_i(n) + 2;
- b.LL.y = b0.UR.y;
- b.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2;
- b.UR.x += 1;
- endp->boxes[0] = b0;
- endp->boxes[1] = b;
- endp->boxn = 2;
- }
- else {
- b.UR.y = MAX(b.UR.y,P->start.p.y);
- endp->boxes[0] = b;
- endp->boxn = 1;
- }
- break;
}
for (orig = e; ED_edge_type(orig) != NORMAL; orig = ED_to_orig(orig));
if (n == orig->tail)
case REGULAREDGE:
endp->boxes[0].UR.y = P->start.p.y;
endp->sidemask = BOTTOM;
+ P->start.p.y -= 1;
break;
}
}
if ((et == REGULAREDGE) && (ND_node_type(n) == NORMAL) && ((side = ED_head_port(e).side))) {
edge_t* orig;
box b0, b = endp->nb;
- switch (side) {
- case LEFT:
- b.UR.x = P->end.p.x;
- b.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2;
- b.LL.y = P->end.p.y;
- endp->boxes[0] = b;
- endp->boxn = 1;
- break;
- case RIGHT:
- b.LL.x = P->end.p.x;
- b.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2;
- b.LL.y = P->end.p.y;
+ if (side & TOP) {
+ endp->sidemask = TOP;
+ b.LL.y = MIN(b.LL.y,P->end.p.y);
endp->boxes[0] = b;
endp->boxn = 1;
- break;
- case BOTTOM:
- if (ND_coord_i(e->tail).x < 2*ND_coord_i(n).x - endp->np.x) {
+ P->start.p.y += 1;
+ }
+ else if (side & BOTTOM) {
+ endp->sidemask = BOTTOM;
+ if (P->end.p.x < ND_coord_i(n).x) { /* go left */
b0.LL.x = b.LL.x-1;
/* b0.UR.y = ND_coord_i(n).y - ND_ht_i(n)/2; */
b0.UR.y = P->end.p.y;
- b0.UR.x = P->end.p.x;
+ b0.UR.x = b.UR.x;
b0.LL.y = ND_coord_i(n).y - ND_ht_i(n)/2 - GD_ranksep(n->graph)/2;
b.UR.x = ND_coord_i(n).x - ND_lw_i(n) - 2;
b.LL.y = b0.UR.y;
endp->boxes[1] = b;
}
else {
- b0.LL.x = P->end.p.x;
+ b0.LL.x = b.LL.x;
b0.UR.y = P->end.p.y;
/* b0.UR.y = ND_coord_i(n).y - ND_ht_i(n)/2; */
b0.UR.x = b.UR.x+1;
endp->boxes[1] = b;
}
endp->boxn = 2;
- break;
- case TOP:
- b.LL.y = MIN(b.LL.y,P->end.p.y);
+ P->end.p.y -= 1;
+ }
+ else if (side & LEFT) {
+ endp->sidemask = LEFT;
+ b.UR.x = P->end.p.x;
+ b.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2;
+ b.LL.y = P->end.p.y;
endp->boxes[0] = b;
endp->boxn = 1;
- break;
+ P->start.p.x -= 1;
+ }
+ else {
+ endp->sidemask = RIGHT;
+ b.LL.x = P->end.p.x;
+ b.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2;
+ b.LL.y = P->end.p.y;
+ endp->boxes[0] = b;
+ endp->boxn = 1;
+ P->start.p.x -= 1;
}
for (orig = e; ED_edge_type(orig) != NORMAL; orig = ED_to_orig(orig));
if (n == orig->head)
case REGULAREDGE:
endp->boxes[0].LL.y = P->end.p.y;
endp->sidemask = TOP;
+ P->start.p.y += 1;
break;
}
}