diff --git a/OZprivate/rawJS/OZTreeModule/src/controller/controller_anim.js b/OZprivate/rawJS/OZTreeModule/src/controller/controller_anim.js index 0606f652b..4cdba567c 100755 --- a/OZprivate/rawJS/OZTreeModule/src/controller/controller_anim.js +++ b/OZprivate/rawJS/OZTreeModule/src/controller/controller_anim.js @@ -184,8 +184,7 @@ export default function (Controller) { let anchor_node = this.dynamic_load_and_calc(dest_OZid, { generation_at_searched_node: config.generation_at_searched_node }); - position_helper.deanchor(this.root); - position_helper.reanchor_at_node(anchor_node); + position_helper.reanchor_at_node(anchor_node, this.root); this.re_calc(); this.trigger_refresh_loop(); resolve() diff --git a/OZprivate/rawJS/OZTreeModule/src/factory/midnode.js b/OZprivate/rawJS/OZTreeModule/src/factory/midnode.js index e3c3acfcd..dd8025db4 100755 --- a/OZprivate/rawJS/OZTreeModule/src/factory/midnode.js +++ b/OZprivate/rawJS/OZTreeModule/src/factory/midnode.js @@ -43,9 +43,9 @@ class Midnode { this.arcr = 1.0; this.arcx = 1.0; this.arcy = 1.0; - this.nextr = new Array(config.factory.child_num); - this.nextx = new Array(config.factory.child_num); - this.nexty = new Array(config.factory.child_num); + this.nextr = new Array(config.factory.child_num); // Relative radius/scale to assign to children, as decided by view _pre_calc() functions + this.nextx = new Array(config.factory.child_num); // Relative x-location ... + this.nexty = new Array(config.factory.child_num); // Relative y-location ... this.gxmin = 1.0; // Node bounding box this.gymin = 1.0; // Node bounding box this.hxmin = 1.0; // Node-and-descendants bounding box @@ -55,13 +55,13 @@ class Midnode { this.hxmax = 1.0; // Node-and-descendants bounding box this.hymax = 1.0; // Node-and-descendants bounding box - this.xvar = 1.0; - this.yvar = 1.0; - this.rvar = 1.0; + this.xvar = 1.0; // x-location of node relative to graphref node updated by position_helper:drawreg_target() + this.yvar = 1.0; // y-location of node ... + this.rvar = 1.0; // radius/scale of node ... this.gvar = false; // gvar is true if this node itself needs to be drawn on screen (i.e onezoom.config.debug_bounding_box = 1) this.dvar = false; // dvar is true if this node (or a descendent node) needs to be drawn on the screen (i.e onezoom.config.debug_bounding_box = 4) - this.graphref = false; - this.targeted = false; + this.graphref = false; // true if this node (or a descendent node) is the "referencing node", i.e. the node from which xvar/yvar/rvar are relative to + this.targeted = false; // true if this node (or a descendent node) is the destination for the current flight this.child_leaf_meta_start = new Array(config.factory.child_num); this.child_leaf_meta_end = new Array(config.factory.child_num); @@ -291,7 +291,20 @@ class Midnode { this._picID_credit = null; this._detail_fetched = false; } - + + /** + * Text representation of node, for debugging purposes + * + * Use with console log, e.g: console.log("Reanchoring to " + node); + * (NB "+", not ",") + */ + toString() { + return [ + this.cname || this.latin_name || 'Node', + this.ott ? '@=' + this.ott : '@_ozid=' + this.ozid, + ].join(" "); + } + /** * Returns the OZid * i.e. negative metacode for leaf, positive metacode for interior node diff --git a/OZprivate/rawJS/OZTreeModule/src/position_helper.js b/OZprivate/rawJS/OZTreeModule/src/position_helper.js index f01f40eaf..bd77a234e 100755 --- a/OZprivate/rawJS/OZTreeModule/src/position_helper.js +++ b/OZprivate/rawJS/OZTreeModule/src/position_helper.js @@ -132,6 +132,9 @@ function get_xyr_target(node, x2,y2,r2,into_node) { } } +/** + * Walk tree from (node), probably root, turning graphref off + */ function deanchor(node) { if (node.graphref) { let length = node.children.length; @@ -370,36 +373,52 @@ function pan_zoom(prop_p, prop_z) { tree_state.yp = tree_centreY + y_add2*(1-prop_p) + (pre_yp2-y_add2-tree_centreY) * Math.pow(r_mult2,prop_z); } -function reanchor_at_node(node) { - node.graphref = true; - if (node.upnode) { - reanchor_at_node(node.upnode); +/** + * Force the anchor to be the given (node), + * (i.e. set graphref on node and all it's ancestors) + */ +function reanchor_at_node(node, root_node) { + // Set graphref false everywhere + deanchor(root_node); + + // Walk up tree from (node), setting graphref + while (node.upnode) { + node.graphref = true; + node = node.upnode; } + // Set graphref on root node + node.graphref = true; } +/** + * Walk tree, anchoring to the first node on-screen that has 2.2 < node.rvar < 22000 + * (i.e. set graphref on this node and it's ancestors) + */ function reanchor(node) { - if (node.dvar) { - node.graphref = true; - if (node.gvar || !node.has_child || (node.rvar > 2.2 && node.rvar < 22000)) { - tree_state.xp = node.xvar; - tree_state.yp = node.yvar; - tree_state.ws = node.rvar / 220; - let length = node.children.length; - for (let i=0; i 2.2 && node.rvar < 22000)) { + // Anchor to this node + tree_state.xp = node.xvar; + tree_state.yp = node.yvar; + tree_state.ws = node.rvar / 220; + // Deanchor everything below this node + for (let i=0; i tree_state.threshold) { for (let other=0; other tree_state.threshold) { let length = node.children.length; @@ -101,26 +101,24 @@ function get_dvar_by_children(node) { return dvar; } -/** Does the given node and it's descendants fit on screen? */ -function node_descendants_in_screen(node) { - if ((node.xvar + node.rvar * node.hxmax) < 0) return false; - else if ((node.xvar + node.rvar * node.hxmin) > tree_state.widthres) return false; - else if ((node.yvar + node.rvar * node.hymax) < 0) return false; - else if ((node.yvar + node.rvar * node.hymin) > tree_state.heightres) return false; - else return true; -} +/** + * Does the bounding box of the node / node-and-descendants fit on screen? + */ +function node_on_screen(node, inclDescendants) { + const x1 = node.xvar + node.rvar * (inclDescendants ? node.hxmin : node.gxmin); + const x2 = node.xvar + node.rvar * (inclDescendants ? node.hxmax : node.gxmax); + const y1 = node.yvar + node.rvar * (inclDescendants ? node.hymin : node.gymin); + const y2 = node.yvar + node.rvar * (inclDescendants ? node.hymax : node.gymax); -/** Does the given node fit on screen? */ -function node_in_screen(node) { - if ((node.xvar + node.rvar * node.gxmax) < 0) return false; - else if ((node.xvar + node.rvar * node.gxmin) > tree_state.widthres) return false; - else if ((node.yvar + node.rvar * node.gymax) < 0) return false; - else if ((node.yvar + node.rvar * node.gymin) > tree_state.heightres) return false; - else return true; + if (x2 < 0) return false; + if (x1 > tree_state.widthres) return false; + if (y2 < 0) return false; + if (y1 > tree_state.heightres) return false; + return true; } function set_node_gvar_dvar(node) { - if(node_in_screen(node)) { + if(node_on_screen(node, false)) { node.gvar = true; node.dvar = true; } else { diff --git a/OZprivate/rawJS/OZTreeModule/src/projection/shape_manager.js b/OZprivate/rawJS/OZTreeModule/src/projection/shape_manager.js index cafe08d41..197e41182 100755 --- a/OZprivate/rawJS/OZTreeModule/src/projection/shape_manager.js +++ b/OZprivate/rawJS/OZTreeModule/src/projection/shape_manager.js @@ -64,8 +64,23 @@ function draw_bounding_box(node, shapes) { } if (debug & 0x2) { // Bounding box for node + parent + s = BezierShape.create(); + s.sx = s.sy = s.ex = s.ey = null; + s.path_points.push(['move', node.xvar + node.rvar * node.gxmin, node.yvar + node.rvar * node.gymin]); + s.path_points.push(['line', node.xvar + node.rvar * node.gxmin, node.yvar + node.rvar * node.gymax]); + s.path_points.push(['line', node.xvar + node.rvar * node.gxmax, node.yvar + node.rvar * node.gymax]); + s.path_points.push(['line', node.xvar + node.rvar * node.gxmax, node.yvar + node.rvar * node.gymin]); + s.path_points.push(['line', node.xvar + node.rvar * node.gxmin, node.yvar + node.rvar * node.gymin]); + s.do_stroke = true; + s.stroke.line_width = 1; + s.height = 0; + s.stroke.color = 'hsl(' + Math.sin(node.metacode) * 360 + ', 100%, 80%)'; + shapes.push(s); + } + + if (debug & 0x1) { // Bounding box text label s = TextShape.create(); - s.text = "" + node.latin_name; + s.text = "" + node.toString(); s.width = (node.xvar + node.rvar * node.gxmax) - (node.xvar + node.rvar * node.gxmin); s.height = 5; s.x = node.xvar + node.rvar * node.gxmin + (s.width / 2); @@ -79,20 +94,6 @@ function draw_bounding_box(node, shapes) { shapes.push(s); } - if (debug & 0x1) { // Bounding box text label - s = BezierShape.create(); - s.sx = s.sy = s.ex = s.ey = null; - s.path_points.push(['move', node.xvar + node.rvar * node.gxmin, node.yvar + node.rvar * node.gymin]); - s.path_points.push(['line', node.xvar + node.rvar * node.gxmin, node.yvar + node.rvar * node.gymax]); - s.path_points.push(['line', node.xvar + node.rvar * node.gxmax, node.yvar + node.rvar * node.gymax]); - s.path_points.push(['line', node.xvar + node.rvar * node.gxmax, node.yvar + node.rvar * node.gymin]); - s.path_points.push(['line', node.xvar + node.rvar * node.gxmin, node.yvar + node.rvar * node.gymin]); - s.do_stroke = true; - s.stroke.line_width = 1; - s.height = 0; - s.stroke.color = 'hsl(' + Math.sin(node.metacode) * 360 + ', 100%, 80%)'; - shapes.push(s); - } } function height_comparator(a, b) {