C

OrganicConstraintData<TNode>

This class allows to define additional constraints on nodes of a graph that will be applied by the OrganicLayout during the layout calculation.
Inheritance Hierarchy

Remarks

Constraints modify the behavior of the organic layout algorithm for nodes of a graph, in order to introduce structures, relative positioning, or area restrictions on the positions of the nodes in the layout.

Type Parameters

TNode

Members

No filters for this type

Constructors

Methods

Adds constraints that cause the given nodes to align parallel to the specified axis.
A node is considered aligned if the axis distance from its center to the center of any other aligned node is no greater than the specified alignment range.
final

Parameters

axis: ConstraintOrientation
HORIZONTAL to align the nodes parallel to the x-axis, VERTICAL to align them parallel to the y-axis.
range?: number
The maximum horizontal distance between the centers of any two aligned nodes if the nodes are aligned vertically, and otherwise the maximum vertical distance between the centers of any two aligned nodes.

Return Value

ItemCollection<TNode>
An ItemCollection<TItem> that is used to define the nodes affected by this constraint.

Throws

Exception ({ name: 'ArgumentError' })
if the given alignment range is negative

Examples

The nodes that are affected by this constraint can be defined using the property source of ItemCollection<TItem>.

Defining the affected nodes.
// align the currently selected nodes on a horizontal line
layoutData.constraints.addAlignmentConstraint(
  ConstraintOrientation.HORIZONTAL,
).source = graphComponent.selection.nodes

Nodes can be also added one by one. This can be more convenient than defining an own list and setting it to source.

Defining the affected nodes one by one.
// align four specific nodes on a horizontal line
const collection = layoutData.constraints.addAlignmentConstraint(
  ConstraintOrientation.HORIZONTAL,
)
collection.items.add(node1)
collection.items.add(node2)
collection.items.add(node3)
collection.items.add(node4)

Alternatively, a powerful option is to use the predicate to set a custom delegate that returns for every node whether it is contained in the set or not:

Using a delegate for defining the affected nodes.
// align the selected nodes on a horizontal line
layoutData.constraints.addAlignmentConstraint(
  ConstraintOrientation.HORIZONTAL,
).predicate = (node) => graphComponent.selection.includes(node)
Adds constraints that cause the specified nodes to be arranged on the border of an ellipse with the given aspect ratio.
Additionally, the nodes can be placed in regular intervals along the border.
final

Parameters

regularPlacement: boolean
true if the nodes should be placed in regular intervals along the border of the ellipse, false otherwise.
aspectRatio?: number
a positive ratio between the horizontal and vertical diameter of the ellipse, or 0, if the ratio should be determined automatically.

Return Value

ItemCollection<TNode>
An ItemCollection<TItem> that is used to define the nodes affected by this constraint.

Throws

Exception ({ name: 'ArgumentError' })
if the given aspect ratio is negative

Examples

The nodes that are affected by this constraint can be defined using the property source of ItemCollection<TItem>.

Defining the affected nodes.
// place selected nodes on an ellipse
layoutData.constraints.addEllipse(true).source =
  graphComponent.selection.nodes

Nodes can also be added one by one. This can be more convenient than defining an own list and setting it to source.

Defining the affected nodes one by one.
// place four specific nodes on an ellipse
const collection = layoutData.constraints.addEllipse(true)
collection.items.add(node1)
collection.items.add(node2)
collection.items.add(node3)
collection.items.add(node4)

Alternatively, a powerful option is to use the predicate to set a custom delegate that returns for every node whether it is contained in the set or not:

Using a delegate for defining the affected nodes.
//  place nodes on an ellipse
layoutData.constraints.addEllipse(true).predicate = (node) =>
  graphComponent.selection.includes(node)
Adds constraints to fix the positions of the specified nodes in relation to one another along one coordinate axis.
final

Parameters

axis: ConstraintOrientation
HORIZONTAL to fix the distances along the x-axis, VERTICAL to fix the distances along the y-axis or BOTH to fix the node's positions relative to each other.

Return Value

ItemCollection<TNode>
An ItemCollection<TItem> that is used to define the nodes affected by this constraint.

Examples

The nodes that are affected by this constraint can be defined using the property source of ItemCollection<TItem>.

Defining the affected nodes.
// fix relative distances of selected nodes
layoutData.constraints.addFixedDistances(
  ConstraintOrientation.BOTH,
).source = graphComponent.selection.nodes

Nodes can also be added one by one. This can be more convenient than defining an own list and setting it to source.

Defining the affected nodes one by one.
// fix relative distances of four specific nodes
const collection = layoutData.constraints.addFixedDistances(
  ConstraintOrientation.BOTH,
)
collection.items.add(node1)
collection.items.add(node2)
collection.items.add(node3)
collection.items.add(node4)

Alternatively, a powerful option is to use the predicate to set a custom delegate that returns for every node whether it is contained in the set or not:

Using a delegate for defining the affected nodes.
// fix relative distances of selected nodes
layoutData.constraints.addFixedDistances(
  ConstraintOrientation.BOTH,
).predicate = (node) => graphComponent.selection.includes(node)
Adds constraints that prevent the specified nodes from occupying an area larger than the defined bounds.
final

Parameters

size: Size
The maximum width and height of the bounds containing all specified nodes.

Return Value

ItemCollection<TNode>
An ItemCollection<TItem> that is used to define the nodes affected by this constraint.

Throws

Exception ({ name: 'ArgumentError' })
if width or height is negative.

Examples

The nodes that are affected by this constraint can be defined using the property source of ItemCollection<TItem>.

Defining the affected nodes.
// create for the selected nodes bounds with 500px width and 400px height
layoutData.constraints.addFloatingBounds(new Size(500, 400)).source =
  graphComponent.selection.nodes

Nodes can also be added one by one. This can be more convenient than defining an own list and setting it to source.

Defining the affected nodes one by one.
// create for two nodes bounds with 500px width and 400px height
const collection = layoutData.constraints.addFloatingBounds(
  new Size(500, 400),
)
collection.items.add(node1)
collection.items.add(node2)

Alternatively, a powerful option is to use the predicate to set a custom delegate that returns for every node whether it is contained in the set or not:

Using a delegate for defining the affected nodes.
// create for the selected nodes bounds with 500px width and 400px height
layoutData.constraints.addFloatingBounds(new Size(500, 400)).predicate = (
  node,
) => graphComponent.selection.includes(node)
Adds constraints that enforce a maximum vertical or horizontal distance between the given nodes.
final

Parameters

node1: TNode
The first node that is constrained with respect to its maximum distance.
node2: TNode
The second node that is constrained with respect to its maximum distance.
distance: number
The largest allowed horizontal resp. vertical distance between both nodes. The distance is measured between the boundaries of the nodes.
axis: ConstraintOrientation
The axis that is used for measuring the distance. HORIZONTAL to restrict the horizontal distance, VERTICAL to restrict the vertical distance or BOTH to restrict both.

Throws

Exception ({ name: 'ArgumentError' })
if the maximum distance is negative.

Examples

Enforcing a maximum distance between two nodes
// bound the horizontal distance between two nodes by 100px
layoutData.constraints.addMaximumDistance(
  node1,
  node2,
  100,
  ConstraintOrientation.HORIZONTAL,
)
Adds constraints that enforce a minimum distance between the given nodes.
final

Parameters

node1: TNode
The first of the two nodes that are constrained with respect to their minimum distance.
node2: TNode
The second of the two nodes that are constrained with respect to their minimum distance.
minimumDistance: number
The minimum required distance between the two nodes. The distance is measured between the boundaries of the nodes.

Throws

Exception ({ name: 'ArgumentError' })
if the minimum distance is negative.

Examples

Enforcing a minimum distance between two specific nodes
// enforces a minimum distance of 100px between the nodes.
layoutData.constraints.addMinimumDistance(node1, node2, 100)
Adds constraints that cause the given nodes to be placed along the specified axis in the order they are given.
final

Parameters

axis: ConstraintOrientation
HORIZONTAL to order the nodes along the x-axis, VERTICAL to order them along the y-axis or BOTH to order them along both axes.

Return Value

ItemMapping<TNode, IComparable>
An ItemMapping<TItem, TValue> that can be used to specify the order of nodes along the given axis.

Examples

The order for some affected nodes can be specified by using the property mapperFunction of ItemMapping<TItem, TValue>.

Specifying a node order via delegate.
// define x-order of selected nodes
layoutData.constraints.addOrderConstraint(
  ConstraintOrientation.HORIZONTAL,
).mapperFunction = (node) =>
  graphComponent.selection.nodes.includes(node) ? node.tag : null

The ranks of the nodes can also be added one by one. This can be more convenient for smaller order constraints.

Defining the affected nodes one by one.
// define x-order of four specific nodes
const mapping = layoutData.constraints.addOrderConstraint(
  ConstraintOrientation.HORIZONTAL,
)
mapping.mapper.set(node2, 1)
mapping.mapper.set(node1, 2)
mapping.mapper.set(node3, 3)
mapping.mapper.set(node4, 4)
Adds constraints that prevent the given nodes from being placed outside the specified rectangle.
final

Parameters

rectangle: Rect
The coordinates of the rectangle.

Return Value

ItemCollection<TNode>
An ItemCollection<TItem> that is used to define the nodes affected by this constraint.

Throws

Exception ({ name: 'ArgumentError' })
if width or height is negative.

Examples

The nodes that are affected by this constraint can be defined using the property source of ItemCollection<TItem>.

Defining the affected nodes.
// create for the selected nodes bounds with 500px width and 400px height
// such that its top-left corner is located at (x=50,y=50)
layoutData.constraints.addPinnedBounds(
  new Rect(50, 50, 500, 400),
).source = graphComponent.selection.nodes

Nodes can also be added one by one. This can be more convenient than defining an own list and setting it to source.

Defining the affected nodes one by one.
// create for two nodes bounds with 500px width and 400px height
// such that its top-left corner is located at (x=50,y=50)
const collection = layoutData.constraints.addPinnedBounds(
  new Rect(50, 50, 500, 400),
)
collection.items.add(node1)
collection.items.add(node2)

Alternatively, a powerful option is to use the predicate to set a custom delegate that returns for every node whether it is contained in the set or not:

Using a delegate for defining the affected nodes.
// create for the selected nodes bounds with 500px width and 400px height
// such that it top-left corner is located at (x=50, y=50)
layoutData.constraints.addPinnedBounds(
  new Rect(50, 50, 500, 400),
).predicate = (node) => graphComponent.selection.includes(node)
Adds constraints that cause the specified nodes to be arranged on the border of a rectangle with the given aspect ratio.
final

Parameters

aspectRatio?: number
a positive ratio between the width and height of the rectangle, or 0, if the ratio should be calculated automatically.

Return Value

ItemCollection<TNode>
An ItemCollection<TItem> that is used to define the nodes affected by this constraint.

Throws

Exception ({ name: 'ArgumentError' })
if the given aspect ratio is negative

Examples

The nodes that are affected by this constraint can be defined using the property source of ItemCollection<TItem>.

Defining the affected nodes.
// place selected nodes on a rectangle
layoutData.constraints.addRectangle().source =
  graphComponent.selection.nodes

Nodes can also be added one by one. This can be more convenient than defining an own list and setting it to source.

Defining the affected nodes one by one.
// place four specific nodes on a rectangle
const collection = layoutData.constraints.addRectangle()
collection.items.add(node1)
collection.items.add(node2)
collection.items.add(node3)
collection.items.add(node4)

Alternatively, a powerful option is to use the predicate to set a custom delegate that returns for every node whether it is contained in the set or not:

Using a delegate for defining the affected nodes.
// place selected nodes on a rectangle
layoutData.constraints.addRectangle().predicate = (node) =>
  graphComponent.selection.includes(node)
Adds constraints that cause the given nodes to be aligned parallel to the specified axis.
The specified distance is enforced between each pair of neighboring nodes along the alignment.
final

Parameters

axis: ConstraintOrientation
HORIZONTAL to align the nodes parallel to the x-axis, VERTICAL to align them parallel to the y-axis.
distance?: number
The distance between neighboring nodes along the alignment. If the value is negative, the distance is determined automatically.

Return Value

ItemCollection<TNode>
An ItemCollection<TItem> that is used to define the nodes affected by this constraint.

Examples

The nodes that are affected by this constraint can be defined using the property source of ItemCollection<TItem>.

Defining the affected nodes.
// regularly align the selected nodes on a horizontal line
layoutData.constraints.addRegularAlignmentConstraint(
  ConstraintOrientation.HORIZONTAL,
).source = graphComponent.selection.nodes

Nodes can be also added one by one. This can be more convenient than defining an own list and setting it to source.

Defining the affected nodes one by one.
// regularly align four specific nodes on a horizontal line
const collection = layoutData.constraints.addRegularAlignmentConstraint(
  ConstraintOrientation.HORIZONTAL,
)
collection.items.add(node1)
collection.items.add(node2)
collection.items.add(node3)
collection.items.add(node4)

Alternatively, a powerful option is to use the predicate to set a custom delegate that returns for every node whether it is contained in the set or not:

Using a delegate for defining the affected nodes.
// regularly align nodes on a horizontal line
layoutData.constraints.addRegularAlignmentConstraint(
  ConstraintOrientation.HORIZONTAL,
).predicate = (node) => graphComponent.selection.includes(node)
Adds constraints that enforce a minimum distance between two sets of nodes.
The sets are separated along the specified axis.
final

Parameters

axis: ConstraintOrientation
HORIZONTAL to separate the nodes along the x-axis, VERTICAL to separate them along the y-axis, BOTH to separate them along both axes.
minimumDistance: number
The minimum distance by which the two sets are separated.

Return Value

OrganicLayoutSeparationConstraint<TNode>
An OrganicLayoutSeparationConstraint<TNode> that is used to define the two sets of nodes that should be separated.

Throws

Exception ({ name: 'ArgumentError' })
if the minimum distance is negative.

Examples

The nodes that are affected by this constraint can be defined using the property source of ItemCollection<TItem>.

Defining the affected nodes.
// horizontally separate selected nodes from non-selected nodes
const constraint = layoutData.constraints.addSeparationConstraint(
  ConstraintOrientation.HORIZONTAL,
  100,
)
constraint.firstSet.source = graph.nodes.filter((node) =>
  graphComponent.selection.includes(node),
)
constraint.secondSet.source = graph.nodes.filter(
  (node) => !graphComponent.selection.includes(node),
)

Nodes can be also added one by one. This can be more convenient than defining an own list and setting it to source.

Defining the affected nodes one by one.
// horizontally separate two specific nodes from two other specific nodes
const constraint = layoutData.constraints.addSeparationConstraint(
  ConstraintOrientation.HORIZONTAL,
  100,
)
constraint.firstSet.items.add(node1)
constraint.firstSet.items.add(node2)
constraint.secondSet.items.add(node3)
constraint.secondSet.items.add(node4)

Alternatively, a powerful option is to use the predicate to set a custom delegate that returns for every node whether it is contained in the set or not:

Using a delegate for defining the affected nodes.
{
  // horizontally separate selected nodes from non-selected nodes
  const constraint = layoutData.constraints.addSeparationConstraint(
    ConstraintOrientation.HORIZONTAL,
    100,
  )
  constraint.firstSet.predicate = (node) =>
    graphComponent.selection.includes(node)
  constraint.secondSet.predicate = (node) =>
    !graphComponent.selection.includes(node)
}