xref: /petsc/share/petsc/saws/js/tree.js (revision 3aa2d9e3a17455108487be9a174c0f069d9014ad)
1// Note: this is the old (NO LONGER WORKING) implementation of the tree diagram drawn using d3.
2
3//This function builds the tree using d3 (http://d3js.org/)
4//A good video explaining the tree:
5//http://www.youtube.com/watch?v=x8dwXoWODZ4 (part 1)
6//http://www.youtube.com/watch?v=iZ6MSHA4FMU (part 2)
7var treeData = {};
8
9function buildTree()
10{
11    //initialize tree
12    treeData = {};
13
14    //clean up matInfo
15    cleanMatInfo();
16    sortMatInfo();
17
18    //calculate number of levels
19    var numberOfLevels = 1;
20    for(var i=0; i<matInfo.length; i++) {
21        var currentLevel = getNumUnderscores(matInfo[i].endtag);
22        if(currentLevel > numberOfLevels)
23            numberOfLevels = currentLevel;
24    }
25
26    for(var i=0; i<matInfo.length; i++) {//first zero doesn't matter
27        var string = getSimpleDescription(matInfo[i].endtag);
28        var obj    = {name: string};//the new object to be placed
29        var endtag = matInfo[i].endtag;
30        var needsAllocation=false;
31
32        if(endtag == "0")
33            treeData=obj;
34
35        //get the last number in the endtag
36        if(endtag == "0" || endtag.substring(endtag.lastIndexOf("_")+1,endtag.length) == "0") {
37            //need to allocate
38            needsAllocation=true;
39        }
40
41        if(getNumUnderscores(endtag) == 1) {
42            if(needsAllocation) {
43                treeData.contents=[];
44            }
45            treeData.contents[getNthPos(endtag,1)] = obj;
46        }
47        else if(getNumUnderscores(endtag) == 2) {
48            if(needsAllocation) {
49                treeData.contents[getNthPos(endtag,1)].contents=[];
50            }
51            treeData.contents[getNthPos(endtag,1)].contents[getNthPos(endtag,2)]=obj;
52        }
53        else if(getNumUnderscores(endtag) == 3) {
54            if(needsAllocation) {
55                treeData.contents[getNthPos(endtag,1)].contents[getNthPos(endtag,2)].contents=[];
56            }
57            treeData.contents[getNthPos(endtag,1)].contents[getNthPos(endtag,2)].contents[getNthPos(endtag,3)]=obj;
58        }
59
60    }
61
62    //---------------------------------------------------
63    //Create a container for the tree - a 'canvas'
64    //[n*310, n* 310] for horizontal
65    //[n*580, n* 310] for vertical
66    var canvas = d3.select("#tree").append("svg")
67	.attr("width", numberOfLevels * 300)
68	.attr("height", numberOfLevels * 200)
69	.append("g")
70	.attr("transform", "translate(10,0)");
71
72    //Call the d3 tree layout
73    var tree = d3.layout.tree()
74	.size([numberOfLevels * 150, numberOfLevels * 250])
75   	.children(function(d) //find who has children from the data structure
76    		  {
77        	      return (!d.contents || d.contents.length === 0) ? null : d.contents;
78    		  });
79
80    //initialize the nodes and links (which are used by d3 to create the paths
81    var nodes = tree.nodes(treeData);
82    var links = tree.links(nodes);
83
84    //create an actual node group on the canvas (where a dot and text will be placed)
85    var node = canvas.selectAll(".node")
86	.data(nodes)
87	.enter()
88	.append("g")
89	.attr("class", "node")
90	.attr("transform", function (d){return "translate(" + d.y + "," + d.x + ")";}) //root: left
91        //.attr("transform", function (d){return "translate(" + d.x + "," + d.y + ")";}) //root: top
92
93    //add to that node a circle
94    //change the circle properties here
95    node.append("circle")
96	.attr("r", 5)
97	.attr("fill", "steelblue")
98
99    //Add text to the node (names)
100    //"foreignObject" is used to allow for rich formatting through mathJax and HTML (such as wrapping)
101    //adjust the size of the box to create the desired aesthetic
102    //Move it with x and y
103    node.append("foreignObject")
104	.attr('width',400)
105  	.attr('height',400)//perhaps just remove these attributes altogether so it can resize itself as needed?
106    //.attr('x', -23)
107  	.attr('requiredFeatures','http://www.w3.org/TR/SVG11/feature#Extensibility')
108  	.append('xhtml')
109	.html(function (d) { return d.name; }) //this is where the data is actually placed in the tree
110
111
112    //diagonal is the d3 method that draws the lines
113    var diagonal = d3.svg.diagonal()
114	.projection(function (d) { return [d.y, d.x]})	//root: left
115        //.projection(function (d) { return [d.x, d.y]}) //root: top
116
117    //Writes everything to screen
118    canvas.selectAll(".link")
119	.data(links)
120	.enter()
121	.append("path")
122	.attr("class", "link")
123	.attr("fill", "none")
124        .attr("stroke", "#404040")
125	.attr("d", diagonal)
126}
127
128//pos goes from 0 to numUnderscores. pos 0 is always "0"
129function getNthPos(endtag,pos)
130{
131    if(pos == 0)
132        return 0;
133    if(pos > getNumUnderscores(endtag))
134        return -1; //error. this is not possible.
135
136    for(var i=0; i<pos; i++) { //remove 'pos' number of underscores
137        endtag = endtag.substring(endtag.indexOf("_")+1, endtag.length);
138    }
139
140    if(endtag.indexOf("_") == -1) //has no more underscores so just return everything that's left
141        return parseInt(endtag);
142    else //otherwise, return up to the next underscore
143        return parseInt(endtag.substring(0,endtag.indexOf("_")));
144    }
145
146//remove all the -1 elements (these get generated when something is deleted)
147function cleanMatInfo()
148{
149    for(var i=0; i<matInfo.length; i++) {
150        if(matInfo[i].endtag == "-1") {
151
152            //shift everything down
153            for(var j=i; j<matInfo.length-1; j++)
154                matInfo[j]=matInfo[j+1];
155
156            i--;//there might be two in a row
157
158            delete matInfo[matInfo.length-1];//remove garbage value
159            matInfo.length--;//after deletion, there will be an "undefined" value there so we need this line to actually shrink the array
160        }
161    }
162}
163
164//selection sort. NOTE: THIS FUNCTION ASSUMES ALL GARBAGE VALUES (ID="-1") HAVE ALREADY BEEN REMOVED USING cleanMatInfo()
165function sortMatInfo()
166{
167    for(var i=0; i<matInfo.length-1; i++) {//only need to go to second to last element
168        var indexOfCurrentSmallest = i;
169        for(var j=i; j<matInfo.length; j++) {
170            if(compare(matInfo[j].endtag,matInfo[indexOfCurrentSmallest].endtag) == -1) {
171                indexOfCurrentSmallest = j;
172            }
173        }
174        //swap i and indexOfCurrentSmallest
175        var temp                        = matInfo[i];
176        matInfo[i]                      = matInfo[indexOfCurrentSmallest];
177        matInfo[indexOfCurrentSmallest] = temp;
178    }
179}
180
181function compare(endtag1, endtag2)
182{
183    if(endtag1 == endtag2)
184        return 0;
185
186    var min = getNumUnderscores(endtag1);
187    if(getNumUnderscores(endtag2) < min)
188        min = getNumUnderscores(endtag2);
189
190    var i=0;
191    for(i=0; i<=min; i++) {
192        if(getNthPos(endtag1,i) < getNthPos(endtag2,i))
193            return -1;
194        if(getNthPos(endtag1,i) > getNthPos(endtag2,i))
195            return 1;
196    }
197
198    //endtags matched up to the end of one endtag so whichever is shorter goes first
199    if(endtag1.length < endtag2.length)
200        return -1;
201    return 1;
202}
203