|
| 1 | +// draw tree class functions start :/ |
| 2 | + |
| 3 | + |
| 4 | +export class Tree{ |
| 5 | + constructor(node=0,children=[]) { |
| 6 | + this.id = 0; |
| 7 | + this.node = node; |
| 8 | + this.width = node.length; |
| 9 | + this.children = children; |
| 10 | + } |
| 11 | +} |
| 12 | + |
| 13 | +export class DrawTree{ |
| 14 | + constructor(tree,parent=undefined,depth=0,number=1) { |
| 15 | + this.x =-1; |
| 16 | + this.y = depth; |
| 17 | + this.tree = tree; |
| 18 | + this.children = []; |
| 19 | + for( let i=0;i<tree.children.length;i++ ){ |
| 20 | + let newTree = new DrawTree(tree.children[i],this,depth+1,i+1); |
| 21 | + this.children.push(newTree); |
| 22 | + } |
| 23 | + this.parent = parent; |
| 24 | + this.thread = undefined; |
| 25 | + this.mod = 0; |
| 26 | + this.ancestor = this; |
| 27 | + this.change = 0; |
| 28 | + this.shift = 0; |
| 29 | + this._lmost_sibling = undefined; |
| 30 | + this.number = number; |
| 31 | + // this.lmost_sibling = this.get_lmost_sibling(); |
| 32 | + } |
| 33 | + |
| 34 | + left = ()=>{ |
| 35 | + if( this.thread!==undefined ) return this.thread; |
| 36 | + if( this.children.length!==0 ) return this.children[0]; |
| 37 | + return undefined; |
| 38 | + return this.thread || this.children.length && this.children[0]; |
| 39 | + } |
| 40 | + right = ()=>{ |
| 41 | + if( this.thread ) return this.thread; |
| 42 | + if( this.children.length ) return this.children[this.children.length-1]; |
| 43 | + return undefined; |
| 44 | + return this.thread || this.children.length && this.children[-1]; |
| 45 | + } |
| 46 | + lbrother = ()=>{ |
| 47 | + let n = undefined; |
| 48 | + if( this.parent ){ |
| 49 | + // for(let node in this.parent.children) |
| 50 | + for(let i=0;i<this.parent.children.length;i++) |
| 51 | + { |
| 52 | + let node = this.parent.children[i]; |
| 53 | + if( node === this ){ |
| 54 | + return n; |
| 55 | + }else{ |
| 56 | + n = node; |
| 57 | + } |
| 58 | + } |
| 59 | + } |
| 60 | + return n; |
| 61 | + } |
| 62 | + get_lmost_sibling = ()=>{ |
| 63 | + if( !this._lmost_sibling && this.parent && this!==this.parent.children[0] ){ |
| 64 | + this._lmost_sibling = this.parent.children[0]; |
| 65 | + } |
| 66 | + return this._lmost_sibling; |
| 67 | + } |
| 68 | + |
| 69 | + |
| 70 | +} |
| 71 | + |
| 72 | + |
| 73 | + |
| 74 | + |
| 75 | +export function buchheim(tree) { |
| 76 | + let dt = firstwalk(new DrawTree(tree)) |
| 77 | + let min = second_walk(dt) |
| 78 | + if (min < 0) { |
| 79 | + third_walk(dt, -min); |
| 80 | + } |
| 81 | + return dt |
| 82 | +} |
| 83 | + |
| 84 | +function third_walk(tree, n) { |
| 85 | + tree.x += n; |
| 86 | + //for (let c in tree.children) |
| 87 | + for(let i=0;i<tree.children;i++) |
| 88 | + { |
| 89 | + let c = tree.children[i]; |
| 90 | + third_walk(c, n); |
| 91 | + } |
| 92 | +} |
| 93 | + |
| 94 | +function firstwalk(v, distance = 1) { |
| 95 | + //console.log('hue hue hue',v); |
| 96 | + if (v.children.length === 0) { |
| 97 | + if (v.get_lmost_sibling()) { |
| 98 | + v.x = v.lbrother().x + distance; |
| 99 | + } else { |
| 100 | + v.x = 0.; |
| 101 | + } |
| 102 | + } else { |
| 103 | + let default_ancestor = v.children[0]; |
| 104 | + //for (let w in v.children) |
| 105 | + for(let i=0;i<v.children.length;i++) { |
| 106 | + let w = v.children[i]; |
| 107 | + firstwalk(w); |
| 108 | + default_ancestor = apportion(w, default_ancestor, distance); |
| 109 | + } |
| 110 | + // console.log("finished v =", v.tree, "children"); |
| 111 | + execute_shifts(v); |
| 112 | + |
| 113 | + let midpoint = (v.children[0].x + v.children[v.children.length-1].x) / 2; |
| 114 | + |
| 115 | + let ell = v.children[0]; |
| 116 | + let arr = v.children[-1]; |
| 117 | + let w = v.lbrother(); |
| 118 | + if (w) { |
| 119 | + v.x = w.x + distance; |
| 120 | + v.mod = v.x - midpoint; |
| 121 | + } else { |
| 122 | + v.x = midpoint; |
| 123 | + } |
| 124 | + } |
| 125 | + return v; |
| 126 | +} |
| 127 | + |
| 128 | + |
| 129 | +function apportion(v, default_ancestor, distance) { |
| 130 | + |
| 131 | + let w = v.lbrother(); |
| 132 | + if (w !== undefined) { |
| 133 | + // inbuchheimnotation: |
| 134 | + //i == inner;o == outer;r == right;l == left;r = +;l = - |
| 135 | + let vir, vor, vil, vol, sir, sor, sol, sil; |
| 136 | + vir = vor = v; |
| 137 | + vil = w; |
| 138 | + vol = v.get_lmost_sibling(); |
| 139 | + sir = sor = v.mod; |
| 140 | + sil = vil.mod; |
| 141 | + sol = vol.mod; |
| 142 | + while (vil.right() && vir.left()) { |
| 143 | + vil = vil.right(); |
| 144 | + vir = vir.left(); |
| 145 | + vol = vol.left(); |
| 146 | + vor = vor.right(); |
| 147 | + vor.ancestor = v; |
| 148 | + let shift = (vil.x + sil) - (vir.x + sir) + distance; |
| 149 | + if (shift > 0) { |
| 150 | + move_subtree(ancestor(vil, v, default_ancestor), v, shift); |
| 151 | + sir = sir + shift; |
| 152 | + sor = sor + shift; |
| 153 | + } |
| 154 | + sil += vil.mod; |
| 155 | + sir += vir.mod; |
| 156 | + sol += vol.mod; |
| 157 | + sor += vor.mod; |
| 158 | + } |
| 159 | + if (vil.right() && !vor.right()) { |
| 160 | + vor.thread = vil.right(); |
| 161 | + vor.mod += sil - sor; |
| 162 | + } else { |
| 163 | + if (vir.left() && !vol.left()) { |
| 164 | + vol.thread = vir.left(); |
| 165 | + vol.mod += sir - sol; |
| 166 | + } |
| 167 | + default_ancestor = v |
| 168 | + } |
| 169 | + } |
| 170 | + return default_ancestor |
| 171 | +} |
| 172 | + |
| 173 | +function move_subtree(wl, wr, shift) { |
| 174 | + let subtrees = wr.number - wl.number; |
| 175 | + // console.log(wl.tree, "is conflicted with", wr.tree, 'moving', subtrees, 'shift', shift); |
| 176 | + // print wl, wr, wr.number, wl.number, shift, subtrees, shift / subtrees |
| 177 | + wr.change -= shift / subtrees; |
| 178 | + wr.shift += shift; |
| 179 | + wl.change += shift / subtrees; |
| 180 | + wr.x += shift; |
| 181 | + wr.mod += shift; |
| 182 | +} |
| 183 | + |
| 184 | +function execute_shifts(v) { |
| 185 | + let shift, change; |
| 186 | + shift = change = 0; |
| 187 | + // for (let w in v.children[:: - 1]) |
| 188 | + for(let i=v.children.length-1;i>=0;i--){ |
| 189 | + let w = v.children[i]; |
| 190 | + //console.log("shift:", w.tree.node, shift, w.change); |
| 191 | + w.x += shift; |
| 192 | + w.mod += shift; |
| 193 | + change += w.change; |
| 194 | + shift += w.shift + change; |
| 195 | + } |
| 196 | +} |
| 197 | + |
| 198 | +function ancestor(vil, v, default_ancestor) { |
| 199 | + |
| 200 | + if (vil.ancestor in v.parent.children){ |
| 201 | + |
| 202 | + return vil.ancestor; |
| 203 | + } |
| 204 | + else |
| 205 | + return default_ancestor; |
| 206 | +} |
| 207 | + |
| 208 | +function second_walk(v, m = 0, depth = 0, min = undefined) { |
| 209 | + v.x += m; |
| 210 | + v.y = depth; |
| 211 | + |
| 212 | + if (min === undefined || v.x < min) |
| 213 | + min = v.x; |
| 214 | + |
| 215 | + // for (let w in v.children) |
| 216 | + for(let i=0;i<v.children.length;i++){ |
| 217 | + let w = v.children[i]; |
| 218 | + min = second_walk(w, m + v.mod, depth + 1, min); |
| 219 | + } |
| 220 | + return min; |
| 221 | +} |
| 222 | + |
| 223 | +function dfs(tree){ |
| 224 | + if( tree.tree.node === 'B' ) return; |
| 225 | + console.log( tree.tree.node, tree.x,tree.y ); |
| 226 | + for(let i=0;i<tree.children.length;i++) |
| 227 | + dfs(tree.children[i]); |
| 228 | +} |
| 229 | +/* |
| 230 | +let blank = new Tree('B',[]); |
| 231 | +let ll = new Tree("ll",[]); |
| 232 | +let lr = new Tree("lr",[]); |
| 233 | +let rr = new Tree("rr",[]); |
| 234 | +let rl = new Tree("rl",[]); |
| 235 | +let l = new Tree("l",[ll,lr]); |
| 236 | +let r = new Tree("r",[rl,rr]); |
| 237 | +let root = new Tree("root",[l,r] ); |
| 238 | +
|
| 239 | +let tree = buchheim(root); |
| 240 | +console.log("=================================================================="); |
| 241 | +dfs(tree); |
| 242 | +*/ |
0 commit comments