C

CurveRoutingStageData<TNode, TEdge, TNodeLabel, TEdgeLabel>

Specifies the layout data for the CurveRoutingStage.
Inheritance Hierarchy

Members

Show:

Constructors

Parameters

Properties

Gets or sets the mapping of edges to their CurveRoutingEdgeDescriptor

A descriptor provides additional routing information and allows to, e.g., specify individual minimum distance values that must be considered when routing an edge.

If an edge is mapped to null, the CurveRoutingStage uses the default descriptor.

conversionfinal

See Also

API
EDGE_DESCRIPTOR_DATA_KEY
Gets or sets the mapping that provides an EdgeLabelPreferredPlacement instance for edge labels.
Carefully note that the CurveRoutingStage only properly considers preferred edge label placement if the coreLayout already correctly considered them or if they are already correct in case that no core layout is defined.
conversionfinal

Examples

Depending on how much customization is needed, some ways of setting EdgeLabelPreferredPlacements are more convenient than others. For example, to set the same descriptor for all labels, you can just use the constant property:

Setting the same EdgeLabelPreferredPlacement for all labels
layoutData.edgeLabelPreferredPlacements = new EdgeLabelPreferredPlacement(
  {
    // Place labels along the edge
    angleReference: LabelAngleReferences.RELATIVE_TO_EDGE_FLOW,
    angle: 0,
    // ... on either side
    edgeSide: LabelEdgeSides.LEFT_OF_EDGE | LabelEdgeSides.RIGHT_OF_EDGE,
    // ... with a bit of distance to the edge
    distanceToEdge: 5,
  },
)

If some labels should use custom placement or this has to be configured ahead of time, you can use the mapper instead:

Customizing the placement of certain labels individually via a mapper
// Place label1 orthogonal to the edge anywhere on it
layoutData.edgeLabelPreferredPlacements.mapper.set(
  label1,
  new EdgeLabelPreferredPlacement({
    placementAlongEdge: LabelAlongEdgePlacements.ANYWHERE,
    angleReference: LabelAngleReferences.RELATIVE_TO_EDGE_FLOW,
    angle: Math.PI / 2,
  }),
)
// Place label2 near the edge's source on either side of it, and make it parallel to the edge
layoutData.edgeLabelPreferredPlacements.mapper.set(
  label2,
  new EdgeLabelPreferredPlacement({
    placementAlongEdge: LabelAlongEdgePlacements.AT_SOURCE,
    edgeSide: LabelEdgeSides.RIGHT_OF_EDGE | LabelEdgeSides.LEFT_OF_EDGE,
    angleReference: LabelAngleReferences.RELATIVE_TO_EDGE_FLOW,
    angle: 0,
  }),
)

When the preferred placement can be inferred from the label itself, a delegate is usually the easiest choice:

Configuring preferred placement for all labels with a delegate
layoutData.edgeLabelPreferredPlacements = (
  label: ILabel,
): EdgeLabelPreferredPlacement => {
  const customData = label.tag as CustomData
  return new EdgeLabelPreferredPlacement({
    angle: 0,
    angleReference: LabelAngleReferences.RELATIVE_TO_EDGE_FLOW,
    // If the tag says to place the label in the center, put it in the center parallel to the edge's path
    // All other labels can be placed anywhere, but on the side of the edge.
    placementAlongEdge: customData.placeInCenter
      ? LabelAlongEdgePlacements.AT_CENTER
      : LabelAlongEdgePlacements.ANYWHERE,
    edgeSide: customData.placeInCenter
      ? LabelEdgeSides.ON_EDGE
      : LabelEdgeSides.LEFT_OF_EDGE | LabelEdgeSides.RIGHT_OF_EDGE,
  })
}

Note that the preferred placement can also be inferred from an arbitrary ILabelModelParameter:

Configuring preferred placement from a label model parameter
layoutData.edgeLabelPreferredPlacements =
  EdgeLabelPreferredPlacement.fromParameter(
    NinePositionsEdgeLabelModel.CENTER_CENTERED,
  )

See Also

API
EdgeLabelPreferredPlacement, EDGE_LABEL_PREFERRED_PLACEMENT_DATA_KEY
Gets or sets the LayoutGrid layout data.
The CurveRoutingStage respects a layout grid such that curved edges are only allowed to intersect a column/row boundary if the edge path created by the core layout algorithm already intersects it.
final
Gets or sets the mapping from nodes to their margins.
Node margins allow to reserve space around nodes. Carefully note that the CurveRoutingStage only properly considers margins if the coreLayout already correctly considered them or if they are already correctly considered in case that no core layout is defined.
conversionfinal

See Also

API
NODE_MARGIN_DATA_KEY
Gets or sets the subset of edges that are in scope for the CurveRoutingStage.
readonlyfinal
Gets or sets a mapping from edges to an object representing their source edge group.
Edges sharing a source group identifier will share a common bus near the source or at a common source node. Importantly, the CurveRoutingStage supports edge grouping such that edges that are correctly grouped by the core layout algorithm remain grouped in the curved layout result. However, it will not create new groupings.
conversionfinal

Examples

One simple way to use source groups is to use the edge's source node as group ID which effectively groups all edges with the same source together:

Grouping all edges on the source side
layoutData.sourceGroupIds = (edge: IEdge) => edge.sourceNode

Another useful way to use a delegate here would be grouping edges by some commonality, such as the same color:

Grouping edges by color
layoutData.sourceGroupIds = (edge: IEdge) => {
  const style = edge.style
  if (style instanceof PolylineEdgeStyle) {
    return style.stroke!.fill
  }
  return null
}

If only certain edges should be grouped it may sometimes be easier to use the mapper to set the group IDs:

Grouping certain edges with a mapper
for (const group of edgeGroups) {
  for (const edge of group) {
    // Use the collection as group ID, since it's common to all edges in it
    layoutData.sourceGroupIds.mapper.set(edge, group)
  }
}

See Also

API
targetGroupIds, SOURCE_EDGE_GROUP_ID_DATA_KEY
Gets or sets a mapping from edges to an object representing their target edge group.
Edges sharing a target group identifier will share a common bus near the target or at a common target node. Importantly, the CurveRoutingStage supports edge grouping such that edges that are correctly grouped by the core layout algorithm remain grouped in the curved layout result. However, it will not create new groupings.
conversionfinal

Examples

One simple way to use source groups is to use the edge's target node as group ID which effectively groups all edges with the same target together:

Grouping all edges on the target side
layoutData.targetGroupIds = (edge: IEdge) => edge.targetNode

Another useful way to use a delegate here would be grouping edges by some commonality, such as the same color:

Grouping edges by color
layoutData.targetGroupIds = (edge: IEdge) => {
  const style = edge.style
  if (style instanceof PolylineEdgeStyle) {
    return style.stroke!.fill
  }
  return null
}

If only certain edges should be grouped it may sometimes be easier to use the mapper to set the group IDs:

Grouping certain edges with a mapper
for (const group of edgeGroups) {
  for (const edge of group) {
    // Use the collection as group ID, since it's common to all edges in it
    layoutData.targetGroupIds.mapper.set(edge, group)
  }
}

See Also

API
sourceGroupIds, TARGET_EDGE_GROUP_ID_DATA_KEY

Methods

Combines this instance with the given layout data.
This keeps the current instance unmodified and instead returns a new instance that dynamically combines the contents of all involved instances.
final

Parameters

data: LayoutData<TNode, TEdge, TNodeLabel, TEdgeLabel>
The LayoutData<TNode, TEdge, TNodeLabel, TEdgeLabel> to combine this instance with.

Return Value

LayoutData<TNode, TEdge, TNodeLabel, TEdgeLabel>
The combined layout data.

See Also

Developer's Guide
API
CompositeLayoutData, GenericLayoutData