DPsim
Graph.cpp
1 /* Copyright 2017-2021 Institute for Automation of Complex Power Systems,
2  * EONERC, RWTH Aachen University
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at https://mozilla.org/MPL/2.0/.
7  *********************************************************************************/
8 
9 #include <graphviz/gvc.h>
10 
11 #include <dpsim-models/Graph.h>
12 
13 using namespace CPS;
14 using namespace CPS::Graph;
15 
16 CPS::Graph::Graph::Graph(const CPS::String &name, Type type, bool strict) {
17  Agdesc_t desc;
18 
19  switch (type) {
20  case Type::directed:
21  desc = strict ? Agstrictdirected : Agdirected;
22  break;
23  case Type::undirected:
24  desc = strict ? Agstrictundirected : Agundirected;
25  break;
26  }
27 
28  mGraph = agopen((char *)name.c_str(), desc, NULL);
29  mPtr = mGraph;
30  mKind = AGRAPH;
31 }
32 
33 CPS::Graph::Graph::~Graph() { agclose(mGraph); }
34 
35 void CPS::Graph::Graph::render(std::ostream &os, const CPS::String &layout,
36  const CPS::String &format) {
37  GVC_t *gvc;
38  char *data;
39  unsigned len;
40 
41  gvc = gvContext();
42 
43  gvLayout(gvc, mGraph, layout.c_str());
44  gvRenderData(gvc, mGraph, format.c_str(), &data, &len);
45 
46  os.write(data, len);
47 
48  gvFreeRenderData(data);
49  gvFreeLayout(gvc, mGraph);
50 
51  gvFreeContext(gvc);
52 }
53 
54 Node *CPS::Graph::Graph::addNode(const CPS::String &name) {
55  auto n = new Node(this, name);
56 
57  mNodes[name] = n;
58 
59  return n;
60 }
61 
62 Edge *CPS::Graph::Graph::addEdge(const CPS::String &name, Node *head,
63  Node *tail) {
64  auto e = new Edge(this, name, head, tail);
65 
66  mEdges[name] = e;
67 
68  return e;
69 }
70 
71 Node *CPS::Graph::Graph::node(const CPS::String &name) { return mNodes[name]; }
72 
73 Edge *CPS::Graph::Graph::edge(const CPS::String &name) { return mEdges[name]; }
74 
75 void CPS::Graph::Element::set(const CPS::String &key, const CPS::String &value,
76  bool html) {
77  Agraph_t *g = agraphof(mPtr);
78 
79  char *d = (char *)"";
80  char *k = (char *)key.c_str();
81  char *v = (char *)value.c_str();
82  char *vd = html ? agstrdup_html(g, v) : agstrdup(g, v);
83 
84  agsafeset(mPtr, k, vd, d);
85 }
86 
87 CPS::Graph::Node::Node(Graph *g, const String &name) {
88  mNode = agnode(g->mGraph, (char *)name.c_str(), 1);
89  mPtr = mNode;
90  mKind = AGNODE;
91 }
92 
93 CPS::Graph::Edge::Edge(Graph *g, const CPS::String &name, Node *head,
94  Node *tail) {
95  mEdge = agedge(g->mGraph, head->mNode, tail->mNode, (char *)name.c_str(), 1);
96  mPtr = mEdge;
97  mKind = AGEDGE;
98 }