Visualize boost graph topology after layout algorithm is performed - boost

I am using fruchterman_reingold_force_directed_layout algorithm on my graph
to get a cluster free layout. Below is code for my vertices and edge
using RectTopology = boost::rectangle_topology<>;
using point = RectTopology::point_type;
class MyVertex{
public:
MyVertex(){ myObject = NULL; }
Mybject* myObject;
point position;
std::string name;
};
class MyEdge{
public:
MyEdge(){ myLine = NULL; }
MyLine* myLine;
double weight;
};
//Boost graph defination
using graphT = boost::adjacency_list<boost::listS, boost::vecS, boost::undirectedS, MyVertex, MyEdge>;
using vertexT = boost::graph_traits<graphT>::vertex_descriptor; //Define Vertex
using vertexIt = boost::graph_traits<graphT>::vertex_iterator; //Vertex Iterator
using edgeT = boost::graph_traits<graphT>::edge_descriptor; //Define Edge
using edgeIt = boost::graph_traits<graphT>::edge_iterator; //Edge Iterator
forcedDirLay(){
boost::minstd_rand gen;
RectTopology rect_top(gen, 0, 0, 1, 1);
boost::random_graph_layout(myGraph, boost::get(&SLDVertex::position, myGraph), rect_top);
boost::fruchterman_reingold_force_directed_layout(myGraph, boost::get(&SLDVertex::position, myGraph), rect_top);
}
Imagine now I have a graph and perform my layout algorithm which all works fine
and I have position info for every vertices.
How can I visualize each vertex where they end up after layout algorithm
finished ? Is there a way to get position info to Dot file and I can visualize
Dot file ?
I have a function to convert my graph to dot file but don't know how
to get position info to dot
file. Thanks in advance.
GraphToDotFile(){
std::ofstream dot(".\\graph.dot");
boost::write_graphviz(dot, myGraph,
boost::make_label_writer(boost::get(&MyVertex::name, myGraph)));
dot.close();
}

You can use dynamic properties to add graphviz attributes, see the example:
https://www.boost.org/doc/libs/1_74_0/libs/graph/example/graphviz.cpp
The attributes that specify the position in graphviz are here:
Position of node, or spline control points.
For nodes, the position indicates the center of the node. On output,
the coordinates are in points.
In neato and fdp, pos can be used to set the initial position of a
node. By default, the coordinates are assumed to be in inches.
However, the -s command line flag can be used to specify different
units. As the output coordinates are in points, feeding the output of
a graph laid out by a Graphviz program into neato or fdp will almost
always require the -s flag.
When the -n command line flag is used with neato, it is assumed the
positions have been set by one of the layout programs, and are
therefore in points. Thus, neato -n can accept input correctly without
requiring a -s flag and, in fact, ignores any such flag.
Valid for: Edges, Nodes.

The neato -n trick works like a champ.
Adding a bit to the above,
yourProg produces graph.dot; then
neato -n -Tpng graph.dot >graph.png
You may have to fiddle with yourProg to make sure that graph.dot has all the required attributes, units are correct, etc. You can produce a tiny example by hand, then
dot -Tdot tiny.gv >tiny.dot
and compare the two .dot files

Related

Sepetate 2 glutinous arrow header in graphviz

Hi my arrow like following:
https://i.imgur.com/EJNtfc3.png
Arrow on the red marked is glutinous.
How do I divide it?
add code
https://www.codepile.net/pile/XKvOwL3A
In your situation fastest fix would be to add nodesep = 0.15 graph attribute (right after digraph { statement). This attribute adjusts the minimal distance between the nodes in one rank. This results in:
Also you may play with headport and tailport attributes, as I suggested in the comment. Shortcut for them is to add a colon after node when you are defining edge.
If you replace TR_Client_Data -> idle with TR_Client_Data -> idle:e you will get this result:
Edges are crossed, but they are apart.
Also I've noticed that you define node attributes in a wrong way: keyword node defines global attributes for all nodes in the graph (or subgraph). If you want to specify attributes for a single node, place them after node definition.
e.g.
WRONG:
node [
shape = point,
fontsize = 12
] start_point;
CORRECT:
start_point [
shape = point,
fontsize = 12
];

vgAppendPathData and vgModifyPathCoords, how to change visibility of path segments

I have a question regarding changing visibility of path segments via VG_LINE_TO_ABS and VG_MOVE_TO_ABS
First, I've been told it's resource expensive to create and destroy OpenVg paths, and it's much fast to create a path, then modify it
Therefore, in my Init function I have
vg3DPath = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, seg_pts, seg_pts * 2, VG_PATH_CAPABILITY_ALL);
vgAppendPathData(vg3DPath, seg_pts, (const VGubyte *)vg3DPathSegments, points);
And in my Draw function I have,
vgModifyPathCoords(vg3DPath, 0, seg_pts, points);
The number of points, seg_pts does not change, only the location of points, stored in the points array (defined as 2*seg_pts in size for X and Y coordinates of each point) .
This works fine.
My issue is that vgModifyPathCoords() does not take the segment description array, vg3DPathSegments
(defined as seg_pts+1 in size, for VG_MOVE_TO_ABS, VG_LINE_TO_ABS ... VG_LINE_TO_ABS, VG_CLOSE_PATH)
If I want to change visibility of some segments. i. e. change some of the VG_LINE_TO_ABS to VG_MOVE_TO_ABS, I cannot pass this into vgModifyPathCoords(..)
My initial thinking was to make vg3DPathSegments, a class private variable, and changing values in it would automatically change those properties in the path, but it's passed as a const, so this does not work.
How can I change these properties of the path?
Is there any better approach?
The language is C++11
The platform is Imx6, Yocto
Thank you very much
-D

Force Network: How to set initial position for select nodes?

I have a simple force network graph of four nodes as an example, here:
https://jsfiddle.net/NovasTaylor/o1qesn6k/
I would like to set the initial position of node "A" using its accompanying data so the node is initially fixed at point (265,143). If I were to double-click that node it would return to being d.fixed=FALSE and the usual forces apply.
From my research here on Stackoverflow I know I need to set the inital .x and .y values as per Bostock's suggestion:
[Fix Node Position in D3 Force-Directed Layout
But I do not quite grasp where and how to do this. I have tried the following code, which I may not have placed in the right sequence. It appears to be the same as having .x and .y in the source data...which also did not work.
for (var i=0, tot=dataset.nodes.length; i < tot; i++) {
if (dataset.nodes[i].fix_x > 0) {
dataset.nodes[i].x = dataset.nodes[i].fix_x
dataset.nodes[i].y = dataset.nodes[i].fix_y
}
}
Your advice would be very much appreciated!
Tim

Graphviz (DOT) Captions

I need to print a large number of graphs using Graphviz DOT. To distinguish which input each graph corresponds to, I want to also have a caption for each graph. Is there anyway to embed this into the DOT representation of the graphs.
You can use label to add a caption to the graph.
Example:
digraph {
A -> B;
label="Graph";
labelloc=top;
labeljust=left;
}
labelloc and labeljust can be used to determine top/bottom and left/right position of the graph label.
All the details and other attributes that can be used to modify the label (font etc) in the graphviz attribute reference.
Tip: Define the graph label end of your dot file, otherwise subgraphs will inherit those properties.
Graph's can have attributes just like nodes and edges do:
digraph {
graph [label="The Tale of Two Cities", labelloc=t, fontsize=30];
node [color=blue];
rankdir = LR;
London -> Paris;
Paris -> London;
}
That dot file produces this graph.
If you are looking for a way to add a caption to a Graph object of graphviz in python. Then the following code can help:
from graphviz import Graph
dot = Graph()
dot.node('1','1')
dot.node('2','2')
dot.edge('1','2', label="link")
dot.attr(label="My caption")
dot.attr(fontsize='25')
dot.render(view=True)
Output:

record nodes and rankdir in graphviz

When I changed the rankdir of my graph from LR to TD, my record nodes also changed their layout direction so they no longer look like a 'record'. I tried applying a separate rankdir to the nodes, but this had no effect.
How does one keep the record nodes with the correct layout?
digraph sample {
graph [rankdir=TD];
node [shape=record];
A [label="ShouldBeTop | ShouldBeBottom"];
B [label="Top | Bottom"];
A -> B;
}
Taking into account that rankdir effectively replaces the notion of "top" and "bottom" for the given graph, that's not surprising.
I am afraid that there is no easy remedy for this, save hacking the source (and that would not be easy at all). You can surround your labels in "{}" with some kind of mass search-replace solution to get the requested effect:
digraph sample { graph [rankdir=TD]; node [shape=record];
A [label="{ShouldBeTop | ShouldBeBottom}"];
B [label="{Top | Bottom}"]; A -> B;
}
You can use html table like labels instead of records. IIRC the table based labels do not rotate with the rank direction. See http://www.graphviz.org/doc/info/shapes.html#html

Resources