5 #include <graphviz/cgraph.h>
7 #include <SimoxUtility/algorithm/string/string_tools.h>
18 char* gv_str(
const char*
c)
20 return const_cast<char*
>(
c);
23 char* gv_str(std::string
const&
s)
25 return const_cast<char*
>(
s.c_str());
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";
37 context = gvContext();
38 graph = agopen(gv_str(
"Graph"), Agdirected,
nullptr);
42 agattr(graph, AGRAPH, (
char*)
"dpi", (
char*)
"72");
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");
59 agattr(graph, AGNODE, (
char*)
"margin", (
char*)
"0,0");
60 agattr(graph, AGNODE, (
char*)
"fontsize", (
char*)
"28");
63 agattr(graph, AGEDGE,
const_cast<char*
>(
"label"),
const_cast<char*
>(
""));
64 agattr(graph, AGEDGE,
const_cast<char*
>(
"fontsize"),
const_cast<char*
>(
"28"));
76 gvFreeContext(context);
82 node_t* node = agnode(graph, gv_str(label), TRUE);
83 agset(node, GRAPHVIZ_ATTR_LABEL, gv_str(label));
84 id2node.emplace(
id, node);
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);
94 agset(edge, GRAPHVIZ_ATTR_LABEL, gv_str(label));
96 id2edge.emplace(std::make_pair(sourceID, targetID), edge);
101 gvLayout(context, graph,
"dot");
103 if (!savePNG.empty())
105 gvRenderFilename(context, graph,
"png", gv_str(savePNG));
107 gvFreeLayout(context, graph);
111 for (
auto& pair : id2node)
114 node_t* node = pair.second;
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);
122 if (splitPos.size() != 2)
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);
135 posX -= width / 2.0f;
136 posY -= height / 2.0f;
139 layoutedNode.
posX = posX;
140 layoutedNode.
posY = posY;
141 layoutedNode.
width = width;
142 layoutedNode.
height = height;
143 layoutedNode.
label = labelString;
145 layouted.
nodes.emplace(
id, layoutedNode);
148 for (
auto& pair : id2edge)
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))
172 if (label.size() > 0)
175 if (
split.size() == 2)
177 layoutedEdge.
label = label;
182 layouted.
edges.emplace(sourceTarget, layoutedEdge);