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