How to interpret Graphviz Edge coordinates from xDOT or JSON

Hi,

I am trying to use the graphviz layout algorithms to format draw.io documents. Currently a bit stuck on how to port over the edge coordinates.

I exported the result as xDOT to parse the edge coordinates. However, they are not translating over very well. Is the pos here showing x,y coordinates with the first pair being closest to “a”, and the last pair closest to the “b”?

a → b
pos=“e,3094.7,304.61 2724.3,353.36 2800.6,344.76 2948.7,327.27 3084.5,306.2”];

Really appreciate the help!

The pos syntax is described here: pos | Graphviz, here splineType | Graphviz and page 36 of https://www.graphviz.org/pdf/dotguide.pdf
What you are seeing is a combination of cubic B-splines and arrowheads.
Note that this is true even for straight lines.

p.s. Once you have the conversion understood, you might consider adding a draw.io output routine to Graphviz.
See https://graphviz.org/doc/addingLayout.txt and Section 6 of https://graphviz.org/pdf/libguide.pdf

Thank you for your reply! Really appreciate your help because I was lost.

I figured one thing out today that helped. I realized Graphviz nodes grow downwards as the y coordinate value gets higher. The opposite is true in Drawio. So I was able to recreate the same vertex positions from graphviz in Draw.io by subtracting the largest value of the Y bounding box with the given coordinate Y value. I also had to convert the graphviz coordinate from the center of the node, to the bottom left corner of the node (which Drawio expects).

Still having some trouble with edges though. I set the spline=polyline on the graph, to get points instead of a Bezier curve. I translated the y coordinates of these edge points the same way as above. However, the edges go through the vertice. Any ideas on what I can try or read?

Drawio:

Desired Graphviz output:

Add -y to your dot/fdp/neato/… command line (Command Line | Graphviz). This should flip the Y coordinates.

oh thanks! Didn’t know what.

Does setting spline=polyline make it so the pos field contains flattened points from the bezier curve?

I’m getting this output from the JSON now for an edge.
“_gvid”: 0,
“tail”: 0,
“head”: 1,
draw”:
[
{
“op”: “c”,
“grad”: “none”,
“color”: “#000000
},
{
“op”: “b”,
“points”: [[82.490,503.940],[78.400,488.450],[73.000,468.000],[73.000,468.000],[73.000,468.000],[73.000,288.000],[73.000,288.000],[73.000,288.000],[76.430,275.020],[79.890,261.900]]
}
],
hdraw”:
[
{
“op”: “S”,
“style”: “solid”
},
{
“op”: “c”,
“grad”: “none”,
“color”: “#000000
},
{
“op”: “C”,
“grad”: “none”,
“color”: “#000000
},
{
“op”: “P”,
“points”: [[83.320,262.620],[82.490,252.060],[76.560,260.840]]
}
],
“pos”: “e,82.493,252.06 82.493,503.94 78.401,488.45 73,468 73,468 73,468 73,288 73,288 73,288 76.429,275.02 79.894,261.9”

I don’t know what “flattened points from the bezier curve” means.
If your edges only consist of straight line segments:

  • toss out any eX,Y or sX,T points (save for later)
  • use points #1, 4, 7, 10, 13, … to define your straight line segments in draw.io.
    • points 1 & 4
    • points 4 & 7
    • points 7 &10
  • eX,Y or sX,T points identify arrowhead intersection points with the node
1 Like

FYI, here is an example of the points used by dot to define two curved edges:
html_dot

1 Like

My monthly PSA: the forum supports code blocks with Graphviz syntax highlighting:

```dot
digraph {
  like -> so[with="a label"];
}
```

which produces:

digraph {
  like -> so[with="a label"];
}
2 Likes

Thank you @smattr and @steveroush. Really appreciate your help and responses for this problem. Using the 1st and 4th points to form straight line segments was an improvement. However, I really wanted to get the smoothed out curve that steveroush you posted in your example.

Here’s what I ended up doing that worked really well. Summarizing for anyone else with a similar problem:

  1. Generate JSON or XDOT format with splines=spline in the graph and -y to flip the coordinates.
  2. Add all the nodes to mxGraph, but make sure to transform the pos from the center of the node, to the bottom left corner (which mxgraph wants).
  3. Take the b-spline control points in pos for each edge (should be 4 points), and interpolate concrete points from it. I sampled 8 points per b-spline, and it gave me a very smooth resulting curve. Reference code I used to sample the b-spline: b-spline/index.js at master · thibauts/b-spline · GitHub. Add all these points to your mxGeometry.
  4. Take the eX,Y or sX,Y and add it to mxGeometry (at the end if end point, beginning if starting points).

I’ll consider adding an output routine later.

FWIW I use the JSON response with the following translations to feed directly into an SVG Path Element:

  1. Drop the leading text
  2. Split the string on " "
  3. Convert the pos from Inches to pixels
  4. Invert the X + Y
  5. Feed directly into an SVG Path Element

Visualization/graphviz.ts at trunk · hpcc-systems/Visualization (github.com) - Includes some offsetting based on width and height…

Hello - I know this an old thread but came across it looking to do something similar.

The approach I ended up taking was:

  1. Render the graph as SVG and extract the edge curves
  2. If the curve is not a straight(ish) line, take the cubic bezier
  3. Decompose the cubic into 1, 2, or 3 curves (depending on the number of inflections
  4. Approximate each of those curves as quadratic bezier (since draw.io does not support cubic curves)
  5. Write the quadratics to mxGraph / draw.io format

You can try it out with my command line tool and take a look at the implementation here