How to transform/scale GV ordinates to PNG ordinates

Hi,

I've have been trying to generate a Graphviz graph, to be displayed on a web page and then overlay clickable regions onto the image so that I can click on particular nodes and do something clever with it.

My problem is translating the ordinates used by Graphviz into genuine xy ordinates that relate to the generated PNG image. I know this issue has been mentioned several times in the past on this and other forums, but I've not managed to find a solution (such that there are) that actually works, or detailed enough to use.

I sort-of have a solution as follows, but there is an error in my calculations that is bad enough to make the result unrealiable in some cases.

This is my method....

-----------------
1/ Take my .gv file (I'll call it source.gv) and process it as follows :-

   dot -Kfdp ./source.gv -o ./stage2.gv

-----------------
2/ This results in a 'stage2.gv" file that looks something like this (I have removed the bulk of the nodes and all the edges, leaving only a few nodes that demonstrate the problem) :-

graph G {
    graph [bb="0,0,5148,3455",
        bgcolor=black,
        dpi=100,
        fontcolor=white,
        fontname=ariel,
        label="15/05/2013 09:52:31",
        lheight=0.21,
        lp="2574,11.5",
        lwidth=2.06,
        margin=0.0,
        pad="0.055500,0.055500",
        ratio=fill,
        size="12.000000,8.000000"
    ];
    node [color=linen,
        fillcolor=bisque4,
        fontname=ariel,
        label="\N",
        shape=box,
        style=filled
    ];
    edge [len=1];
    1     [fillcolor=olivedrab1,
        height=0.5,
        pos="2001.5,78.657",
        width=0.75];
    13     [fillcolor=olivedrab1,
        height=0.5,
        pos="251.4,559.52",
        width=0.75];
    17     [fillcolor=olivedrab1,
        height=0.5,
        pos="269.08,962.3",
        width=0.75];
    25     [height=0.5,
        pos="2839.5,1113.7",
        width=0.75];
    30     [fillcolor=olivedrab1,
        height=0.5,
        pos="4592.7,1335.6",
        width=0.75];
    43     [fillcolor=olivedrab1,
        height=0.5,
        pos="3327,2142.4",
        width=0.75];
    36     [fillcolor=olivedrab1,
        height=0.5,
        pos="2505.6,1983.5",
        width=0.75];
}

-----------------
3/ I then read back this "stage2.gv" file and parse it to extact the position data. After I have done this, I pass the "stage2.gv" file back to Graphviz to render the final PNG image with the following command line :-

dot -Kneato -Tpng -n stage2.gn -o graph.png

-----------------
4/ Meanwhile, this is how I interpret the position data extracted out of the "stage2.gv" file. If I take only the x ordinates for now (the y ordinates are treated exactly the same), I work out the following :-

The "bb" is (5148 - 1 + 1) = 5149 "things" wide

I say "things" because no matter how I manipulate the numvbers, I don't think I've managed to relate this number to anything in the real world; dpi/points?

The width of the generated image is 12.0 inches wide @ 100dpi (note I set dpi = 100 in the condfig). This seems accurate and the generated PNG image is indeed 1200 pixels wide. So far, so good.

I calculate a "scaling" value of 5149 / 12 = 429.083

-----------------
4/ If I then take one of the nodes' x positions (say node 36), I then apply this "scaling" as follows:-

Node 36's x ordinate = 2505.6

PNG x posn = 2506.6 * 100 / 429.083 = 584  [ x 100 because 100dpi ]

The ACTUAL (correct) x position of the centre of node 36 on the PNG image is more like 581, so I'm pretty close; close enough to live with the error.

However, the error becomes more pronounces towards the edge of the image. If I take node 17, for example, and do the same calculations, I get :-

PNG x posn = 269.08 * 100 / 429.083 = 62.71

The ACTUAL (corect) x position of the centre of node 17 on the PNG image is more like 12. When the size of the node is only 13 pixels wide (which it is in this case), then the error is not acceptable.

Checking the other nodes scattered about the image shows me that the error gravitates towards the centre of the image; A node places in the ecentre will have no error, and the error becomes progressively worse as the node position moves towards the edge.

-----------------
I have seen and read this...

http://www.graphviz.org/content/faqcoordtransformation

...and I've hunted about (and found) several other references to this problem, but none that actually provide an answer.

...and I've even set my "pad" and "margin" to zero on occasion to try and eliminate the problem, but it doesn't seem to influence it at all.

I suppose my question is, what am I missing here? What am I doing wrong?

One could probable work

One could probable work through the numbers to figure out the exact coordinate transformation, but this calculation is already during output. Just do

    dot -Ntooltip="\N" -Kfdp ./source.gv -Tpng -o ./stage2.png -Tcmapx -o ./stage2.map

The file stage2.map will contain the exact coordinates, in pixels, of each node. The title field will be the node's name, so you can associate each node with its coordinates. Indeed, you can embed the URL you want associated with each node in the graph using the URL or href attribute. The output can immediately be used as a client-side image map. See

    http://www.graphviz.org/content/output-formats#dcmapx

for more information about setting up client-side or server-side image maps.

It works!

Just a quick note to say thank you for your suggestion. It works like a charm. I still have to read the file back and parse it again to do what I want to do (the output I need is too complex to be accomodated by the standard output), but the co-ordinates are now correct.

Thanks again,

R.

Recent comments