Logo ROOT   6.14/05
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
22 extern 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 
27 lt_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 
40 The Graph Structure is an interface to the graphviz package.
41 
42 The graphviz package is a graph visualization system. This interface consists in
43 three 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 
51 Begin_Macro(source)
52 ../../../tutorials/graphs/graphstruct.C
53 End_Macro
54 
55 A 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 
124 TGraphNode *TGraphStruct::AddNode(const char *name, const char *title)
125 {
126  if (!fNodes) fNodes = new TList;
127 
128  TGraphNode *node = (TGraphNode*)fNodes->FindObject(name);
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 
141 void 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 
273 void 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 
326 void TGraphStruct::Streamer(TBuffer &/*b*/)
327 {
328 }
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
void CreateGVNode(GVizAgraph_t *gv)
Create the GraphViz node into the GraphViz data structure gv.
Definition: TGraphNode.cxx:61
void DumpAsDotFile(const char *filename)
Dump this graph structure as a "dot" file.
const char Option_t
Definition: RtypesCore.h:62
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
int Int_t
Definition: RtypesCore.h:41
virtual void Draw(Option_t *option="")
Default Draw method for all objects.
Definition: TObject.cxx:195
Double_t fMargin
Margin around the graph (in dots)
Definition: TGraphStruct.h:32
virtual TObject * FindObject(const char *name) const
Delete a TObjLink object.
Definition: TList.cxx:574
The Graph Structure is an interface to the graphviz package.
Definition: TGraphStruct.h:24
virtual void AppendPad(Option_t *option="")
Append graphics object to current pad.
Definition: TObject.cxx:105
TList * fNodes
List of nodes in this TGraphStruct.
Definition: TGraphStruct.h:30
An edge object connecting two nodes which can be added in a TGraphStruct.
Definition: TGraphEdge.h:25
void AddNode(TGraphNode *node)
Add the node "node" in this TGraphStruct.
TGraphNode * GetNode1()
Definition: TGraphEdge.h:51
void Layout()
Layout this node in the GraphViz space.
Definition: TGraphNode.cxx:106
void Layout()
Layout this edge in the GraphViz space.
Definition: TGraphEdge.cxx:132
virtual ~TGraphStruct()
Graph Structure default destructor.
A doubly linked list.
Definition: TList.h:44
Int_t Layout()
Layout the graph into a GraphViz data structure.
void SetMargin(Double_t m=10)
Definition: TGraphStruct.h:49
TList * fEdges
List of edges in this TGraphStruct.
Definition: TGraphStruct.h:31
virtual TObject * First() const
Return the first object in the list. Returns 0 when list is empty.
Definition: TList.cxx:655
void AddEdge(TGraphEdge *edge)
Add the edge "edge" in this TGraphStruct.
void Draw(Option_t *option="")
Draw the graph.
char * Form(const char *fmt,...)
virtual TObject * After(const TObject *obj) const
Returns the object after object obj.
Definition: TList.cxx:327
TGraphNode * GetNode2()
Definition: TGraphEdge.h:52
void SaveAttributes(std::ostream &)
Save attributes as a C++ statement(s) on output stream out called by TGraphStruct::SavePrimitive.
Definition: TGraphNode.cxx:155
#define ClassImp(name)
Definition: Rtypes.h:359
A graph node object which can be added in a TGraphStruct.
Definition: TGraphNode.h:27
GVizAgraph_t * fGVGraph
Graphviz graph.
Definition: TGraphStruct.h:28
TGraphStruct()
Graph Structure default constructor.
void CreateGVEdge(GVizAgraph_t *gv)
Create the GraphViz edge into the GraphViz data structure gv.
Definition: TGraphEdge.cxx:75
virtual void Add(TObject *obj)
Definition: TList.h:87
Definition: file.py:1
#define gPad
Definition: TVirtualPad.h:285
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
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Definition: TCollection.h:182
GVC_s * fGVC
Graphviz context.
Definition: TGraphStruct.h:29
char name[80]
Definition: TGX11.cxx:109
virtual void SavePrimitive(std::ostream &out, Option_t *option="")
Save primitive as a C++ statement(s) on output stream out.
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48