Logo ROOT   6.16/01
Reference Guide
TGraphStruct.cxx
Go to the documentation of this file.
1// @(#)root/hist:$Id$
2// Author: Olivier Couet 13/07/09
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#include "Riostream.h"
13#include "TPad.h"
14#include "TGraphStruct.h"
15
16#include <stdio.h>
17
18#include <gvc.h>
19#include <gvplugin.h>
20
21#ifdef GVIZ_STATIC
22extern gvplugin_library_t gvplugin_dot_layout_LTX_library;
23///extern gvplugin_library_t gvplugin_neato_layout_LTX_library;
24///extern gvplugin_library_t gvplugin_core_LTX_library;
25
26
27lt_symlist_t lt_preloaded_symbols[] = {
28 { "gvplugin_dot_layout_LTX_library", (void*)(&gvplugin_dot_layout_LTX_library) },
29/// { "gvplugin_neato_layout_LTX_library", (void*)(&gvplugin_neato_layout_LTX_library) },
30/// { "gvplugin_core_LTX_library", (void*)(&gvplugin_core_LTX_library) },
31 { 0, 0 }
32};
33#endif
34
36
37/** \class TGraphStruct
38\ingroup gviz
39
40The Graph Structure is an interface to the graphviz package.
41
42The graphviz package is a graph visualization system. This interface consists in
43three classes:
44
45 - TGraphStruct: holds the graph structure. It uses the graphviz library to
46 layout the graphs and the ROOT graphics to paint them.
47 - TGraphNode: Is a graph node object which can be added in a TGraphStruct.
48 - TGraphEdge: Is an edge object connecting two nodes which can be added in
49 a TGraphStruct.
50
51Begin_Macro(source)
52../../../tutorials/graphs/graphstruct.C
53End_Macro
54
55A graph structure can be dumped into a "dot" file using DumpAsDotFile.
56*/
57
58////////////////////////////////////////////////////////////////////////////////
59/// Graph Structure default constructor.
60
62{
63 fNodes = 0;
64 fEdges = 0;
65 fGVGraph = 0;
66 fGVC = 0;
67
68 SetMargin();
69}
70
71////////////////////////////////////////////////////////////////////////////////
72/// Graph Structure default destructor.
73
75{
76 gvFreeLayout(fGVC,(Agraph_t*)fGVGraph);
77 agclose((Agraph_t*)fGVGraph);
78 gvFreeContext(fGVC);
79
80 if (fNodes) delete fNodes;
81 if (fEdges) delete fEdges;
82
83}
84
85////////////////////////////////////////////////////////////////////////////////
86/// Add the edge "edge" in this TGraphStruct.
87
89{
90 if (!fEdges) fEdges = new TList;
91
92 fEdges->Add(edge);
93}
94
95////////////////////////////////////////////////////////////////////////////////
96/// Create an edge between n1 and n2 and put it in this graph.
97///
98/// Two edges can connect the same nodes the same way, so there
99/// is no need to check if an edge already exists.
100
102{
103 if (!fEdges) fEdges = new TList;
104
105 TGraphEdge *edge = new TGraphEdge(n1, n2);
106 fEdges->Add(edge);
107
108 return edge;
109}
110
111////////////////////////////////////////////////////////////////////////////////
112/// Add the node "node" in this TGraphStruct.
113
115{
116 if (!fNodes) fNodes = new TList;
117
118 fNodes->Add(node);
119}
120
121////////////////////////////////////////////////////////////////////////////////
122/// Create the node "name" if it does not exist and add it to this TGraphStruct.
123
124TGraphNode *TGraphStruct::AddNode(const char *name, const char *title)
125{
126 if (!fNodes) fNodes = new TList;
127
129
130 if (!node) {
131 node = new TGraphNode(name, title);
132 fNodes->Add(node);
133 }
134
135 return node;
136}
137
138////////////////////////////////////////////////////////////////////////////////
139/// Dump this graph structure as a "dot" file.
140
141void TGraphStruct::DumpAsDotFile(const char *filename)
142{
143 if (!fGVGraph) {
144 Int_t ierr = Layout();
145 if (ierr) return;
146 }
147 FILE *file;
148 file=fopen(filename,"wt");
149 if (file) {
150 agwrite((Agraph_t*)fGVGraph, file);
151 fclose(file);
152 }
153}
154
155////////////////////////////////////////////////////////////////////////////////
156/// Draw the graph
157
159{
160 if (!fGVGraph) {
161 Int_t ierr = Layout();
162 if (ierr) return;
163 }
164
165 // Get the bounding box
166 if (gPad) {
167 gPad->Range(GD_bb((Agraph_t*)fGVGraph).LL.x-fMargin, GD_bb((Agraph_t*)fGVGraph).LL.y-fMargin,
168 GD_bb((Agraph_t*)fGVGraph).UR.x+fMargin, GD_bb((Agraph_t*)fGVGraph).UR.y+fMargin);
169 }
170
171 AppendPad(option);
172
173 // Draw the nodes
174 if (fNodes) {
175 TGraphNode *node;
176 node = (TGraphNode*) fNodes->First();
177 node->Draw();
178 for(Int_t i = 1; i < fNodes->GetSize(); i++){
179 node = (TGraphNode*)fNodes->After(node);
180 if (node) node->Draw();
181 }
182 }
183
184 // Draw the edges
185 if (fEdges) {
186 TGraphEdge *edge;
187 edge = (TGraphEdge*) fEdges->First();
188 edge->Draw();
189 for(Int_t i = 1; i < fEdges->GetSize(); i++){
190 edge = (TGraphEdge*)fEdges->After(edge);
191 if (edge) edge->Draw();
192 }
193 }
194}
195
196////////////////////////////////////////////////////////////////////////////////
197/// Layout the graph into a GraphViz data structure
198
200{
201 TGraphNode *node;
202 TGraphEdge *edge;
203
204 // Create the graph context.
205 if (fGVC) gvFreeContext(fGVC);
206#ifdef GVIZ_STATIC
207 fGVC = gvContextPlugins(lt_preloaded_symbols, 0);
208#else
209 fGVC = gvContext();
210#endif
211
212 // Create the graph.
213 if (fGVGraph) {
214 gvFreeLayout(fGVC,(Agraph_t*)fGVGraph);
215 agclose((Agraph_t*)fGVGraph);
216 }
217#ifdef WITH_CGRAPH
218 fGVGraph = (GVizAgraph_t*)agopen((char*)"GVGraph", Agdirected, 0);
219#else
220 fGVGraph = (GVizAgraph_t*)agopen((char*)"GVGraph", AGDIGRAPH);
221#endif
222
223 // Put the GV nodes into the GV graph
224 if (fNodes) {
225 node = (TGraphNode*) fNodes->First();
226 node->CreateGVNode(fGVGraph);
227 for(Int_t i = 1; i < fNodes->GetSize(); i++){
228 node = (TGraphNode*)fNodes->After(node);
229 if (node) node->CreateGVNode(fGVGraph);
230 }
231 }
232
233 // Put the edges into the graph
234 if (fEdges) {
235 edge = (TGraphEdge*) fEdges->First();
236 edge->CreateGVEdge(fGVGraph);
237 for(Int_t i = 1; i < fEdges->GetSize(); i++){
238 edge = (TGraphEdge*)fEdges->After(edge);
239 if (edge) edge->CreateGVEdge(fGVGraph);
240 }
241 }
242
243 // Layout the graph
244 int ierr = gvLayout(fGVC, (Agraph_t*)fGVGraph, (char*)"dot");
245 if (ierr) return ierr;
246
247 // Layout the nodes
248 if (fNodes) {
249 node = (TGraphNode*) fNodes->First();
250 node->Layout();
251 for(Int_t i = 1; i < fNodes->GetSize(); i++){
252 node = (TGraphNode*)fNodes->After(node);
253 if (node) node->Layout();
254 }
255 }
256
257 // Layout the edges
258 if (fEdges) {
259 edge = (TGraphEdge*) fEdges->First();
260 edge->Layout();
261 for(Int_t i = 1; i < fEdges->GetSize(); i++){
262 edge = (TGraphEdge*)fEdges->After(edge);
263 if (edge) edge->Layout();
264 }
265 }
266
267 return 0;
268}
269
270////////////////////////////////////////////////////////////////////////////////
271/// Save primitive as a C++ statement(s) on output stream out
272
273void TGraphStruct::SavePrimitive(std::ostream &out, Option_t * /*= ""*/)
274{
275 out<<" TGraphStruct *graphstruct = new TGraphStruct();"<<std::endl;
276
277 // Save the nodes
278 if (fNodes) {
279 TGraphNode *node;
280 node = (TGraphNode*) fNodes->First();
281 out<<" TGraphNode *"<<node->GetName()<<" = graphstruct->AddNode(\""<<
282 node->GetName()<<"\",\""<<
283 node->GetTitle()<<"\");"<<std::endl;
284 node->SaveAttributes(out);
285 for(Int_t i = 1; i < fNodes->GetSize(); i++){
286 node = (TGraphNode*)fNodes->After(node);
287 if (node) {
288 out<<" TGraphNode *"<<node->GetName()<<" = graphstruct->AddNode(\""<<
289 node->GetName()<<"\",\""<<
290 node->GetTitle()<<"\");"<<std::endl;
291 node->SaveAttributes(out);
292 }
293 }
294 }
295
296 // Save the edges
297 if (fEdges) {
298 TGraphEdge *edge;
299 Int_t en = 1;
300 edge = (TGraphEdge*) fEdges->First();
301 out<<" TGraphEdge *"<<"e"<<en<<
302 " = new TGraphEdge("<<
303 edge->GetNode1()->GetName()<<","<<
304 edge->GetNode2()->GetName()<<");"<<std::endl;
305 out<<" graphstruct->AddEdge("<<"e"<<en<<");"<<std::endl;
306 edge->SaveAttributes(out,Form("e%d",en));
307 for(Int_t i = 1; i < fEdges->GetSize(); i++){
308 en++;
309 edge = (TGraphEdge*)fEdges->After(edge);
310 if (edge) {
311 out<<" TGraphEdge *"<<"e"<<en<<
312 " = new TGraphEdge("<<
313 edge->GetNode1()->GetName()<<","<<
314 edge->GetNode2()->GetName()<<");"<<std::endl;
315 out<<" graphstruct->AddEdge("<<"e"<<en<<");"<<std::endl;
316 edge->SaveAttributes(out,Form("e%d",en));
317 }
318 }
319 }
320
321 out<<" graphstruct->Draw();"<<std::endl;
322}
323
324////////////////////////////////////////////////////////////////////////////////
325
326void TGraphStruct::Streamer(TBuffer &/*b*/)
327{
328}
int Int_t
Definition: RtypesCore.h:41
const char Option_t
Definition: RtypesCore.h:62
#define ClassImp(name)
Definition: Rtypes.h:363
char * Form(const char *fmt,...)
#define gPad
Definition: TVirtualPad.h:286
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Definition: TCollection.h:182
An edge object connecting two nodes which can be added in a TGraphStruct.
Definition: TGraphEdge.h:25
void CreateGVEdge(GVizAgraph_t *gv)
Create the GraphViz edge into the GraphViz data structure gv.
Definition: TGraphEdge.cxx:75
void Layout()
Layout this edge in the GraphViz space.
Definition: TGraphEdge.cxx:132
TGraphNode * GetNode2()
Definition: TGraphEdge.h:52
void SaveAttributes(std::ostream &, const char *)
Save attributes as a C++ statement(s) on output stream out called by TGraphStruct::SavePrimitive.
Definition: TGraphEdge.cxx:214
TGraphNode * GetNode1()
Definition: TGraphEdge.h:51
A graph node object which can be added in a TGraphStruct.
Definition: TGraphNode.h:27
void SaveAttributes(std::ostream &)
Save attributes as a C++ statement(s) on output stream out called by TGraphStruct::SavePrimitive.
Definition: TGraphNode.cxx:155
void CreateGVNode(GVizAgraph_t *gv)
Create the GraphViz node into the GraphViz data structure gv.
Definition: TGraphNode.cxx:61
void Layout()
Layout this node in the GraphViz space.
Definition: TGraphNode.cxx:106
The Graph Structure is an interface to the graphviz package.
Definition: TGraphStruct.h:24
TList * fEdges
List of edges in this TGraphStruct.
Definition: TGraphStruct.h:31
void AddNode(TGraphNode *node)
Add the node "node" in this TGraphStruct.
virtual void SavePrimitive(std::ostream &out, Option_t *option="")
Save primitive as a C++ statement(s) on output stream out.
virtual ~TGraphStruct()
Graph Structure default destructor.
GVC_s * fGVC
Graphviz context.
Definition: TGraphStruct.h:29
void Draw(Option_t *option="")
Draw the graph.
TList * fNodes
List of nodes in this TGraphStruct.
Definition: TGraphStruct.h:30
Double_t fMargin
Margin around the graph (in dots)
Definition: TGraphStruct.h:32
Int_t Layout()
Layout the graph into a GraphViz data structure.
void SetMargin(Double_t m=10)
Definition: TGraphStruct.h:49
GVizAgraph_t * fGVGraph
Graphviz graph.
Definition: TGraphStruct.h:28
void AddEdge(TGraphEdge *edge)
Add the edge "edge" in this TGraphStruct.
void DumpAsDotFile(const char *filename)
Dump this graph structure as a "dot" file.
TGraphStruct()
Graph Structure default constructor.
A doubly linked list.
Definition: TList.h:44
virtual void Add(TObject *obj)
Definition: TList.h:87
virtual TObject * After(const TObject *obj) const
Returns the object after object obj.
Definition: TList.cxx:327
virtual TObject * FindObject(const char *name) const
Delete a TObjLink object.
Definition: TList.cxx:574
virtual TObject * First() const
Return the first object in the list. Returns 0 when list is empty.
Definition: TList.cxx:655
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
virtual void AppendPad(Option_t *option="")
Append graphics object to current pad.
Definition: TObject.cxx:105
virtual void Draw(Option_t *option="")
Default Draw method for all objects.
Definition: TObject.cxx:195
Definition: file.py:1