Multi-page Layout

This section presents the multi-page layout concept.

About the Concept

Multi-page layout enables the presentation of large graphs in an easily navigable and clear manner. It means breaking apart a given graph into a set of smaller graphs so that each layout of a small graph fits into a given width and height.

A multi-page layout with its set of small graphs avoids common presentation problems of large graphs with many nodes and edges. Problems, like, e.g., graph elements that are hardly discernible because of a small zoom level when viewing/printing the entire graph, or long edge paths that are hard to follow over numerous poster pages in a poster print-out of a graph.

The algorithm aims to find small graphs whose layout utilizes the specified width and height to the best extent. It puts as many as possible elements from the original graph into each small graph, thus minimizing the number of resulting small graphs.

Figure 5.94. Multi-page layout sample

Multi-page layout sample
Multi-page layout sample
Original diagram. Four (out of eight) small graphs that result from running multi-page layout. Blue nodes are directly from the original diagram, yellow nodes are additional proxy elements (see text).

Breaking apart the original graph is done by sub-dividing it and, for each connection between two nodes that is cut, introducing additional nodes and edges as proxy elements in both involved smaller graphs. The proxy elements in either small graph stand in for the original edge and can be used as a means to get to the corresponding other small graph.

Sub-division can furthermore also take place at the node level, where nodes with many connections are split up into multiple "parts" that are distributed to different small graphs. This also introduces additional nodes and edges as proxy elements in the involved smaller graphs.

Carefully observe that, in contrast to the major layout algorithms of the yFiles library, multi-page layout produces not a single graph as its result, but instead a set of graphs.

Terminology

The original graph that is given to the algorithm is also called the model graph. The smaller graphs that result from sub-dividing and augmenting the model graph are referred to as the page graphs. The additional nodes and edges that are introduced to represent an edge from the original graph between two nodes which are in different page graphs after sub-division, are called connector nodes and connector edges, respectively, or also often simply connectors.

Figure 5.95. Replacing an edge and introducing connector nodes and connector edges

Replacing an edge and introducing connector nodes and connector edges
Replacing an edge and introducing connector nodes and connector edges
Connected nodes A and B with their neighbors in the original graph. A and B in different page graphs. Both nodes have an additional connector node (emphasized, smaller) and an additional connector edge (emphasized) that stand in for the connecting edge of the original graph.

Further nodes and edges are added when a node with many connections needs to be split up into multiple parts in order to be able to assign these parts to different page graphs. Each of the parts gets an equal share of the original neighbor nodes (roughly).

The additional new parts of the original node are called proxy nodes, all edges incident to them are called proxy edges. They represent the connections between the original node and its neighbors. For each of the proxy nodes in other page graphs, the original node gets a so-called proxy reference node as a new neighbor. The connecting edge to this new neighbor is called proxy reference edge.

Figure 5.96. Splitting up a node and introducing a proxy node, proxy edges, a proxy reference node, and a proxy reference edge

Splitting up a node and introducing a proxy node, proxy edges, a proxy reference node, and a proxy reference edge
Splitting up a node and introducing a proxy node, proxy edges, a proxy reference node, and a proxy reference edge
Splitting up a node and introducing a proxy node, proxy edges, a proxy reference node, and a proxy reference edge
Original node with its neighbors. The node (conceptually) before the split. The node split up into two "parts," A and A', in different page graphs, each having (roughly) one half of the original neighbors. A' (emphasized, normal size) is a proxy node of the original node A. It is connected to the original node's neighbors by means of proxy edges (emphasized) that stand in for the connecting edges of the original graph. A has an additional proxy reference node (emphasized, smaller) that references proxy node A'. The connecting edge is a proxy reference edge (emphasized).

Relevant Classes

The following table lists the relevant classes and interfaces for multi-page layout:

Table 5.66. Relevant classes for this algorithm

Classname Description
MultiPageLayouter Main algorithm. See the description below.
MultiPageLayout The container to hold the results of a multi-page layout, i.e., the page graphs. See Related Classes and Interfaces.
ElementFactory Interface that defines element creation callbacks for customization of the additional nodes and edges that augment the page graphs. See Related Classes and Interfaces.

Class MultiPageLayouter

Class MultiPageLayouter is the main class for calculating multi-page layouts. It generates a set of so-called page graphs whose layouts each fit into a given width and height. To calculate the actual layouts of the page graphs, it relies on a core layout algorithm.

Class MultiPageLayouter uses a scheme that is different from that of the yFiles major layout algorithms in several ways:

  • The preferred way to start a multi-page layout is to use the calcLayout method of class MultiPageLayouter.
  • The result of the layout is a set of graphs, the page graphs.
  • The original graph that is given to MultiPageLayouter is not modified in any way.
  • The page graphs contain graph elements from the original graph plus additional nodes and edges.

A multi-page layout is started using:

Layout Invocation
API
calcLayout(graph:LayoutGraph):MultiPageLayout
Description Method to start multi-page layout.

The result of the algorithm is returned in a MultiPageLayout container object. The original graph that is given to MultiPageLayouter is not modified in any way.

Note that invoking a multi-page layout using the applyLayout convenience method of adapter class CopiedLayoutIGraph implicitly calls MultiPageLayouter's doLayout method (originally defined in interface Layouter). This method, however, does not return a MultiPageLayout object, i.e., the result of the layout calculation is not accessible without further setup.

Important

The result of a multi-page layout calculation cannot be returned through MultiPageLayouter's doLayout method.

Instead, the MultiPageLayout container object needs to be retrieved through an implementation of interface LayoutCallback, which needs to be registered with MultiPageLayouter using:

layoutCallback:LayoutCallback
Description Sets the LayoutCallback implementation. After a multi-page layout has completed, the implementation gets called and receives the MultiPageLayout container object holding the resulting page graphs.

A simple LayoutCallback implementation:

Example 5.33. LayoutCallback implementation

public class SimpleLayoutCallback implements LayoutCallback {
  var result:MultiPageLayout;

  function layoutDone(result:MultiPageLayout):void {
    this.result = result;
  }

  function pop():MultiPageLayout {
    var result:MultiPageLayout = this.result;
    this.result = null;
    return result;
  }
}

Note that the resulting page graphs in the MultiPageLayout container object are all of type LayoutGraph. In tutorial demo application MultiPageLayouterDemo.mxml helper class MultiPageIGraphBuilder is used to build a folded graph view that contains the page graphs from a multi-page layout calculation.

Setup for Layout

To calculate a multi-page layout, class MultiPageLayouter needs

  • a core layout algorithm to actually compute the layouts of the page graphs
  • data providers registered with the original graph that provide unique IDs for all nodes, edges, node labels, and edge labels of the model graph
  • a LayoutCallback implementation, if the layout is invoked using the doLayout method of class MultiPageLayouter

The core layout algorithm can be set using the coreLayouter property (originally defined in interface LayoutStage):

Example 5.34. Setting the core layouter

// Create multi-page layout algorithm.
var mpl:MultiPageLayouter = new MultiPageLayouter();

// Create and set core layout algorithm.
mpl.coreLayouter = new IncrementalHierarchicLayouter();

MultiPageLayouter uses unique IDs for the elements from the original graph to relate page graph elements to their originals from the model graph. In particular, the IDs are necessary to collect the information that is returned for connectors and proxy elements as part of the MultiPageLayout container.

Unique IDs for nodes and edges can be specified using the data provider look-up keys NODE_ID_DPKEY and EDGE_ID_DPKEY, respectively, unique IDs for node labels and edge labels using the look-up keys NODE_LABEL_ID_DPKEY and EDGE_LABEL_ID_DPKEY, respectively.

The following code shows the canonical approach to provide unique IDs for graph elements.

Example 5.35. Canonical setup of mandatory unique IDs for graph elements

// An IMapper implementation that simply returns the given object itself as its 
// unique ID.
public class MyIMapper implements IMapper {  
  public function lookupValue(key:Object):Object { return key; }
  
  public function mapValue(key:Object, value:Object):void {}
  public function unMapValue(key:Object):void {}
}  

function setupCanonicalUniqueIDs(modelGraph:IGraph):void {
  var idProvider:IMapper = new MyIMapper();
  var registry:IMapperRegistry = modelGraph.mapperRegistry;
  
  // Use this IMapper implementation for all kinds of graph elements that need 
  // unique IDs.
  registry.addMapper(MultiPageLayouter.NODE_ID_DPKEY, idProvider);
  registry.addMapper(MultiPageLayouter.EDGE_ID_DPKEY, idProvider);
  registry.addMapper(MultiPageLayouter.NODE_LABEL_ID_DPKEY, idProvider);
  registry.addMapper(MultiPageLayouter.EDGE_LABEL_ID_DPKEY, idProvider);
}

In summary, the setup of MultiPageLayouter looks like this:

Example 5.36. Setup of MultiPageLayouter

// 'modelGraph' is of com.yworks.graph.model.IGraph.

// Create multi-page layout algorithm.
var mpl:MultiPageLayouter = new MultiPageLayouter();

// Create and set core layout algorithm.
var ihl:IncrementalHierarchicLayouter = new IncrementalHierarchicLayouter();
mpl.coreLayouter = ihl;

// Set up unique IDs for graph elements.
setupCanonicalUniqueIDs(modelGraph);

var callback:SimpleLayoutCallback = new SimpleLayoutCallback();
mpl.layoutCallback = callback;

// Calculate multi-page layout.
CopiedLayoutIGraph.applyLayout(modelGraph, mpl);

// Get the resulting page graphs.
var result:MultiPageLayout = callback.pop();

// Now, do something with 'result'...

// Remove the data providers registered by setupCanonicalUniqueIDs.
modelGraph.mapperRegistry.removeMapper(MultiPageLayouter.EDGE_LABEL_ID_DPKEY);
modelGraph.mapperRegistry.removeMapper(MultiPageLayouter.NODE_LABEL_ID_DPKEY);
modelGraph.mapperRegistry.removeMapper(MultiPageLayouter.EDGE_ID_DPKEY);
modelGraph.mapperRegistry.removeMapper(MultiPageLayouter.NODE_ID_DPKEY);

Layout Options

Page Size
API
maxPageSize:YDimension
Description Specifies the page dimensions, i.e., the width and height into which the layout of a page graph needs to fit.

By default, MultiPageLayouter distributes the nodes from the original graph to the page graphs automatically. By means of a data provider that is bound to the graph using the look-up key NODE_CLUSTER_ID_DPKEY, nodes of the original graph that should end up in the same page graph can be assigned an object that serves as an ID. MultiPageLayouter then tries to distribute nodes with the same ID to the same page graph.

Algorithm Execution Options

Maximal Duration
API
preferredMaximalDuration:uint
Description

Sets the preferred maximal duration of the layout process in milliseconds. By default, the algorithm runs without time restriction.

Higher values enable the algorithm to find a smaller set of page graphs, where each makes better use of the available page size. Also, there are less connectors and proxy elements in the page graphs.

Related Classes and Interfaces

Class MultiPageLayout

Class MultiPageLayout is the container to hold the results of the multi-page layout. It is returned by the calcLayout method of class MultiPageLayouter.

MultiPageLayout provides access to all page graphs from the layout result and enables identification of original graph elements, connectors, and proxy elements. This information is encapsulated in NodeInfo and EdgeInfo objects, respectively NodeLabelInfo and EdgeLabelInfo objects.

The following code shows how to use NodeInfo objects to find all indexes of page graphs that are connected to the first page graph from a multi-page layout result:

Example 5.37. Querying the MultiPageLayout

// 'result' is of type yworks.yfiles.layout.multipage.MultiPageLayout.

// Get the first from the resulting page graphs.
var firstGraph:LayoutGraph = result.getPage(0);

for (var nc:NodeCursor = firstGraph.nodes(); nc.ok(); nc.next()) {
  var n:Node = nc.node();
  // Get the NodeInfo object for the current node.
  var ni:NodeInfo = result.getNodeInfo(node);
  
  // Is the current node a connector node?
  if (ni.type == NodeInfo.TYPE_CONNECTOR) {
    // Get its opposite connector node.
    var oppositeConnectorNode:Node = ni.referencingNode();
    // Get the opposite's node NodeInfo object.
    var ni2:NodeInfo = result.getNodeInfo(oppositeConnectorNode);
    
    // Find out the index of the page graph the opposite node is in.
    var otherPage:int = ni2.pageNo();
    trace("Connector node (" + node + 
          ") connects to page graph at index: " + otherPage);
  }
}

Interface ElementFactory

During the sub-division process, class MultiPageLayouter uses an implementation of interface ElementFactory as a factory to create the

  • connector nodes and edges,
  • proxy nodes and edges, and
  • proxy reference nodes and edges

that replace elements of the original graph and augment the page graphs. Class DefaultElementFactory is the predefined default implementation, which provides convenient implementations of all callback methods.

Tutorial Demo Code

Tutorial demo application MultiPageLayouterDemo.mxml shows how to use class MultiPageLayouter to sub-divide large graphs into smaller bits of navigable information.

Supplemental Layout Data

Class MultiPageLayouter knows a number of data provider keys which are used to retrieve supplemental layout data for a graph's elements. The data is bound to the graph by means of a data provider which is registered using a given look-up key. Table 5.67, “Data provider look-up keys” lists all look-up keys that MultiPageLayouter tests during the layout process in order to query supplemental data.

Binding supplemental layout data to a graph is described in the section called “Providing Supplemental Layout Data”.

Table 5.67. Data provider look-up keys

Key Element Type Value Type Description
NODE_ID_DPKEY node Object For each node an Object that is used as a unique ID.
EDGE_ID_DPKEY edge Object For each edge an Object that is used as a unique ID.
NODE_LABEL_ID_DPKEY NodeLabelLayout Object For each NodeLabelLayout instance an Object that is used as a unique ID.
EDGE_LABEL_ID_DPKEY EdgeLabelLayout Object For each EdgeLabelLayout instance an Object that is used as a unique ID.
NODE_CLUSTER_ID_DPKEY node Object For each node an arbitrary Object indicating its cluster ID. This ID is used to find nodes that preferably should be in the same page graph.
EDGE_TYPE_DPKEY edge Object For each edge an arbitrary Object indicating its (application-specific) type.