use of org.eclipse.elk.core.UnsupportedGraphException in project elk by eclipse.
the class ElkLayered method reviewAndCorrectHierarchicalProcessors.
/**
* It is not permitted that any of the child-graphs specifies a hierarchical
* layout processor ({@link IHierarchyAwareLayoutProcessor}) that is not specified by the root node.
*
* It depends on the concrete processor how this is fixed.
*
* @param root the root graph
* @param graphs all graphs of the handled hierarchy
*/
private void reviewAndCorrectHierarchicalProcessors(final LGraph root, final Collection<LGraph> graphs) {
// Crossing minimization
// overwrite invalid child configuration (only layer sweep is hierarchical)
CrossingMinimizationStrategy parentCms = root.getProperty(LayeredOptions.CROSSING_MINIMIZATION_STRATEGY);
if (parentCms != CrossingMinimizationStrategy.LAYER_SWEEP) {
graphs.forEach(child -> {
CrossingMinimizationStrategy childCms = child.getProperty(LayeredOptions.CROSSING_MINIMIZATION_STRATEGY);
if (childCms == CrossingMinimizationStrategy.LAYER_SWEEP) {
throw new UnsupportedGraphException("The hierarchy aware processor " + childCms + " in child node " + child + " is only allowed if the root node specifies the same hierarchical processor.");
}
});
}
// Greedy switch (simply copy the behavior of the root to all children)
final GreedySwitchType rootType = root.getProperty(LayeredOptions.CROSSING_MINIMIZATION_GREEDY_SWITCH_HIERARCHICAL_TYPE);
graphs.forEach(g -> g.setProperty(LayeredOptions.CROSSING_MINIMIZATION_GREEDY_SWITCH_HIERARCHICAL_TYPE, rootType));
}
use of org.eclipse.elk.core.UnsupportedGraphException in project elk by eclipse.
the class ElkGraphImporter method transformEdge.
// /////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Edge Transformation
/**
* Transforms the given edge if it's not a hyperedge. If it is a hyperedge, throws an exception.
*
* @param elkedge the edge to transform
* @param elkparent the node in the original graph which currently gets transformed into {@code lgraph}
* @param lgraph the layered graph
* @return the transformed edge, or {@code null} if it cannot be transformed
* @throws UnsupportedGraphException if the edge is a hyperedge.
*/
private LEdge transformEdge(final ElkEdge elkedge, final ElkNode elkparent, final LGraph lgraph) {
checkEdgeValidity(elkedge);
// Get a few basic information about the edge
ElkConnectableShape elkSourceShape = elkedge.getSources().get(0);
ElkConnectableShape elkTargetShape = elkedge.getTargets().get(0);
ElkNode elkSourceNode = ElkGraphUtil.connectableShapeToNode(elkSourceShape);
ElkNode elkTargetNode = ElkGraphUtil.connectableShapeToNode(elkTargetShape);
ElkEdgeSection edgeSection = elkedge.getSections().isEmpty() ? null : elkedge.getSections().get(0);
// Find the transformed source and target nodes
LNode sourceLNode = (LNode) nodeAndPortMap.get(elkSourceNode);
LNode targetLNode = (LNode) nodeAndPortMap.get(elkTargetNode);
LPort sourceLPort = null;
LPort targetLPort = null;
// Find the transformed source port, if any
if (elkSourceShape instanceof ElkPort) {
// If the ElkPort is a regular port, it will map to an LPort; if it's an external port, it
// will map to an LNode
LGraphElement sourceElem = nodeAndPortMap.get(elkSourceShape);
if (sourceElem instanceof LPort) {
sourceLPort = (LPort) sourceElem;
} else if (sourceElem instanceof LNode) {
sourceLNode = (LNode) sourceElem;
sourceLPort = sourceLNode.getPorts().get(0);
}
}
// Find the transformed target port, if any
if (elkTargetShape instanceof ElkPort) {
// If the ElkPort is a regular port, it will map to an LPort; if it's an external port, it
// will map to an LNode
LGraphElement targetElem = nodeAndPortMap.get(elkTargetShape);
if (targetElem instanceof LPort) {
targetLPort = (LPort) targetElem;
} else if (targetElem instanceof LNode) {
targetLNode = (LNode) targetElem;
targetLPort = targetLNode.getPorts().get(0);
}
}
// reason, we back out
if (sourceLNode == null || targetLNode == null) {
throw new UnsupportedGraphException("The source or the target of edge " + elkedge + " could not be found. " + "This usually happens when an edge connects a node laid out by ELK Layered to a node in " + "another level of hierarchy laid out by either another instance of ELK Layered or another " + "layout algorithm alltogether. The former can be solved by setting the hierarchyHandling " + "option to INCLUDE_CHILDREN.");
}
// Create a layered edge
LEdge ledge = new LEdge();
ledge.copyProperties(elkedge);
ledge.setProperty(InternalProperties.ORIGIN, elkedge);
// Clear junction points, since they are recomputed from scratch
ledge.setProperty(LayeredOptions.JUNCTION_POINTS, null);
// If we have a self-loop, set the appropriate graph property
Set<GraphProperties> graphProperties = lgraph.getProperty(InternalProperties.GRAPH_PROPERTIES);
if (sourceLNode == targetLNode) {
graphProperties.add(GraphProperties.SELF_LOOPS);
}
// Create source and target ports if they do not exist yet
if (sourceLPort == null) {
PortType portType = PortType.OUTPUT;
KVector sourcePoint = null;
if (edgeSection != null && sourceLNode.getProperty(LayeredOptions.PORT_CONSTRAINTS).isSideFixed()) {
sourcePoint = new KVector(edgeSection.getStartX(), edgeSection.getStartY());
// The coordinates need to be relative to us
ElkUtil.toAbsolute(sourcePoint, elkedge.getContainingNode());
ElkUtil.toRelative(sourcePoint, elkparent);
// source), we may need to adjust the coordinates
if (ElkGraphUtil.isDescendant(elkTargetNode, elkSourceNode)) {
// External source port: put it on the west side
portType = PortType.INPUT;
sourcePoint.add(sourceLNode.getPosition());
}
}
sourceLPort = LGraphUtil.createPort(sourceLNode, sourcePoint, portType, lgraph);
}
if (targetLPort == null) {
PortType portType = PortType.INPUT;
KVector targetPoint = null;
if (edgeSection != null && targetLNode.getProperty(LayeredOptions.PORT_CONSTRAINTS).isSideFixed()) {
targetPoint = new KVector(edgeSection.getEndX(), edgeSection.getEndY());
// Adjust the coordinates
// MIGRATE Not sure yet if this really does what we want it to do
ElkUtil.toAbsolute(targetPoint, elkedge.getContainingNode());
ElkUtil.toRelative(targetPoint, elkparent);
}
targetLPort = LGraphUtil.createPort(targetLNode, targetPoint, portType, targetLNode.getGraph());
}
// Finally set the source and target of the edge
ledge.setSource(sourceLPort);
ledge.setTarget(targetLPort);
// If the ports have multiple incoming or outgoing edges, the HYPEREDGE property needs to be set
if (sourceLPort.getIncomingEdges().size() > 1 || sourceLPort.getOutgoingEdges().size() > 1 || targetLPort.getIncomingEdges().size() > 1 || targetLPort.getOutgoingEdges().size() > 1) {
graphProperties.add(GraphProperties.HYPEREDGES);
}
// Transform the edge's labels
for (ElkLabel elklabel : elkedge.getLabels()) {
if (!elklabel.getProperty(LayeredOptions.NO_LAYOUT) && !Strings.isNullOrEmpty(elklabel.getText())) {
LLabel llabel = transformLabel(elklabel);
ledge.getLabels().add(llabel);
// edge label placement is actually properly defined
switch(llabel.getProperty(LayeredOptions.EDGE_LABELS_PLACEMENT)) {
case HEAD:
case TAIL:
graphProperties.add(GraphProperties.END_LABELS);
break;
case CENTER:
graphProperties.add(GraphProperties.CENTER_LABELS);
llabel.setProperty(LayeredOptions.EDGE_LABELS_PLACEMENT, EdgeLabelPlacement.CENTER);
}
}
}
// Copy the original bend points of the edge in case they are required
CrossingMinimizationStrategy crossMinStrat = lgraph.getProperty(LayeredOptions.CROSSING_MINIMIZATION_STRATEGY);
NodePlacementStrategy nodePlaceStrat = lgraph.getProperty(LayeredOptions.NODE_PLACEMENT_STRATEGY);
boolean bendPointsRequired = crossMinStrat == CrossingMinimizationStrategy.INTERACTIVE || nodePlaceStrat == NodePlacementStrategy.INTERACTIVE;
if (edgeSection != null && !edgeSection.getBendPoints().isEmpty() && bendPointsRequired) {
KVectorChain originalBendpoints = ElkUtil.createVectorChain(edgeSection);
KVectorChain importedBendpoints = new KVectorChain();
// MIGRATE We may have to do some coordinate conversion here
for (KVector point : originalBendpoints) {
importedBendpoints.add(new KVector(point));
}
ledge.setProperty(InternalProperties.ORIGINAL_BENDPOINTS, importedBendpoints);
}
return ledge;
}
use of org.eclipse.elk.core.UnsupportedGraphException in project elk by eclipse.
the class ElkGraphImporter method transformEdges.
/**
* Transforms the edges defined by the given layout node.
*
* @param parentNode the layout node whose edges to transform.
* @param fgraph the force graph.
* @param elemMap the element map that maps the original {@code KGraph} elements to the
* transformed {@code FGraph} elements.
*/
private void transformEdges(final ElkNode parentNode, final FGraph fgraph, final Map<ElkNode, FNode> elemMap) {
for (ElkNode knode : parentNode.getChildren()) {
for (ElkEdge kedge : ElkGraphUtil.allOutgoingEdges(knode)) {
// We don't support hyperedges
if (kedge.isHyperedge()) {
throw new UnsupportedGraphException("Graph must not contain hyperedges.");
}
// exclude edges that pass hierarchy bounds as well as self-loops
if (!kedge.isHierarchical() && knode != ElkGraphUtil.connectableShapeToNode(kedge.getTargets().get(0))) {
// create a force edge
FEdge newEdge = new FEdge();
newEdge.copyProperties(kedge);
// TODO
// newEdge.checkProperties(Properties.LABEL_SPACING, Properties.REPULSIVE_POWER);
newEdge.setProperty(InternalProperties.ORIGIN, kedge);
newEdge.setSource(elemMap.get(knode));
newEdge.setTarget(elemMap.get(ElkGraphUtil.connectableShapeToNode(kedge.getTargets().get(0))));
fgraph.getEdges().add(newEdge);
// transform the edge's labels
for (ElkLabel klabel : kedge.getLabels()) {
FLabel newLabel = new FLabel(newEdge, klabel.getText());
newLabel.copyProperties(klabel);
newLabel.setProperty(InternalProperties.ORIGIN, klabel);
newLabel.getSize().x = Math.max(klabel.getWidth(), 1);
newLabel.getSize().y = Math.max(klabel.getHeight(), 1);
newLabel.refreshPosition();
fgraph.getLabels().add(newLabel);
}
}
}
}
}
use of org.eclipse.elk.core.UnsupportedGraphException in project elk by eclipse.
the class DotExporter method transformEdges.
/**
* Transform the edges of the given parent node.
*
* @param parent a parent node
* @param statements the list to which new statements are added
* @param transData transformation data
*/
private void transformEdges(final ElkNode parent, final List<Statement> statements, final IDotTransformationData<ElkNode, GraphvizModel> transData) {
boolean hierarchy = transData.getProperty(HIERARCHY);
boolean transformEdgeLayout = transData.getProperty(TRANSFORM_EDGE_LAYOUT);
Direction direction = parent.getProperty(CoreOptions.DIRECTION);
boolean vertical = direction == Direction.DOWN || direction == Direction.UP || direction == Direction.UNDEFINED;
LinkedList<ElkNode> nodes = new LinkedList<>(parent.getChildren());
BiMap<ElkGraphElement, String> nodeIds = transData.getProperty(GRAPH_ELEMS).inverse();
while (!nodes.isEmpty()) {
ElkNode source = nodes.removeFirst();
for (ElkEdge edge : ElkGraphUtil.allOutgoingEdges(source)) {
// We don't support hyperedges
if (edge.isHyperedge()) {
throw new UnsupportedGraphException("Hyperedges are not supported.");
}
ElkNode target = ElkGraphUtil.connectableShapeToNode(edge.getTargets().get(0));
// cross-hierarchy edges are considered only if hierarchy mode is active
if (source.getParent() == target.getParent() || hierarchy && isInsideGraph(target, transData.getSourceGraph())) {
EdgeStatement edgeStatement = DotFactory.eINSTANCE.createEdgeStatement();
List<Attribute> attributes = edgeStatement.getAttributes();
// set source node or cluster
Node sourceNode = DotFactory.eINSTANCE.createNode();
if (hierarchy && !source.getChildren().isEmpty()) {
sourceNode.setName(source.getProperty(CLUSTER_DUMMY));
attributes.add(createAttribute(Attributes.LTAIL, nodeIds.get(source)));
} else {
sourceNode.setName(nodeIds.get(source));
}
edgeStatement.setSourceNode(sourceNode);
// set target node or cluster
EdgeTarget edgeTarget = DotFactory.eINSTANCE.createEdgeTarget();
Node targetNode = DotFactory.eINSTANCE.createNode();
if (hierarchy && !target.getChildren().isEmpty()) {
targetNode.setName(target.getProperty(CLUSTER_DUMMY));
attributes.add(createAttribute(Attributes.LHEAD, nodeIds.get(target)));
} else {
targetNode.setName(nodeIds.get(target));
}
edgeTarget.setTargetnode(targetNode);
edgeStatement.getEdgeTargets().add(edgeTarget);
// add edge labels at head, tail, and middle position
setEdgeLabels(edge, attributes, vertical);
if (transData.getProperty(USE_EDGE_IDS)) {
// add comment with edge identifier
String edgeID = getEdgeID(edge, transData);
attributes.add(createAttribute(Attributes.COMMENT, "\"" + edgeID + "\""));
}
// include edge routing for full export, if there is one
if (!edge.getSections().isEmpty()) {
ElkEdgeSection edgeSection = edge.getSections().get(0);
if (transformEdgeLayout && (edgeSection.getBendPoints().size() > 0 || edgeSection.getStartX() != 0 || edgeSection.getStartY() != 0 || edgeSection.getEndX() != 0 || edgeSection.getEndY() != 0)) {
StringBuilder pos = new StringBuilder();
Iterator<KVector> pointIter = ElkUtil.createVectorChain(edgeSection).iterator();
while (pointIter.hasNext()) {
KVector point = pointIter.next();
ElkUtil.toAbsolute(point, edge.getContainingNode());
pos.append(point.x);
pos.append(",");
pos.append(point.y);
if (pointIter.hasNext()) {
pos.append(" ");
}
}
attributes.add(createAttribute(Attributes.POS, "\"" + pos + "\""));
}
}
statements.add(edgeStatement);
}
}
if (hierarchy) {
nodes.addAll(source.getChildren());
}
}
}
Aggregations