How to make edge reach node boundary?

In my simple two-node, one-edge directed graph, the edge is not reaching the target node’s visible boundary. This happens in dot, circo, fdp, and twopi, at all rankdirs, and with splines set to ‘spline’, ‘line’, or to nothing at all. It also doesn’t matter whether overlap is set to ‘prism’ or not set at all.

I’ve tried setting nodesep and ranksep to various values or just to the defaults.

I’m using graphviz 2.47.2.

What am I missing?

Here’s the source:

digraph IdeaTree {
graph [ notranslate=“true” labelloc=t inputscale=“72” ranksep=“1.0” overlap=“prism” dpi=“72” splines=“spline” rankdir=“LR”]
node [ pin=“true” fixedsize=“true”]
edge [ arrowsize=“4.0” arrowhead=“normal” headclip=“true” ]
“36047” [ id=“36047” pos=“238.5,-162.0” width=“6.62” height=“4.50” shape=“rectangle” label=“qwer”]
“36113” [ id=“36113” pos=“711.0,-162.0” width=“4.50” height=“4.50” shape=“rectangle” label=“asdf”]
“36047” → “36113”
}

And the json output (edited to show only the relevant parts). You’ll notice that the target node’s left border is at 549, but the edge’s rightmost point is 508, so the edge stops 41 pts. before reaching the node.

{
“name”: “IdeaTree”,
“bb”: “0,0,873,324”,
“dpi”: “72”,
“inputscale”: “72”,
“notranslate”: “true”,
“overlap”: “prism”,
“rankdir”: “LR”,
“ranksep”: “1.0”,
“splines”: “spline”,
“objects”: [
{
draw”:
[
{
“op”: “p”,
“points”: [[873.000,324.000],[549.000,324.000],[549.000,0.000],[873.000,0.000]]
}
],
“fixedsize”: “true”,
“height”: “4.5”,
“label”: “asdf”,
“pin”: “true”,
“pos”: “711,162”,
“shape”: “rectangle”,
“width”: “4.5”
}
],
“edges”: [
{
draw”:
[
{
“op”: “b”,
“points”: [[477.160,162.000],[487.700,162.000],[498.230,162.000],[508.670,162.000]]
}
],
“arrowhead”: “normal”,
“arrowsize”: “4.0”,
“headclip”: “true”,
“pos”: “e,548.92,162 477.16,162 487.7,162 498.23,162 508.67,162”
}
]
}

Unfortunately, a known problem: [Output Generation] Failure of arrowhead and arrowtail to respect penwidth (#372) · Issues · graphviz / graphviz · GitLab and Allign node's stroke with end of the arrow's path width

p.s. would you please share your source again, but use “pre-formatted text” </> button, instead of blockquote. When I copy/paste, I get lots of non-printable chars.

Your prompt responses are great.

Here’s the source again:

digraph IdeaTree {
graph [ notranslate="true" labelloc=t  inputscale="72" ranksep="1.0"  overlap="prism"   dpi="72"  splines="spline"  rankdir="LR"]
node [ pin="true"  fixedsize="true"]
edge [    arrowsize="4.0" arrowhead="normal"  headclip="true" ]
"36047" [ id="36047" pos="238.5,-162.0" width="6.62" height="4.50" shape="rectangle" label="qwer"]
"36113" [ id="36113" pos="711.0,-162.0" width="4.50" height="4.50" shape="rectangle" label="asdf"]
"36047" -> "36113" 
}

Now that I’ve explained that it is a known problem, I’m going to back-up and say that I’m not seeing any problem. Whoops.
The JSON “issue” is really just the peculiar (to me) syntax of edges with arrows. Arrow(s) are specified at the beginning of the edge, regardless of whether the arrow is at the head or the tail (see Attributes | Graphviz) Note: e,548.92,162 below:

“pos”: “e,548.92,162 477.16,162 487.7,162 498.23,162 508.67,162”

Giving:

Ah, you’re using ‘pos’ and I’ve been using ‘draw’.

Comparing the two in the JSON output:

"_draw_":
          "op": "b",
          "points": [[477.170,-162.000],[487.700,-162.000],[498.230,-162.000],[508.660,-162.000]]

and:

"pos": "e,548.9,-162 477.17,-162 487.7,-162 498.23,-162 508.66,-162"

for the same edge.

‘pos’ has the extreme right endpoint at the beginning, as you point out. ‘draw’ doesn’t have the last point.

So…what’s the intended purpose of draw vs. pos?

Output Formats says ‘draw’ is for B splines, and
splineType | Graphviz says that ‘pos’ is also a spline type.

I’ve confirmed that when the edge is curved, ‘pos’ is still the same as ‘draw’ except for the inclusion as its initial point the rightmost end of the edge.

What I’ve resorted to, since my code relies on other values present in ‘draw’, is to pop the first entry in ‘pos’ and append it to the end of ‘draw’.

Could this be a bug that crept into graphviz, since at one time my code worked without this hack?

The “pos” attribute is a terse text description of an edge. Note that the drawing attributes of an edge are implied. In particular, there is no indication what the shape of an arrowhead is. Typically, in a directed graph, the e part gives the point where the arrowhead touches the node. The rest of the points specifies the spline that goes from a point touching the tail node to a point close to the head node. How one draws an arrowhead using the last spline point and the point given by e depends on other attributes of the edge. It is a peculiar syntax, but it is sufficient if you only use dot or friends to do the rendering.

With time, it became apparent that some applications wanted to do their own rendering, using the layout provided by Graphviz. For this to happen, either the application would have to incorporate all of the rendering information implicit in the Graphviz renderers, or more drawing information would need to be provided in the output. This led to the xdot format, where the new attributes specify in detail how to draw each graph object (except for fonts and the various style attributes such as dotted splines). In particular, the _draw_ attribute for an edge provides just the control points for the associated spline. How to draw the arrowhead is completely described in the _hdraw_ attribute.

Of course, the application still needs to be able to parse the dot language. For this reason, the json output format was introduced. This is just a simple translation of the xdot format into json, relying on the ready availability of json parsers.

In short, if you want to know the details of how an edge (or node) is drawn, use the _draw_, _hdraw_, etc, attributes in either xdot or json.

1 Like

Very valuable information. I’m glad you’re around with your historical knowledge.