|
Search this API | ||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object y.layout.organic.InteractiveOrganicLayouter
public class InteractiveOrganicLayouter
This algorithm arranges graphs in an organic fashion and offers special functionality to interact with the graph while the algorithm is running.
Besides the organic graph arrangement, this algorithm enables to immediately visualize changes made to a graph. Changes can be committed and the layout will be locally updated. That way, live interactions with an adapting graph layout are possible. Another advantage is that it is not necessary to compute a completely new layout if only small changes were made.
This algorithm supports the organic layout style which is characterized by a natural distribution of nodes. It is well suited to exhibit clusters and symmetric properties of a graph. Nodes are placed in a space-saving manner and distances between neighbors are highly uniform. Edges maintain uniform lengths too and are routed with straight-line segments without bends.
Organic diagrams are well suited for visualizing relations in large networks, for example, in bioinformatics, enterprise networking, social networks visualization, mesh visualization or system management.
Organic layout obtained using this algorithm
The internal basis for computing actual layouts is a force-directed approach placing the nodes of the input graph. The graph is modeled as a physical system with appropriate forces acting on it. Nodes are considered as electrically charged particles with mutually repulsive forces. Edges are modeled as forces that attract adjacent nodes. A good diagram is obtained from an equilibrium state of the system, i.e., the nodes are rearranged based on the physical forces until the system reaches a (local) minimum of the sum of the forces.
InteractiveOrganicLayouter
is designed to run in a thread on its own. This allows for
creating interactive user interfaces where the layout algorithm runs while users interact
with the graph. The algorithm can then react to changes by immediately adapting the layout.
However, the algorithm can also be executed in a single-threaded mode using
startLayoutSingleThreaded(LayoutGraph)
. A Context
instance provides the necessary methods to control the layout calculation.
Several update methods allow to indicate lightweight changes on the graph, for example,
setCenter(Node, double, double)
for node location updates.
These updates will be scheduled and executed at a specific point within the life-cycle of the layout algorithm.
They are ideally suited for usage in interactive scenarios, where users, for example, change node positions
via mouse-dragging.
If a CopiedLayoutGraph
is being laid out, structural changes (e.g. creation or removal of nodes and edges)
in the original graph can be automatically scheduled and applied to the CopiedLayoutGraph
instance.
Enable automatic structure updates
for this feature.
Method addStructureUpdate(Runnable)
allows to schedule a custom Runnable
instance that
is executed in a synchronized context and can safely update the structure of the graph.
It is easiest to start the algorithm in its own thread using startLayout(LayoutGraph)
.
Furthermore, it is strongly recommended to start it by passing a copy of the original graph
(i.e. a CopiedLayoutGraph
instance) as parameter to the mentioned method.
Importantly, changes will not be automatically applied to the input graph. Updates can be scheduled
via various methods (e.g. setCenter(Node, double, double)
). The whole layout will then internally
be adjusted accordingly and changes are stored as intermediate results. Such intermediate results can be
committed
in order to apply them to the actual graph.
SmartOrganicLayouter
instead of this class.Nested Class Summary | |
---|---|
static interface |
InteractiveOrganicLayouter.SingleThreadContext
A InteractiveOrganicLayouter.SingleThreadContext provides control over the layout calculation in the case of
single-threaded algorithm execution. |
Field Summary |
---|
Fields inherited from interface y.layout.Layouter |
---|
EDGE_ID_DPKEY, NODE_ID_DPKEY, NODE_TYPE_DPKEY, SELECTED_EDGES, SELECTED_NODES |
Constructor Summary | |
---|---|
InteractiveOrganicLayouter()
Creates a new instance of the InteractiveOrganicLayouter with default settings. |
Method Summary | |
---|---|
void |
addStructureUpdate(java.lang.Runnable runnable)
Schedules an update for the structure of the graph, which will automatically be executed at a later point in the life-cycle of this algorithm. |
boolean |
canLayout(LayoutGraph graph)
Accepts all general non-empty graphs. |
void |
commitPositions()
Writes calculated intermediate locations of nodes and edges to the actual graph. |
double |
commitPositionsSmoothly(double maxMovement,
double factor)
Writes calculated intermediate locations of nodes and edges to the actual graph and returns the largest movement value. |
void |
doLayout(LayoutGraph graph)
Calculates an organic layout for the given input graph, however, the layout is not automatically applied to the graph. |
void |
enableOnlyCore()
Disables all predefined LayoutStage s so that upon doLayout(y.layout.LayoutGraph) only the internal
organic layout algorithm will be executed. |
YPoint |
getCenter(Node node)
Polls the current coordinates of the center of the given node. |
double |
getCenterX(Node node)
Polls the current x-coordinate of the center location of the given node. |
double |
getCenterY(Node node)
Polls the current y-coordinate of the center location of the given node. |
double |
getCompactness()
Returns the compactness factor for the layout algorithm. |
long |
getLastWakeupTime()
Returns the time when the last wake-up, that is, call to wakeUp() , occurred. |
long |
getMaxTime()
Specifies the maximum duration in milliseconds that this algorithm is allowed to run. |
OutputRestriction |
getOutputRestriction()
Returns an OutputRestriction which restricts the area for the layout result of this algorithm. |
double |
getPreferredEdgeLength()
Returns the default preferred edge length. |
double |
getPreferredNodeDistance()
Returns the preferred distance between nodes. |
double |
getQuality()
Returns the ratio of layout quality versus running time. |
double |
getStress(Node node)
Polls the current stress value of a given node. |
double |
getWorkingRatio()
Returns the working ratio which defines the amount of processor time this algorithm tries to get. |
boolean |
isAutomaticStructureUpdateEnabled()
Returns whether or not this algorithm performs automatic structure updates on the graph copy if the original graph changes. |
boolean |
isRunning()
Determines whether or not this layout algorithm is currently running. |
boolean |
isSleeping()
Determines whether or not this layout algorithm is currently sleeping. |
boolean |
isStopped()
Determines whether or not this layout algorithm has stopped. |
void |
setAutomaticStructureUpdateEnabled(boolean automaticStructureUpdateEnabled)
Specifies whether or not this algorithm performs automatic structure updates on the graph copy if the original graph changes. |
void |
setCenter(Node node,
double x,
double y)
Schedules an update for the center location of the given node. |
void |
setCenterX(Node node,
double x)
Schedules an update for the center location's x-coordinate of the given node. |
void |
setCenterY(Node node,
double y)
Schedules an update for the center location's y-coordinate of the given node. |
void |
setCompactness(double compactness)
Specifies the compactness factor for the layout algorithm. |
void |
setInertia(Node node,
double inertia)
Schedules an update for the inertia of the given node. |
void |
setMaxTime(long maxTime)
Specifies the maximum duration in milliseconds that this algorithm is allowed to run. |
void |
setOutputRestriction(OutputRestriction restriction)
Specifies an OutputRestriction which restricts the area for the layout result of this algorithm. |
void |
setPreferredEdgeLength(double preferredEdgeLength)
Specifies the default preferred edge length. |
void |
setPreferredEdgeLength(Edge edge,
double newEdgeLength)
Schedules an update for the preferred length of the given edge. |
void |
setPreferredNodeDistance(double preferredNodeDistance)
Specifies the preferred distance between nodes. |
void |
setQuality(double quality)
Specifies the ratio of layout quality versus running time. |
void |
setRadius(Node node,
double radius)
Schedules an update for the radius of the given node. |
void |
setStress(Node node,
double stress)
Schedules an update for the stress value of the given node. |
void |
setWorkingRatio(double workingRatio)
Specifies the working ratio which defines the amount of processor time this algorithm tries to get. |
java.lang.Thread |
startLayout(LayoutGraph graph)
Starts the layout process calculating an organic layout for the input
graph in a new, separate Thread . |
InteractiveOrganicLayouter.SingleThreadContext |
startLayoutSingleThreaded(LayoutGraph graph)
Creates a context object that provides methods to
continue and
stop the layout calculation
for running this layout algorithm in a single-threaded environment. |
void |
stop()
Stops the layout algorithm. |
void |
stopAndWait()
Stops a previously started algorithm and then blocks
until the current layout calculation is completed. |
void |
syncStructure()
Synchronizes the structure of the graph copy with the original graph. |
void |
wakeUp()
Wakes up the algorithm with the effect that it will restart/continue the layout calculation. |
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Constructor Detail |
---|
public InteractiveOrganicLayouter()
InteractiveOrganicLayouter
with default settings.
Method Detail |
---|
public void enableOnlyCore()
LayoutStage
s so that upon doLayout(y.layout.LayoutGraph)
only the internal
organic layout algorithm will be executed.
This method is called upon construction of this class so that by default additional
LayoutStage
s are deactivated. This method may be overridden if the additional
stages should stay active (e.g. override the method and return silently).
CanonicMultiStageLayouter
to compute
the organic layout and this method delegates to CanonicMultiStageLayouter.enableOnlyCore()
.CanonicMultiStageLayouter.enableOnlyCore()
public boolean isAutomaticStructureUpdateEnabled()
If this feature is enabled, a listener will be registered with the original input graph. This listener will automatically transfer structural changes on the original graph to the graph copy and update its internal data structures.
true
if automatic structure updates on the graph copy are enabled,
false
otherwisesetAutomaticStructureUpdateEnabled(boolean)
public void setAutomaticStructureUpdateEnabled(boolean automaticStructureUpdateEnabled)
If this feature is enabled, a listener will be registered with the original input graph. This listener will automatically transfer structural changes on the original graph to the graph copy and update its internal data structures.
automaticStructureUpdateEnabled
- true
if automatic structure updates on the graph copy should
be enabled, false
otherwisepublic double getCompactness()
Smaller values result in less compact drawings, greater values result in more compact drawings.
The compactness value needs to lie in [0,1]
.
0.4
may lead
to components drifting away from each other.[0,1]
setCompactness(double)
public void setCompactness(double compactness)
Smaller values result in less compact drawings, greater values result in more compact drawings.
The compactness value needs to lie in [0,1]
.
0.4
may lead
to components drifting away from each other.compactness
- the compactness value in [0,1]
java.lang.IllegalArgumentException
- if the specified value is outside the interval [0,1]
Compactness is set to 0 | Compactness is set to 1 |
public boolean canLayout(LayoutGraph graph)
canLayout
in interface Layouter
graph
- the input graph
true
if the given graph contains at least one node, false
otherwiseLayouter.doLayout(LayoutGraph)
public void doLayout(LayoutGraph graph)
Changes have to be committed
to update the graph with the actual calculated positions.
InteractiveOrganicLayouter
on a CopiedLayoutGraph
:
InteractiveOrganicLayouter layouter = new InteractiveOrganicLayouter(); Graph2D originalGraph = new Graph2D(); CopiedLayoutGraph copy = new CopiedLayoutGraph( originalGraph ); layouter.setAutomaticStructureUpdateEnabled( true ); layouter.doLayout( copy );
doLayout
in interface Layouter
CopiedLayoutGraph
is given as input, the setters and getters with a
Node
or Edge
as parameter may be used with instances from both, the original graph
or the copied graph.CopiedLayoutGraph
to buffer the original graph.
Then, automatic structure updates
can be enabled
to enforce that changes to the original graph are automatically applied to the copied graph.graph
- the input graphstartLayout(LayoutGraph)
,
startLayoutSingleThreaded(LayoutGraph)
public java.lang.Thread startLayout(LayoutGraph graph)
layout process
calculating an organic layout for the input
graph in a new, separate Thread
.
daemon thread
.graph
- the input graph
Thread
instance that has been created and started and in which the layout algorithm is runningdoLayout(LayoutGraph)
,
startLayoutSingleThreaded(LayoutGraph)
public InteractiveOrganicLayouter.SingleThreadContext startLayoutSingleThreaded(LayoutGraph graph)
context object
that provides methods to
continue
and
stop
the layout calculation
for running this layout algorithm in a single-threaded environment.
Usage:
Call doLayout(long)
on the created instance
to run the actual layout calculation for some specified period of time, whenever the layout should
be recalculated. To actually transfer the changes, commitPositions()
should be called subsequently.
InteractiveOrganicLayouter.SingleThreadContext.doLayout(long)
needs to be made to do so.graph
- the input graph
context instance
to control layout calculationInteractiveOrganicLayouter.SingleThreadContext
,
doLayout(LayoutGraph)
,
startLayout(LayoutGraph)
public void commitPositions()
Update methods like setCenter(Node, double, double)
schedule changes which cause
that the whole layout will internally be adjusted. All adjustments are stored as intermediate results.
This method immediately transfers all these intermediate results to the actual input graph.
is running
.commitPositionsSmoothly(double, double)
public double commitPositionsSmoothly(double maxMovement, double factor)
Update methods like setCenter(Node, double, double)
schedule changes which cause
that the whole layout will internally be adjusted. All adjustments are stored as intermediate results.
This method smoothly transfers all these intermediate results to the actual input graph.
Positions are, however, not transferred directly (use commitPositions()
if that is intended).
Instead, the nodes are moved towards the calculated position. The movement is restricted
to the given maximum distance.
The movement will be calculated as (movement) = (factor) * (distance between calculated and actual location)
The returned largest movement can be used for estimating the difference between calculated layout
and actual positions. If the return value is 0
, the calculated layout was completely transferred.
25
times a second, suitable parameter values
are 50
for the maximum movement and 0.15
for the factor.is running
.maxMovement
- the maximum distance a node will be movedfactor
- a factor that determines the node movement
0
, if the calculated layout has been transferred completelycommitPositions()
public void wakeUp()
This method is useful if the layouter is sleeping
but should be notified
of changes (e.g. due to user interaction).
setCenter(Node, double, double)
or setStress(Node, double)
.stopped
), it can not be awakened again.isSleeping()
public long getLastWakeupTime()
wakeUp()
, occurred.
The time is defined in terms of the difference between the current time and midnight, January 1, 1970 UTC, measured in milliseconds.
wakeUp()
occurredpublic void addStructureUpdate(java.lang.Runnable runnable)
The given Runnable
will be queued and executed at a specific time. The Runnable
can make
structural changes (e.g. removal/creation of edges or nodes). They will be synchronized with the rest
of the layout algorithm.
setCenter(Node, double, double)
.runnable
- a Runnable
making structural changes on the graphpublic void stop()
In contrast to stopAndWait()
, the algorithm terminates immediately and will not
wait until the ongoing layout calculation is finished.
wakeUp()
.isStopped()
,
stopAndWait()
public boolean isStopped()
If the algorithm has stopped, it terminated all its layout calculations. It is not running
anymore and can not be restarted/continued by calling wakeUp()
.
true
if the layout algorithm has stopped,
false
otherwisepublic boolean isSleeping()
Sleeping indicates that the algorithm has not stopped
yet but is waiting (i.e. doing
nothing). It can be notified to continue its work using wakeUp()
.
maximum runtime
was exceeded.true
if this algorithm is currently sleeping,
false
otherwisewakeUp()
public boolean isRunning()
The algorithm is running if the layout process is still active, the algorithm has not
stopped
yet and is not sleeping
.
true
if this algorithm is currently running,
false
otherwisepublic double getWorkingRatio()
A working ratio value of 1
means that the algorithm will try to run as fast as possible.
Lower values will lead to small breaks after each internal round.
The ratio needs to be a value in (0,1]
.
setWorkingRatio(double)
public void setWorkingRatio(double workingRatio)
A working ratio value of 1
means that the algorithm will try to run as fast as possible.
Lower values will lead to small breaks after each internal round.
The ratio needs to be a value in (0,1]
.
workingRatio
- the working ratio value
java.lang.IllegalArgumentException
- if the given ratio is not in (0,1]
.public void setPreferredEdgeLength(double preferredEdgeLength)
This length does not define the actual absolute length of edges, but the layout algorithm considers the specified preference where possible.
The preferred edge length needs to be non-negative.
setPreferredEdgeLength(Edge, double)
instead to schedule updates.preferredEdgeLength
- the preferred edge length
java.lang.IllegalArgumentException
- if the specified edge length is negativesetPreferredEdgeLength(Edge, double)
Preferred edge length 40 | Preferred edge length 100 |
public double getPreferredEdgeLength()
This length does not define the actual absolute length of edges, but the layout algorithm considers the specified preference where possible.
The preferred edge length needs to be non-negative.
setPreferredEdgeLength(Edge, double)
instead to schedule updates.setPreferredEdgeLength(double)
public void setPreferredNodeDistance(double preferredNodeDistance)
The minimum node distance needs to be non-negative.
preferredNodeDistance
- the non-negative preferred distance between nodes
java.lang.IllegalArgumentException
- if the specified minimum node distance is negativePreferred node distance 40 | Preferred node distance 100 |
public double getPreferredNodeDistance()
The minimum node distance needs to be non-negative.
setPreferredNodeDistance(double)
public void setPreferredEdgeLength(Edge edge, double newEdgeLength)
This method can be used while layout calculation is in progress (e.g. for interactive layout scenarios).
However, the change will not directly be applied to the graph itself but only stored internally
as an intermediate result. Scheduled updates can be committed to the graph while the algorithm is running using
methods commitPositions()
or commitPositionsSmoothly(double, double)
.
woken up
after
scheduling this update.edge
- the edge whose preferred length should be updatednewEdgeLength
- the new preferred edge lengthpublic void setInertia(Node node, double inertia)
The inertia is defined to be a value from the interval [0,1]
.
1.0
: The node will not move.
0.5
: The node will only move half as far as it would with an inertia of 0.0
.
0.0
: The node will move as fast as possible.
This method can be used while layout calculation is in progress (e.g. for interactive layout scenarios).
However, the change will not directly be applied to the graph itself but only stored internally
as an intermediate result. Scheduled updates can be committed to the graph while the algorithm is running using
methods commitPositions()
or commitPositionsSmoothly(double, double)
.
woken up
after
scheduling this update.node
- the node whose inertia to setinertia
- an inertia value between 0
and 1
java.lang.IllegalArgumentException
- if the given inertia value is negative or greater than 1
public void setCenter(Node node, double x, double y)
This method can be used while layout calculation is in progress (e.g. for interactive layout scenarios).
However, the change will not directly be applied to the graph itself but only stored internally
as an intermediate result. Scheduled updates can be committed to the graph while the algorithm is running using
methods commitPositions()
or commitPositionsSmoothly(double, double)
.
woken up
after
scheduling this update.node
- the node that should be updatedx
- the desired x-coordinate of the given nodey
- the desired y-coordinate of the given nodepublic void setRadius(Node node, double radius)
This method can be used while layout calculation is in progress (e.g. for interactive layout scenarios).
However, the change will not directly be applied to the graph itself but only stored internally
as an intermediate result. Scheduled updates can be committed to the graph while the algorithm is running using
methods commitPositions()
or commitPositionsSmoothly(double, double)
.
woken up
after
scheduling this update.node
- the node whose radius should be updatedradius
- the desired radius for the given nodepublic void setStress(Node node, double stress)
The stress value indicates how far a node will possibly move. The higher the stress of a node is, the farther it may move.
This method can be used while layout calculation is in progress (e.g. for interactive layout scenarios).
However, the change will not directly be applied to the graph itself but only stored internally
as an intermediate result. Scheduled updates can be committed to the graph while the algorithm is running using
methods commitPositions()
or commitPositionsSmoothly(double, double)
.
The stress value is defined to be a value from the interval [0,1]
.
woken up
after
scheduling this update.node
- the node whose stress value should be updatedstress
- a stress value from the interval [0,1]
java.lang.IllegalArgumentException
- if the given stress value is negative or greater than 1
public double getStress(Node node)
The stress value indicates how far a node will possibly move. The higher the stress of a node is, the farther it may move.
The stress value is defined to be a value from the interval [0,1]
.
setStress(Node, double)
, this
method will not necessarily return that same value for the same node. The reason is that
the algorithm may be sleeping
and did therefore not notice the change yet.node
- the node for which the stress value should be polled
setStress(Node, double)
public void setCenterX(Node node, double x)
This method can be used while layout calculation is in progress (e.g. for interactive layout scenarios).
However, the change will not directly be applied to the graph itself but only stored internally
as an intermediate result. Scheduled updates can be committed to the graph while the algorithm is running using
methods commitPositions()
or commitPositionsSmoothly(double, double)
.
woken up
after
scheduling this update.node
- the node that should be updatedx
- the desired x-coordinate of the given nodesetCenterY(Node, double)
,
setCenter(Node, double, double)
public void setCenterY(Node node, double y)
This method can be used while layout calculation is in progress (e.g. for interactive layout scenarios).
However, the change will not directly be applied to the graph itself but only stored internally
as an intermediate result. Scheduled updates can be committed to the graph while the algorithm is running using
methods commitPositions()
or commitPositionsSmoothly(double, double)
.
woken up
after
scheduling this update.node
- the node that should be updatedy
- the desired y-coordinate of the given nodesetCenterX(Node, double)
,
setCenter(Node, double, double)
public YPoint getCenter(Node node)
The returned coordinates do not necessarily correspond to the actual location of the node in the input graph.
They may only be intermediate results stored in the algorithm. This will be the case if
scheduled updates were not yet completely committed
to the actual graph.
set
earlier, it will not
necessarily be the result of this method. Reasons can be that changes need to be committed
first, or the algorithm is sleeping
.node
- the node for which the center should be polled
YPoint
representing the center location of the given node,
or null
if nothing about the node is knownsetCenter(Node, double, double)
public double getCenterX(Node node)
The returned coordinate is not necessarily the actual x-coordinate of the node in the input graph
but only an intermediate result stored in the algorithm. This will be the case if
scheduled updates were not yet completely committed
to the actual graph.
set
earlier, it will not
necessarily be the result of this method. Reasons can be that changes need to be committed
first, or the algorithm is sleeping
.node
- the node for which the x-coordinate should be polled
setCenterX(Node, double)
public double getCenterY(Node node)
The returned coordinate is not necessarily the actual y-coordinate of the node in the input graph
but only an intermediate result stored in the algorithm. This will be the case if
scheduled updates were not yet completely committed
to the actual graph.
set
earlier, it will not
necessarily be the result of this method. Reasons can be that changes need to be committed
first, or the algorithm is sleeping
.node
- the node for which the y-coordinate should be polled
setCenterY(Node, double)
public void setMaxTime(long maxTime)
The duration needs to be non-negative.
sleep
.Long.MAX_VALUE
. No time restriction is imposed.maxTime
- the maximum duration in milliseconds
java.lang.IllegalArgumentException
- if the specified maximum duration has a negative valuepublic void setQuality(double quality)
The larger the ratio, the better the quality of the resulting layout but the longer it may take to perform the layout calculation.
The value needs to lie within [0,1]
.
quality
- a value between 0.0
(low quality, fast) and 1.0
(high quality, slow)
java.lang.IllegalArgumentException
- if the specified ratio is outside the interval [0,1]
public long getMaxTime()
The duration needs to be non-negative.
sleep
.setMaxTime(long)
public double getQuality()
The larger the ratio, the better the quality of the resulting layout but the longer it may take to perform the layout calculation.
The value needs to lie within [0,1]
.
0.0
(low quality, fast) and 1.0
(high quality, slow)public void syncStructure()
running
.CopiedLayoutGraph
instance as parameter to methods startLayout(LayoutGraph)
,
doLayout(LayoutGraph)
or startLayoutSingleThreaded(LayoutGraph)
.java.lang.IllegalStateException
- if the currently handled graph is not of type CopiedLayoutGraph
public void setOutputRestriction(OutputRestriction restriction)
OutputRestriction
which restricts the area for the layout result of this algorithm.
OutputRestriction.NONE
. No area restriction is imposed.restriction
- the OutputRestriction
instance for restricting the area of the layout
java.lang.IllegalArgumentException
- if the given restriction is null
OutputRestriction
No restriction | Circular restriction | Elliptical restriction | Rectangular restriction |
public OutputRestriction getOutputRestriction()
OutputRestriction
which restricts the area for the layout result of this algorithm.
OutputRestriction
instance for restricting the area of the layoutsetOutputRestriction(OutputRestriction)
public void stopAndWait()
started
algorithm and then blocks
until the current layout calculation is completed.
isStopped()
,
stop()
|
© Copyright 2000-2022, yWorks GmbH. All rights reserved. |
||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |