Automatic Port Assignment

Tips & Tricks

Summary

Adjusting port assignments for ports outside or inside a node's visual representation

This article was written for an older version. It is only online as a reference for customers using this old version. The information it contains is probably out of date.

The latest information can be found in the yFiles documentation

Description

When layouting a graph (and/or routing its edges), yFiles' layout algorithms automatically determine an edge's source point and target point or, in yFiles Viewer speak, its source and target port. Depending on the layout algorithm, ports are usually placed on the center of the associated node or on the border of the node's bounding box. For some use cases, these port assignments are insufficient. E.g. for nodes with non-rectangular visual representations, the second of the above mentioned strategies oftentimes results in ports outside the node.

Class PortCalculator is a LayoutStage that can be used to improve the ports outside the node situtation. PortCalculator queries each edge for appropriate implementations of interface IntersectionCalculator, which know enough about the visual representation of the edge's source or target node to calculate an appropriate port location. yFiles' Viewer framework comes with a generic IntersectionCalculator provider (NodeRealizerIntersectionCalculator), which can be used with Graph2D instances:

// let graph be an instance of y.view.Graph2D

// associate appropriate IntersectionCalculator instances to the Graph2D
graph.addDataProvider(
    IntersectionCalculator.SOURCE_INTERSECTION_CALCULATOR_DPKEY,
    new NodeRealizerIntersectionCalculator(graph, true));
graph.addDataProvider(
    IntersectionCalculator.TARGET_INTERSECTION_CALCULATOR_DPKEY,
    new NodeRealizerIntersectionCalculator(graph, false));

(new PortCalculator()).doLayout(graph);

// cleanup our IntersectionCalculators
graph.removeDataProvider(IntersectionCalculator.TARGET_INTERSECTION_CALCULATOR_DPKEY);
graph.removeDataProvider(IntersectionCalculator.SOURCE_INTERSECTION_CALCULATOR_DPKEY);
When working with graphs that are not of type Graph2D, custom IntersectionCalculator implementations have to be provided.

For the case where ports are assigned to some point inside a node's visual representation, yFiles' Viewer framework automatically displays edges as if ports were placed on the border of the node's visual representation. Still, ports can be moved from the inside of a node to its border using a similar approach like PortCalculator as demonstrated by PortCalculator2, ContainsTest, and NodeRealizerContainsTest, which are attached to this article. This works best if ports are not outside of a node's visual representation, which suggests to run this strategy right after PortCalculator has done its thing.

// let graph be an instance of y.view.Graph2D

graph.addDataProvider(
    IntersectionCalculator.SOURCE_INTERSECTION_CALCULATOR_DPKEY,
    new NodeRealizerIntersectionCalculator(graph, true));
graph.addDataProvider(
    IntersectionCalculator.TARGET_INTERSECTION_CALCULATOR_DPKEY,
    new NodeRealizerIntersectionCalculator(graph, false));

// besides intersection calculators, a dedicated inclusion test implementation is
// needed to determine whether a port lies inside the visual representation of a 
// node or not
graph.addDataProvider(
    ContainsTest.CONTAINS_TEST_DPKEY,
    new NodeRealizerContainsTest());

final CompositeLayoutStage cls = new CompositeLayoutStage();
// run PortCalculator first ...
cls.prependStage(new PortCalculator());
// ... and our inverse strategy second
cls.prependStage(new PortCalculator2());
cls.doLayout(graph);

// cleanup
graph.removeDataProvider(ContainsTest.CONTAINS_TEST_DPKEY);
graph.removeDataProvider(IntersectionCalculator.TARGET_INTERSECTION_CALCULATOR_DPKEY);
graph.removeDataProvider(IntersectionCalculator.SOURCE_INTERSECTION_CALCULATOR_DPKEY);
Since all of the major yFiles layout algorithms extend CanonicMultiStageLayouter, both strategies can be directly prepended to a layouter instance instead of CompositeLayoutStage.
As of yFiles for Java 2.7, Graph2DLayoutExecutor's portIntersectionCalculatorEnabled property should be used instead of PortCalculator and IntersectionCalculator.

Resources

Categories this article belongs to:
yFiles for Java > yFiles Layout > Automatic Graph Layout > Layout Stages
yFiles for Java > yFiles Layout > Automatic Graph Layout > Advanced Layout Features
Applies to:
yFiles for Java 2: 2.5, 2.6, 2.7
Keywords:
port - assignment - layout - stage - intersection calculator - inclusion test - data provider