Interactive Organic Layout

Class InteractiveOrganicLayouter provides organic layout for use in interactive environments. Its strength is its capability to generate continuous updates to the layout of a graph during calculation. Furthermore, it also allows a user to seemingly simultaneously perform arbitrary modifications to a graph, which are subsequently accounted for in the layout calculation.

In contrast to the majority of yFiles layout algorithms, class InteractiveOrganicLayouter does not inherit from CanonicMultiStageLayouter, but is instead provided as an implementation of interface ILayouter as depicted in Figure 10.55, “Interactive organic layout implementation”.

Important

Due to the interactive nature of this layout algorithm, the IGraph-related adapter mechanisms to run a layout algorithm are not applicable.

Figure 10.55. Interactive organic layout implementation

Interactive organic layout implementation.

Among other things, this means that there is no special support for routing of either self-loops or parallel edges, for example. In particular, when a graph contains parallel edges, they will be routed using overlapping edge paths.

General Usage

InteractiveOrganicLayouter is designed to be used in a concurrent setup where the layout algorithm runs in a thread of its own. This enables an application that executes on the UI thread and presents a graphical user interface (GUI) to the user to remain fully interactive even while the layout algorithm performs its calculations. Moreover, the actual setup also enables modifications to the graph seemingly simultaneous to the layout calculation by InteractiveOrganicLayouter.

Setup

First and foremost, the setup for using interactive organic layout relies on a thread to encapsulate the layout functionality. The thread can be created and started by means of the following convenience method. It subsequently begins the layout calculation for the given graph.

Thread StartLayout(LayoutGraph graph)
Description Creates and starts the layout thread.

If the graph that is to be processed by InteractiveOrganicLayouter is intended to allow structural modifications by a user, then it is strongly recommended to use an instance of CopiedLayoutGraph instead of a simple LayoutGraph. Doing so helps avoiding race conditions and synchronization problems that occur when nodes and/or edges can be added to or removed from the graph while the layout algorithm performs its calculations.

Creation of the layout thread using a copy of the original graph is shown in Example 10.26, “Creating the layout thread”.

Example 10.26. Creating the layout thread

void CreateAndStartLayoutThread(InteractiveOrganicLayouter iol, 
                                LayoutGraph graph) {
  // Create a copy of the given graph. Using an instance of CopiedLayoutGraph 
  // helps avoiding race conditions with graph *structure* modifications from a 
  // user.
  CopiedLayoutGraph clg = new CopiedLayoutGraph(graph);
  iol.StartLayout(clg);
}

State

Interactive organic layout algorithm can be in either of three states: running, sleeping, or stopped. When running, the algorithm lives on the allowed maximal runtime and continuously calculates "intermediate" layouts for the given graph. When sleeping, the algorithm does nothing, but is still "alive." In contrast, when stopped, the algorithm is terminated. Figure 10.56, “State diagram for InteractiveOrganicLayouter” depicts the states and the possible state transitions of InteractiveOrganicLayouter.

Figure 10.56. State diagram for InteractiveOrganicLayouter

State diagram for InteractiveOrganicLayouter.

The following properties and methods can be used to query the current state of an InteractiveOrganicLayouter instance, change its state, and set the maximal runtime. Note that when an instance is changed from "sleeping" to "running" state, the maximal runtime is again fully available.

bool Running { get; }
bool Sleeping { get; }
bool Stopped { get; }
Description Properties to query the algorithm's current state.
void WakeUp()
void Stop()
void StopAndWait()
Description Methods to change the current state.
long MaxTime { get; set; }
Description Determines the maximal runtime when in "running" state.

Polling for Results

The concurrent setup as used with InteractiveOrganicLayouter means that the layout process does not return a single result by itself, but instead continuously generates "intermediate" results as long as it is in "running" state. These results are in the layout algorithm's data structures only, but can be polled by a user at any time and be used as continuous updates to the layout of a graph.

The following methods allow to easily poll either the current coordinates of single nodes or commit all current positions of nodes to the original graph at once:

double GetCenterX(Node node)
double GetCenterY(Node node)
YPoint GetCenter(Node node)
Description Retrieve the current center coordinate(s) of a single node from InteractiveOrganicLayouter's data structures.
void CommitPositions()
double CommitPositionsSmoothly(double maxMovement, double percentage)
Description Updates all node locations with the coordinates from InteractiveOrganicLayouter's data structures.

Typically, to assign the "intermediate" results in a contiuous fashion to the original graph, a technique similar to that outlined in Example 10.27, “Repeatedly polling InteractiveOrganicLayouter for the current node positions” can be used. The current positions of all nodes are repeatedly polled by means of a System.Windows.Threading.DispatcherTimer.

Example 10.27. Repeatedly polling InteractiveOrganicLayouter for the current node positions

void CreateAndStartPollingTimer(InteractiveOrganicLayouter iol) {
  // Create and start a Timer object that will poll the given
  // InteractiveOrganicLayouter instance every 15 milliseconds to update the
  // node positions in the original graph.
  DispatcherTimer timer = new DispatcherTimer();
  timer.Tick += delegate {
    // Test if the layout algorithm is in running state.
      if (iol == null || !iol.Running) {
        return;
      }
      // Smoothly update the node positions from the layout algorithm's data
      // structures to the original graph.
      iol.CommitPositionsSmoothly(50, 0.05);
    };

  // This could be adjusted for smoother or less smoother and better performing
  // updates.
  timer.Interval = TimeSpan.FromMilliseconds(15);
  timer.Start();
}

Interaction

The interactive organic layout algorithm allows a user to seemingly simultaneously modify node positions and also node-related parameters while layout calculation takes place. The following methods can be used to update InteractiveOrganicLayouter's data structures with new node positions, and also to specify further node-related parameters that determine, e.g., the size of a node or its inertia:

void SetCenterX(Node node, double x)
void SetCenterY(Node node, double y)
void SetCenter(Node node, double x, double y)
Description Set the current center coordinate(s) of a single node in InteractiveOrganicLayouter's data structures.
void SetInertia(Node node, double inertia)
void SetRadius(Node node, double radius)
Description Further node-related parameters used by InteractiveOrganicLayouter.

In addition, InteractiveOrganicLayouter optionally also supports modifications to the original graph's structure, i.e., nodes and/or edges can be added to or removed from the graph and the layout calculation subsequently properly accounts for these changes. The following property has to be used to enable support for structural modifications.

Important

To avoid race conditions and synchronization problems when structural changes to the graph are allowed, it is strongly recommended to provide InteractiveOrganicLayouter a copy of the original graph using an instance of CopiedLayoutGraph. See also the section called “Setup”.

bool AutomaticStructureUpdateEnabled { get; set; }
Description Enables/disables automatic updates for structural changes in the original graph.

To properly support arbitrary structural modifications to the original graph, interactive organic layout relies on proper notification by means of graph events. To this end, an IGraphListener is registered with the original graph that informs InteractiveOrganicLayouter of any structural changes that occur. See also the description of graph listeners in the section called “Events and Listeners”.

As an alternative to using automatic structure updates, the structure of the original graph can also be synchronized explicitly using code similar to that shown in Example 10.28, “Performing explicit structure updates”.

Example 10.28. Performing explicit structure updates

// 'iol' is of type yWorks.yFiles.Layout.Organic.InteractiveOrganicLayouter.

bool enabled = iol.AutomaticStructureUpdateEnabled;
// Disable automatic structure updates. 
iol.AutomaticStructureUpdateEnabled = false;

// Perform the actual graph structure modifications on the original graph. 
// For example, remove some nodes and edges... 
ModifyOriginalGraphStructureHere();

// Synchronize the structure of the original graph with that of the copy given 
// to InteractiveOrganicLayouter. 
iol.SyncStructure();

// Reset to previous behavior for automatic structure updates. 
iol.AutomaticStructureUpdateEnabled = enabled;

Supplemental Layout Data

Class InteractiveOrganicLayouter 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 10.41, “Data provider look-up keys” lists all look-up keys for InteractiveOrganicLayouter.

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

Table 10.41. Data provider look-up keys

Key Element Type Value Type Description
PreferredEdgeLengthDpKey Edge double For each edge a double value that indicates its preferred length.

Layout Options

Interactive organic layout provides a set of options that affect its behavior. These options can be set using the properties and setter methods of class InteractiveOrganicLayouter.

Maximal Runtime
API
long MaxTime { get; set; }
Description Sets the maximal duration of the layout process in milliseconds.

After the layout process has finished or the time specified using Maximal Runtime is spent, InteractiveOrganicLayouter will sleep, i.e., it has to be awakened before another layout process can be invoked (see also the description of running/sleeping state of InteractiveOrganicLayouter).

If this upper bound is hit during the layout process, the quality of the layout may not be optimal. Increasing the value increases the likeliness of an optimal layout.

Preferred Node Distance
API
double PreferredNodeDistance { set; }
Description The preferred node distance which will be used to calculate the layout. The layout algorithm tries to arrange the nodes in such a way that the desired distance is complied with.

The following property and setter method allow to specify the general preferred length for all edges, respectively individual preferred edge length. The layout algorithm tries to arrange the nodes in such a way that the edges have the desired edge length. Note that the edge length is measured from node border to node border.

Preferred Edge Length
API
double PreferredEdgeLength { get; set; }
void SetPreferredEdgeLength(Edge edge, double newEdgeLength)
Description Property and setter method to specify general preferred edge length, respectively individual preferred edge length.

Alternatively, to specify the preferred edge length for each edge individually, a data provider holding such supplemental layout data can be bound to the graph. The data provider is expected to be registered with the graph using key PreferredEdgeLengthDpKey. Note that in the absence of an individual preferred edge length the general preferred edge length will be used.

Important

Although the data provider look-up key defined in class OrganicLayouter is used to specify individual preferred edge lengths, the actual type of data provided are double values.

Quality
API
double Quality { get; set; }
Description This setting can be used to adjust the quality of the layout calculated by the layout algorithm. Small values lead to short running times, while greater values result in better quality. For large graph structures (hundreds and thousands of nodes) it is advisable to begin with smaller values and to gradually increase them.

Output Restrictions

Class InteractiveOrganicLayouter allows to impose so-called "output restrictions" on the result of the layout calculcation. More precisely, the layout result can be determined to fit into a specified region, e.g., a rectangle or a circle. Also, the layout result can be restricted to a specified aspect ratio, too.

OutputRestriction OutputRestriction { get; set; }
Description Class OutputRestriction serves as a factory to create predefined output restrictions that can be used in conjunction with this property.