From 2bb68de4f183e783cae8534f0f1198f1e9a42dd4 Mon Sep 17 00:00:00 2001 From: Gonzalo Bellver Date: Fri, 13 Jan 2012 12:37:11 -0300 Subject: [PATCH] BalancedSorter predict and verify --- .../javascript/nlayout/AbstractBasicSorter.js | 7 +- .../main/javascript/nlayout/BalancedSorter.js | 103 +++++++----- .../main/javascript/nlayout/OriginalLayout.js | 5 +- .../src/test/javascript/static/TestSuite.js | 150 +++++++++++++++--- .../src/test/javascript/static/layout.html | 35 ++-- 5 files changed, 226 insertions(+), 74 deletions(-) diff --git a/mindplot/src/main/javascript/nlayout/AbstractBasicSorter.js b/mindplot/src/main/javascript/nlayout/AbstractBasicSorter.js index fc7684b1..daf6d60f 100644 --- a/mindplot/src/main/javascript/nlayout/AbstractBasicSorter.js +++ b/mindplot/src/main/javascript/nlayout/AbstractBasicSorter.js @@ -25,7 +25,7 @@ mindplot.nlayout.AbstractBasicSorter = new Class({ }, _computeChildrenHeight : function(treeSet, node, heightCache) { - var height = node.getSize().height + (mindplot.nlayout.SymmetricSorter.INTERNODE_VERTICAL_PADDING * 2); // 2* Top and down padding; + var height = node.getSize().height + (mindplot.nlayout.AbstractBasicSorter.INTERNODE_VERTICAL_PADDING * 2); // 2* Top and down padding; var result; var children = treeSet.getChildren(node); @@ -54,4 +54,7 @@ mindplot.nlayout.AbstractBasicSorter = new Class({ }); return result; } -}); \ No newline at end of file +}); + +mindplot.nlayout.AbstractBasicSorter.INTERNODE_VERTICAL_PADDING = 5; +mindplot.nlayout.AbstractBasicSorter.INTERNODE_HORIZONTAL_PADDING = 30; \ No newline at end of file diff --git a/mindplot/src/main/javascript/nlayout/BalancedSorter.js b/mindplot/src/main/javascript/nlayout/BalancedSorter.js index dcb440d1..5d255367 100644 --- a/mindplot/src/main/javascript/nlayout/BalancedSorter.js +++ b/mindplot/src/main/javascript/nlayout/BalancedSorter.js @@ -52,65 +52,64 @@ mindplot.nlayout.BalancedSorter = new Class({ }, predict : function(parent, graph, position) { - - // No children... - var children = graph.getChildren(parent); - if (children.length == 0) { - return [0,parent.getPosition()]; // @Todo:Change x ... - } + // Filter nodes on one side.. + var children = this._getChildrenForSide(parent, graph, position); // Try to fit within ... - // - // - Order is change if the position top position is changed ... - // - Suggested position is the middle between the two topics... - // var result = null; - children.forEach(function(child) { + var last = children.getLast(); + children.each(function(child, index) { var cpos = child.getPosition(); if (position.y > cpos.y) { - result = [child.getOrder(),{x:cpos.x,y:cpos.y + child.getSize().height}]; - } - - // Ok, no overlap. Suggest a new order. - if (result) { - var last = children.getLast(); - result = [last.getOrder() + 1,{x:cpos.x,y:cpos.y - (mindplot.nlayout.BalancedSorter.INTERNODE_VERTICAL_PADDING * 4)}]; + yOffset = child == last ? + child.getSize().height + mindplot.nlayout.BalancedSorter.INTERNODE_VERTICAL_PADDING * 2 : + (children[index + 1].getPosition().y - child.getPosition().y)/2; + result = [child.getOrder() + 2,{x:cpos.x, y:cpos.y + yOffset}]; } }); + // Position wasn't below any node, so it must be inserted above + if (!result) { + var first = children[0]; + result = [position.x > 0 ? 0 : 1, { + x:first.getPosition().x, + y:first.getPosition().y - first.getSize().height - mindplot.nlayout.BalancedSorter.INTERNODE_VERTICAL_PADDING * 2 + }]; + } return result; }, insert: function(treeSet, parent, child, order) { - var children = this._getSortedChildren(treeSet, parent); + var children = this._getChildrenForOrder(parent, treeSet, order); - // Shift all the elements in one. In case of balanced sorter, order don't need to be continues ... - var collision = order; - for (var i = order; i < children.length; i++) { + // Shift all the elements by two, so side is the same. + // In case of balanced sorter, order don't need to be continuous... + var max = 0; + for (var i = 0; i < children.length; i++) { var node = children[i]; - - // @Todo: This must be review. Order balance need to be defined ... - if (node.getOrder() == collision) { - collision = collision + 1; - node.setOrder(collision); + max = Math.max(max, node.getOrder()); + if (node.getOrder() >= order) { + max = Math.max(max, node.getOrder() + 2); + node.setOrder(node.getOrder() + 2); } } - child.setOrder(order); + + var newOrder = order > (max+1) ? (max + 2) : order; + child.setOrder(newOrder); }, detach:function(treeSet, node) { var parent = treeSet.getParent(node); - var children = this._getSortedChildren(treeSet, parent); - var order = node.getOrder(); - $assert(children[order] === node, "Node seems not to be in the right position"); + // Filter nodes on one side.. + var children = this._getChildrenForOrder(parent, treeSet, node.getOrder()); - // Shift all the nodes ... - for (var i = node.getOrder() + 1; i < children.length; i++) { - var child = children[i]; - child.setOrder(child.getOrder() - 1); - } - node.setOrder(0); + children.each(function(child, index) { + if (child.getOrder() > node.getOrder()) { + child.setOrder(child.getOrder() - 2); + } + }); + node.setOrder(node.getOrder() % 2 == 0 ? 0 : 1); }, computeOffsets:function(treeSet, node) { @@ -155,7 +154,7 @@ mindplot.nlayout.BalancedSorter = new Class({ } var yOffset = ysum + heights[i].height / 2; - var xOffset = direction * (node.getSize().width + mindplot.nlayout.SymmetricSorter.INTERNODE_HORIZONTAL_PADDING); + var xOffset = direction * (node.getSize().width + mindplot.nlayout.BalancedSorter.INTERNODE_HORIZONTAL_PADDING); $assert(!isNaN(xOffset), "xOffset can not be null"); $assert(!isNaN(yOffset), "yOffset can not be null"); @@ -165,14 +164,34 @@ mindplot.nlayout.BalancedSorter = new Class({ return result; }, - toString:function() { - return "Balanced Sorter"; + _getChildrenForSide: function(parent, graph, position) { + return graph.getChildren(parent).filter(function(child) { + return position.x > 0 ? child.getPosition().x > 0 : child.getPosition().x < 0; + }); + }, + + _getChildrenForOrder: function(parent, graph, order) { + return this._getSortedChildren(graph, parent).filter(function(node) { + return node.getOrder() % 2 == order % 2; + }); }, verify:function(treeSet, node) { - // @todo... + // Check that all is consistent ... + var children = this._getChildrenForOrder(node, treeSet, node.getOrder()); + + // All odd ordered nodes should be "continuous" by themselves + // All even numbered nodes should be "continuous" by themselves + var factor = node.getOrder() % 2 == 0 ? 2 : 1; + for (var i = 0; i < children.length; i++) { + $assert(children[i].getOrder() == (i*factor), "missing order elements"); + } + }, + + toString:function() { + return "Balanced Sorter"; } }); mindplot.nlayout.BalancedSorter.INTERNODE_VERTICAL_PADDING = 5; -mindplot.nlayout.BalancedSorter.INTERNODE_HORIZONTAL_PADDING = 5; +mindplot.nlayout.BalancedSorter.INTERNODE_HORIZONTAL_PADDING = 30; diff --git a/mindplot/src/main/javascript/nlayout/OriginalLayout.js b/mindplot/src/main/javascript/nlayout/OriginalLayout.js index c21e22f4..c82dea78 100644 --- a/mindplot/src/main/javascript/nlayout/OriginalLayout.js +++ b/mindplot/src/main/javascript/nlayout/OriginalLayout.js @@ -50,10 +50,11 @@ mindplot.nlayout.OriginalLayout = new Class({ disconnectNode: function(nodeId) { var node = this._treeSet.find(nodeId); - $assert(this._treeSet.getParent(node), "Node already disconnected"); + var parent = this._treeSet.getParent(node); + $assert(parent, "Node already disconnected"); // Remove from children list. - var sorter = node.getSorter(); + var sorter = parent.getSorter(); sorter.detach(this._treeSet, node); // Disconnect the new node ... diff --git a/mindplot/src/test/javascript/static/TestSuite.js b/mindplot/src/test/javascript/static/TestSuite.js index 549b62d0..e3233dda 100644 --- a/mindplot/src/test/javascript/static/TestSuite.js +++ b/mindplot/src/test/javascript/static/TestSuite.js @@ -28,6 +28,7 @@ mindplot.nlayout.TestSuite = new Class({ this.testReconnect(); this.testRemoveNode(); this.testSymmetricPredict(); + this.testBalancedPredict(); }, testAligned: function() { @@ -151,6 +152,35 @@ mindplot.nlayout.TestSuite = new Class({ manager.layout(); manager.plot("testBalanced8", plotsize); + manager.addNode(13, mindplot.nlayout.TestSuite.NODE_SIZE, position); + manager.connectNode(0, 13, 4); + manager.layout(); + manager.plot("testBalanced9", {width:1000, height:400}); + + manager.addNode(14, mindplot.nlayout.TestSuite.NODE_SIZE, position); + manager.connectNode(0, 14, 5); + manager.layout(); + manager.plot("testBalanced10", {width:1000, height:400}); + + manager.addNode(15, mindplot.nlayout.TestSuite.NODE_SIZE, position); + manager.connectNode(0, 15, 4); + manager.layout(); + manager.plot("testBalanced11", {width:1000, height:400}); + + manager.addNode(16, mindplot.nlayout.TestSuite.NODE_SIZE, position); + manager.connectNode(0, 16, 25); + manager.layout(); + manager.plot("testBalanced12", {width:1000, height:400}); + + manager.addNode(17, mindplot.nlayout.TestSuite.NODE_SIZE, position); + manager.addNode(18, mindplot.nlayout.TestSuite.NODE_SIZE, position); + manager.addNode(19, mindplot.nlayout.TestSuite.NODE_SIZE, position); + manager.connectNode(0, 17, 11); + manager.connectNode(0, 18, 13); + manager.connectNode(0, 19, 10); + manager.layout(); + manager.plot("testBalanced13", {width:1000, height:400}); + $assert(manager.find(1).getPosition().x > 0, "even order nodes must be at right of central topic"); $assert(manager.find(3).getPosition().x > 0, "even order nodes must be at right of central topic"); $assert(manager.find(5).getPosition().x > 0, "even order nodes must be at right of central topic"); @@ -181,7 +211,7 @@ mindplot.nlayout.TestSuite = new Class({ // Now connect one with two.... manager.connectNode(0, 1, 0); - manager.connectNode(0, 2, 0); + manager.connectNode(0, 2, 1); manager.connectNode(1, 3, 0); // Basic layout repositioning ... @@ -365,8 +395,18 @@ mindplot.nlayout.TestSuite = new Class({ manager.addNode(2, mindplot.nlayout.TestSuite.NODE_SIZE, position); manager.addNode(3, mindplot.nlayout.TestSuite.NODE_SIZE, position); manager.addNode(4, mindplot.nlayout.TestSuite.NODE_SIZE, position); + manager.addNode(5, mindplot.nlayout.TestSuite.NODE_SIZE, position); + manager.addNode(6, mindplot.nlayout.TestSuite.NODE_SIZE, position); + manager.addNode(7, mindplot.nlayout.TestSuite.NODE_SIZE, position); + manager.addNode(8, mindplot.nlayout.TestSuite.NODE_SIZE, position); + manager.addNode(9, mindplot.nlayout.TestSuite.NODE_SIZE, position); manager.connectNode(0, 1, 0); + manager.connectNode(0, 5, 1); + manager.connectNode(0, 6, 2); + manager.connectNode(0, 7, 3); + manager.connectNode(0, 8, 4); + manager.connectNode(0, 9, 5); manager.connectNode(1, 2, 0); manager.connectNode(1, 3, 1); manager.connectNode(3, 4, 0); @@ -387,6 +427,18 @@ mindplot.nlayout.TestSuite = new Class({ manager.layout(true); manager.plot("testRemoveNode2", {width:1000, height:200}); + // Remove a node from the root node + console.log("\t--- Remove node 6 ---"); + manager.removeNode(6); + manager.layout(true); + manager.plot("testRemoveNode3", {width:1000, height:200}); + + // Remove a node from the root node + console.log("\t--- Remove node 5 ---"); + manager.removeNode(5); + manager.layout(true); + manager.plot("testRemoveNode4", {width:1000, height:200}); + $assert(manager.find(1).getPosition().y == manager.find(2).getPosition().y, "After removal of node 3, nodes 1 and 2 should be alingned"); console.log("\n"); }, @@ -423,36 +475,96 @@ mindplot.nlayout.TestSuite = new Class({ manager.layout(); - console.log("\tPredict where would a node be if tried to add as children of node 9 and dropped at (-280, 45):"); - var predict1 = manager.plot("testPredict1", {width:1000, height:400}); + console.log("\tAdded as child of node 9 and dropped at (-280, 45):"); + var predict1 = manager.plot("testSymmetricPredict1", {width:1000, height:400}); this._plotPrediction(predict1, manager.predict(9, {x:-280, y:45})); - console.log("\tPredict where would a node be if tried to add as children of node 1 and dropped at (155, -90):"); - var predict2 = manager.plot("testPredict2", {width:1000, height:400}); + console.log("\tAdded as child of node 1 and dropped at (155, -90):"); + var predict2 = manager.plot("testSymmetricPredict2", {width:1000, height:400}); this._plotPrediction(predict2, manager.predict(1, {x:-155, y:-90})); - console.log("\tPredict where would a node be if tried to add as children of node 5 and dropped at (375, 15):"); - var predict3 = manager.plot("testPredict3", {width:1000, height:400}); + console.log("\tAdded as child of node 5 and dropped at (375, 15):"); + var predict3 = manager.plot("testSymmetricPredict3", {width:1000, height:400}); this._plotPrediction(predict3, manager.predict(5, {x:375, y:15})); - console.log("\tPredict where would a node be if tried to add as children of node 5 and dropped at (375, 45):"); - var predict4 = manager.plot("testPredict4", {width:1000, height:400}); + console.log("\tAdded as child of node 5 and dropped at (375, 45):"); + var predict4 = manager.plot("testSymmetricPredict4", {width:1000, height:400}); this._plotPrediction(predict4, manager.predict(5, {x:375, y:45})); - console.log("\tPredict where would a node be if tried to add as children of node 5 and dropped at (375, 45):"); - var predict5 = manager.plot("testPredict5", {width:1000, height:400}); + console.log("\tAdded as child of node 5 and dropped at (375, 45):"); + var predict5 = manager.plot("testSymmetricPredict5", {width:1000, height:400}); this._plotPrediction(predict5, manager.predict(5, {x:375, y:65})); - console.log("\tPredict where would a node be if tried to add as children of node 3 and dropped at (280, 45):"); - var predict6 = manager.plot("testPredict6", {width:1000, height:400}); + console.log("\tAdded as child of node 3 and dropped at (280, 45):"); + var predict6 = manager.plot("testSymmetricPredict6", {width:1000, height:400}); this._plotPrediction(predict6, manager.predict(3, {x:280, y:45})); - console.log("\tPredict where would a node be if tried to add as children of node 3 and dropped at (255, 110):"); - var predict7 = manager.plot("testPredict7", {width:1000, height:400}); + console.log("\tAdded as child of node 3 and dropped at (255, 110):"); + var predict7 = manager.plot("testSymmetricPredict7", {width:1000, height:400}); this._plotPrediction(predict7, manager.predict(3, {x:255, y:110})); - console.log("\tPredict where would a node be if tried to add as children of node 2 and dropped at (-260, 0):"); - var predict8 = manager.plot("testPredict8", {width:1000, height:400}); + console.log("\tAdded as child of node 2 and dropped at (-260, 0):"); + var predict8 = manager.plot("testSymmetricPredict8", {width:1000, height:400}); this._plotPrediction(predict8, manager.predict(2, {x:-260, y:0})); - console.log("\tPredict where would a node be if tried to add as children of node 5 and dropped at (380, -30):"); - var predict9 = manager.plot("testPredict9", {width:1000, height:400}); + console.log("\tAdded as child of node 5 and dropped at (380, -30):"); + var predict9 = manager.plot("testSymmetricPredict9", {width:1000, height:400}); this._plotPrediction(predict9, manager.predict(5, {x:380, y:-30})); }, + testBalancedPredict: function() { + console.log("testBalancedPredict"); + var position = {x:0, y:0}; + var manager = new mindplot.nlayout.LayoutManager(0, mindplot.nlayout.TestSuite.ROOT_NODE_SIZE); + + manager.addNode(1, mindplot.nlayout.TestSuite.NODE_SIZE, position); + manager.addNode(2, mindplot.nlayout.TestSuite.NODE_SIZE, position); + manager.addNode(3, mindplot.nlayout.TestSuite.NODE_SIZE, position); + manager.addNode(4, mindplot.nlayout.TestSuite.NODE_SIZE, position); + manager.addNode(5, mindplot.nlayout.TestSuite.NODE_SIZE, position); + manager.addNode(7, mindplot.nlayout.TestSuite.NODE_SIZE, position); + manager.addNode(8, mindplot.nlayout.TestSuite.NODE_SIZE, position); + manager.addNode(9, mindplot.nlayout.TestSuite.NODE_SIZE, position); + manager.addNode(10, mindplot.nlayout.TestSuite.NODE_SIZE, position); + manager.addNode(11, mindplot.nlayout.TestSuite.NODE_SIZE, position); + + manager.connectNode(0,1,0); + manager.connectNode(0,2,1); + manager.connectNode(0,3,2); + manager.connectNode(0,4,3); + manager.connectNode(0,5,4); + manager.connectNode(4,7,0); + manager.connectNode(4,8,1); + manager.connectNode(8,9,0); + manager.connectNode(3,10,0); + manager.connectNode(3,11,1); + + manager.layout(); + + console.log("\tAdded as child of node 0 and dropped at (165, -70):"); + var predict1 = manager.plot("testBalancedPredict1", {width:1000, height:400}); + this._plotPrediction(predict1, manager.predict(0, {x:165, y:-70})); + console.log("\tAdded as child of node 0 and dropped at (165, -10):"); + var predict2 = manager.plot("testBalancedPredict2", {width:1000, height:400}); + this._plotPrediction(predict2, manager.predict(0, {x:165, y:-10})); + console.log("\tAdded as child of node 0 and dropped at (145, 15):"); + var predict3 = manager.plot("testBalancedPredict3", {width:1000, height:400}); + this._plotPrediction(predict3, manager.predict(0, {x:145, y:15})); + console.log("\tAdded as child of node 0 and dropped at (145, 70):"); + var predict4 = manager.plot("testBalancedPredict4", {width:1000, height:400}); + this._plotPrediction(predict4, manager.predict(0, {x:145, y:70})); + + console.log("\tAdded as child of node 0 and dropped at (-145, -50):"); + var predict5 = manager.plot("testBalancedPredict5", {width:1000, height:400}); + this._plotPrediction(predict5, manager.predict(0, {x:-145, y:-50})); + console.log("\tAdded as child of node 0 and dropped at (-145, -10):"); + var predict6 = manager.plot("testBalancedPredict6", {width:1000, height:400}); + this._plotPrediction(predict6, manager.predict(0, {x:-145, y:-10})); + console.log("\tAdded as child of node 0 and dropped at (-145, 40):"); + var predict7 = manager.plot("testBalancedPredict7", {width:1000, height:400}); + this._plotPrediction(predict7, manager.predict(0, {x:-145, y:400})); + + console.log("\tAdded as child of node 0 and dropped at (0, 40):"); + var predict8 = manager.plot("testBalancedPredict8", {width:1000, height:400}); + this._plotPrediction(predict8, manager.predict(0, {x:0, y:40})); + console.log("\tAdded as child of node 0 and dropped at (0, 0):"); + var predict9 = manager.plot("testBalancedPredict9", {width:1000, height:400}); + this._plotPrediction(predict9, manager.predict(0, {x:0, y:0})); + }, + _plotPrediction: function(canvas, prediction) { console.log("\t\tprediction {order:" + prediction[0] + ", position: (" + prediction.getLast().x + "," + prediction.getLast().y + ")}"); var cx = prediction.getLast().x + canvas.width / 2 - mindplot.nlayout.TestSuite.NODE_SIZE.width / 2; diff --git a/mindplot/src/test/javascript/static/layout.html b/mindplot/src/test/javascript/static/layout.html index 1b6bd5c0..6f92b3cc 100644 --- a/mindplot/src/test/javascript/static/layout.html +++ b/mindplot/src/test/javascript/static/layout.html @@ -59,6 +59,11 @@
+
+
+
+
+

testEvents:

@@ -80,18 +85,30 @@

testRemoveNode:

+
+

testSymmetricPredict:

-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

testBalancedPredict:

+
+
+
+
+
+
+
+
+
\ No newline at end of file