GraphvizLayout.cpp
Go to the documentation of this file.
1 #include "GraphvizLayout.h"
2 
4 
5 #include <graphviz/cgraph.h>
6 
7 #include <SimoxUtility/algorithm/string/string_tools.h>
8 
9 #include <vector>
10 
11 
12 namespace armarx
13 {
14 
15  namespace
16  {
17 
18  char* gv_str(const char* c)
19  {
20  return const_cast<char*>(c);
21  }
22 
23  char* gv_str(std::string const& s)
24  {
25  return const_cast<char*>(s.c_str());
26  }
27 
28  char GRAPHVIZ_ATTR_LABEL[] = "label";
29  char GRAPHVIZ_ATTR_POS[] = "pos";
30  char GRAPHVIZ_ATTR_WIDTH[] = "width";
31  char GRAPHVIZ_ATTR_HEIGHT[] = "height";
32  char GRAPHVIZ_ATTR_LABEL_POS[] = "lp";
33  }
34 
36  {
37  context = gvContext();
38  graph = agopen(gv_str("Graph"), Agdirected, nullptr);
39 
40 
41  // Setup properties
42  agattr(graph, AGRAPH, (char*)"dpi", (char*)"72"); // needs to be 72 because graphviz's bounding box is always calculated with 72dpi
43  // Bounding box of drawing
44  // How is this used and specified? In pixels?
45  // Do we need it?
46  // agattr(graph, AGRAPH, (char*)"bb", (char*)"0,0,1210,744");
47  // Maximum drawing size in inches
48  // Why would we set that?
49  //agattr(graph, AGRAPH, (char*)"size", (char*)"5,5");
50  agattr(graph, AGRAPH, (char*)"overlap", (char*)"prism");
51  agattr(graph, AGRAPH, (char*)"splines", (char*)"true");
52  agattr(graph, AGRAPH, (char*)"pad", (char*)"0.2");
53  agattr(graph, AGRAPH, (char*)"nodesep", (char*)"0.4");
54  agattr(graph, AGRAPH, (char*)"sep", (char*)"1");
55  agattr(graph, AGRAPH, (char*)"overlap_shrink", (char*)"true");
56  agattr(graph, AGRAPH, (char*)"rankdir", (char*)"LR");
57  agattr(graph, AGRAPH, (char*)"ratio", (char*)"compress");
58 
59  agattr(graph, AGNODE, (char*)"margin", (char*)"0,0");
60  agattr(graph, AGNODE, (char*)"fontsize", (char*)"28");
61 
62  //Set default attributes for future edges
63  agattr(graph, AGEDGE, const_cast<char*>("label"), const_cast<char*>(""));
64  agattr(graph, AGEDGE, const_cast<char*>("fontsize"), const_cast<char*>("28"));
65  }
66 
68  {
69  if (graph)
70  {
71  agclose(graph);
72  }
73  if (context)
74  {
75  gvFinalize(context);
76  gvFreeContext(context);
77  }
78  }
79 
80  void GraphvizLayout::addNode(int id, const std::string& label)
81  {
82  node_t* node = agnode(graph, gv_str(label), TRUE);
83  agset(node, GRAPHVIZ_ATTR_LABEL, gv_str(label));
84  id2node.emplace(id, node);
85  }
86 
87  void GraphvizLayout::addEdge(int sourceID, int targetID, const std::string& label)
88  {
89  node_t* source = id2node.at(sourceID);
90  node_t* target = id2node.at(targetID);
91  edge_t* edge = agedge(graph, source, target, gv_str("edge"), TRUE);
92  if (label.size() > 0)
93  {
94  agset(edge, GRAPHVIZ_ATTR_LABEL, gv_str(label));
95  }
96  id2edge.emplace(std::make_pair(sourceID, targetID), edge);
97  }
98 
99  GraphvizLayoutedGraph GraphvizLayout::finish(std::string const& savePNG)
100  {
101  gvLayout(context, graph, "dot");
102  attach_attrs(graph);
103  if (!savePNG.empty())
104  {
105  gvRenderFilename(context, graph, "png", gv_str(savePNG));
106  }
107  gvFreeLayout(context, graph);
108 
109  GraphvizLayoutedGraph layouted;
110 
111  for (auto& pair : id2node)
112  {
113  int id = pair.first;
114  node_t* node = pair.second;
115 
116  std::string labelString = agget(node, GRAPHVIZ_ATTR_LABEL);
117  std::string posString = agget(node, GRAPHVIZ_ATTR_POS);
118  std::string widthString = agget(node, GRAPHVIZ_ATTR_WIDTH);
119  std::string heightString = agget(node, GRAPHVIZ_ATTR_HEIGHT);
120 
121  std::vector<std::string> splitPos = simox::alg::split(posString, ",");
122  if (splitPos.size() != 2)
123  {
124  continue;
125  }
126 
127  float posX = std::stof(splitPos[0]);
128  float posY = std::stof(splitPos[1]);
129  float width = std::stof(widthString);
130  float height = std::stof(heightString);
131  // DPI conversion?
132  width *= 72.0f;
133  height *= 72.0f;
134  // Graphviz and Qt have different conventions for position (top-left vs. center)
135  posX -= width / 2.0f;
136  posY -= height / 2.0f;
137 
138  GraphvizLayoutedNode layoutedNode;
139  layoutedNode.posX = posX;
140  layoutedNode.posY = posY;
141  layoutedNode.width = width;
142  layoutedNode.height = height;
143  layoutedNode.label = labelString;
144 
145  layouted.nodes.emplace(id, layoutedNode);
146  }
147 
148  for (auto& pair : id2edge)
149  {
150  std::pair<int, int> sourceTarget = pair.first;
151  edge_t* edge = pair.second;
152  std::string posString = agget(edge, GRAPHVIZ_ATTR_POS);
153  std::string label = agget(edge, GRAPHVIZ_ATTR_LABEL);
154  std::string labelPos = "";
155  if (char* lp = agget(edge, GRAPHVIZ_ATTR_LABEL_POS))
156  {
157  labelPos = lp;
158  }
159 
161 
162  GraphvizLayoutedEdge layoutedEdge;
163  layoutedEdge.controlPoints = spline.controlPointList();
164  if (spline.endPoint)
165  {
166  layoutedEdge.endPoint = *spline.endPoint;
167  }
168  if (spline.startPoint)
169  {
170  layoutedEdge.startPoint = *spline.startPoint;
171  }
172  if (label.size() > 0)
173  {
174  std::vector<std::string> split = simox::alg::split(labelPos, ",");
175  if (split.size() == 2)
176  {
177  layoutedEdge.label = label;
178  layoutedEdge.labelPosX = std::stof(split[0]);
179  layoutedEdge.labelPosY = std::stof(split[1]);
180  }
181  }
182  layouted.edges.emplace(sourceTarget, layoutedEdge);
183  }
184 
185  return layouted;
186  }
187 
188 
189 
190 }
GraphvizLayout.h
armarx::GraphvizLayoutedEdge::endPoint
std::optional< QPointF > endPoint
Definition: GraphvizLayout.h:27
armarx::GraphvizLayoutedNode::height
float height
Definition: GraphvizLayout.h:19
GraphvizConverter.h
armarx::GraphvizConverter::convertToSpline
static SupportPoints convertToSpline(const std::string &graphVizSplineType)
Definition: GraphvizConverter.cpp:171
boost::target
Vertex target(const detail::edge_base< Directed, Vertex > &e, const PCG &)
Definition: point_cloud_graph.h:688
armarx::GraphvizLayout::~GraphvizLayout
~GraphvizLayout()
Definition: GraphvizLayout.cpp:67
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:43
armarx::GraphvizLayoutedEdge::startPoint
std::optional< QPointF > startPoint
Definition: GraphvizLayout.h:26
armarx::GraphvizLayoutedGraph::nodes
std::map< int, GraphvizLayoutedNode > nodes
Definition: GraphvizLayout.h:36
armarx::GraphvizLayout::GraphvizLayout
GraphvizLayout()
Definition: GraphvizLayout.cpp:35
armarx::GraphvizLayoutedEdge::labelPosY
float labelPosY
Definition: GraphvizLayout.h:31
armarx::SupportPoints::startPoint
QPointPtr startPoint
Definition: Transition.h:57
armarx::GraphvizLayout::addNode
void addNode(int id, std::string const &label)
Definition: GraphvizLayout.cpp:80
armarx::SupportPoints::endPoint
QPointPtr endPoint
Definition: Transition.h:58
armarx::GraphvizLayout::addEdge
void addEdge(int sourceID, int targetID, const std::string &label)
Definition: GraphvizLayout.cpp:87
boost::source
Vertex source(const detail::edge_base< Directed, Vertex > &e, const PCG &)
Definition: point_cloud_graph.h:681
armarx::GraphvizLayoutedNode::posX
float posX
Definition: GraphvizLayout.h:16
armarx::SupportPoints::controlPointList
QList< QPointF > controlPointList() const
Definition: GraphvizConverter.cpp:364
armarx::GraphvizLayoutedEdge
Definition: GraphvizLayout.h:23
armarx::GraphvizLayoutedNode::posY
float posY
Definition: GraphvizLayout.h:17
armarx::GraphvizLayout::finish
GraphvizLayoutedGraph finish(std::string const &savePNG="")
Definition: GraphvizLayout.cpp:99
armarx::GraphvizLayoutedEdge::controlPoints
QList< QPointF > controlPoints
Definition: GraphvizLayout.h:25
armarx::SupportPoints
Definition: Transition.h:43
armarx::GraphvizLayoutedEdge::labelPosX
float labelPosX
Definition: GraphvizLayout.h:30
armarx::GraphvizLayoutedEdge::label
std::string label
Definition: GraphvizLayout.h:29
armarx::GraphvizLayoutedGraph
Definition: GraphvizLayout.h:34
armarx::ctrlutil::s
double s(double t, double s0, double v0, double a0, double j)
Definition: CtrlUtil.h:33
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28
armarx::GraphvizLayoutedNode::width
float width
Definition: GraphvizLayout.h:18
armarx::GraphvizLayoutedGraph::edges
std::map< std::pair< int, int >, GraphvizLayoutedEdge > edges
Definition: GraphvizLayout.h:37
armarx::GraphvizLayoutedNode
Definition: GraphvizLayout.h:14
armarx::split
std::vector< std::string > split(const std::string &source, const std::string &splitBy, bool trimElements=false, bool removeEmptyElements=false)
Definition: StringHelpers.cpp:36
armarx::GraphvizLayoutedNode::label
std::string label
Definition: GraphvizLayout.h:20