ROOT logo
// @(#)root/hist:$Id: TGraphStruct.cxx 31144 2009-11-13 08:56:21Z brun $
// Author: Olivier Couet 13/07/09

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "Riostream.h"
#include "TPad.h"
#include "TGraphStruct.h"

#include <stdio.h>

#include <gvc.h>
#include <gvplugin.h>

#ifdef GVIZ_STATIC
extern gvplugin_library_t gvplugin_dot_layout_LTX_library;
///extern gvplugin_library_t gvplugin_neato_layout_LTX_library;
///extern gvplugin_library_t gvplugin_core_LTX_library;


lt_symlist_t lt_preloaded_symbols[] = {
   { "gvplugin_dot_layout_LTX_library",   (void*)(&gvplugin_dot_layout_LTX_library) },
///   { "gvplugin_neato_layout_LTX_library", (void*)(&gvplugin_neato_layout_LTX_library) },
///   { "gvplugin_core_LTX_library",         (void*)(&gvplugin_core_LTX_library) },
   { 0, 0 }
};
#endif

ClassImp(TGraphStruct)


//______________________________________________________________________________
/* Begin_Html
<center><h2>Graph Structure class</h2></center>
The Graph Structure is an interface to the graphviz package.
<p>
The graphviz package is a graph visualization system. This interface consists in
three classes:
<ol>
<li> TGraphStruct: holds the graph structure. It uses the graphiz library to
     layout the graphs and the ROOT graphics to paint them.
<li> TGraphNode: Is a graph node object which can be added in a TGraphStruct.
<li> TGraphEdge: Is an edge object connecting two nodes which can be added in 
     a TGraphStruct.
</ol>
End_Html
Begin_Macro(source)
../../../tutorials/graphs/graphstruct.C
End_Macro
Begin_Html
A graph structure can be dumped into a "dot" file using DumpAsDotFile.
End_Html */


//______________________________________________________________________________
TGraphStruct::TGraphStruct()
{
   // Graph Structure default constructor.

   fNodes   = 0;
   fEdges   = 0;
   fGVGraph = 0;
   fGVC     = 0;

   SetMargin();
}


//______________________________________________________________________________
TGraphStruct::~TGraphStruct()
{
   // Graph Structure default destructor.

   gvFreeLayout(fGVC,fGVGraph);
   agclose(fGVGraph);
   gvFreeContext(fGVC);

   if (fNodes) delete fNodes;
   if (fEdges) delete fEdges;

}


//______________________________________________________________________________
void TGraphStruct::AddEdge(TGraphEdge *edge)
{
   // Add the edge "edge" in this TGraphStruct.

   if (!fEdges) fEdges = new TList;

   fEdges->Add(edge);
}


//______________________________________________________________________________
TGraphEdge *TGraphStruct::AddEdge(TGraphNode *n1, TGraphNode *n2)
{
   // Create an edge between n1 and n2 and put it in this graph.
   //
   // Two edges can connect the same nodes the same way, so there
   // is no need to check if an edge already exists.

   if (!fEdges) fEdges = new TList;

   TGraphEdge *edge = new TGraphEdge(n1, n2);
   fEdges->Add(edge);

   return edge;
}


//______________________________________________________________________________
void TGraphStruct::AddNode(TGraphNode *node)
{
   // Add the node "node" in this TGraphStruct.

   if (!fNodes) fNodes = new TList;

   fNodes->Add(node);
}


//______________________________________________________________________________
TGraphNode *TGraphStruct::AddNode(const char *name, const char *title)
{
   // Create the node "name" if it does not exist and add it to this TGraphStruct.

   if (!fNodes) fNodes = new TList;

   TGraphNode *node = (TGraphNode*)fNodes->FindObject(name);

   if (!node) {
      node = new TGraphNode(name, title);
      fNodes->Add(node);
   }

   return node;
}



//______________________________________________________________________________
void TGraphStruct::DumpAsDotFile(const char *filename)
{
   // Dump this graph structure as a "dot" file.

   if (!fGVGraph) {
     Int_t ierr = Layout();
     if (ierr) return;
   }
   FILE  *file;
   file=fopen(filename,"wt");
   agwrite(fGVGraph, file);
   fclose(file);
}


//______________________________________________________________________________
void TGraphStruct::Draw(Option_t *option)
{
   // Draw the graph

   if (!fGVGraph) {
     Int_t ierr = Layout();
     if (ierr) return;
   }

   // Get the bounding box
   if (gPad) {
      gPad->Range(GD_bb(fGVGraph).LL.x-fMargin, GD_bb(fGVGraph).LL.y-fMargin,
                  GD_bb(fGVGraph).UR.x+fMargin, GD_bb(fGVGraph).UR.y+fMargin);
   }

   AppendPad(option);

   // Draw the nodes
   if (fNodes) {
      TGraphNode *node;
      node = (TGraphNode*) fNodes->First();
      node->Draw();
      for(Int_t i = 1; i < fNodes->GetSize(); i++){
         node = (TGraphNode*)fNodes->After(node);
         node->Draw();
      }
   }

   // Draw the edges
   if (fEdges) {
      TGraphEdge *edge;
      edge = (TGraphEdge*) fEdges->First();
      edge->Draw();
      for(Int_t i = 1; i < fEdges->GetSize(); i++){
         edge = (TGraphEdge*)fEdges->After(edge);
         edge->Draw();
      }
   }
}


//______________________________________________________________________________
Int_t TGraphStruct::Layout()
{
   // Layout the graph into a GraphViz data structure

   TGraphNode *node;
   TGraphEdge *edge;

   // Create the graph context.
   if (fGVC) gvFreeContext(fGVC);
#ifdef GVIZ_STATIC
   fGVC = gvContextPlugins(lt_preloaded_symbols, 0);
#else
   fGVC = gvContext();
#endif

   // Create the graph.
   if (fGVGraph) {
      gvFreeLayout(fGVC,fGVGraph);
      agclose(fGVGraph);
   }
   fGVGraph = agopen((char*)"GVGraph", AGDIGRAPH);

   // Put the GV nodes into the GV graph
   if (fNodes) {
      node = (TGraphNode*) fNodes->First();
      node->CreateGVNode(fGVGraph);
      for(Int_t i = 1; i < fNodes->GetSize(); i++){
         node = (TGraphNode*)fNodes->After(node);
         node->CreateGVNode(fGVGraph);
      }
   }

   // Put the edges into the graph
   if (fEdges) {
      edge = (TGraphEdge*) fEdges->First();
      edge->CreateGVEdge(fGVGraph);
      for(Int_t i = 1; i < fEdges->GetSize(); i++){
         edge = (TGraphEdge*)fEdges->After(edge);
         edge->CreateGVEdge(fGVGraph);
      }
   }

   // Layout the graph
   int ierr = gvLayout(fGVC, fGVGraph, (char*)"dot");
   if (ierr) return ierr;

   // Layout the nodes
   if (fNodes) {
      node = (TGraphNode*) fNodes->First();
      node->Layout();
      for(Int_t i = 1; i < fNodes->GetSize(); i++){
         node = (TGraphNode*)fNodes->After(node);
         node->Layout();
      }
   }

   // Layout the edges
   if (fEdges) {
      edge = (TGraphEdge*) fEdges->First();
      edge->Layout();
      for(Int_t i = 1; i < fEdges->GetSize(); i++){
         edge = (TGraphEdge*)fEdges->After(edge);
         edge->Layout();
      }
   }

   return 0;
}


//______________________________________________________________________________
void TGraphStruct::SavePrimitive(ostream &out, Option_t * /*= ""*/)
{
   // Save primitive as a C++ statement(s) on output stream out

   out<<"   TGraphStruct *graphstruct = new  TGraphStruct();"<<endl;

   // Save the nodes
   if (fNodes) {
      TGraphNode *node;
      node = (TGraphNode*) fNodes->First();
      out<<"   TGraphNode *"<<node->GetName()<<" = graphstruct->AddNode(\""<<
                            node->GetName()<<"\",\""<<
                            node->GetTitle()<<"\");"<<endl;
      node->SaveAttributes(out);
      for(Int_t i = 1; i < fNodes->GetSize(); i++){
         node = (TGraphNode*)fNodes->After(node);
         out<<"   TGraphNode *"<<node->GetName()<<" = graphstruct->AddNode(\""<<
                               node->GetName()<<"\",\""<<
                               node->GetTitle()<<"\");"<<endl;
         node->SaveAttributes(out);
      }
   }

   // Save the edges
   if (fEdges) {
      TGraphEdge *edge;
      Int_t en = 1;
      edge = (TGraphEdge*) fEdges->First();
      out<<"   TGraphEdge *"<<"e"<<en<<
                            " = new TGraphEdge("<<
                            edge->GetNode1()->GetName()<<","<<
                            edge->GetNode2()->GetName()<<");"<<endl;
      out<<"   graphstruct->AddEdge("<<"e"<<en<<");"<<endl;
      edge->SaveAttributes(out,Form("e%d",en));
      for(Int_t i = 1; i < fEdges->GetSize(); i++){
         en++;
         edge = (TGraphEdge*)fEdges->After(edge);
         out<<"   TGraphEdge *"<<"e"<<en<<
                               " = new TGraphEdge("<<
                               edge->GetNode1()->GetName()<<","<<
                               edge->GetNode2()->GetName()<<");"<<endl;
         out<<"   graphstruct->AddEdge("<<"e"<<en<<");"<<endl;
         edge->SaveAttributes(out,Form("e%d",en));
      }
   }

   out<<"   graphstruct->Draw();"<<endl;
}


//______________________________________________________________________________
void TGraphStruct::Streamer(TBuffer &/*b*/)
{
}
 TGraphStruct.cxx:1
 TGraphStruct.cxx:2
 TGraphStruct.cxx:3
 TGraphStruct.cxx:4
 TGraphStruct.cxx:5
 TGraphStruct.cxx:6
 TGraphStruct.cxx:7
 TGraphStruct.cxx:8
 TGraphStruct.cxx:9
 TGraphStruct.cxx:10
 TGraphStruct.cxx:11
 TGraphStruct.cxx:12
 TGraphStruct.cxx:13
 TGraphStruct.cxx:14
 TGraphStruct.cxx:15
 TGraphStruct.cxx:16
 TGraphStruct.cxx:17
 TGraphStruct.cxx:18
 TGraphStruct.cxx:19
 TGraphStruct.cxx:20
 TGraphStruct.cxx:21
 TGraphStruct.cxx:22
 TGraphStruct.cxx:23
 TGraphStruct.cxx:24
 TGraphStruct.cxx:25
 TGraphStruct.cxx:26
 TGraphStruct.cxx:27
 TGraphStruct.cxx:28
 TGraphStruct.cxx:29
 TGraphStruct.cxx:30
 TGraphStruct.cxx:31
 TGraphStruct.cxx:32
 TGraphStruct.cxx:33
 TGraphStruct.cxx:34
 TGraphStruct.cxx:35
 TGraphStruct.cxx:36
 TGraphStruct.cxx:37
 TGraphStruct.cxx:38
 TGraphStruct.cxx:39
 TGraphStruct.cxx:40
 TGraphStruct.cxx:41
 TGraphStruct.cxx:42
 TGraphStruct.cxx:43
 TGraphStruct.cxx:44
 TGraphStruct.cxx:45
 TGraphStruct.cxx:46
 TGraphStruct.cxx:47
 TGraphStruct.cxx:48
 TGraphStruct.cxx:49
 TGraphStruct.cxx:50
 TGraphStruct.cxx:51
 TGraphStruct.cxx:52
 TGraphStruct.cxx:53
 TGraphStruct.cxx:54
 TGraphStruct.cxx:55
 TGraphStruct.cxx:56
 TGraphStruct.cxx:57
 TGraphStruct.cxx:58
 TGraphStruct.cxx:59
 TGraphStruct.cxx:60
 TGraphStruct.cxx:61
 TGraphStruct.cxx:62
 TGraphStruct.cxx:63
 TGraphStruct.cxx:64
 TGraphStruct.cxx:65
 TGraphStruct.cxx:66
 TGraphStruct.cxx:67
 TGraphStruct.cxx:68
 TGraphStruct.cxx:69
 TGraphStruct.cxx:70
 TGraphStruct.cxx:71
 TGraphStruct.cxx:72
 TGraphStruct.cxx:73
 TGraphStruct.cxx:74
 TGraphStruct.cxx:75
 TGraphStruct.cxx:76
 TGraphStruct.cxx:77
 TGraphStruct.cxx:78
 TGraphStruct.cxx:79
 TGraphStruct.cxx:80
 TGraphStruct.cxx:81
 TGraphStruct.cxx:82
 TGraphStruct.cxx:83
 TGraphStruct.cxx:84
 TGraphStruct.cxx:85
 TGraphStruct.cxx:86
 TGraphStruct.cxx:87
 TGraphStruct.cxx:88
 TGraphStruct.cxx:89
 TGraphStruct.cxx:90
 TGraphStruct.cxx:91
 TGraphStruct.cxx:92
 TGraphStruct.cxx:93
 TGraphStruct.cxx:94
 TGraphStruct.cxx:95
 TGraphStruct.cxx:96
 TGraphStruct.cxx:97
 TGraphStruct.cxx:98
 TGraphStruct.cxx:99
 TGraphStruct.cxx:100
 TGraphStruct.cxx:101
 TGraphStruct.cxx:102
 TGraphStruct.cxx:103
 TGraphStruct.cxx:104
 TGraphStruct.cxx:105
 TGraphStruct.cxx:106
 TGraphStruct.cxx:107
 TGraphStruct.cxx:108
 TGraphStruct.cxx:109
 TGraphStruct.cxx:110
 TGraphStruct.cxx:111
 TGraphStruct.cxx:112
 TGraphStruct.cxx:113
 TGraphStruct.cxx:114
 TGraphStruct.cxx:115
 TGraphStruct.cxx:116
 TGraphStruct.cxx:117
 TGraphStruct.cxx:118
 TGraphStruct.cxx:119
 TGraphStruct.cxx:120
 TGraphStruct.cxx:121
 TGraphStruct.cxx:122
 TGraphStruct.cxx:123
 TGraphStruct.cxx:124
 TGraphStruct.cxx:125
 TGraphStruct.cxx:126
 TGraphStruct.cxx:127
 TGraphStruct.cxx:128
 TGraphStruct.cxx:129
 TGraphStruct.cxx:130
 TGraphStruct.cxx:131
 TGraphStruct.cxx:132
 TGraphStruct.cxx:133
 TGraphStruct.cxx:134
 TGraphStruct.cxx:135
 TGraphStruct.cxx:136
 TGraphStruct.cxx:137
 TGraphStruct.cxx:138
 TGraphStruct.cxx:139
 TGraphStruct.cxx:140
 TGraphStruct.cxx:141
 TGraphStruct.cxx:142
 TGraphStruct.cxx:143
 TGraphStruct.cxx:144
 TGraphStruct.cxx:145
 TGraphStruct.cxx:146
 TGraphStruct.cxx:147
 TGraphStruct.cxx:148
 TGraphStruct.cxx:149
 TGraphStruct.cxx:150
 TGraphStruct.cxx:151
 TGraphStruct.cxx:152
 TGraphStruct.cxx:153
 TGraphStruct.cxx:154
 TGraphStruct.cxx:155
 TGraphStruct.cxx:156
 TGraphStruct.cxx:157
 TGraphStruct.cxx:158
 TGraphStruct.cxx:159
 TGraphStruct.cxx:160
 TGraphStruct.cxx:161
 TGraphStruct.cxx:162
 TGraphStruct.cxx:163
 TGraphStruct.cxx:164
 TGraphStruct.cxx:165
 TGraphStruct.cxx:166
 TGraphStruct.cxx:167
 TGraphStruct.cxx:168
 TGraphStruct.cxx:169
 TGraphStruct.cxx:170
 TGraphStruct.cxx:171
 TGraphStruct.cxx:172
 TGraphStruct.cxx:173
 TGraphStruct.cxx:174
 TGraphStruct.cxx:175
 TGraphStruct.cxx:176
 TGraphStruct.cxx:177
 TGraphStruct.cxx:178
 TGraphStruct.cxx:179
 TGraphStruct.cxx:180
 TGraphStruct.cxx:181
 TGraphStruct.cxx:182
 TGraphStruct.cxx:183
 TGraphStruct.cxx:184
 TGraphStruct.cxx:185
 TGraphStruct.cxx:186
 TGraphStruct.cxx:187
 TGraphStruct.cxx:188
 TGraphStruct.cxx:189
 TGraphStruct.cxx:190
 TGraphStruct.cxx:191
 TGraphStruct.cxx:192
 TGraphStruct.cxx:193
 TGraphStruct.cxx:194
 TGraphStruct.cxx:195
 TGraphStruct.cxx:196
 TGraphStruct.cxx:197
 TGraphStruct.cxx:198
 TGraphStruct.cxx:199
 TGraphStruct.cxx:200
 TGraphStruct.cxx:201
 TGraphStruct.cxx:202
 TGraphStruct.cxx:203
 TGraphStruct.cxx:204
 TGraphStruct.cxx:205
 TGraphStruct.cxx:206
 TGraphStruct.cxx:207
 TGraphStruct.cxx:208
 TGraphStruct.cxx:209
 TGraphStruct.cxx:210
 TGraphStruct.cxx:211
 TGraphStruct.cxx:212
 TGraphStruct.cxx:213
 TGraphStruct.cxx:214
 TGraphStruct.cxx:215
 TGraphStruct.cxx:216
 TGraphStruct.cxx:217
 TGraphStruct.cxx:218
 TGraphStruct.cxx:219
 TGraphStruct.cxx:220
 TGraphStruct.cxx:221
 TGraphStruct.cxx:222
 TGraphStruct.cxx:223
 TGraphStruct.cxx:224
 TGraphStruct.cxx:225
 TGraphStruct.cxx:226
 TGraphStruct.cxx:227
 TGraphStruct.cxx:228
 TGraphStruct.cxx:229
 TGraphStruct.cxx:230
 TGraphStruct.cxx:231
 TGraphStruct.cxx:232
 TGraphStruct.cxx:233
 TGraphStruct.cxx:234
 TGraphStruct.cxx:235
 TGraphStruct.cxx:236
 TGraphStruct.cxx:237
 TGraphStruct.cxx:238
 TGraphStruct.cxx:239
 TGraphStruct.cxx:240
 TGraphStruct.cxx:241
 TGraphStruct.cxx:242
 TGraphStruct.cxx:243
 TGraphStruct.cxx:244
 TGraphStruct.cxx:245
 TGraphStruct.cxx:246
 TGraphStruct.cxx:247
 TGraphStruct.cxx:248
 TGraphStruct.cxx:249
 TGraphStruct.cxx:250
 TGraphStruct.cxx:251
 TGraphStruct.cxx:252
 TGraphStruct.cxx:253
 TGraphStruct.cxx:254
 TGraphStruct.cxx:255
 TGraphStruct.cxx:256
 TGraphStruct.cxx:257
 TGraphStruct.cxx:258
 TGraphStruct.cxx:259
 TGraphStruct.cxx:260
 TGraphStruct.cxx:261
 TGraphStruct.cxx:262
 TGraphStruct.cxx:263
 TGraphStruct.cxx:264
 TGraphStruct.cxx:265
 TGraphStruct.cxx:266
 TGraphStruct.cxx:267
 TGraphStruct.cxx:268
 TGraphStruct.cxx:269
 TGraphStruct.cxx:270
 TGraphStruct.cxx:271
 TGraphStruct.cxx:272
 TGraphStruct.cxx:273
 TGraphStruct.cxx:274
 TGraphStruct.cxx:275
 TGraphStruct.cxx:276
 TGraphStruct.cxx:277
 TGraphStruct.cxx:278
 TGraphStruct.cxx:279
 TGraphStruct.cxx:280
 TGraphStruct.cxx:281
 TGraphStruct.cxx:282
 TGraphStruct.cxx:283
 TGraphStruct.cxx:284
 TGraphStruct.cxx:285
 TGraphStruct.cxx:286
 TGraphStruct.cxx:287
 TGraphStruct.cxx:288
 TGraphStruct.cxx:289
 TGraphStruct.cxx:290
 TGraphStruct.cxx:291
 TGraphStruct.cxx:292
 TGraphStruct.cxx:293
 TGraphStruct.cxx:294
 TGraphStruct.cxx:295
 TGraphStruct.cxx:296
 TGraphStruct.cxx:297
 TGraphStruct.cxx:298
 TGraphStruct.cxx:299
 TGraphStruct.cxx:300
 TGraphStruct.cxx:301
 TGraphStruct.cxx:302
 TGraphStruct.cxx:303
 TGraphStruct.cxx:304
 TGraphStruct.cxx:305
 TGraphStruct.cxx:306
 TGraphStruct.cxx:307
 TGraphStruct.cxx:308
 TGraphStruct.cxx:309
 TGraphStruct.cxx:310
 TGraphStruct.cxx:311
 TGraphStruct.cxx:312
 TGraphStruct.cxx:313
 TGraphStruct.cxx:314
 TGraphStruct.cxx:315
 TGraphStruct.cxx:316
 TGraphStruct.cxx:317
 TGraphStruct.cxx:318
 TGraphStruct.cxx:319
 TGraphStruct.cxx:320
 TGraphStruct.cxx:321
 TGraphStruct.cxx:322
 TGraphStruct.cxx:323
 TGraphStruct.cxx:324
 TGraphStruct.cxx:325
 TGraphStruct.cxx:326
 TGraphStruct.cxx:327
 TGraphStruct.cxx:328
 TGraphStruct.cxx:329
 TGraphStruct.cxx:330
 TGraphStruct.cxx:331