public class mxOrganicLayout extends mxGraphLayout
In addition to the four aesthetic criteria the concept of a border line
which induces an energy cost to nodes in proximity to the graph bounds is
introduced to attempt to restrain the graph. All of the 5 factors can be
switched on or off using the isOptimize...
variables.
Simulated Annealing is a force-directed layout and is one of the more expensive, but generally effective layouts of this type. Layouts like the spring layout only really factor in edge length and inter-node distance being the lowest CPU intensive for the most aesthetic gain. The additional factors are more expensive but can have very attractive results.
The main loop of the algorithm consist of processing the nodes in a
deterministic order. During the processing of each node a circle of radius
moveRadius
is made around the node and split into
triesPerCell
equal segments. Each point between neighbour
segments is determined and the new energy of the system if the node were
moved to that position calculated. Only the necessary nodes and edges are
processed new energy values resulting in quadratic performance, O(VE),
whereas calculating the total system energy would be cubic. The default
implementation only checks 8 points around the radius of the circle, as
opposed to the suggested 30 in the paper. Doubling the number of points
double the CPU load and 8 works almost as well as 30.
The moveRadius
replaces the temperature as the influencing
factor in the way the graph settles in later iterations. If the user does
not set the initial move radius it is set to half the maximum dimension
of the graph. Thus, in 2 iterations a node may traverse the entire graph,
and it is more sensible to find minima this way that uphill moves, which
are little more than an expensive 'tilt' method. The factor by which
the radius is multiplied by after each iteration is important, lowering
it improves performance but raising it towards 1.0 can improve the
resulting graph aesthetics. When the radius hits the minimum move radius
defined, the layout terminates. The minimum move radius should be set
a value where the move distance is too minor to be of interest.
Also, the idea of a fine tuning phase is used, as described in the paper.
This involves only calculating the edge to node distance energy cost
at the end of the algorithm since it is an expensive calculation and
it really an 'optimizating' function. fineTuningRadius
defines the radius value that, when reached, causes the edge to node
distance to be calculated.
There are other special cases that are processed after each iteration.
unchangedEnergyRoundTermination
defines the number of
iterations, after which the layout terminates. If nothing is being moved
it is assumed a good layout has been found. In addition to this if
no nodes are moved during an iteration the move radius is halved, presuming
that a finer granularity is required.
Modifier and Type | Class and Description |
---|---|
class |
mxOrganicLayout.CellWrapper
Internal representation of a node or edge that holds cached information
to enable the layout to perform more quickly and to simplify the code
|
Modifier and Type | Field and Description |
---|---|
protected boolean |
approxNodeDimensions
Whether or not to use approximate node dimensions or not.
|
protected double |
averageNodeArea
The average amount of area allocated per node.
|
protected double |
borderLineCostFactor
Cost factor applied to energy calculations for node promixity to the
notional border of the graph.
|
protected double |
boundsHeight
The height coordinate of the final graph
|
protected double |
boundsWidth
The width coordinate of the final graph
|
protected double |
boundsX
The x coordinate of the final graph
|
protected double |
boundsY
The y coordinate of the final graph
|
protected boolean |
disableEdgeStyle
Specifies if the STYLE_NOEDGESTYLE flag should be set on edges that are
modified by the result.
|
protected mxOrganicLayout.CellWrapper[] |
e
Internal models collection of edges to be laid out
|
protected double |
edgeCrossingCostFactor
Cost factor applied to energy calculations involving edges that cross
over one another.
|
protected double |
edgeDistanceCostFactor
Cost factor applied to energy calculations involving the distance
nodes and edges.
|
protected double |
edgeLengthCostFactor
Cost factor applied to energy calculations for the edge lengths.
|
protected double |
fineTuningRadius
The radius below which fine tuning of the layout should start
This involves allowing the distance between nodes and edges to be
taken into account in the total energy calculation.
|
protected double |
initialMoveRadius
The initial value of
moveRadius . |
protected boolean |
isFineTuning
Whether or not fine tuning is on.
|
protected boolean |
isOptimizeBorderLine
Whether or not nodes will contribute an energy cost as they approach
the bound of the graph.
|
protected boolean |
isOptimizeEdgeCrossing
Whether or not edges crosses will be calculated as an energy cost
function.
|
protected boolean |
isOptimizeEdgeDistance
Whether or not the distance between edge and nodes will be calculated
as an energy cost function.
|
protected boolean |
isOptimizeEdgeLength
Whether or not edge lengths will be calculated as an energy cost
function.
|
protected boolean |
isOptimizeNodeDistribution
Whether or not node distribute will contribute an energy cost where
nodes are close together.
|
protected int |
iteration
current iteration number of the layout
|
protected double |
maxDistanceLimit
distance limit beyond which energy costs due to object repulsive is
not calculated as it would be too insignificant
|
protected double |
maxDistanceLimitSquared
cached version of
maxDistanceLimit squared |
protected int |
maxIterations
Limit to the number of iterations that may take place.
|
protected double |
minDistanceLimit
prevents from dividing with zero and from creating excessive energy
values
|
protected double |
minDistanceLimitSquared
cached version of
minDistanceLimit squared |
protected double |
minMoveRadius
when
moveRadius reaches this value, the algorithm is terminated |
protected double |
moveRadius
The current radius around each node where the next position energy
values will be calculated for a possible move
|
protected double |
nodeDistributionCostFactor
Cost factor applied to energy calculations involving the general node
distribution of the graph.
|
protected double |
radiusScaleFactor
The factor by which the
moveRadius is multiplied by after
every iteration. |
protected boolean |
resetEdges
Specifies if all edge points of traversed edges should be removed.
|
protected int |
triesPerCell
determines, in how many segments the circle around cells is divided, to
find a new position for the cell.
|
protected int |
unchangedEnergyRoundCount
Keeps track of how many consecutive round have passed without any energy
changes
|
protected int |
unchangedEnergyRoundTermination
The number of round of no node moves taking placed that the layout
terminates
|
protected mxOrganicLayout.CellWrapper[] |
v
Internal models collection of nodes ( vertices ) to be laid out
|
protected double[] |
xNormTry
Array of the x portion of the normalised test vectors that
are tested for a lower energy around each vertex.
|
protected double[] |
yNormTry
Array of the y portion of the normalised test vectors that
are tested for a lower energy around each vertex.
|
graph, parent, useBoundingBox
Constructor and Description |
---|
mxOrganicLayout(mxGraph graph)
Constructor for mxOrganicLayout.
|
mxOrganicLayout(mxGraph graph,
java.awt.geom.Rectangle2D bounds)
Constructor for mxOrganicLayout.
|
Modifier and Type | Method and Description |
---|---|
protected double |
calcEnergyDelta(int index,
double oldNodeDistribution,
double oldEdgeDistance,
double oldEdgeCrossing,
double oldBorderLine,
double oldEdgeLength,
double oldAdditionalFactorsEnergy)
Calculates the change in energy for the specified node.
|
void |
execute(java.lang.Object parent)
Implements
|
protected double |
getAdditionFactorsEnergy(int i)
Hook method to adding additional energy factors into the layout.
|
double |
getAverageNodeArea() |
protected double |
getBorderline(int i)
This method calculates the energy of the distance of the specified
node to the notional border of the graph.
|
double |
getBorderLineCostFactor() |
protected int[] |
getConnectedEdges(int cellIndex)
Returns all Edges that are connected with the specified cell
|
protected double |
getEdgeCrossing(int i)
This method calculates the energy of the distance from the specified
edge crossing any other edges.
|
protected double |
getEdgeCrossingAffectedEdges(int node)
Obtains the energy cost function for the specified node being moved.
|
double |
getEdgeCrossingCostFactor() |
protected double |
getEdgeDistanceAffectedNodes(int node)
Obtains the energy cost function for the specified node being moved.
|
double |
getEdgeDistanceCostFactor() |
protected double |
getEdgeDistanceFromEdge(int i)
This method calculates the energy of the distance between Cells and
Edges.
|
protected double |
getEdgeDistanceFromNode(int i)
This method calculates the energy of the distance between Cells and
Edges.
|
protected double |
getEdgeLength(int i)
This method calculates the energy due to the length of the specified
edge.
|
protected double |
getEdgeLengthAffectedEdges(int node)
Obtains the energy cost function for the specified node being moved.
|
double |
getEdgeLengthCostFactor() |
double |
getFineTuningRadius() |
double |
getInitialMoveRadius() |
double |
getMaxDistanceLimit() |
int |
getMaxIterations() |
double |
getMinDistanceLimit() |
double |
getMinMoveRadius() |
protected double |
getNodeDistribution(int i)
Calculates the energy cost of the specified node relative to all other
nodes.
|
double |
getNodeDistributionCostFactor() |
double |
getRadiusScaleFactor() |
protected int[] |
getRelevantEdges(int cellIndex)
Returns all Edges that are not connected to the specified cell
|
int |
getTriesPerCell() |
int |
getUnchangedEnergyRoundTermination() |
boolean |
isApproxNodeDimensions() |
boolean |
isDisableEdgeStyle() |
boolean |
isFineTuning() |
boolean |
isOptimizeBorderLine() |
boolean |
isOptimizeEdgeCrossing() |
boolean |
isOptimizeEdgeDistance() |
boolean |
isOptimizeEdgeLength() |
boolean |
isOptimizeNodeDistribution() |
boolean |
isResetEdges() |
boolean |
isVertexIgnored(java.lang.Object vertex)
Returns true if the given vertex has no connected edges.
|
protected void |
performRound()
The main round of the algorithm.
|
void |
setApproxNodeDimensions(boolean approxNodeDimensions) |
void |
setAverageNodeArea(double averageNodeArea) |
void |
setBorderLineCostFactor(double borderLineCostFactor) |
void |
setDisableEdgeStyle(boolean disableEdgeStyle) |
void |
setEdgeCrossingCostFactor(double edgeCrossingCostFactor) |
void |
setEdgeDistanceCostFactor(double edgeDistanceCostFactor) |
void |
setEdgeLengthCostFactor(double edgeLengthCostFactor) |
void |
setFineTuning(boolean isFineTuning) |
void |
setFineTuningRadius(double fineTuningRadius) |
void |
setInitialMoveRadius(double initialMoveRadius) |
void |
setMaxDistanceLimit(double maxDistanceLimit) |
void |
setMaxIterations(int maxIterations) |
void |
setMinDistanceLimit(double minDistanceLimit) |
void |
setMinMoveRadius(double minMoveRadius) |
void |
setNodeDistributionCostFactor(double nodeDistributionCostFactor) |
void |
setOptimizeBorderLine(boolean isOptimizeBorderLine) |
void |
setOptimizeEdgeCrossing(boolean isOptimizeEdgeCrossing) |
void |
setOptimizeEdgeDistance(boolean isOptimizeEdgeDistance) |
void |
setOptimizeEdgeLength(boolean isOptimizeEdgeLength) |
void |
setOptimizeNodeDistribution(boolean isOptimizeNodeDistribution) |
void |
setRadiusScaleFactor(double radiusScaleFactor) |
void |
setResetEdges(boolean resetEdges) |
void |
setTriesPerCell(int triesPerCell) |
void |
setUnchangedEnergyRoundTermination(int unchangedEnergyRoundTermination) |
java.lang.String |
toString()
Returns
Organic , the name of this algorithm. |
arrangeGroups, getConstraint, getConstraint, getGraph, getParentOffset, getVertexBounds, isEdgeIgnored, isUseBoundingBox, isVertexMovable, moveCell, setEdgePoints, setEdgeStyleEnabled, setOrthogonalEdge, setUseBoundingBox, setVertexLocation
protected boolean isOptimizeEdgeDistance
protected boolean isOptimizeEdgeCrossing
protected boolean isOptimizeEdgeLength
protected boolean isOptimizeBorderLine
protected boolean isOptimizeNodeDistribution
protected double minMoveRadius
moveRadius
reaches this value, the algorithm is terminatedprotected double moveRadius
protected double initialMoveRadius
moveRadius
. If this is set to zero
the layout will automatically determine a suitable value.protected double radiusScaleFactor
moveRadius
is multiplied by after
every iteration. A value of 0.75 is a good balance between performance
and aesthetics. Increasing the value provides more chances to find
minimum energy positions and decreasing it causes the minimum radius
termination condition to occur more quickly.protected double averageNodeArea
bounds
is not set this value mutiplied by the number of nodes to find
the total graph area. The graph is assumed square.protected double fineTuningRadius
protected int maxIterations
protected double edgeDistanceCostFactor
isOptimizeEdgeDistance
must be true for edge to nodes
distances to be taken into account.protected double edgeCrossingCostFactor
isOptimizeEdgeCrossing
must be true for edge crossings
to be taken into account.protected double nodeDistributionCostFactor
isOptimizeNodeDistribution
must be true for this general
distribution to be applied.protected double borderLineCostFactor
isOptimizeBorderLine
must be true for border
repulsion to be applied.protected double edgeLengthCostFactor
isOptimizeEdgeLength
must be true for edge length
shortening to be applied.protected double boundsX
protected double boundsY
protected double boundsWidth
protected double boundsHeight
protected int iteration
protected int triesPerCell
performRound
method might further improve accuracy for a
small performance hit. The change is described in the method comment.protected double minDistanceLimit
protected double minDistanceLimitSquared
minDistanceLimit
squaredprotected double maxDistanceLimit
protected double maxDistanceLimitSquared
maxDistanceLimit
squaredprotected int unchangedEnergyRoundCount
protected int unchangedEnergyRoundTermination
protected boolean approxNodeDimensions
protected mxOrganicLayout.CellWrapper[] v
protected mxOrganicLayout.CellWrapper[] e
protected double[] xNormTry
protected double[] yNormTry
protected boolean isFineTuning
isFineTuning
is switched to
true
if and when the fineTuningRadius
radius is reached. Switching this variable to true
before the algorithm runs mean the node to edge cost function
is always calculated.protected boolean disableEdgeStyle
protected boolean resetEdges
public mxOrganicLayout(mxGraph graph)
public mxOrganicLayout(mxGraph graph, java.awt.geom.Rectangle2D bounds)
public boolean isVertexIgnored(java.lang.Object vertex)
isVertexIgnored
in class mxGraphLayout
vertex
- Object that represents the vertex to be tested.public void execute(java.lang.Object parent)
execute
in interface mxIGraphLayout
execute
in class mxGraphLayout
parent
- Parent cell that contains the children to be layed out.protected void performRound()
moveRadius
are
selected and the total energy of the system calculated if that node
were moved to that new position. If a lower energy position is found
this is accepted and the algorithm moves onto the next node. There
may be a slightly lower energy value yet to be found, but forcing
the loop to check all possible positions adds nearly the current
processing time again, and for little benefit. Another possible
strategy would be to take account of the fact that the energy values
around the circle decrease for half the loop and increase for the
other, as a general rule. If part of the decrease were seen, then
when the energy of a node increased, the previous node position was
almost always the lowest energy position. This adds about two loop
iterations to the inner loop and only makes sense with 16 tries or more.protected double calcEnergyDelta(int index, double oldNodeDistribution, double oldEdgeDistance, double oldEdgeCrossing, double oldBorderLine, double oldEdgeLength, double oldAdditionalFactorsEnergy)
index
- The index of the node in the vertices
arrayoldNodeDistribution
- The previous node distribution energy cost of this nodeoldEdgeDistance
- The previous edge distance energy cost of this nodeoldEdgeCrossing
- The previous edge crossing energy cost for edges connected to
this nodeoldBorderLine
- The previous border line energy cost for this nodeoldEdgeLength
- The previous edge length energy cost for edges connected to
this nodeoldAdditionalFactorsEnergy
- The previous energy cost for additional factors from
sub-classesprotected double getNodeDistribution(int i)
i
- the index of the node in the array v
protected double getBorderline(int i)
i
- the index of the node in the array v
protected double getEdgeLengthAffectedEdges(int node)
getEdgeLength
for all
edges connected to the specified nodenode
- the node whose connected edges cost functions are to be
calculatedprotected double getEdgeLength(int i)
i
- the index of the edge in the array e
protected double getEdgeCrossingAffectedEdges(int node)
getEdgeCrossing
for all
edges connected to the specified nodenode
- the node whose connected edges cost functions are to be
calculatedprotected double getEdgeCrossing(int i)
i
- the index of the edge in the array e
protected double getEdgeDistanceFromNode(int i)
i
- the index of the node in the array v
protected double getEdgeDistanceAffectedNodes(int node)
getEdgeDistanceFromEdge
for all
edges connected to the specified nodenode
- the node whose connected edges cost functions are to be
calculatedprotected double getEdgeDistanceFromEdge(int i)
i
- the index of the edge in the array e
protected double getAdditionFactorsEnergy(int i)
i
- the nodes whose energy is being calculatedprotected int[] getRelevantEdges(int cellIndex)
cellIndex
- the cell index to which the edges are not connectedprotected int[] getConnectedEdges(int cellIndex)
cellIndex
- the cell index to which the edges are connectedpublic java.lang.String toString()
Organic
, the name of this algorithm.toString
in class java.lang.Object
public double getAverageNodeArea()
public void setAverageNodeArea(double averageNodeArea)
averageNodeArea
- The averageNodeArea to set.public double getBorderLineCostFactor()
public void setBorderLineCostFactor(double borderLineCostFactor)
borderLineCostFactor
- The borderLineCostFactor to set.public double getEdgeCrossingCostFactor()
public void setEdgeCrossingCostFactor(double edgeCrossingCostFactor)
edgeCrossingCostFactor
- The edgeCrossingCostFactor to set.public double getEdgeDistanceCostFactor()
public void setEdgeDistanceCostFactor(double edgeDistanceCostFactor)
edgeDistanceCostFactor
- The edgeDistanceCostFactor to set.public double getEdgeLengthCostFactor()
public void setEdgeLengthCostFactor(double edgeLengthCostFactor)
edgeLengthCostFactor
- The edgeLengthCostFactor to set.public double getFineTuningRadius()
public void setFineTuningRadius(double fineTuningRadius)
fineTuningRadius
- The fineTuningRadius to set.public double getInitialMoveRadius()
public void setInitialMoveRadius(double initialMoveRadius)
initialMoveRadius
- The initialMoveRadius to set.public boolean isFineTuning()
public void setFineTuning(boolean isFineTuning)
isFineTuning
- The isFineTuning to set.public boolean isOptimizeBorderLine()
public void setOptimizeBorderLine(boolean isOptimizeBorderLine)
isOptimizeBorderLine
- The isOptimizeBorderLine to set.public boolean isOptimizeEdgeCrossing()
public void setOptimizeEdgeCrossing(boolean isOptimizeEdgeCrossing)
isOptimizeEdgeCrossing
- The isOptimizeEdgeCrossing to set.public boolean isOptimizeEdgeDistance()
public void setOptimizeEdgeDistance(boolean isOptimizeEdgeDistance)
isOptimizeEdgeDistance
- The isOptimizeEdgeDistance to set.public boolean isOptimizeEdgeLength()
public void setOptimizeEdgeLength(boolean isOptimizeEdgeLength)
isOptimizeEdgeLength
- The isOptimizeEdgeLength to set.public boolean isOptimizeNodeDistribution()
public void setOptimizeNodeDistribution(boolean isOptimizeNodeDistribution)
isOptimizeNodeDistribution
- The isOptimizeNodeDistribution to set.public int getMaxIterations()
public void setMaxIterations(int maxIterations)
maxIterations
- The maxIterations to set.public double getMinDistanceLimit()
public void setMinDistanceLimit(double minDistanceLimit)
minDistanceLimit
- The minDistanceLimit to set.public double getMinMoveRadius()
public void setMinMoveRadius(double minMoveRadius)
minMoveRadius
- The minMoveRadius to set.public double getNodeDistributionCostFactor()
public void setNodeDistributionCostFactor(double nodeDistributionCostFactor)
nodeDistributionCostFactor
- The nodeDistributionCostFactor to set.public double getRadiusScaleFactor()
public void setRadiusScaleFactor(double radiusScaleFactor)
radiusScaleFactor
- The radiusScaleFactor to set.public int getTriesPerCell()
public void setTriesPerCell(int triesPerCell)
triesPerCell
- The triesPerCell to set.public int getUnchangedEnergyRoundTermination()
public void setUnchangedEnergyRoundTermination(int unchangedEnergyRoundTermination)
unchangedEnergyRoundTermination
- The unchangedEnergyRoundTermination to set.public double getMaxDistanceLimit()
public void setMaxDistanceLimit(double maxDistanceLimit)
maxDistanceLimit
- The maxDistanceLimit to set.public boolean isApproxNodeDimensions()
public void setApproxNodeDimensions(boolean approxNodeDimensions)
approxNodeDimensions
- the approxNodeDimensions to setpublic boolean isDisableEdgeStyle()
public void setDisableEdgeStyle(boolean disableEdgeStyle)
disableEdgeStyle
- the disableEdgeStyle to setpublic boolean isResetEdges()
public void setResetEdges(boolean resetEdges)
resetEdges
- the resetEdges to setCopyright (c) 2010-2017 Gaudenz Alder, JGraph Ltd. All rights reserved.