Browse Source

Added releaseFunction to openCluster.

flowchartTest
Alex de Mulder 9 years ago
parent
commit
e96d228ab8
9 changed files with 5290 additions and 5198 deletions
  1. +1
    -0
      HISTORY.md
  2. +5186
    -5149
      dist/vis.js
  3. +15
    -2
      docs/network/index.html
  4. +1
    -1
      examples/network/other/clustering.html
  5. +37
    -5
      lib/network/modules/Clustering.js
  6. +1
    -1
      lib/network/modules/components/Node.js
  7. +2
    -1
      lib/network/modules/components/edges/BezierEdgeDynamic.js
  8. +8
    -4
      lib/network/modules/components/physics/BarnesHutSolver.js
  9. +39
    -35
      test/networkTest.html

+ 1
- 0
HISTORY.md View File

@ -20,6 +20,7 @@ http://visjs.org
- Fixed #904, correctly parsing global font options now.
- Fixed dataView support for storePositions.
- Second click on node is no longer unselect.
- Added releaseFunction to openCluster.
## 2015-05-28, version 4.1.0

+ 5186
- 5149
dist/vis.js
File diff suppressed because it is too large
View File


+ 15
- 2
docs/network/index.html View File

@ -630,12 +630,25 @@ var locales = {
</tr>
<tr class="collapsible toggle" onclick="toggleTable('methodTable','openCluster', this);">
<td colspan="2"><span parent="openCluster" class="right-caret"></span> openCluster(
<code>String nodeId</code>)
<code>String nodeId, Object options</code>)
</tr>
<tr class="hidden" parent="openCluster">
<td class="midMethods">Returns: none</td>
<td>Opens the cluster, releases the contained nodes and edges, removing the cluster node and cluster
edges.
edges. The options object is optional and currently supports one option, releaseFunction, which is a function that can be used to manually
position the nodes after the cluster is opened. <br>
<pre class="code">
function releaseFunction (clusterPosition, containedNodesPositions) {
var newPositions = {};
// clusterPosition = {x:clusterX, y:clusterY};
// containedNodesPositions = {nodeId:{x:nodeX,y:nodeY}, nodeId2....}
newPositions[nodeId] = {x:newPosX, y:newPosY};
return newPositions;
}</pre>
This function is expected to return the newPositions, which can be the containedNodesPositions (altered) or a new object. This has to be an object with keys equal
to the nodeIds that exist in the containedNodesPositions and an <code>{x:x,y:y}</code> position object. <br><br>
For all nodeIds not listed in this returned object, we will position them at the location of the cluster. This is also the default behaviour when no releaseFunction is defined.
</td>
</tr>

+ 1
- 1
examples/network/other/clustering.html View File

@ -77,7 +77,7 @@ Click any of the buttons below to cluster the network. On every push the network
network.on("selectNode", function(params) {
if (params.nodes.length == 1) {
if (network.isCluster(params.nodes[0]) == true) {
network.openCluster(params.nodes[0])
network.openCluster(params.nodes[0]);
}
}
})

+ 37
- 5
lib/network/modules/Clustering.js View File

@ -304,6 +304,7 @@ class ClusterEngine {
* @private
*/
_cluster(childNodesObj, childEdgesObj, options, refreshData = true) {
console.log(childNodesObj)
// kill condition: no children so cant cluster
if (Object.keys(childNodesObj).length === 0) {return;}
@ -454,7 +455,7 @@ class ClusterEngine {
* @param {String} clusterNodeId | the ID of the cluster node
* @param {Boolean} refreshData | wrap up afterwards if not true
*/
openCluster(clusterNodeId, refreshData = true) {
openCluster(clusterNodeId, options, refreshData = true) {
// kill conditions
if (clusterNodeId === undefined) {throw new Error("No clusterNodeId supplied to openCluster.");}
if (this.body.nodes[clusterNodeId] === undefined) {throw new Error("The clusterNodeId supplied to openCluster does not exist.");}
@ -466,14 +467,45 @@ class ClusterEngine {
let containedNodes = clusterNode.containedNodes;
let containedEdges = clusterNode.containedEdges;
// allow the user to position the nodes after release.
if (options.releaseFunction !== undefined) {
let positions = {};
let clusterPosition = {x:clusterNode.x, y:clusterNode.y};
for (let nodeId in containedNodes) {
if (containedNodes.hasOwnProperty(nodeId)) {
let containedNode = this.body.nodes[nodeId];
positions[nodeId] = {x: containedNode.x, y: containedNode.y};
}
}
let newPositions = options.releaseFunction(clusterPosition, positions);
for (let nodeId in containedNodes) {
if (containedNodes.hasOwnProperty(nodeId)) {
let containedNode = this.body.nodes[nodeId];
if (newPositions[nodeId] !== undefined) {
containedNode.x = newPositions[nodeId].x || clusterNode.x;
containedNode.y = newPositions[nodeId].y || clusterNode.y;
}
}
}
}
else {
// copy the position from the cluster
for (let nodeId in containedNodes) {
if (containedNodes.hasOwnProperty(nodeId)) {
let containedNode = this.body.nodes[nodeId];
containedNode = containedNodes[nodeId];
// inherit position
containedNode.x = clusterNode.x;
containedNode.y = clusterNode.y;
}
}
}
// release nodes
for (let nodeId in containedNodes) {
if (containedNodes.hasOwnProperty(nodeId)) {
let containedNode = this.body.nodes[nodeId];
containedNode = containedNodes[nodeId];
// inherit position
containedNode.x = clusterNode.x;
containedNode.y = clusterNode.y;
// inherit speed
containedNode.vx = clusterNode.vx;

+ 1
- 1
lib/network/modules/components/Node.js View File

@ -123,7 +123,7 @@ class Node {
if (options.x !== undefined) {this.x = parseInt(options.x); this.predefinedPosition = true;}
if (options.y !== undefined) {this.y = parseInt(options.y); this.predefinedPosition = true;}
if (options.size !== undefined) {this.baseSize = options.size;}
if (options.value !== undefined) {options.value = parseInt(options.value);}
if (options.value !== undefined) {options.value = parseFloat(options.value);}
// copy group options

+ 2
- 1
lib/network/modules/components/edges/BezierEdgeDynamic.js View File

@ -40,7 +40,8 @@ class BezierEdgeDynamic extends BezierEdgeBase {
}
togglePhysics(status) {
this.via.setOptions({physics:status})
this.via.setOptions({physics:status});
this.positionBezierNode();
}
/**

+ 8
- 4
lib/network/modules/components/physics/BarnesHutSolver.js View File

@ -5,6 +5,7 @@ class BarnesHutSolver {
this.physicsBody = physicsBody;
this.barnesHutTree;
this.setOptions(options);
this.randomSeed = 5;
}
setOptions(options) {
@ -13,6 +14,11 @@ class BarnesHutSolver {
this.overlapAvoidanceFactor = 1 - Math.max(0, Math.min(1,this.options.avoidOverlap)); // if 1 then min distance = 0.5, if 0.5 then min distance = 0.5 + 0.5*node.shape.radius
}
seededRandom() {
var x = Math.sin(this.randomSeed++) * 10000;
return x - Math.floor(x);
}
/**
* This function calculates the forces the nodes apply on eachother based on a gravitational model.
@ -282,10 +288,8 @@ class BarnesHutSolver {
// we move one node a pixel and we do not put it in the tree.
if (parentBranch.children[region].children.data.x === node.x &&
parentBranch.children[region].children.data.y === node.y) {
//node.x += Math.random();
//node.y += Math.random();
node.x += 0.1;
node.y += 0.1;
node.x += this.seededRandom();
node.y += this.seededRandom();
}
else {
this._splitBranch(parentBranch.children[region]);

+ 39
- 35
test/networkTest.html
File diff suppressed because it is too large
View File


Loading…
Cancel
Save