I'm trying too see whether I can use the Dot programming language to apply it to an old project of mine.
The task is simple: create a high quality graph with ease.
Unfortunately, while it has been fairly easy to implement the details of my graph, I wound up having to take loads of time just for adjusting the layout.
Furthermore, it is quite unclear to me how the order of my instructions impact my graph, but it actually looks like putting the last instruction of my code at the beginning produces a completely different output!
Here is the code:
digraph {
TOP [shape=doublecircle]
TOP->TOP->{rank=same a->b->c->b->a}
a:s->c:s
a:nw->a:sw
c:ne->c:se
b:s->b:s
}
so. firstly, i finally mastered the 'get nodes to be on the same horizontal/vertical line' through ranking...
I also kinda fixed the problem of edges doing stupid interconnections (all free space below the graph for connections, and the edge winds up zig-zagging through the whole graph in an awkward way and overlapping everything?) using the direction indicators ":e" and the such (i believe they are called routes...), but it looks like graphviz isn't using them in a smart way, because the result looks funny to me.
Here is the output, how do I get it to avoid edge overlappings and make enough space for future (long) labels?
(made with dot -Tpng test.dot -o test.png)
(also, I would need to add a c->a edge at the bottom too, but adding one the "normal" way ruined everything)
You can use invisible nodes to "re-route" your edges as desired (edited as per comments below):
digraph
{
/* layout */
// node width to create space for longer labels
node [ width = 1.75 ];
{ rank=same; a; b; c }
/* nodes */
t [ label = "TOP", shape = doublecircle, width = 1];
a [ label = "short" ];
b [ label = "medium" ];
c [ label = "rather l o n g"]
// invisible nodes to 're-route' the edges
x [ style = invis, shape = point, width = 0 ];
y [ style = invis, shape = point, width = 0 ];
/* edges */
t -> t;
t -> { a b c }
t -> { a b c } [dir = back ]; // added for reverse arrows
a -> b -> c -> b -> a;
a:nw -> a:sw;
c:ne -> c:se;
b:s -> b:s;
// put the invisible nodes at the desired places with invisible edges
b -> x -> y [ style = invis ];
// edges to invisible nodes must not have heads
c:sw -> x [ arrowhead = "none" ];
x -> a:se;
a:s -> y [ arrowhead = "none" ];
y -> c:s;
}
yields
Related
I'm working with graphviz on LinuxArch. If I print my .svg I use the command dot -Tsvg example.dot -o exampale.svg. My graph is printed and that works fine. I read some other questions on that topic Link 1, Link 2, also the documentation on graphviz.org didn't give me a clue.
Question: I want to line break in a node. How I can do it?
The following code is working, but not always. Full Code:
digraph G {
//general settings
graph [fontname="Arial"];
node [fontname="Arial"];
edge [fontname="Arial"];
//data of graph
subgraph cluster_1
{
label = "Cluster 1";
style=filled;
color="#E0E0E0";
margin=20;
node [style=filled,color=white];
"I'm text" -> "I want a donat.";
"I want a donat." -> a1[label="Love food,\nlove it so much!"];
}
subgraph cluster_2
{
label = "Cluster 2";
style=filled;
color="#E0E0E0";
margin=20;
node [style=filled,color=white];
Start -> a2[label="sit amet,\nconsetetur"];
a2 ->
{
b2[label="Lorem Impsum\ndollar sit amet."];
}
}
}
Result: (Green marked is working and the problem is Red marked.)
It seems to me you are confusing node and edge declarations.
Try changing the lines
"I'm text" -> "I want a donat.";
"I want a donat." -> a1[label="Love food,\nlove it so much!"];
into
a1[label="Love food,\nlove it so much!"];
"I'm text" -> "I want a donat.";
"I want a donat." -> a1;
What this actually does is that a1 is defined as a node with a label. The node id a1 can then be used to declare edges between nodes.
Here is an other example, with explicit node declarations for all nodes, and then the edge declarations using the node identifiers:
imtext[label="I'm text"];
donat[label="I want a donat."];
a1[label="Love food,\nlove it so much!"];
imtext -> donat -> a1;
I've a network graph
Now I've some connected nodes and as you can see most of the nodes only have one connected node that is their degree is 1. Now I'd like to remove such nodes to clear the clutter. Unable to find how to since last 2 days. No such helper functions available in visjs documentation. Would appreciate help.
I believe the algorithm suggested by the 1st answer -by macramole- (before updates) would actually hide the non-connected nodes (degree 0), instead of the ones with degree 1.
I would probably just iterate over all the edges in the network while keeping 'degree' counters for each node that is an endpoint in the edge you are visiting (you can obtain these nodes by grabbing the edge.from and edge.to values, as shown above). You would increment the degree counter for a node, whenever the node is 'hit' in this search through the edges.
Eventually you'll end up with the degree value for each node in the network, at which point you can decide which ones to hide.
Updating this answer now to include my suggested code (note: nodes and edges are vis DataSet instances):
Example code:
var nodeToDegrees = {}; // keeps a map of node ids to degrees
var nodeFrom, nodeTo;
for (edge in edges) {
nodeFrom = edge.from;
nodeTo = edge.to;
nodeToDegrees[nodeFrom] = nodeToDegrees[nodeFrom] ? nodeToDegrees[nodeFrom] + 1 : 0;
nodeToDegrees[nodeTo] = nodeToDegrees[nodeTo] ? nodeToDegrees[nodeTo] + 1 : 0;
}
for (node in nodes) {
if (nodeToDegrees[node.id] = 1) nodes.update([{node.id, hidden: true}]);
}
This might work:
var DEGREES_HIDDEN = 1;
for ( var node of nodes ) {
node.cantLinks = 0;
for ( var link of links ) {
if ( link.from == node.id || link.to == node.id ) {
node.cantLinks++;
}
}
}
for ( var node of nodes ) {
if ( node.cantLinks <= DEGREES_HIDDEN ) {
node.hidden = true;
}
}
Nodes and links are arrays not vis.DataSet, I create the latter after doing that.
Doesn't look very nice perfomance wise but it does get the job done. Hope you find it useful.
I would like to point an edge towards another edge in graphviz using the dot format.
What I got so far:
digraph G {
Hello->dummy;
dummy->World;
dummy[shape=point width=0];
Test->dummy;
}
which produces
what I would like to get is something more similar to this:
Any ideas how to do so?
Maybe rank = same does the trick?
digraph G
{
{ rank = same; Test; dummy } // dummy and Test on the same level
dummy[ shape = point, width = 0 ]; // connector
Hello -> dummy[ arrowhead = none ]; // remove arrowhead to connector
dummy -> Test[ dir = back ]; // you want Test on the right side
dummy -> World;
}
yields
[arrowhead=none] with you dummy middleman does the job for me.
digraph G {
Hello->dummy[arrowhead=none];
dummy->World;
dummy[shape=point width=0];
Test->dummy;
}
I've added feature request for it in Graphviz's issue tracker.
Based on my experience with Zedgraph I could not set both of X and Y axes scale same to have a correct scatter graph! Assume we have a square grid of 10x10m cells in which each cell is a square shape 1x1m. when we try to draw points of such data, the output is not acceptable because each axis scaled to different scale. It is worse when we try to call Zoomall, then we find all points are fitted to chart area regardless their equal spacing!
I hope someone can help me to find a solution. Although Zedgraph is flexible library but this is a big fault!
perfectly aware, this q. is 9 years old, but still..
Have just encountered and solved the issue of presenting the graph in a square pane.
(It seems that was the OP question)
It's a bit "brute" and invokes redundant redraws, but gets the job done.
//"GraphWinFormsHost" is my ZGraph container
GraphWinFormsHost.SizeChanged += (sender, args) =>
{
//"IsEqualScale" is my property, indicating a square is needed
if(_ChartData == null || !_ChartData.IsEqualScale)
return;
_ZedGraphControl.GraphPane.Chart.IsRectAuto = true;
_ZedGraphControl.Refresh();
//here, the graph pane is redrawn according to available space
float x = _ZedGraphControl.GraphPane.Chart.Rect.X;
float y = _ZedGraphControl.GraphPane.Chart.Rect.Y;
float h = _ZedGraphControl.GraphPane.Chart.Rect.Height;
float w = _ZedGraphControl.GraphPane.Chart.Rect.Width;
float min = Math.Min(h, w);
_ZedGraphControl.GraphPane.Chart.Rect = new RectangleF(x, y, min, min);
};
Is Scale.IsAnyOrdinal true for any Axis.Scale's ?
ZedGraph appears to position nodes based on index offset rather than node value when the Scale.Type is set to AxisType.Text, Ordinal, DateAsOrdinal, or LinearAsOrdinal.
I recently had to solve the same problem. This is what has worked for me:
zg1.AxisChange();
if (myPane.XAxis.Scale.Max > myPane.YAxis.Scale.Max) {
myPane.YAxis.Scale.Max = myPane.XAxis.Scale.Max;
myPane.YAxis.Scale.Min = myPane.XAxis.Scale.Min;
myPane.YAxis.Scale.MajorStep = myPane.XAxis.Scale.MajorStep;
} else {
myPane.XAxis.Scale.Max = myPane.YAxis.Scale.Max;
myPane.XAxis.Scale.Min = myPane.YAxis.Scale.Min;
myPane.XAxis.Scale.MajorStep = myPane.YAxis.Scale.MajorStep;
}
zg1.AxisChange();
With the first call to AxisChange the control automatically calculate the correct values for my data. Then I copy the relevant parameters from one scale to the other one and apply the change.
How can I get the actual position of a node in the scene. The absolute position, regardless of any containers/transforms.
For example, I want to translate a certain node a so that it would temporarily overlap another node b. So I wish to set his translateX property to b.globalX-a.globalX.
The documentation says:
Defines the X coordinate of the
translation that is added to the
transformed coordinates of this Node
for the purpose of layout. Containers
or Groups performing layout will set
this variable relative to
layoutBounds.minX in order to position
the node at the desired layout
location.
For example, if child should have a
final location of finalX:
child.layoutX = finalX - child.layoutBounds.minX;
That is, the final coordinates of any node should be
finalX = node.layoutX + node.layoutBounds.minX
However running the following code:
var rect;
Stage {
title: "Application title"
width: 250
height:250
scene: Scene {
content: [
Stack{content:[rect = Rectangle { width:10 height:10}] layoutX:10}
]
}
}
println("finalX = {rect.layoutX+rect.layoutBounds.minX}");
gives me finalX = 0.0 instead of finalX = 10.0 as the docs seemingly state.
Is there a clear method to get the absolutely final positioning coordinates in JavaFX?
For bounds:
bounds = rect.localToScene(rect.getBoundsInLocal());
Work for JavaFx 1 and 2.
The only solution I found so far is
rect.localToScene(rect.layoutBounds.minX, rect.layoutBounds.minY) // a Point2D{x:Float y:Float} object
Which doesn't seem to me as the "best" way to do that (note that this function is not bound). Still it works for JavaFX 1.2.
Since JavaFX 8, there are additional methods converting local coordinates to screen coordinates. Their names start with "localToScreen"
You can check following link
http://docs.oracle.com/javase/8/javafx/api/javafx/scene/Node.html#localToScreen-double-double-