"neato" tool v2.37 curved lines crosses boxes unlike "dot" tool

I have a problem. User moves box controls on canvas. "dot" tool produces curved lines to not cross boxes. Since user can move boxes, I need to use "neato" tool which provides exact positions of box controls in pixels (user can move these boxes).

But unfortunately "neato" tool is crossing boxes while drawing curved lines (inputs and outputs of boxes).

Is there a possibility to use some tool and command-line arguments to display boxes at user's wished positions, while curved connection lines will not cross these boxes and will be curved around them?

Any suggestion is welcome.

run:
d:\tmp>"c:\Program Files (x86)\Graphviz2.37\bin\neato.exe" -Tjpg -n _data.gv > _data.jpg

here is my neato ("_data.gv") script:

--- snip ---
digraph G {
splines=curved;
graph [dpi="72"];
bgcolor="lightgray";
n_a [label="", color="lightgray", rectangular="true", shape="box", width="0.001", height="0.001", pos="0,500!"];
n_b [label="", color="lightgray", rectangular="true", shape="box", width="0.001", height="0.001", pos="2840,-963!"];
n0 [label="{{|}|{|}}", color="lightgray", fixedsize="true", rectangular="true", shape="record", width="6.83333", height="0.861111", pos="268,-318!"];
n1 [label="{{|}|{|}|{|}}", color="lightgray", fixedsize="true", rectangular="true", shape="record", width="9.27778", height="1.22222", pos="1057,-385!"];
n2 [label="{{|}|{|}|{|}|{|}}", color="lightgray", fixedsize="true", rectangular="true", shape="record", width="9.34722", height="1.58333", pos="1030,-227!"];
n3 [label="{{|}|{|}}", color="lightgray", fixedsize="true", rectangular="true", shape="record", width="6.83333", height="0.861111", pos="294,-437!"];
n4 [label="{{|}|{|}|{|}}", color="lightgray", fixedsize="true", rectangular="true", shape="record", width="9.27778", height="1.22222", pos="996,-501!"];
n5 [label="{{|}|{|}}", color="lightgray", fixedsize="true", rectangular="true", shape="record", width="6.83333", height="0.861111", pos="320,-744!"];
n6 [label="{{|}|{|}}", color="lightgray", fixedsize="true", rectangular="true", shape="record", width="6.83333", height="0.861111", pos="275,-539!"];
n7 [label="{{|}|{|}|{|}}", color="lightgray", fixedsize="true", rectangular="true", shape="record", width="9.27778", height="1.22222", pos="1116,-671!"];
n8 [label="{{|}|{|}}", color="lightgray", fixedsize="true", rectangular="true", shape="record", width="9.15278", height="0.861111", pos="1668,-633!"];
n9 [label="{{|}|{|}}", color="lightgray", fixedsize="true", rectangular="true", shape="record", width="6.83333", height="0.861111", pos="801,-879!"];
n10 [label="{{|}|{|}}", color="lightgray", fixedsize="true", rectangular="true", shape="record", width="9.15278", height="0.861111", pos="1812,-215!"];
n11 [label="{{|}|{|}|{|}|{|}|{|}|{|}|{|}}", color="lightgray", fixedsize="true", rectangular="true", shape="record", width="9.66667", height="2.66667", pos="1734,-344!"];
n12 [label="{{|}|{|}}", color="lightgray", fixedsize="true", rectangular="true", shape="record", width="6.72222", height="0.861111", pos="250,-39!"];
n13 [label="{{|}|{|}}", color="lightgray", fixedsize="true", rectangular="true", shape="record", width="6.83333", height="0.861111", pos="2281,-527!"];
n14 [label="{{|}|{|}|{|}}", color="lightgray", fixedsize="true", rectangular="true", shape="record", width="9.15278", height="1.22222", pos="2452,-406!"];
n15 [label="{{|}|{|}}", color="lightgray", fixedsize="true", rectangular="true", shape="record", width="6.83333", height="0.861111", pos="1589,-476!"];
n16 [label="{{|}|{|}}", color="lightgray", fixedsize="true", rectangular="true", shape="record", width="6.83333", height="0.861111", pos="1597,-556!"];
n17 [label="{{|}|{|}}", color="lightgray", fixedsize="true", rectangular="true", shape="record", width="6.83333", height="0.861111", pos="2240,-624!"];
n18 [label="{{|}|{|}}", color="lightgray", fixedsize="true", rectangular="true", shape="record", width="6.83333", height="0.861111", pos="2238,-709!"];
n19 [label="{{|}|{|}}", color="lightgray", fixedsize="true", rectangular="true", shape="record", width="6.72222", height="0.861111", pos="750,-39!"];
n20 [label="{{|}|{|}|{|}|{|}|{|}}", color="lightgray", fixedsize="true", rectangular="true", shape="record", width="9.94444", height="1.94444", pos="2483,-264!"];
n0:out1 -> n1:in2 [arrowhead="vee"];
n1:out1 -> n2:in2 [arrowhead="vee"];
n3:out1 -> n4:in2 [arrowhead="vee"];
n4:out1 -> n2:in3 [arrowhead="vee"];
n5:out1 -> n4:in1 [arrowhead="vee"];
n6:out1 -> n7:in2 [arrowhead="vee"];
n7:out1 -> n8:in1 [arrowhead="vee"];
n8:out1 -> n1:in1 [arrowhead="vee"];
n9:out1 -> n7:in1 [arrowhead="vee"];
n2:out1 -> n10:in1 [arrowhead="vee"];
n10:out1 -> n11:in1 [arrowhead="vee"];
n12:out1 -> n11:in6 [arrowhead="vee"];
n13:out1 -> n14:in2 [arrowhead="vee"];
n15:out1 -> n11:in4 [arrowhead="vee"];
n16:out1 -> n11:in5 [arrowhead="vee"];
n17:out1 -> n11:in2 [arrowhead="vee"];
n18:out1 -> n11:in3 [arrowhead="vee"];
n11:out2 -> n19:in1 [arrowhead="vee"];
n11:out3 -> n20:in1 [arrowhead="vee"];
}
--- snip ---

Still there is no schedule?

Still there is no schedule? And how the work progresses? Do you still have only sketch, or the development has began yet?

(The indentations are moving

(The indentations are moving things unnecessarily far to the right, so I am adding a comment to your original post.)

1. esep=+20 tells neato to pretend each of the nodes is increased by a 20-point margin and then route the edges to avoid the enlarged rectangles, but only if none of the bigger rectangles intersects any other rectangle. If there is any overlap, it reverts to line segments. If you increase each of your nodes by 20 points, you'll find that some of them overlap.

I only suggested esep=+20 to get some extra space so the edges would be clearer. For this example, there is already plenty of space, so you don't need to set esep at all and you'll get curved edges.

Out of curiosity, what tool are you using to invoke neato? Neato produces a warning message if it can't route using splines. If you checked this, it would be clear what is going wrong.

2. Yes, if you run using overlaps=false, the node positions may change. That is how overlaps are removed. If that is possible, your application needs to recompute the placement of widgets. As I said in one of my first replies, if you can't allow widgets to move because the position was specified by the user, and some of the nodes overlap, you can't get edges drawn as curves avoiding nodes.

By the way, there is no attribute called "rectangle" used by neato.

 

Is there some plan to improve

Is there some plan to improve algorithm such as when nodes overlaps and line can't be written in a normal way, to chose diferent path for line (in extreme case to curve it around all nodes, say around full image) to reach final destination? That would be great.

> Out of curiosity, what tool are you using to invoke neato? Neato produces a warning message if it can't route using splines. If you checked this, it would be clear what is going wrong.

I am using wxWidgets library, which is actually cross-platform middle layer for standard syscalls, I am sending neato script via pipe to stdin and gathering JPG result via stdout pipe, but I must admit that my application doesn't read stderr file descriptor at all.

Yes, I have sketched out an

Yes, I have sketched out an algorithm to route edges even if nodes overlap. The problem is one of time.

You might consider linking directly to the graphviz library. You can install your own error handler.

I'm waiting impantiently! I

I'm waiting impantiently! I understand that this is a big challenge, and my mathematical skills are far from perfect to implement such algorithm nor how to compute multi-curved lines. Anayways, thank you very much for you effort!

Question: does NEATO print errors and warnings to stderr? (As I wrote before I don't read stderr at all). Because I don't want to link library to my application, since I'm affraid of crashing neato library, therefore crashing my whole application. E.g. I had a few crashes, but that was my own fault, when my application generated wrong script for neato as my error, with insane values like position not computed as a float by DPI, but 3 or 4 digits long integers, so IMO the crash was legitimate (out of memory due to *BIG* image?). I'd like for sake of stability call neato as spawned sub-process and communicate via pipes to it.

Yes, errors and warnings are

Yes, errors and warnings are written to stderr by default. Even if you can't read this via a pipe, I would think there is some way to make sure this gets saved somewhere where you can check it.

I understand your desire to use neato as a separate process. Indeed, the first part of the library manual encourages people to do this rather than use the library API.

Is there some time schedule?

Is there some time schedule?

Impossible to say.

Impossible to say.

Gretings, it is very

Gretings,

it is very important to me, I can make a financial donation, where it's apply.

Beest,

VooDooMan

.

topic bump

Greetings,

Sill no progress?

best,

vdm

.

Setting splines=curves

Setting splines=curves results in edges being drawn as circular arcs, which may well cross intermediate nodes If you want edges to avoid nodes, as dot does, you want to use splines=true. Unfortunately, spline routing at present assumes no two nodes overlap each other (within a given margin), which is not the case with your input.

Setting splines=curves

unfortunatelly, setting "Setting splines=curves" had no effect.

Setting splines=curves

 

Thank you very much for your suggestion, I modified code to generate neato script with "Setting splines=curves", but please give me some time, since I need to recompile the whole SW that is generating "neato" script, and I will get back to you with result report.

Thank you very much for your time.

 

Setting splines=curves

thank you very much, I will give a try to "splines=true;" and after recompiling my SW I will get back to you with my observations/results.

best,

vdm

.

Setting splines=curves

I had no luck with suggested settings with neato :-/

Any ideas are greatly appreciated!

Best, TIA!,

vdm

.

Did you catch my warning that

Did you catch my warning that the nodes must not overlap? For spline routing to work, there must be sufficient room between every pair of nodes, as specified by the esep attribute. If I run neato with -Goverlap=false, I get edges drawn as splines.

"neato" tool v2.37 curved lines crosses boxes unlike "dot" tool

Sorry for long delay, I had to work on something else with a higher priority.

I just upgraded to graphviz-2.37.20140221.msi to be sure.

When my command line looks like:

1.

char* argv[]={ GRAPHVIZ_BIN, "-Tjpg", "-n", NULL };

I get lines that crosses boxes.

2.

If I add "-Goverlap=false", then whole output is shifted, and it is not respecting positions, so generated image on canvas under controls is shifted. But still lines are crossing boxes.

3.

When command line is:

char* argv[]={ GRAPHVIZ_BIN, "-Tjpg", "-n", "-Goverlap=false", "-Gesep=1", NULL };

it looks similar to [2.] (shifted, lines crossing boxes).

My wish is that lines would go like "zig-zag" flowing around boxes, since the boxes drawn on canvas are hidden by floating controls above them, since generated image is on background. The user can move those boxes on the screen, in that case neato is re-run with new generated script, so I cannot control overlapping or not overlapping of boxes.

Please, could you tell me what I am doing wrong? If you have an idea, I would like to see exact command line, and/or suggestion about adjusting generated neato script.

I enabled debugging in my SW to show boxes, so this is my generated neato script for test case is:

http://pastebin.com/e0HaqXxW

TIA!

First, please install

First, please install tomorrow's version (22 Feb), as I just fixed a bug which may affect the drawing of your graphs. Sorry.

Now, 1. is the status quo.

2. will remove overlaps, but as you have not reset the splines parameter, the edges will still cross. You mention that the positions have changed. Yes, the nodes had to be moved in order to remove the overlap. If you plan to layer controls on top of the image, you will have to redo the coordinates. You can either read these from the graph, or use cmap or svg output to get the relevant geometries.

3. is the same as 2. as you are using multiplicative rather than additive margins.

I would change splines=curved to splines=true in the graph. Then run

    neato -Goverlap=false -Gesep=+20 -n

on your graph. When I do this, I get this image. (The ports aren't correct because your input graph hasn't defined them.)

"neato" tool v2.37 curved lines crosses boxes unlike "dot" tool

> First, please install tomorrow's version (22 Feb), as I just fixed a bug which may affect the drawing of your graphs. Sorry.

It's okay regarding yesterday's bug, we are not machines.

Now I have problem when resulting image has not proper dimensions, so I needed to rescale it before use, because the *user* decides where the box should be placed. But I am approaching this goal.

It would be great if I could specify positions in pixels, and everything would not be proportional (DPI, float positions) but "bitmap" rather (integer pixels positions).

Thank you very much for suggestions, and the great SW!

It looks like neato ignores

It looks like neato ignores "pos" attribute rectangle node attribute ("box") for arguments:

static char* argv[]={ GRAPHVIZ_BIN, "-Tjpg", "-n", "-Goverlap=false", "-Gesep=+20", NULL };

And my next question is: is "pos" in inches and adjusted by DPI specified in script?

Another question is: It is not too much clear to me what means "!" suffix in "pos" attribute in the PDF documentation, there is mentioned to "pin position", could you please be more elaborative?

>> It looks like neato

>> It looks like neato ignores "pos" attribute rectangle node attribute ("box") for arguments:

>>static char* argv[]={ GRAPHVIZ_BIN, "-Tjpg", "-n", "-Goverlap=false", "-Gesep=+20", NULL };

I don't understand what you are saying. There is a pos attribute for nodes. It is a comma-separated list of numbers specifying the coordinates of the center of the node. If you specify -n to neato, it will place the nodes at the position specified by "pos", i.e., it doesn't do any layout. However, if you specify overlap removal, it will move the nodes as necessary. I don't know what a "rectangle node attribute" is unless you mean shape=box, which just specifies the shape of the node. Its size is determined by many factors.

>> And my next question is: is "pos" in inches and adjusted by DPI specified in script?

No, most units are in points, but some are in inchces. Check the documentation http://www.graphviz.org/content/attrs#dpos. It is unfortunate that Graphviz uses mixed units and that one can't specify the unit, but we've never had time to add this feature. All calculations are in device-independent units. DPI is only used to calculate how large an image is in inches, and to guide the final mapping from universal coordinates to pixels if the output is a bitmap.

>>Another question is: It is not too much clear to me what means "!" suffix in "pos" attribute in the PDF >>documentation, there is mentioned to "pin position", could you please be more elaborative?

See http://www.graphviz.org/content/attrs#dpin Obviously, the "!" suffix is redundant if you run neato -n.

 

1. When I use command

1. When I use command line:

char* argv[]={ GRAPHVIZ_BIN, "-Tjpg", "-n", "-Gesep=+20", NULL };

I get correct positions of boxes and their sizes. But lines are crossing through boxes and not flowing around them. The latter is not my intended behaviour.

screenshot:

2. When I add "-Goverlap=false" to command line as you suggested:

char* argv[]={ GRAPHVIZ_BIN, "-Tjpg", "-n", "-Goverlap=false", "-Gesep=+20", NULL };

neato is generating image with wrong positions of boxes than user specified in my SW's GUI.

screenshot:

NB: the generated script is the same (only position of lower box has been changed by user / me).

script follows:

---snip---

digraph G {
splines=true;
graph [dpi="72"];
bgcolor="lightgray";
n_a [label="", color="black", rectangular="true", shape="box", width="0.001", height="0.001", pos="0,0"];
n_b [label="", color="black", rectangular="true", shape="box", width="0.001", height="0.001", pos="596,-406"];
n0 [label="{{<in0>|<out0>}|{<in1>|<out1>}}", color="black", fixedsize="true", rectangular="true", shape="record", width="6.72222", height="0.861111", pos="250,-39"];
n1 [label="{{<in0>|<out0>}|{<in1>|<out1>}}", color="black", fixedsize="true", rectangular="true", shape="record", width="6.72222", height="0.861111", pos="355,-322"];
n0:out1 -> n1:in1 [arrowhead="vee"];
}
---snip---

best regards, TIA!

Recent comments