Monday, January 30, 2012

How to use Dracula Graph Library from .NET

Create the following classes in your project
 
 using System;  
 using System.Collections.Generic;  
 using System.Linq;  
 using System.Web;  
 /// <summary>  
 /// Summary description for WGData  
 /// </summary>  
 public class WGData  
 {  
   //This class takes set of sentences and then convert them into  
   //Nodes and edges  
      public struct Data{  
         public string id;  
       }  
      public struct DataEdges  
      {  
        public string id;  
        public Int64 weight;  
        public string source;  
        public string target;  
      }  
      public struct Nodes  
      {  
        public Data data;  
      }  
      public struct Edges  
      {  
        public DataEdges data;  
      }  
      public List<Nodes> nodes;  
      public List<Edges> edges;  
   public WGData(Dictionary<string, GraphEdge> sentenceData, List<string> AllWords)  
      {  
     int length = AllWords.Count;  
     nodes = new List<Nodes>();  
     edges = new List<Edges>();  
     foreach (string word in AllWords)  
     {  
       Nodes nd = new Nodes();  
       nd.data.id = word;  
       nodes.Add(nd);  
     }  
     foreach (string sentence in sentenceData.Keys)  
     {  
       string[] Words = sentence.Split(" ");  
       Edges ed = new Edges();  
       ed.data.id = Words[0] + Words[1];  
       ed.data.weight = sentenceData[Words[0] + " " + Words[1]].LinkWeight;  
       ed.data.source = Words[0];  
       ed.data.target = Words[1];  
       edges.Add(ed);  
     }  
      }  
 }  

 using System;  
 using System.Collections.Generic;  
 using System.Web;  
 using System.Web.UI;  
 /// <summary>  
 /// Summary description for WeightedGraph  
 /// </summary>  
 public class WeightedGraph  
 {  
   
   private string[] myWords;  
   private Dictionary<string,GraphEdge> sentenceData;  
   private object locker;  
      public WeightedGraph()  
      {  
     sentenceData = new Dictionary<string, GraphEdge>();  
     locker = new object();  
      }  
   public void BuildData(string[] Words)  
   {  
     myWords = Words;  
     try  
     {  
       if (myWords.Length > 1) //This mean two words at least  
       {  
         for (int i = 0; i < myWords.Length - 1; i++)  
         {  
           GraphEdge gBond = new GraphEdge();  
           gBond.FirstNode = myWords[i];  
           gBond.SecondNode = myWords[i + 1];  
           string sentence = myWords[i] + " " + myWords[i + 1];  
           lock (locker)  
           {  
             if (!sentenceData.ContainsKey(sentence))  
             {  
               sentenceData.Add(sentence, gBond);  
             }  
           }  
         }  
       }  
     }  
     catch (Exception ex)  
     {  
       throw new Exception("Error while constructing WeightedGraph data : " + ex.Message);  
     }  
   }  
   public Dictionary<string, GraphEdge> GraphData()  
   {  
     if(sentenceData.Count > 0)  
     {  
       return sentenceData;  
     }  
     else  
     {  
       return null;  
     }  
   }  
 }  

 using System;  
 using System.Collections.Generic;  
 using System.Linq;  
 using System.Web;  
 /// <summary>  
 /// Summary description for GraphBond  
 /// </summary>  
 public class GraphEdge  
 {  
   //This class represent and edge between two nodes in the graph  
   //The weight also defined here  
   //And the names of the two nodes in the edge  
   public string FirstNode = null;  
   public string SecondNode = null;  
   public Int64 LinkWeight = 0;  
 }  
 using System;  
 using System.Collections.Generic;  
 using System.IO;  
 using System.Linq;  
 using System.Web;  
 /// <summary>  
 /// Summary description for BuildWeightedGraphJSCode  
 /// </summary>  
 public class BuildWeightedGraphJSCode  
 {  
   //This class takes the input nodes and the edges of all sentences  
   //And try to form the fourmla of dracula library by constructing the javascript code  
   //To add the nodes and the edges to the graph  
   //The code is divided into 3 files header , and the string contains the edges nodes created by this calls and the footer  
   //Then merge all the files togther into one string contains all the dracula fourmla of JavaScript code  
   //The returned code used to draw the graph  
   private string mSentence = null;  
   private string mJavaScriptCode =null;  
   public string JavaScriptCode { get { GetJSCode(); return mJavaScriptCode; } }  
   public WGData wgData;  
      public BuildWeightedGraphJSCode(List<string> sentences)  
      {  
     List<string> Words = new List<string>();  
     WeightedGraph wg = new WeightedGraph();  
     foreach (string sentenec in sentences)  
     {  
       mSentence = sentenec;  
       string [] WordOfThisSentence = mSentence.Split(" ");  
       foreach (string word in WordOfThisSentence)  
       {  
         if(Words.Contains(word) == false)  
         {  
           Words.Add(word);  
         }  
       }  
       wg.BuildData(WordOfThisSentence);  
       wgData = new WGData(wg.GraphData(), Words);  
     }  
      }  
   private void GetJSCode()  
   {  
     /*string json = JsonConvert.SerializeObject(wgData);  
     ScriptManager.RegisterStartupScript(this, typeof(Page), "drawWG", " DrawWeightedGraph(" + json + ",true , " +"'"+ Words [0]+"'"+ ");", true);  
     */  
     StreamReader sr = new StreamReader(HttpRuntime.AppDomainAppPath + @"\bin\graphhead.txt");  
     string header = sr.ReadToEnd();  
     sr.Close();  
     //sr = new StreamReader(appPath + @"\bin\graphmed.txt");  
     //string med = sr.ReadToEnd();  
     string allNodes = null;  
     foreach (WGData.Nodes nd in wgData.nodes)  
     {  
       string nodeString = "g.addNode('" + nd.data.id + "', {render:render});";  
       allNodes = allNodes + nodeString + "\n";  
     }  
     string allEdges = null;  
     foreach (WGData.Edges edg in wgData.edges)  
     {  
       if (edg.data.source != "" & edg.data.target != "" && edg.data.source != null & edg.data.target != null)  
       {  
         string edgeString = "g.addEdge('" + edg.data.source + "','" + edg.data.target + "', {weight:9, directed: true, fill : '#56f', stroke : '#bfa' , label : '" + edg.data.weight + "'});";  
         allEdges = allEdges + edgeString + "\n";  
       }  
     }  
     string med = allNodes + allEdges;  
     sr = new StreamReader(HttpRuntime.AppDomainAppPath + @"\bin\graphtail.txt");  
     string tail = sr.ReadToEnd();  
     mJavaScriptCode = header + med + tail;  
   }  
 }  
Then to use the library you have to refrence dracula library JavaScript files in your page , Download link : http://www.graphdracula.net/showcase/ Finally add the following code to your .CS file, You may change the weight on the connections between the nodes , Default value is 0
             BuildWeightedGraphJSCode buildJavaScriptCode = new BuildWeightedGraphJSCode(Sentences);  
             for (int i = 0; i < buildJavaScriptCode.wgData.edges.Count; i++)  
             {  
               WGData.Edges edg = buildJavaScriptCode.wgData.edges[i];  
               edg.data.weight = 0;  
               buildJavaScriptCode.wgData.edges[i] = edg;  
             }  
             ScriptManager.RegisterStartupScript(this, typeof(Page), "drawWG", buildJavaScriptCode.JavaScriptCode, true);  
The above code will draw the graph on the default div called "canvas"
 var redraw;  
 function CreateGraph(){  
   var width = $(parent).width() - 300;  
   var height = $(parent).height() - 300;  
   /* Showcase of the Bellman-Ford search algorithm finding shortest paths   
     from one point to every node */  
   /* */  
   /* We need to write a new node renderer function to display the computed  
     distance.  
     (the Raphael graph drawing implementation of Dracula can draw this shape,  
     please consult the RaphaelJS reference for details http://raphaeljs.com/) */  
   var render = function(r, n) {  
       /* the Raphael set is obligatory, containing all you want to display */  
       var set = r.set().push(  
         /* custom objects go here */  
         r.rect(n.point[0]-30, n.point[1]-13, 60, 44).attr({"fill": "#feb", r : "12px", "stroke-width" : n.distance == 0 ? "3px" : "1px" })).push(  
         r.text(n.point[0], n.point[1] + 10, (n.label || n.id) + "\n" + (n.distance == undefined ? "" : n.distance) + ""));  
       return set;  
     };  
   var g = new Graph();  
   /* modify the edge creation to attach random weights */  
   g.edgeFactory.build = function(source, target) {  
      var e = jQuery.extend(true, {}, this.template);  
      e.source = source;  
      e.target = target;  
      e.style.label = e.weight = Math.floor(Math.random() * 10) + 1;  
      return e;  
   }  
Create file called graphead.txt and insert into bin folder using the above code
  /* random edge weights (our undirected graph is modelled as a bidirectional graph) */  
 /*  for(e in g.edges)  
     if(g.edges[e].backedge != undefined) {  
       g.edges[e].weight = Math.floor(Math.random()*10) + 1;  
       g.edges[e].backedge.weight = g.edges[e].weight;  
     }  
 */  
   /* layout the graph using the Spring layout implementation */  
   var layouter = new Graph.Layout.Spring(g);  
   /* draw the graph using the RaphaelJS draw implementation */  
   /* calculating the shortest paths via Bellman Ford */  
 //  bellman_ford(g, g.nodes["Berlin"]);  
   /* calculating the shortest paths via Dijkstra */  
   //dijkstra(g, g.nodes["Berlin"]);  
   /* calculating the shortest paths via Floyd-Warshall */  
   //floyd_warshall(g, g.nodes["Berlin"]);  
   /* colourising the shortest paths and setting labels */  
   for(e in g.edges) {  
     if(g.edges[e].target.predecessor === g.edges[e].source || g.edges[e].source.predecessor === g.edges[e].target) {  
       g.edges[e].style.stroke = "#bfa";  
       g.edges[e].style.fill = "#56f";  
     } else {  
       g.edges[e].style.stroke = "#aaa";  
     }  
   }  
   var renderer = new Graph.Renderer.Raphael('canvas', g, width, height);  
   redraw = function() {  
     layouter.layout();  
     renderer.draw();  
   };  
 /*  var pos=0;  
   step = function(dir) {  
     pos+=dir;  
     var renderer = new Graph.Renderer.Raphael('canvas', g.snapshots[pos], width, height);  
     renderer.draw();  
   };*/  
      };  
 $(document).ready(function(){  
      //CreateGraph();  
 });  
 $("#canvas").html("");  
 CreateGraph();  
 StylingGraph();  
and ceate another file called graphtail.txt and insert the above code in it , the file must be placed in the bin folder