Search this API

y.layout
Class ParallelEdgeLayouter

java.lang.Object
  extended by y.layout.AbstractLayoutStage
      extended by y.layout.ParallelEdgeLayouter
All Implemented Interfaces:
Layouter, LayoutStage

public class ParallelEdgeLayouter
extends AbstractLayoutStage

ParallelEdgeLayouter is a LayoutStage that routes parallel edges which connect the same pair of nodes in a graph.

Layout Style

The edge paths of parallel edges consist of parallel segments. At the end points, the edges can either still be parallel or joined in one point.


The master edge determining the routing is highlighted

Concept

ParallelEdgeLayouter performs four basic steps:

  1. For each set of parallel edges between the same endpoints, the algorithm removes all edges but one from the input graph (the remaining edge is called the leading or master edge)
  2. Invoke the core layout algorithm on the graph without parallel edges
  3. Reinsert all previously removed parallel edges
  4. Route the parallel edges such that their path is parallel to that of the associated master edge.

Features

ParallelEdgeLayouter can either be used as a LayoutStage wrapping a layout algorithm which cannot handle parallel edges. Then it will hide the parallel edges from this core layout algorithm and take over the routing of them.
If no core layout algorithm is specified, ParallelEdgeLayouter can work alone. It will route only the parallel edges and keep the remaining graph unchanged. Note that, since the parallel edges' paths are parallel to the path of the associated master edge, the master edge should always have a suitable route before calling the ParallelEdgeLayouter.

To find out which edges this stage routed, a DataAcceptor can be registered with the graph with key ROUTED_PARALLEL_EDGES_DPKEY. Parallel edges that were hidden during the core layout and then routed by this stage are marked. Leading edges are not marked. This may be convenient if parallel edges require further consideration, e.g., to place labels their labels (the core layout could not do that because they were hidden).

Parallel edges can either be all edges between the same two nodes, ignoring the direction, or edges are only considered parallel if they share the same source node and target node. Hence, they share the same direction.

To make sure that the ports of all parallel edges are on the end nodes, the first and last segments can be joined. However, these segments won't be parallel.

There are two ways to define the distance between two parallel edges. First, an absolute distance can be defined. Parallel segments will keep this distance. Second, the distance can be determined relative to the node bounds. Depending on the size of the nodes and the number of parallel edges between them, the distance between parallel edges is adjusted. This will keep the edges straight in most cases.

It is possible to select custom master edges. All edges that are parallel to the selected edges will be temporarily removed.

 
In order to obtain suitable routes for the parallel edges, the associated leading/master edges must have suitable routes, too. This can be achieved by either specifying a suitable core layout algorithm or by any other method that ensures that the input graph already has suitable routes (e.g., by calling LayoutTool.resetPaths(LayoutGraph)) before applying the ParallelEdgeLayouter if the edges should receive straight-line routes).
 

Field Summary
protected  EdgeList hiddenEdges
          Holds the list of parallel edges that are hidden from the core layout algorithm.
static java.lang.Object LEADING_EDGE_DPKEY
          A DataProvider key for specifying the master edges Marked edges won't be removed for the core layout algorithm.
protected  double lineDistance
          Holds the line distance assigned between parallel edges.
 EdgeMap parallelEdges
          EdgeMap that associates a hidden edge with the unique parallel edge not hidden from the core layout algorithm.
static java.lang.Object ROUTED_PARALLEL_EDGES_DPKEY
          A DataAcceptor key for publishing the parallel edges that were routed and not treated as leading edges In the DataAcceptor registered with the graph with this key all parallel edges which are no leading (master) edges are marked.
static java.lang.Object SCOPE_DPKEY
          A DataProvider key for marking edges that will be routed
 
Fields inherited from interface y.layout.Layouter
EDGE_ID_DPKEY, NODE_ID_DPKEY, NODE_TYPE_DPKEY, SELECTED_EDGES, SELECTED_NODES
 
Constructor Summary
ParallelEdgeLayouter()
          Creates a new ParallelEdgeLayouter instance with default settings.
ParallelEdgeLayouter(Layouter coreLayouter)
          Creates a new ParallelEdgeLayouter instance using the given core layout algorithm.
 
Method Summary
 boolean canLayout(LayoutGraph graph)
          Accepts all graphs that can be handled by the core layout algorithm after removing all parallel edges.
 void doLayout(LayoutGraph graph)
          Delegates the arrangement of nodes and edges to the core layout algorithm and routes the parallel edges.
protected  void findAndHideParallelEdges(Graph graph)
          Hides all parallel edges leaving a master edge in the graph.
 double getAbsJoinEndDistance()
          Returns the absolute distance from the end point of the joined lines to the first parallel segments.
 double getLineDistance()
          Returns the distance between two adjacent edge paths that run in parallel.
 double getRelJoinEndDistance()
          Returns the relative distance from the end point of the joined lines to the first parallel segments.
 boolean isDirectedModeEnabled()
          Returns whether or not the direction of edges should be considered.
 boolean isJoinEndsEnabled()
          Returns whether or not to join end points of parallel edges.
 boolean isLeadingEdgeAdjustmentEnabled()
          Returns whether or not to adjust the leading edge to obtain more symmetric results.
 boolean isUsingAdaptiveLineDistances()
          Returns whether or not the distances between parallel edges should be determined automatically according to the sizes of their source and target nodes.
protected  void layoutParallelEdges(LayoutGraph graph, EdgeMap parallelEdges)
          Assigns a layout to all parallel edges.
 void setAbsJoinEndDistance(double absJoinEndDistance)
          Specifies the absolute distance from the end point of the joined lines to the first parallel segments.
 void setDirectedModeEnabled(boolean directedModeEnabled)
          Specifies whether or not the direction of edges should be considered.
 void setJoinEndsEnabled(boolean joinEndsEnabled)
          Specifies whether or not to join end points of parallel edges.
 void setLeadingEdgeAdjustmentEnabled(boolean leadingEdgeAdjustmentEnabled)
          Specifies whether or not to adjust the leading edge to obtain more symmetric results.
 void setLineDistance(double distance)
          Specifies the distance between two adjacent edge paths that run in parallel.
 void setRelJoinEndDistance(double relJoinEndDistance)
          Specifies the relative distance from the end point of the joined lines to the first parallel segments.
 void setUsingAdaptiveLineDistances(boolean usingAdaptiveLineDistances)
          Specifies whether or not the distances between parallel edges should be determined automatically according to the sizes of their source and target nodes.
 
Methods inherited from class y.layout.AbstractLayoutStage
canLayoutCore, doLayoutCore, getCoreLayouter, setCoreLayouter
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

SCOPE_DPKEY

public static final java.lang.Object SCOPE_DPKEY
A DataProvider key for marking edges that will be routed

 
If no DataProvider is registered with the given key, all edges will be routed.

LEADING_EDGE_DPKEY

public static final java.lang.Object LEADING_EDGE_DPKEY
A DataProvider key for specifying the master edges

Marked edges won't be removed for the core layout algorithm. All edges parallel to the master edges will get parallel paths.

If no leading edge is specified for a bundle of parallel edges, it will be determined automatically. If there is more than one leading edge, the first one is chosen.


ROUTED_PARALLEL_EDGES_DPKEY

public static final java.lang.Object ROUTED_PARALLEL_EDGES_DPKEY
A DataAcceptor key for publishing the parallel edges that were routed and not treated as leading edges

In the DataAcceptor registered with the graph with this key all parallel edges which are no leading (master) edges are marked. This way, it is easily possible to determine the set of edges that were hidden during the core layout.

Knowing which parallel edges were identified and hidden during the core layout can be a valuable information for use cases where it is required to handle such edges specifically. A frequent scenario is, for example, the requirement to place edge labels of these edges. The core layout is not able to do so, because parallel edges are hidden. A generic labeling algorithm where only the labels of the parallel edges are affected and placed can now easily be applied (see AbstractLabelingAlgorithm.setSelection(Object).

 
If the ParallelEdgeLayouter runs as part of a CanonicMultiStageLayouter, stages like the labeling which run after this stage can already use the information published with the data acceptor registered with this key. This way the the labeling stage can, for example, handle labels of non-leading, parallel edges in a specific way.
See Also:
LEADING_EDGE_DPKEY

hiddenEdges

protected EdgeList hiddenEdges
Holds the list of parallel edges that are hidden from the core layout algorithm.


parallelEdges

public EdgeMap parallelEdges
EdgeMap that associates a hidden edge with the unique parallel edge not hidden from the core layout algorithm.


lineDistance

protected double lineDistance
Holds the line distance assigned between parallel edges.

Constructor Detail

ParallelEdgeLayouter

public ParallelEdgeLayouter(Layouter coreLayouter)
Creates a new ParallelEdgeLayouter instance using the given core layout algorithm.

Parameters:
coreLayouter - the core layout routine
See Also:
AbstractLayoutStage.setCoreLayouter(Layouter)

ParallelEdgeLayouter

public ParallelEdgeLayouter()
Creates a new ParallelEdgeLayouter instance with default settings.

Method Detail

isDirectedModeEnabled

public boolean isDirectedModeEnabled()
Returns whether or not the direction of edges should be considered.

In directed mode, only edges that share the same source and target node will be routed in parallel. Edges that connect to the same nodes but in different directions won't be considered parallel.

In undirected mode, all edges connecting the same pair of nodes will be routed in parallel.

Returns:
true if the direction of parallel edges must be the same, false otherwise

setDirectedModeEnabled

public void setDirectedModeEnabled(boolean directedModeEnabled)
Specifies whether or not the direction of edges should be considered.

In directed mode, only edges that share the same source and target node will be routed in parallel. Edges that connect to the same nodes but in different directions won't be considered parallel.

In undirected mode, all edges connecting the same pair of nodes will be routed in parallel.

Default Value:
The default value is false. All edges that connect the same pair of nodes are considered parallel, ignoring their directions.
Parameters:
directedModeEnabled - true if the direction of parallel edges must be the same, false otherwise
Sample Graphs:

false

true

isUsingAdaptiveLineDistances

public boolean isUsingAdaptiveLineDistances()
Returns whether or not the distances between parallel edges should be determined automatically according to the sizes of their source and target nodes.

If enabled, the distances between edges are chosen such that all parallel edges can be drawn as straight lines and still connect to the nodes' bounds.

Returns:
true if the distances are determined according to the nodes' bounds, false otherwise
See Also:
setUsingAdaptiveLineDistances(boolean), setLineDistance(double)

setUsingAdaptiveLineDistances

public void setUsingAdaptiveLineDistances(boolean usingAdaptiveLineDistances)
Specifies whether or not the distances between parallel edges should be determined automatically according to the sizes of their source and target nodes.

If enabled, the distances between edges are chosen such that all parallel edges can be drawn as straight lines and still connect to the nodes' bounds.

Default Value:
The default value is true. The distances between parallel edges are adjusted to the nodes' bounds.
Parameters:
usingAdaptiveLineDistances - true if the distances should be determined according to the nodes' bounds, false otherwise
See Also:
setLineDistance(double)
Sample Graphs:

false

true

setLineDistance

public void setLineDistance(double distance)
Specifies the distance between two adjacent edge paths that run in parallel.

The distance needs to be non-negative.

 
If adaptive line distances are used, the resulting distance may be less than the specified distance.
Default Value:
The default value is 10.
Parameters:
distance - the distance between two parallel edges
Throws:
java.lang.IllegalArgumentException - if the specified distance is less than 0
See Also:
setUsingAdaptiveLineDistances(boolean)
Sample Graphs:

10

20

getLineDistance

public double getLineDistance()
Returns the distance between two adjacent edge paths that run in parallel.

The distance needs to be non-negative.

 
If adaptive line distances are used, the resulting distance may be less than the specified distance.
Returns:
the distance between two parallel edges
See Also:
setLineDistance(double), setUsingAdaptiveLineDistances(boolean)

doLayout

public void doLayout(LayoutGraph graph)
Delegates the arrangement of nodes and edges to the core layout algorithm and routes the parallel edges.

Parameters:
graph - the input graph
See Also:
Layouter.canLayout(LayoutGraph)

canLayout

public boolean canLayout(LayoutGraph graph)
Accepts all graphs that can be handled by the core layout algorithm after removing all parallel edges.

If there is no core layout algorithm, all graphs are accepted.

Parameters:
graph - the input graph
Returns:
true if there is no core layout algorithm or the core layout algorithm accepts the graph, false otherwise
See Also:
Layouter.doLayout(LayoutGraph)

layoutParallelEdges

protected void layoutParallelEdges(LayoutGraph graph,
                                   EdgeMap parallelEdges)
Assigns a layout to all parallel edges.

The layout for each parallel edge follows the layout of the master edge which was not removed from the core layout algorithm.

This method is called when the core layout algorithm is finished. It may be overridden to introduce a custom routing for parallel edges.

Parameters:
graph - the graph after the core layout
parallelEdges - the map that provides all parallel edges for each master edge
See Also:
setJoinEndsEnabled(boolean), setUsingAdaptiveLineDistances(boolean), setLeadingEdgeAdjustmentEnabled(boolean)

findAndHideParallelEdges

protected void findAndHideParallelEdges(Graph graph)
Hides all parallel edges leaving a master edge in the graph.

ParallelEdgeLayouter detects parallel edges of the given graph. From each set of parallel edges it hides all but one edge from the given graph.

This method is called before invoking the core layout algorithm. It may be overridden to change the selection of leading edges. Hidden edges should be stored in hiddenEdges to enable un-hiding later on.

Parameters:
graph - the input graph
See Also:
setDirectedModeEnabled(boolean), SCOPE_DPKEY

isJoinEndsEnabled

public boolean isJoinEndsEnabled()
Returns whether or not to join end points of parallel edges.

If enabled, all edges end with non-parallel segments that connect at the same point to the node. Otherwise, all segments of the edges are parallel. In this case, some edges may not connect to the nodes' bounds.

Returns:
true if edges are joined at the ends, false otherwise
See Also:
setJoinEndsEnabled(boolean), setAbsJoinEndDistance(double), setRelJoinEndDistance(double)

setJoinEndsEnabled

public void setJoinEndsEnabled(boolean joinEndsEnabled)
Specifies whether or not to join end points of parallel edges.

If enabled, all edges end with non-parallel segments that connect at the same point to the node. Otherwise, all segments of the edges are parallel. In this case, some edges may not connect to the nodes' bounds.

Default Value:
The default value is false. Parallel edges have only parallel segments.
Parameters:
joinEndsEnabled - true if edges should be joined at the ends, false otherwise
See Also:
setAbsJoinEndDistance(double), setRelJoinEndDistance(double)
Sample Graphs:

false

true

getAbsJoinEndDistance

public double getAbsJoinEndDistance()
Returns the absolute distance from the end point of the joined lines to the first parallel segments.

The absolute distance needs to be non-negative.

 
This distance is only considered if parallel edge paths are joined.
Returns:
the absolute distance from the end point to the first/last bend of parallel edges
See Also:
setAbsJoinEndDistance(double), setJoinEndsEnabled(boolean), setRelJoinEndDistance(double)

setAbsJoinEndDistance

public void setAbsJoinEndDistance(double absJoinEndDistance)
Specifies the absolute distance from the end point of the joined lines to the first parallel segments.

The absolute distance needs to be non-negative.

 
This distance is only considered if parallel edge paths are joined.
Default Value:
The default value is 20.
Parameters:
absJoinEndDistance - the absolute distance from the end point to the first/last bend of parallel edges
Throws:
java.lang.IllegalArgumentException - if the specified distance is negative
See Also:
setJoinEndsEnabled(boolean), setRelJoinEndDistance(double)
Sample Graphs:

20

10

getRelJoinEndDistance

public double getRelJoinEndDistance()
Returns the relative distance from the end point of the joined lines to the first parallel segments.

The length is relative to the corresponding original segment's length. It needs to have a value in the interval [0,1].

 
This distance is only considered if parallel edge paths are joined.
Returns:
the relative distance from the end point to the first/last bend of parallel edges
See Also:
setRelJoinEndDistance(double), setJoinEndsEnabled(boolean), setAbsJoinEndDistance(double)

setRelJoinEndDistance

public void setRelJoinEndDistance(double relJoinEndDistance)
Specifies the relative distance from the end point of the joined lines to the first parallel segments.

The length is relative to the corresponding original segment's length. It needs to have a value in the interval [0,1].

 
This distance is only considered if parallel edge paths are joined.
Default Value:
The default value is 0.1.
Parameters:
relJoinEndDistance - the relative distance from the end point to the first/last bend of parallel edges
Throws:
java.lang.IllegalArgumentException - if the specified relative distance is less than 0 or greater than 1
See Also:
setJoinEndsEnabled(boolean), setAbsJoinEndDistance(double)
Sample Graphs:

0.1

0.4

isLeadingEdgeAdjustmentEnabled

public boolean isLeadingEdgeAdjustmentEnabled()
Returns whether or not to adjust the leading edge to obtain more symmetric results.

 
Enabling this property may change the original ports of the master edge.
Returns:
true if the leading edge is adjusted, false otherwise
See Also:
setLeadingEdgeAdjustmentEnabled(boolean)

setLeadingEdgeAdjustmentEnabled

public void setLeadingEdgeAdjustmentEnabled(boolean leadingEdgeAdjustmentEnabled)
Specifies whether or not to adjust the leading edge to obtain more symmetric results.

 
Enabling this property may change the original ports of the master edge.
Default Value:
The default value is true. The leading edge is adjusted for more symmetric results.
Parameters:
leadingEdgeAdjustmentEnabled - true if the leading edge should be adjusted, false otherwise
Sample Graphs:

false

true

© Copyright 2000-2022,
yWorks GmbH.
All rights reserved.