summaryrefslogtreecommitdiff
path: root/src/js/layout/mxFastOrganicLayout.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/js/layout/mxFastOrganicLayout.js')
-rw-r--r--src/js/layout/mxFastOrganicLayout.js591
1 files changed, 0 insertions, 591 deletions
diff --git a/src/js/layout/mxFastOrganicLayout.js b/src/js/layout/mxFastOrganicLayout.js
deleted file mode 100644
index d7d6b5d..0000000
--- a/src/js/layout/mxFastOrganicLayout.js
+++ /dev/null
@@ -1,591 +0,0 @@
-/**
- * $Id: mxFastOrganicLayout.js,v 1.37 2011-04-28 13:14:55 david Exp $
- * Copyright (c) 2006-2010, JGraph Ltd
- */
-/**
- * Class: mxFastOrganicLayout
- *
- * Extends <mxGraphLayout> to implement a fast organic layout algorithm.
- * The vertices need to be connected for this layout to work, vertices
- * with no connections are ignored.
- *
- * Example:
- *
- * (code)
- * var layout = new mxFastOrganicLayout(graph);
- * layout.execute(graph.getDefaultParent());
- * (end)
- *
- * Constructor: mxCompactTreeLayout
- *
- * Constructs a new fast organic layout for the specified graph.
- */
-function mxFastOrganicLayout(graph)
-{
- mxGraphLayout.call(this, graph);
-};
-
-/**
- * Extends mxGraphLayout.
- */
-mxFastOrganicLayout.prototype = new mxGraphLayout();
-mxFastOrganicLayout.prototype.constructor = mxFastOrganicLayout;
-
-/**
- * Variable: useInputOrigin
- *
- * Specifies if the top left corner of the input cells should be the origin
- * of the layout result. Default is true.
- */
-mxFastOrganicLayout.prototype.useInputOrigin = true;
-
-/**
- * Variable: resetEdges
- *
- * Specifies if all edge points of traversed edges should be removed.
- * Default is true.
- */
-mxFastOrganicLayout.prototype.resetEdges = true;
-
-/**
- * Variable: disableEdgeStyle
- *
- * Specifies if the STYLE_NOEDGESTYLE flag should be set on edges that are
- * modified by the result. Default is true.
- */
-mxFastOrganicLayout.prototype.disableEdgeStyle = true;
-
-/**
- * Variable: forceConstant
- *
- * The force constant by which the attractive forces are divided and the
- * replusive forces are multiple by the square of. The value equates to the
- * average radius there is of free space around each node. Default is 50.
- */
-mxFastOrganicLayout.prototype.forceConstant = 50;
-
-/**
- * Variable: forceConstantSquared
- *
- * Cache of <forceConstant>^2 for performance.
- */
-mxFastOrganicLayout.prototype.forceConstantSquared = 0;
-
-/**
- * Variable: minDistanceLimit
- *
- * Minimal distance limit. Default is 2. Prevents of
- * dividing by zero.
- */
-mxFastOrganicLayout.prototype.minDistanceLimit = 2;
-
-/**
- * Variable: minDistanceLimit
- *
- * Minimal distance limit. Default is 2. Prevents of
- * dividing by zero.
- */
-mxFastOrganicLayout.prototype.maxDistanceLimit = 500;
-
-/**
- * Variable: minDistanceLimitSquared
- *
- * Cached version of <minDistanceLimit> squared.
- */
-mxFastOrganicLayout.prototype.minDistanceLimitSquared = 4;
-
-/**
- * Variable: initialTemp
- *
- * Start value of temperature. Default is 200.
- */
-mxFastOrganicLayout.prototype.initialTemp = 200;
-
-/**
- * Variable: temperature
- *
- * Temperature to limit displacement at later stages of layout.
- */
-mxFastOrganicLayout.prototype.temperature = 0;
-
-/**
- * Variable: maxIterations
- *
- * Total number of iterations to run the layout though.
- */
-mxFastOrganicLayout.prototype.maxIterations = 0;
-
-/**
- * Variable: iteration
- *
- * Current iteration count.
- */
-mxFastOrganicLayout.prototype.iteration = 0;
-
-/**
- * Variable: vertexArray
- *
- * An array of all vertices to be laid out.
- */
-mxFastOrganicLayout.prototype.vertexArray;
-
-/**
- * Variable: dispX
- *
- * An array of locally stored X co-ordinate displacements for the vertices.
- */
-mxFastOrganicLayout.prototype.dispX;
-
-/**
- * Variable: dispY
- *
- * An array of locally stored Y co-ordinate displacements for the vertices.
- */
-mxFastOrganicLayout.prototype.dispY;
-
-/**
- * Variable: cellLocation
- *
- * An array of locally stored co-ordinate positions for the vertices.
- */
-mxFastOrganicLayout.prototype.cellLocation;
-
-/**
- * Variable: radius
- *
- * The approximate radius of each cell, nodes only.
- */
-mxFastOrganicLayout.prototype.radius;
-
-/**
- * Variable: radiusSquared
- *
- * The approximate radius squared of each cell, nodes only.
- */
-mxFastOrganicLayout.prototype.radiusSquared;
-
-/**
- * Variable: isMoveable
- *
- * Array of booleans representing the movable states of the vertices.
- */
-mxFastOrganicLayout.prototype.isMoveable;
-
-/**
- * Variable: neighbours
- *
- * Local copy of cell neighbours.
- */
-mxFastOrganicLayout.prototype.neighbours;
-
-/**
- * Variable: indices
- *
- * Hashtable from cells to local indices.
- */
-mxFastOrganicLayout.prototype.indices;
-
-/**
- * Variable: allowedToRun
- *
- * Boolean flag that specifies if the layout is allowed to run. If this is
- * set to false, then the layout exits in the following iteration.
- */
-mxFastOrganicLayout.prototype.allowedToRun = true;
-
-/**
- * Function: isVertexIgnored
- *
- * Returns a boolean indicating if the given <mxCell> should be ignored as a
- * vertex. This returns true if the cell has no connections.
- *
- * Parameters:
- *
- * vertex - <mxCell> whose ignored state should be returned.
- */
-mxFastOrganicLayout.prototype.isVertexIgnored = function(vertex)
-{
- return mxGraphLayout.prototype.isVertexIgnored.apply(this, arguments) ||
- this.graph.getConnections(vertex).length == 0;
-};
-
-/**
- * Function: execute
- *
- * Implements <mxGraphLayout.execute>. This operates on all children of the
- * given parent where <isVertexIgnored> returns false.
- */
-mxFastOrganicLayout.prototype.execute = function(parent)
-{
- var model = this.graph.getModel();
- this.vertexArray = [];
- var cells = this.graph.getChildVertices(parent);
-
- for (var i = 0; i < cells.length; i++)
- {
- if (!this.isVertexIgnored(cells[i]))
- {
- this.vertexArray.push(cells[i]);
- }
- }
-
- var initialBounds = (this.useInputOrigin) ?
- this.graph.view.getBounds(this.vertexArray) :
- null;
- var n = this.vertexArray.length;
-
- this.indices = [];
- this.dispX = [];
- this.dispY = [];
- this.cellLocation = [];
- this.isMoveable = [];
- this.neighbours = [];
- this.radius = [];
- this.radiusSquared = [];
-
- if (this.forceConstant < 0.001)
- {
- this.forceConstant = 0.001;
- }
-
- this.forceConstantSquared = this.forceConstant * this.forceConstant;
-
- // Create a map of vertices first. This is required for the array of
- // arrays called neighbours which holds, for each vertex, a list of
- // ints which represents the neighbours cells to that vertex as
- // the indices into vertexArray
- for (var i = 0; i < this.vertexArray.length; i++)
- {
- var vertex = this.vertexArray[i];
- this.cellLocation[i] = [];
-
- // Set up the mapping from array indices to cells
- var id = mxCellPath.create(vertex);
- this.indices[id] = i;
- var bounds = this.getVertexBounds(vertex);
-
- // Set the X,Y value of the internal version of the cell to
- // the center point of the vertex for better positioning
- var width = bounds.width;
- var height = bounds.height;
-
- // Randomize (0, 0) locations
- var x = bounds.x;
- var y = bounds.y;
-
- this.cellLocation[i][0] = x + width / 2.0;
- this.cellLocation[i][1] = y + height / 2.0;
- this.radius[i] = Math.min(width, height);
- this.radiusSquared[i] = this.radius[i] * this.radius[i];
- }
-
- // Moves cell location back to top-left from center locations used in
- // algorithm, resetting the edge points is part of the transaction
- model.beginUpdate();
- try
- {
- for (var i = 0; i < n; i++)
- {
- this.dispX[i] = 0;
- this.dispY[i] = 0;
- this.isMoveable[i] = this.isVertexMovable(this.vertexArray[i]);
-
- // Get lists of neighbours to all vertices, translate the cells
- // obtained in indices into vertexArray and store as an array
- // against the orginial cell index
- var edges = this.graph.getConnections(this.vertexArray[i], parent);
- var cells = this.graph.getOpposites(edges, this.vertexArray[i]);
- this.neighbours[i] = [];
-
- for (var j = 0; j < cells.length; j++)
- {
- // Resets the points on the traversed edge
- if (this.resetEdges)
- {
- this.graph.resetEdge(edges[j]);
- }
-
- if (this.disableEdgeStyle)
- {
- this.setEdgeStyleEnabled(edges[j], false);
- }
-
- // Looks the cell up in the indices dictionary
- var id = mxCellPath.create(cells[j]);
- var index = this.indices[id];
-
- // Check the connected cell in part of the vertex list to be
- // acted on by this layout
- if (index != null)
- {
- this.neighbours[i][j] = index;
- }
-
- // Else if index of the other cell doesn't correspond to
- // any cell listed to be acted upon in this layout. Set
- // the index to the value of this vertex (a dummy self-loop)
- // so the attraction force of the edge is not calculated
- else
- {
- this.neighbours[i][j] = i;
- }
- }
- }
- this.temperature = this.initialTemp;
-
- // If max number of iterations has not been set, guess it
- if (this.maxIterations == 0)
- {
- this.maxIterations = 20 * Math.sqrt(n);
- }
-
- // Main iteration loop
- for (this.iteration = 0; this.iteration < this.maxIterations; this.iteration++)
- {
- if (!this.allowedToRun)
- {
- return;
- }
-
- // Calculate repulsive forces on all vertices
- this.calcRepulsion();
-
- // Calculate attractive forces through edges
- this.calcAttraction();
-
- this.calcPositions();
- this.reduceTemperature();
- }
-
- var minx = null;
- var miny = null;
-
- for (var i = 0; i < this.vertexArray.length; i++)
- {
- var vertex = this.vertexArray[i];
-
- if (this.isVertexMovable(vertex))
- {
- var bounds = this.getVertexBounds(vertex);
-
- if (bounds != null)
- {
- this.cellLocation[i][0] -= bounds.width / 2.0;
- this.cellLocation[i][1] -= bounds.height / 2.0;
-
- var x = this.graph.snap(this.cellLocation[i][0]);
- var y = this.graph.snap(this.cellLocation[i][1]);
-
- this.setVertexLocation(vertex, x, y);
-
- if (minx == null)
- {
- minx = x;
- }
- else
- {
- minx = Math.min(minx, x);
- }
-
- if (miny == null)
- {
- miny = y;
- }
- else
- {
- miny = Math.min(miny, y);
- }
- }
- }
- }
-
- // Modifies the cloned geometries in-place. Not needed
- // to clone the geometries again as we're in the same
- // undoable change.
- var dx = -(minx || 0) + 1;
- var dy = -(miny || 0) + 1;
-
- if (initialBounds != null)
- {
- dx += initialBounds.x;
- dy += initialBounds.y;
- }
-
- this.graph.moveCells(this.vertexArray, dx, dy);
- }
- finally
- {
- model.endUpdate();
- }
-};
-
-/**
- * Function: calcPositions
- *
- * Takes the displacements calculated for each cell and applies them to the
- * local cache of cell positions. Limits the displacement to the current
- * temperature.
- */
-mxFastOrganicLayout.prototype.calcPositions = function()
-{
- for (var index = 0; index < this.vertexArray.length; index++)
- {
- if (this.isMoveable[index])
- {
- // Get the distance of displacement for this node for this
- // iteration
- var deltaLength = Math.sqrt(this.dispX[index] * this.dispX[index] +
- this.dispY[index] * this.dispY[index]);
-
- if (deltaLength < 0.001)
- {
- deltaLength = 0.001;
- }
-
- // Scale down by the current temperature if less than the
- // displacement distance
- var newXDisp = this.dispX[index] / deltaLength
- * Math.min(deltaLength, this.temperature);
-
- var newYDisp = this.dispY[index] / deltaLength
- * Math.min(deltaLength, this.temperature);
-
- // reset displacements
- this.dispX[index] = 0;
- this.dispY[index] = 0;
-
- // Update the cached cell locations
- this.cellLocation[index][0] += newXDisp;
- this.cellLocation[index][1] += newYDisp;
- }
- }
-};
-
-/**
- * Function: calcAttraction
- *
- * Calculates the attractive forces between all laid out nodes linked by
- * edges
- */
-mxFastOrganicLayout.prototype.calcAttraction = function()
-{
- // Check the neighbours of each vertex and calculate the attractive
- // force of the edge connecting them
- for (var i = 0; i < this.vertexArray.length; i++)
- {
- for (var k = 0; k < this.neighbours[i].length; k++)
- {
- // Get the index of the othe cell in the vertex array
- var j = this.neighbours[i][k];
-
- // Do not proceed self-loops
- if (i != j &&
- this.isMoveable[i] &&
- this.isMoveable[j])
- {
- var xDelta = this.cellLocation[i][0] - this.cellLocation[j][0];
- var yDelta = this.cellLocation[i][1] - this.cellLocation[j][1];
-
- // The distance between the nodes
- var deltaLengthSquared = xDelta * xDelta + yDelta
- * yDelta - this.radiusSquared[i] - this.radiusSquared[j];
-
- if (deltaLengthSquared < this.minDistanceLimitSquared)
- {
- deltaLengthSquared = this.minDistanceLimitSquared;
- }
-
- var deltaLength = Math.sqrt(deltaLengthSquared);
- var force = (deltaLengthSquared) / this.forceConstant;
-
- var displacementX = (xDelta / deltaLength) * force;
- var displacementY = (yDelta / deltaLength) * force;
-
- this.dispX[i] -= displacementX;
- this.dispY[i] -= displacementY;
-
- this.dispX[j] += displacementX;
- this.dispY[j] += displacementY;
- }
- }
- }
-};
-
-/**
- * Function: calcRepulsion
- *
- * Calculates the repulsive forces between all laid out nodes
- */
-mxFastOrganicLayout.prototype.calcRepulsion = function()
-{
- var vertexCount = this.vertexArray.length;
-
- for (var i = 0; i < vertexCount; i++)
- {
- for (var j = i; j < vertexCount; j++)
- {
- // Exits if the layout is no longer allowed to run
- if (!this.allowedToRun)
- {
- return;
- }
-
- if (j != i &&
- this.isMoveable[i] &&
- this.isMoveable[j])
- {
- var xDelta = this.cellLocation[i][0] - this.cellLocation[j][0];
- var yDelta = this.cellLocation[i][1] - this.cellLocation[j][1];
-
- if (xDelta == 0)
- {
- xDelta = 0.01 + Math.random();
- }
-
- if (yDelta == 0)
- {
- yDelta = 0.01 + Math.random();
- }
-
- // Distance between nodes
- var deltaLength = Math.sqrt((xDelta * xDelta)
- + (yDelta * yDelta));
- var deltaLengthWithRadius = deltaLength - this.radius[i]
- - this.radius[j];
-
- if (deltaLengthWithRadius > this.maxDistanceLimit)
- {
- // Ignore vertices too far apart
- continue;
- }
-
- if (deltaLengthWithRadius < this.minDistanceLimit)
- {
- deltaLengthWithRadius = this.minDistanceLimit;
- }
-
- var force = this.forceConstantSquared / deltaLengthWithRadius;
-
- var displacementX = (xDelta / deltaLength) * force;
- var displacementY = (yDelta / deltaLength) * force;
-
- this.dispX[i] += displacementX;
- this.dispY[i] += displacementY;
-
- this.dispX[j] -= displacementX;
- this.dispY[j] -= displacementY;
- }
- }
- }
-};
-
-/**
- * Function: reduceTemperature
- *
- * Reduces the temperature of the layout from an initial setting in a linear
- * fashion to zero.
- */
-mxFastOrganicLayout.prototype.reduceTemperature = function()
-{
- this.temperature = this.initialTemp * (1.0 - this.iteration / this.maxIterations);
-};