1//this recursive function should always be called on the root solver (endtag = "0"). 2//targetEndtag is the endtag of the solver option that is currently being asked. the reason we have this as a parameter is because there is simply not enough space to display a diagram of the ENTIRE solver. so, we only display a path to the current solver option 3//x,y are the x and y coordinates of the upper lefthand corner of the svg (should initially be called with 0,0) 4//this function returns a string that needs to be put into an svg in the html page 5function drawDiagrams(data,endtag,targetEndtag,x,y) { 6 7 if(data["0"].x_extreme == undefined) 8 data["0"].x_extreme = 0; 9 if(data["0"].y_extreme == undefined) 10 data["0"].y_extreme = 0; 11 12 var numChildren = getNumChildren(data,endtag); 13 14 if(numChildren == 0) //base case. no children. 15 return ""; 16 if(targetEndtag.indexOf(endtag) != 0) //base case. endtag is not on the path to targetEndtag. 17 return ""; 18 19 var ret = ""; 20 21 if(data[endtag].pc_type == "fieldsplit") { 22 if(x+400 > data["0"].x_extreme) 23 data["0"].x_extreme = x+400; 24 if(y+400 > data["0"].y_extreme) 25 data["0"].y_extreme = y+400; 26 } 27 else if(data[endtag].pc_type == "mg") { 28 var mg_levels = data[endtag].mg_levels; 29 var global_downshift = 141*mg_levels + 68*mg_levels; 30 if(x+465 > data["0"].x_extreme) 31 data["0"].x_extreme = x+465; 32 if(y+global_downshift > data["0"].y_extreme) 33 data["0"].y_extreme = y+global_downshift; 34 } 35 36 if(data[endtag].pc_type == "fieldsplit") { //draw fieldsplit diagram 37 var colors = ["green","blue","red"]; 38 var layer = 0; 39 ret += "<polygon points=\""+x+","+y+" "+(x+400)+","+y+" "+(x+400)+","+(y+400)+" "+x+","+(y+400)+"\" style=\"fill:khaki;stroke:black;stroke-width:1\"></polygon>"; 40 layer = 1; 41 42 function drawFieldsplit(data,endtag,level,targetEndtag,x,y,size) { //(x,y) is the upper lefthand corner. size is the size of one side of the parent square (in pixels) 43 //work = draw the children of the fieldsplit then call draw on each child 44 if(targetEndtag.indexOf(endtag) != 0) 45 return ""; //endtag is not on the path to the targetEndtag 46 47 var ret = ""; 48 49 var numChildren = getNumChildren(data,endtag); 50 if(numChildren == 0) 51 return; 52 var colorNum = level;//the depth of the fieldsplit within other fieldsplits 53 54 for(var i=0; i<numChildren; i++) { 55 var side = size/(numChildren+1);//leave one extra block of space 56 var curr_x = x + i*side; 57 var curr_y = y + i*side; 58 59 ret += "<polygon points=\""+curr_x+","+curr_y+" "+(curr_x+side)+","+curr_y+" "+(curr_x+side)+","+(curr_y+side)+" "+curr_x+","+(curr_y+side)+"\" style=\"fill:"+colors[colorNum]+";stroke:black;stroke-width:1\"></polygon>"; 60 61 var childEndtag = endtag + "_" + i; 62 //only draw if child is indeed a fieldsplit 63 64 if(data[childEndtag] != undefined && data[childEndtag].pc_type == "fieldsplit") 65 ret += drawFieldsplit(data,childEndtag, level+1, targetEndtag, curr_x, curr_y, size/numChildren); 66 67 //if child is mg, then it is time to switch drawing methods 68 else if(data[childEndtag] != undefined && data[childEndtag].pc_type == "mg") { 69 var possible = drawDiagrams(data,childEndtag,targetEndtag,x+size+20+146,y+i*side); 70 if(possible != "") {//don't draw the arrow if there is no diagram following 71 ret += "<image x=\""+(x+size+20)+"\" y=\""+(y+i*side+side/2-13)+"\" width=\"146\" height=\"26\" xlink:href=\"images/arrow.png\"></image>"; 72 ret += possible; 73 } 74 } 75 } 76 var side = size/(numChildren+1);//side of the blank square 77 var blank_x = x + numChildren*side; 78 var blank_y = y + numChildren*side; 79 80 var inc = side/4;//the increment 81 for(var i=1; i<4; i++) { //add diagonal ellipsis 82 var x_coord = blank_x + i*inc; 83 var y_coord = blank_y + i*inc; 84 ret += "<circle cx=\""+x_coord+"\" cy=\"" + y_coord + "\" r=\"2\" stroke=\"black\" stroke-width=\"2\" fill=\"black\"></circle>"; 85 } 86 87 return ret; 88 } 89 ret += drawFieldsplit(data,endtag,0,targetEndtag,x,y,400); 90 } 91 92 else if(data[endtag].pc_type == "mg") { //draw multigrid diagram. multigrid diagram doesn't use an inner recursive function because it's not that complex to draw. 93 94 var selectedChild = ""; 95 96 //generate a parallelogram for each layer 97 for(var i=0; i<numChildren; i++) { //i represents the multigrid level (i=0 would be coarse) 98 var dim = 3+2*i;//dimxdim grid 99 var global_downshift = 141*i + 68*i; 100 101 ret += "<polygon points=\""+x+","+(y+141+global_downshift)+" "+ (x+141)+","+(y+global_downshift)+" "+(x+465)+","+(y+global_downshift)+" "+(x+324)+","+(y+141+global_downshift)+"\" style=\"fill:khaki;stroke:black;stroke-width:1\"> </polygon>"; 102 103 for(var j=1; j<dim; j++) {//draw 'vertical' lines 104 var inc = 324/dim;//parallogram is 324 wide and 200 on the slant side (1.6x) 105 var shift = j*inc; 106 var top_shift = shift + 141; 107 ret += "<line x1=\""+(x+shift)+"\" y1=\""+(y+141+global_downshift)+"\" x2=\""+(x+top_shift)+"\" y2=\""+(y+global_downshift)+"\" style='stroke:black;stroke-width:1'></line>"; 108 } 109 for(var j=1; j<dim; j++) {//draw horizontal lines 110 var inc = 141/dim;//parallelogram is 141 tall 111 var horiz_shift = (141/dim) * j; 112 var horiz_shift_end = horiz_shift + 324; 113 114 var shift = 141 - inc * j; 115 ret += "<line x1=\""+(x+horiz_shift)+"\" y1=\""+(y+shift+global_downshift) +"\" x2=\""+(x+horiz_shift_end)+"\" y2=\""+(y+shift+global_downshift)+"\" style='stroke:black;stroke-width:1'></line>"; 116 } 117 118 if(i != numChildren-1)//add transition arrows image if there are more grids left 119 ret += "<image x=\""+x+"\" y=\""+(y+141+global_downshift)+"\" width=\"349\" height=\"68\" xlink:href=\"/images/transition.bmp\"/>"; //images in svg are handled differently. can't simply use <img> 120 121 //if the current child is the one that is on the path to the target, then record it 122 var childEndtag = endtag + "_" + i; 123 124 if(targetEndtag.indexOf(childEndtag) == 0) { //this can only happen with 1 child (the one that is on the path to the target) 125 selectedChild = i; 126 } 127 } 128 129 var new_x = x + 465; 130 var new_y = y + (selectedChild) * (141+68);//manipulate based on selectedChild 131 132 //recursively draw the rest of the path to targetEndtag 133 134 var possible = drawDiagrams(data,endtag+"_"+selectedChild,targetEndtag,new_x+146,new_y); 135 if(possible != "") {//only add the arrow if something was actually drawn 136 ret += "<image x=\""+(new_x-45)+"\" y=\""+(new_y+70)+"\" width=\"146\" height=\"26\" xlink:href=\"images/arrow.png\"></image>"; 137 ret += possible; 138 } 139 } 140 141 return ret; 142} 143