Managing nodes and hyperedges
Describes how to connect nodes using hyperedges, the differences between IlvLinkImage and IlvHyperEdge, hyperedge ends, and how to retrieve incident hyperedges at nodes.
Shows how to add a node to a hypergraph, how to connect several nodes via a hyperedge, and provides an example of creating a hypergraph with four nodes and a hyperedge.
Describes the
IlvLinkImage and
IlvHyperEdge classes and discusses orientation and changing the end nodes of a link.
Describes how hyperedges can have not only multiple end nodes, but multiple ends at the same node.
Defines the methods for retrieving links or hyperedges incident to a node.
Connecting nodes with hyperedges
To connect multiple nodes by a hyperedge, you must create the nodes and add them to the hypergraph. This works in
IlvHyperGrapher exactly in the same way as in
IlvGrapher.
To add a node:
Call one of the following methods:
void addNode(IlvGraphic obj, boolean redraw) To connect several nodes by a hyperedge:
1. Create the hyperedge.
The constructor of the hyperedge is:
While the constructor of
IlvLinkImage takes only one node as the from or the to node, the constructor of
IlvHyperEdge takes a vector of nodes as from and to nodes.
2. Add the hyperedge to the hypergraph with one of the following methods:
The layer parameter in the second method specifies the manager layer where the hyperedge is placed. If the layer parameter is missing, the link insertion layer, which is obtained by using the method getLinkInsertionLayer(), is used to place the hyperedge.
The following code example shows how to create a hypergraph, four nodes, and a hyperedge.
Creating a hypergraph with four nodes and a hyperedge
IlvHyperGrapher grapher = new IlvHyperGrapher();
IlvGraphicVector fromNodes = new IlvGraphicVector();
IlvGraphicVector toNodes = new IlvGraphicVector();
IlvGraphic node1 = new IlvLabel(new IlvPoint(0,0), "node 1");
IlvGraphic node2 = new IlvLabel(new IlvPoint(100,0), "node 2");
IlvGraphic node3 = new IlvLabel(new IlvPoint(100,30), "node 3");
IlvGraphic node4 = new IlvLabel(new IlvPoint(100,60), "node 4");
grapher.addNode(node1, false);
grapher.addNode(node2, false);
grapher.addNode(node3, false);
grapher.addNode(node4, false);
fromNodes.addElement(node1);
toNodes.addElement(node2);
toNodes.addElement(node3);
toNodes.addElement(node4);
IlvHyperEdge edge = new IlvHyperEdge(fromNodes, toNodes);
grapher.addHyperEdge(edge, false);
Differences between IlvLinkImage and IlvHyperEdge
The classes
IlvLinkImage and
IlvHyperEdge differ in the following areas:
Orientation
Normal links ( IlvLinkImage ) have a flag that indicates whether they are oriented. If the links are oriented, an arrowhead will be drawn. The orientation flag is necessary because, if an arrowhead were always drawn, then there would be no way of drawing a link between two nodes that did not represent a flow direction.
Hyperedges are always oriented. Therefore, an arrowhead is drawn at the target nodes and this arrowhead cannot be switched off.
This feature is not a restriction. If you want to draw a hyperedge between several nodes without an arrowhead, create a hyperedge that has all these nodes as sources, but has no target node.
You can also create a hyperedge that has only target nodes, but no source node. In this case, an arrowhead is drawn at all end nodes of the hyperedge.
You can see that hyperedges are much more flexible than normal links.
If a hyperedge has exactly one source node and one target node, then it will look like, and behave approximately as, a normal oriented link.
If a hyperedge has exactly two source nodes and zero target nodes, then it will look like a normal unoriented link.
Changing end nodes of a link
To change the end nodes of an IlvLinkImage object, you must remove the IlvLinkImage from the graph. Then you must change the end nodes and reinsert the link into the graph.
Changing the end nodes of an
IlvHyperEdge object is more convenient. The end nodes can be changed while the hyperedge remains in the hypergraph. For example, you can add an empty hyperedge with zero end nodes to the hypergraph. Then you can add source and target nodes later. You must encapsulate all operations that change the end nodes of a hyperedge into
applyToObject sessions. See
Modifying geometric properties of objects in
The Essential Features of JViews Framework user documentation for more details.
The operations that can be carried out on IlvHyperEdge are shown in the following table.
Operations on IlvHyperEdge
Operation | Description |
setFrom(nodeVector) | Removes all old source nodes from the hyperedge and adds all nodes contained in the input vector as new source nodes of the hyperedge. |
setTo(nodeVector) | Removes all old target nodes from the hyperedge and adds all nodes contained in the input vector as new targets of the hyperedge. |
addFrom(node) | Adds the input node to the list of source nodes of the hyperedge. |
addTo(node) | Adds the input node to the list of target nodes of the hyperedge. |
removeFrom(node) | Removes the input node from the list of source nodes of the hyperedge. |
removeTo(node) | Removes the input node from the list of target nodes of the hyperedge. |
The following code example shows how to create an empty hyperedge, add it to the hypergraph, and then add some source nodes.
Creating an empty hyperedge and adding source nodes
IlvHyperGrapher grapher = new IlvHyperGrapher();
grapher.setMinHyperEdgeEndCount(0);
...
IlvHyperEdge edge = new IlvHyperEdge();
grapher.addHyperEdge(edge, false);
...
grapher.applyToObject(edge,
new IlvApplyObject() {
public void apply(IlvGraphic obj, Object arg) {
((IlvHyperEdge)obj).addFrom(node1);
((IlvHyperEdge)obj).addFrom(node2);
((IlvHyperEdge)obj).addFrom(node3);
}
}, arg, redraw);
Hyperedge ends
Normal links (
IlvLinkImage) can be incident to one node at most twice: if the link is a self-loop, that is, if the source and target of the link is the same node, then the link will occur in the list of incident links at the node twice. Both ends of the link are easily distinguishable, because one is the source end and the other is the target end.
Not only can a hyperedge (
IlvHyperEdge) have multiple end nodes, but it can also have multiple ends at the same node. Therefore this link is incident to the node multiple times. For example, if you call
addFrom multiple times for the same node at the same hyperedge, this hyperedge will have multiple source ends at that node. See the following figure.
Multiple ends at the same node
How can you distinguish the different ends of the hyperedge at the node?
The interface
IlvHyperEdgeEnd serves as the end indicator of a hyperedge. Instances of this interface are called the hyperedge ends. The default implementation is
IlvDefaultHyperEdgeEnd.
The hyperedge ends technically belong to the hyperedge and not to the node. They point to the end node.
If a source or target node is added to the hyperedge, a new hyperedge end is created internally and connects the hyperedge to the node. If the hyperedge is removed from the hypergraph, all ends of the hyperedge will also be removed.
If a hyperedge connects to one node multiple times, there will be multiple different instances of IlvHyperEdgeEnd stored in the hyperedge. All these instances point to the node. The hyperedge ends can be distinguished from each other, even though the corresponding end node is the same.
The following table shows methods included in the API of IlvHyperEdgeEnd.
Methods of IlvHyperEdgeEnd
Method | Description |
| Returns the hyperedge that contains the specified end. |
| Returns the node that is connected to the hyperedge by the end. |
| Returns the position of the end. The input transformer indicates the coordinate system (untransformed manager coordinates or transformed view coordinates if t is the transformer for drawing the hyperedge). Usually, you should pass the value true for the flag. |
| Sets the position of the end. |
The following table shows the API of IlvHyperEdge in more detail. It explains how the operations influence the hyperedge ends and which additional API exists for manipulating the hyperedge ends directly at the hyperedge.
Methods of IlvHyperEdge
API | Description |
| Creates a new hyperedge end that points to the input node. The hyperedge end is stored as source in the hyperedge. Finally, the hyperedge end is returned, so that you can use it to set the precise position of the hyperedge end. Note that this modifies the geometry of the hyperedge and therefore must be encapsulated in an applyToObject session. |
| Creates a new hyperedge end that points to the input node. The hyperedge end is stored as target in the hyperedge. Finally, the hyperedge end is returned, so that you can use it to set the precise position of the hyperedge end. Note that this modifies the geometry of the hyperedge and therefore must be encapsulated in an applyToObject session. |
| Collects all source hyperedge ends that point to the input node. These ends are removed from the sources of the hyperedge. |
| Collects all target hyperedge ends that point to the input node. These ends are removed from the targets of the hyperedge. |
| Removes one source hyperedge end. Other hyperedge ends are not affected, even if they point to the same node. |
| Removes one target hyperedge end. Other hyperedge ends are not affected, even if they point to the same node. |
| Returns the source nodes of the hyperedge. Each node occurs at the most once in the enumeration, even if multiple hyperedge ends point to this node. |
| Returns the target nodes of the hyperedge. Each node occurs at the most once in the enumeration, even if multiple hyperedge ends point to this node. |
| Returns the number of source nodes of the hyperedge. |
| Returns the number of target nodes of the hyperedge. |
| Returns the source hyperedge ends. |
| Returns the target hyperedge ends. |
| Returns the number of source hyperedge ends. |
| Returns the number of target hyperedge ends. |
As a general rule, when the end nodes are retrieved or counted, a node occurs once only, even if there are multiple ends at a node. When the ends are retrieved or counted, multiple ends that point to the same node occur as distinguishable items. Therefore, the following equation is true:
edge.getFromCount() <= edge.getFromEndsCount()
edge.getToCount() <= edge.getToEndsCount()
Important You should never remove source nodes or source ends while iterating over the objects returned by getFrom() or getFromEnds().
Important You should never remove target nodes or target ends while iterating over the objects returned by getTo() or getToEnds().
The class
IlvHyperEdge has other useful API, such as API for retrieving the ends or end nodes in an array, which is convenient if you need to remove the ends, or for checking whether a given end is source or target. See the reference documentation of
IlvHyperEdge for details.
Retrieving incident hyperedges at nodes
Nodes are any
IlvGraphic object that is added to the graph by a call to
addNode. Instances of
IlvLinkImage or
IlvHyperEdge cannot be added as nodes to the hypergraph; they must be added as links (by a call to
addLink) or as hyperedges (by a call to
addHyperEdge).
The same node can serve as end node for normal links and for hyperedges.
IlvHyperGrapher provides different API for retrieving links or hyperedges that are
incident to a node.
Methods for retrieving links or hyperedges incident to a node
API | Description |
| Returns the normal links ( IlvLinkImage ) that have the node as source, but does not return any hyperedges. |
| Returns the normal links ( IlvLinkImage ) that have the node as target, but does not return any hyperedges. |
| Returns the hyperedges ( IlvHyperEdge ) that have the node as source, but does not return any normal links. |
| Returns the hyperedges ( IlvHyperEdge ) that have the node as target, but does not return any normal links. |
| Returns the number of normal links that have the node as source. |
| Returns the number of normal links that have the node as target. |
| Returns the number of hyperedges that have the node as source. |
| Returns the number of hyperedges that have the node as target. |
A hyperedge can have the same source node or the same target node multiple times. Say that a hyperedge,
linkA, has the node,
nodeB, five times as source node. (See the following figure.) By calling the methods shown in table
Methods for retrieving links or hyperedges incident to a node,
linkA would occur once only, even if it is incident to a node multiple times; that is,
grapher.getHyperEdgesFrom(nodeB) would return
linkA once only and
grapher.getHyperEdgesFromCount(nodeB) would count
linkA once only.
Multiple ends at the same node
Multiple occurrences of the same source or target node are distinguished by the hyperedge end. The hyperedge linkA has five different hyperedge ends that point to nodeB. Therefore, IlvHyperGrapher provides methods for retrieving the hyperedge ends incident to a node. These methods are shown in the following table.
Methods for retrieving hyperedge ends
Method | Description |
| Returns the hyperedge ends ( IlvHyperEdgeEnd ) of those hyperedges that have the node as source. |
| Returns the hyperedge ends ( IlvHyperEdgeEnd ) of those hyperedges that have the node as target. |
| Returns the number of hyperedge ends of those hyperedges that have the node as source. |
| Returns the number of hyperedge ends of those hyperedges that have the node as target. |
In the example illustrated by the figure
Multiple ends at the same node,
grapher.getHyperEdgeEndsFrom(nodeB) returns five different ends for the link
linkA and
grapher.getHyperEdgeEndsFromCount(nodeB) counts
linkA five times, because it actually counts the ends of
linkA.
Copyright © 2018, Rogue Wave Software, Inc. All Rights Reserved.