use of org.eclipse.elk.graph.ElkEdgeSection in project sirius-components by eclipse-sirius.
the class ELKLayoutedDiagramProvider method getLayoutedEdge.
private Edge getLayoutedEdge(Edge edge, ElkEdge elkEdge, Map<String, ElkGraphElement> id2ElkGraphElements) {
List<Position> routingPoints = new ArrayList<>();
ElkNode containingNode = elkEdge.getContainingNode();
double xOffset = 0;
double yOffset = 0;
if (containingNode != null) {
xOffset = containingNode.getX();
yOffset = containingNode.getY();
ElkNode parent = containingNode.getParent();
while (parent instanceof ElkNode) {
xOffset += parent.getX();
yOffset += parent.getY();
parent = parent.getParent();
}
}
if (!elkEdge.getSections().isEmpty()) {
ElkEdgeSection section = elkEdge.getSections().get(0);
Position startPosition = Position.at(xOffset + section.getStartX(), yOffset + section.getStartY());
routingPoints.add(startPosition);
for (ElkBendPoint bendPoint : section.getBendPoints()) {
Position position = Position.at(xOffset + bendPoint.getX(), yOffset + bendPoint.getY());
routingPoints.add(position);
}
Position endPosition = Position.at(xOffset + section.getEndX(), yOffset + section.getEndY());
routingPoints.add(endPosition);
}
Label beginLabel = edge.getBeginLabel();
if (beginLabel != null) {
beginLabel = this.getLayoutedLabel(beginLabel, id2ElkGraphElements, xOffset, yOffset);
}
Label centerLabel = edge.getCenterLabel();
if (centerLabel != null) {
centerLabel = this.getLayoutedLabel(centerLabel, id2ElkGraphElements, xOffset, yOffset);
}
Label endLabel = edge.getEndLabel();
if (endLabel != null) {
endLabel = this.getLayoutedLabel(endLabel, id2ElkGraphElements, xOffset, yOffset);
}
// @formatter:off
return Edge.newEdge(edge).beginLabel(beginLabel).centerLabel(centerLabel).endLabel(endLabel).routingPoints(routingPoints).build();
// @formatter:on
}
use of org.eclipse.elk.graph.ElkEdgeSection in project elk by eclipse.
the class StraightLineEdgeRouter method routeEdges.
/**
* Route edges from node center to node center. Then clip it, to not cross the node.
*/
public void routeEdges(final ElkNode node) {
for (ElkEdge edge : ElkGraphUtil.allOutgoingEdges(node)) {
if (!(edge.getSources().get(0) instanceof ElkPort)) {
ElkNode target = ElkGraphUtil.connectableShapeToNode(edge.getTargets().get(0));
if (!edge.isHierarchical()) {
double sourceX = node.getX() + node.getWidth() / 2;
double sourceY = node.getY() + node.getHeight() / 2;
double targetX = target.getX() + target.getWidth() / 2;
double targetY = target.getY() + target.getHeight() / 2;
// Clipping
KVector vector = new KVector();
vector.x = targetX - sourceX;
vector.y = targetY - sourceY;
KVector sourceClip = new KVector(vector.x, vector.y);
ElkMath.clipVector(sourceClip, node.getWidth(), node.getHeight());
vector.x -= sourceClip.x;
vector.y -= sourceClip.y;
sourceX = targetX - vector.x;
sourceY = targetY - vector.y;
KVector targetClip = new KVector(vector.x, vector.y);
ElkMath.clipVector(targetClip, target.getWidth(), target.getHeight());
vector.x -= targetClip.x;
vector.y -= targetClip.y;
targetX = sourceX + vector.x;
targetY = sourceY + vector.y;
ElkEdgeSection section = ElkGraphUtil.firstEdgeSection(edge, true, true);
section.setStartLocation(sourceX, sourceY);
section.setEndLocation(targetX, targetY);
routeEdges(target);
}
}
}
}
use of org.eclipse.elk.graph.ElkEdgeSection in project elk by eclipse.
the class GraphRenderer method renderEdge.
/**
* Paints an edge for the given dirty area.
*
* @param edge the edge to paint
* @param graphics the graphics context used to paint
* @param area dirty area that needs painting
* @param offset offset to be added to relative coordinates
* @param labelAlpha alpha value for labels
*/
private void renderEdge(final ElkEdge edge, final GC graphics, final Rectangle area, final KVector offset, final int labelAlpha) {
if (configurator.getEdgeColor() == null) {
return;
}
// Find our if the edge is actually eligible to be painted
if (isEdgeFullyContainedInGraphToDraw(edge)) {
// Get a PaintRectangle ready for the edge
PaintRectangle rect = boundsMap.get(edge);
if (rect == null) {
rect = new PaintRectangle(edge, offset, scale);
boundsMap.put(edge, rect);
}
if (!rect.painted && rect.intersects(area)) {
// Gather some information
final boolean splineEdge = edge.getProperty(CoreOptions.EDGE_ROUTING) == EdgeRouting.SPLINES;
final boolean directedEdge = edge.getProperty(CoreOptions.EDGE_TYPE) != EdgeType.UNDIRECTED;
graphics.setAlpha(255);
// The background color is required to fill the arrow of directed edges
graphics.setForeground(configurator.getEdgeColor());
graphics.setBackground(configurator.getEdgeColor());
for (ElkEdgeSection edgeSection : edge.getSections()) {
KVectorChain bendPoints = ElkUtil.createVectorChain(edgeSection);
bendPoints.scale(scale).offset(offset);
// Draw the damn edge already...!
Path path = new Path(graphics.getDevice());
Iterator<KVector> pointIter = bendPoints.iterator();
KVector startPoint = pointIter.next();
path.moveTo((float) startPoint.x, (float) startPoint.y);
KVector point1 = null;
KVector point2 = null;
while (pointIter.hasNext()) {
if (splineEdge) {
if (point1 == null) {
point1 = pointIter.next();
} else if (point2 == null) {
point2 = pointIter.next();
} else {
KVector endPoint = pointIter.next();
path.cubicTo((float) point1.x, (float) point1.y, (float) point2.x, (float) point2.y, (float) endPoint.x, (float) endPoint.y);
point1 = null;
point2 = null;
}
} else {
KVector nextPoint = pointIter.next();
path.lineTo((float) nextPoint.x, (float) nextPoint.y);
}
}
if (splineEdge && point2 != null) {
path.quadTo((float) point1.x, (float) point1.y, (float) point2.x, (float) point2.y);
} else if (splineEdge && point1 != null) {
path.lineTo((float) point1.x, (float) point1.y);
}
graphics.drawPath(path);
if (directedEdge) {
// Draw an arrow at the last segment of the connection
KVector referencePoint;
if (splineEdge && (bendPoints.size() - 1) % 3 != 1) {
int beginIndex;
if ((bendPoints.size() - 1) % 3 == 2) {
beginIndex = bendPoints.size() - 2;
} else {
beginIndex = bendPoints.size() - 3;
}
referencePoint = ElkMath.getPointOnBezierSegment(0.5, bendPoints.toArray(beginIndex));
} else {
referencePoint = bendPoints.get(bendPoints.size() - 2);
}
int[] arrowPoly = makeArrow(referencePoint, bendPoints.getLast());
if (arrowPoly != null) {
graphics.fillPolygon(arrowPoly);
}
}
}
rect.painted = true;
}
}
// paint junction points
KVectorChain vc = edge.getProperty(CoreOptions.JUNCTION_POINTS);
if (vc != null) {
for (KVector v : vc) {
KVector center = v.clone().scale(scale).add(offset).sub(2, 2);
graphics.fillOval((int) center.x, (int) center.y, 6, 6);
}
}
// paint the edge labels
if (configurator.getEdgeLabelFont() != null) {
graphics.setFont(configurator.getEdgeLabelFont());
for (ElkLabel label : edge.getLabels()) {
renderLabel(label, graphics, area, offset, labelAlpha);
}
}
}
use of org.eclipse.elk.graph.ElkEdgeSection in project elk by eclipse.
the class GraphRenderingCanvas method calculateRequiredCanvasSizeAndBaseOffset.
/**
* Sets size of the canvas by looking up the biggest distances between graph elements in x- and y-direction
* and return a KVector with the required offset of the origin coordinates to fit all elements on the canvas.
*
* @param graph to be painted
*/
private KVector calculateRequiredCanvasSizeAndBaseOffset(final ElkNode graph) {
if (graph != null) {
double minX = Double.MAX_VALUE;
double maxX = Double.MIN_VALUE;
double minY = Double.MAX_VALUE;
double maxY = Double.MIN_VALUE;
// check all nodes for their coordinates
for (ElkNode node : graph.getChildren()) {
minX = Math.min(minX, node.getX());
maxX = Math.max(maxX, node.getX() + node.getWidth());
minY = Math.min(minY, node.getY());
maxY = Math.max(maxY, node.getY() + node.getHeight());
// check node labels
for (ElkLabel nodeLabel : node.getLabels()) {
minX = Math.min(minX, node.getX() + nodeLabel.getX());
maxX = Math.max(maxX, node.getX() + nodeLabel.getX() + nodeLabel.getWidth());
minY = Math.min(minY, node.getY() + nodeLabel.getY());
maxY = Math.max(maxY, node.getY() + nodeLabel.getY() + nodeLabel.getHeight());
}
}
for (ElkEdge edge : graph.getContainedEdges()) {
// check all sections of the edges for their coordinates
for (ElkEdgeSection edgeSection : edge.getSections()) {
minX = Math.min(minX, edgeSection.getStartX());
minY = Math.min(minY, edgeSection.getStartY());
maxX = Math.max(maxX, edgeSection.getStartX());
maxY = Math.max(maxY, edgeSection.getStartY());
minX = Math.min(minX, edgeSection.getEndX());
minY = Math.min(minY, edgeSection.getEndY());
maxX = Math.max(maxX, edgeSection.getEndX());
maxY = Math.max(maxY, edgeSection.getEndY());
for (ElkBendPoint bendPoint : edgeSection.getBendPoints()) {
minX = Math.min(minX, bendPoint.getX());
minY = Math.min(minY, bendPoint.getY());
maxX = Math.max(maxX, bendPoint.getX());
maxY = Math.max(maxY, bendPoint.getY());
}
}
// check edge labels
for (ElkLabel edgeLabel : edge.getLabels()) {
minX = Math.min(minX, edgeLabel.getX());
maxX = Math.max(maxX, edgeLabel.getX() + edgeLabel.getWidth());
minY = Math.min(minY, edgeLabel.getY());
maxY = Math.max(maxY, edgeLabel.getY() + edgeLabel.getHeight());
}
}
int x = ((int) (Math.max(graph.getWidth(), maxX) - Math.min(0, minX))) + 1;
int y = ((int) (Math.max(graph.getHeight(), maxY) - Math.min(0, minY))) + 1;
setSize(new Point(x, y));
return new KVector((-Math.min(0, minX)), (-Math.min(0, minY)));
}
return new KVector();
}
use of org.eclipse.elk.graph.ElkEdgeSection in project elk by eclipse.
the class RecursiveGraphLayoutEngine method postProcessInsideSelfLoops.
/**
* Post-processes self loops routed inside by offsetting their coordinates by the coordinates of
* their parent node. The post processing is necessary since the self loop coordinates are
* relative to their parent node's upper left corner since, at that point, the parent node's
* final coordinates are not determined yet.
*
* @param insideSelfLoops
* list of inside self loops to post-process.
*/
protected void postProcessInsideSelfLoops(final List<ElkEdge> insideSelfLoops) {
for (final ElkEdge selfLoop : insideSelfLoops) {
// MIGRATE Adapt to hyperedges and make error-safe
final ElkConnectableShape node = ElkGraphUtil.connectableShapeToNode(selfLoop.getSources().get(0));
final double xOffset = node.getX();
final double yOffset = node.getY();
// Offset the edge coordinates by the node's position
// MIGRATE Adapt to hyperedges. Also, what about multiple edge sections?
ElkEdgeSection section = selfLoop.getSections().get(0);
section.setStartLocation(section.getStartX() + xOffset, section.getStartY() + yOffset);
section.setEndLocation(section.getEndX() + xOffset, section.getEndY() + yOffset);
for (final ElkBendPoint bend : section.getBendPoints()) {
bend.set(bend.getX() + xOffset, bend.getY() + yOffset);
}
// Offset junction points by the node position
selfLoop.getProperty(CoreOptions.JUNCTION_POINTS).offset(xOffset, yOffset);
}
}
Aggregations