use of org.eclipse.elk.core.math.KVector in project elk by eclipse.
the class DotImporter method transformAttribute.
/**
* Apply the property given in the attribute to a property holder.
*
* @param target the property holder that receives the new property
* @param attribute a Graphviz attribute that contains the property
* @param transData transformation data
*/
private void transformAttribute(final IPropertyHolder target, final Attribute attribute, final IDotTransformationData<GraphvizModel, ElkNode> transData) {
String name = attribute.getName();
String value = trimValue(attribute);
try {
if (Attributes.LAYOUT.equals(name)) {
Command command = Command.parse(value);
if (command != Command.INVALID) {
target.setProperty(CoreOptions.ALGORITHM, "org.eclipse.elk.algorithm.graphviz." + command);
} else {
target.setProperty(CoreOptions.ALGORITHM, value);
}
} else if (Attributes.WIDTH.equals(name)) {
target.setProperty(PROP_DEF_WIDTH, Float.valueOf(value) * DotExporter.DPI);
} else if (Attributes.HEIGHT.equals(name)) {
target.setProperty(PROP_DEF_HEIGHT, Float.valueOf(value) * DotExporter.DPI);
} else if (Attributes.FIXEDSIZE.equals(name)) {
Boolean fixedSize = Boolean.valueOf(value);
target.setProperty(CoreOptions.NODE_SIZE_CONSTRAINTS, fixedSize ? SizeConstraint.fixed() : EnumSet.of(SizeConstraint.MINIMUM_SIZE));
} else if (Attributes.NODESEP.equals(name)) {
target.setProperty(CoreOptions.SPACING_NODE_NODE, Double.valueOf(value));
} else if (Attributes.PACK.equals(name)) {
target.setProperty(CoreOptions.SEPARATE_CONNECTED_COMPONENTS, Boolean.valueOf(value));
} else if (Attributes.PAD.equals(name)) {
if (value.indexOf(',') >= 0) {
KVector pad = new KVector();
pad.parse(value);
ElkPadding padding = new ElkPadding(pad.x / 2, pad.y / 2);
target.setProperty(CoreOptions.PADDING, padding);
} else {
target.setProperty(CoreOptions.PADDING, new ElkPadding(Float.valueOf(value)));
}
} else if (Attributes.RANKDIR.equals(name)) {
if (value.equals("TB")) {
target.setProperty(CoreOptions.DIRECTION, Direction.DOWN);
} else if (value.equals("BT")) {
target.setProperty(CoreOptions.DIRECTION, Direction.UP);
} else if (value.equals("LR")) {
target.setProperty(CoreOptions.DIRECTION, Direction.RIGHT);
} else if (value.equals("RL")) {
target.setProperty(CoreOptions.DIRECTION, Direction.LEFT);
}
} else if (Attributes.SPLINES.equals(name)) {
if (value.equals("spline") || value.equals("true")) {
target.setProperty(CoreOptions.EDGE_ROUTING, EdgeRouting.SPLINES);
} else if (value.equals("polyline") || value.equals("line") || value.equals("false")) {
target.setProperty(CoreOptions.EDGE_ROUTING, EdgeRouting.POLYLINE);
} else if (value.equals("ortho")) {
target.setProperty(CoreOptions.EDGE_ROUTING, EdgeRouting.ORTHOGONAL);
}
} else if (Attributes.START.equals(name)) {
if (value.startsWith("random")) {
int random = 0;
try {
random = Integer.parseInt(value.substring("random".length()));
} catch (NumberFormatException e) {
// ignore exception
}
target.setProperty(CoreOptions.RANDOM_SEED, random);
}
} else if (Attributes.WEIGHT.equals(name)) {
target.setProperty(CoreOptions.PRIORITY, (int) Float.parseFloat(value));
}
} catch (NumberFormatException exception) {
transData.log("Discarding attribute " + attribute.getName() + "=" + attribute.getValue() + " since its value could not be parsed correctly.");
} catch (IllegalArgumentException exception) {
transData.log("Discarding attribute " + attribute.getName() + "=" + attribute.getValue() + " since its value could not be parsed correctly.");
}
}
use of org.eclipse.elk.core.math.KVector in project elk by eclipse.
the class DotImporter method applyLayout.
/**
* Apply layout to an edge and its labels.
*
* @param edge an edge
* @param offset its offset in the graph
* @param graph the Graphviz graph
*/
private void applyLayout(final ElkEdge edge, final KVector offset, final Graph graph) {
EdgeStatement edgeStatement = (EdgeStatement) edge.getProperty(PROP_STATEMENT);
if (edgeStatement.eContainer() == null) {
// this can happen when an edge with multiple target declarations was found
graph.getStatements().add(edgeStatement);
}
// transfer edge bend points and source / target points
List<Attribute> attributes = edgeStatement.getAttributes();
removeAttributes(attributes, Attributes.POS);
if (!edge.getSections().isEmpty()) {
StringBuilder bendpointString = new StringBuilder("\"");
KVectorChain vectorChain = ElkUtil.createVectorChain(edge.getSections().get(0));
ListIterator<KVector> chainIter = vectorChain.listIterator();
while (chainIter.hasNext()) {
KVector point = chainIter.next().add(offset);
bendpointString.append(point.x);
bendpointString.append(',');
bendpointString.append(point.y);
if (chainIter.hasNext()) {
bendpointString.append(' ');
}
}
bendpointString.append('\"');
attributes.add(DotExporter.createAttribute(Attributes.POS, bendpointString.toString()));
}
// transfer label positions
for (ElkLabel label : edge.getLabels()) {
String attrKey = null;
switch(label.getProperty(CoreOptions.EDGE_LABELS_PLACEMENT)) {
case CENTER:
attrKey = Attributes.LABELPOS;
break;
case HEAD:
attrKey = Attributes.HEADLP;
break;
case TAIL:
attrKey = Attributes.TAILLP;
break;
}
if (attrKey != null) {
removeAttributes(attributes, attrKey);
double xpos = label.getX() + label.getWidth() / 2 + offset.x;
double ypos = label.getY() + label.getHeight() / 2 + offset.y;
String posString = "\"" + Double.toString(xpos) + "," + Double.toString(ypos) + "\"";
attributes.add(DotExporter.createAttribute(attrKey, posString));
}
}
}
use of org.eclipse.elk.core.math.KVector in project elk by eclipse.
the class DotImporter method applyLayout.
/*---------- Layout Transfer KGraph to Dot ----------*/
/**
* Apply layout to a parent node and its children.
*
* @param parent a parent node
* @param offset the node's offset in the graph
* @param graph the Graphviz graph
*/
private void applyLayout(final ElkNode parent, final KVector offset, final Graph graph) {
for (ElkNode elknode : parent.getChildren()) {
Statement statement = elknode.getProperty(PROP_STATEMENT);
if (statement == null) {
// the node was only declared implicitly - create an explicit declaration
NodeStatement stm = DotFactory.eINSTANCE.createNodeStatement();
Node node = DotFactory.eINSTANCE.createNode();
node.setName(elknode.getProperty(PROP_ID));
stm.setNode(node);
graph.getStatements().add(stm);
statement = stm;
}
if (statement instanceof NodeStatement) {
List<Attribute> attributes = ((NodeStatement) statement).getAttributes();
// transfer node position
removeAttributes(attributes, Attributes.POS);
double xpos = elknode.getX() + elknode.getWidth() / 2 + offset.x;
double ypos = elknode.getY() + elknode.getHeight() / 2 + offset.y;
String posString = "\"" + Double.toString(xpos) + "," + Double.toString(ypos) + "\"";
attributes.add(DotExporter.createAttribute(Attributes.POS, posString));
// transfer node size
removeAttributes(attributes, Attributes.WIDTH);
attributes.add(DotExporter.createAttribute(Attributes.WIDTH, elknode.getWidth() / DotExporter.DPI));
removeAttributes(attributes, Attributes.HEIGHT);
attributes.add(DotExporter.createAttribute(Attributes.HEIGHT, elknode.getHeight() / DotExporter.DPI));
} else if (statement instanceof Subgraph) {
applyLayout(elknode, new KVector(offset).add(elknode.getX(), elknode.getY()), graph);
}
for (ElkEdge elkedge : ElkGraphUtil.allOutgoingEdges(elknode)) {
applyLayout(elkedge, offset, graph);
}
}
// transfer graph size to bounding box
List<Statement> statements;
Statement graphStm = parent.getProperty(PROP_STATEMENT);
if (graphStm instanceof Subgraph) {
statements = ((Subgraph) graphStm).getStatements();
} else {
statements = graph.getStatements();
}
removeGraphAttributes(statements, Attributes.BOUNDINGBOX);
String bbString = "\"0,0," + Double.toString(parent.getWidth()) + "," + Double.toString(parent.getHeight()) + "\"";
statements.add(DotExporter.createAttribute(Attributes.BOUNDINGBOX, bbString));
}
use of org.eclipse.elk.core.math.KVector in project elk by eclipse.
the class DotImporter method transform.
/*---------- Transformation Dot to KGraph ----------*/
/**
* Transform a Dot graph to a KNode.
*
* @param statements
* a list of Dot statements
* @param parent
* a KNode
* @param transData
* transformation data instance
* @param nodeProps
* properties that are applied to all nodes
* @param edgeProps
* properties that are applied to all edges
*/
private void transform(final List<Statement> statements, final ElkNode parent, final IDotTransformationData<GraphvizModel, ElkNode> transData, final IPropertyHolder nodeProps, final IPropertyHolder edgeProps) {
DotSwitch<Object> statementSwitch = new DotSwitch<Object>() {
public Object caseNodeStatement(final NodeStatement statement) {
transformNode(statement, parent, transData, nodeProps);
return null;
}
public Object caseEdgeStatement(final EdgeStatement statement) {
transformEdge(statement, parent, transData, edgeProps);
return null;
}
public Object caseSubgraph(final Subgraph subgraph) {
ElkNode subElkNode = parent;
if (subgraph.getName() != null && subgraph.getName().startsWith("cluster")) {
subElkNode = transformNode(subgraph.getName(), parent, transData);
if (subElkNode.getProperty(PROP_STATEMENT) != null) {
transData.log("Discarding cluster subgraph \"" + subgraph.getName() + "\" since its id is already used.");
return null;
} else {
// the subgraph inherits all settings of its parent
subElkNode.copyProperties(parent);
subElkNode.setProperty(PROP_STATEMENT, subgraph);
}
}
MapPropertyHolder subNodeProps = new MapPropertyHolder();
subNodeProps.copyProperties(nodeProps);
MapPropertyHolder subEdgeProps = new MapPropertyHolder();
subEdgeProps.copyProperties(edgeProps);
transform(subgraph.getStatements(), subElkNode, transData, subNodeProps, subEdgeProps);
return null;
}
public Object caseAttributeStatement(final AttributeStatement statement) {
switch(statement.getType()) {
case GRAPH:
for (Attribute attr : statement.getAttributes()) {
caseAttribute(attr);
}
break;
case NODE:
for (Attribute attr : statement.getAttributes()) {
transformAttribute(nodeProps, attr, transData);
}
break;
case EDGE:
for (Attribute attr : statement.getAttributes()) {
transformAttribute(edgeProps, attr, transData);
}
break;
}
return null;
}
public Object caseAttribute(final Attribute attribute) {
if (Attributes.MARGIN.equals(attribute.getName())) {
ElkPadding padding = parent.getProperty(CoreOptions.PADDING);
if (attribute.getValue().indexOf(',') >= 0) {
KVector value = new KVector();
try {
value.parse(attribute.getValue());
padding.setLeft((float) value.x);
padding.setRight((float) value.x);
padding.setTop((float) value.y);
padding.setBottom((float) value.y);
} catch (IllegalArgumentException exception) {
transData.log("Discarding attribute \"" + attribute.getName() + "\" since its value could not be parsed correctly.");
}
} else {
try {
float value = Float.parseFloat(trimValue(attribute));
padding.setLeft(value);
padding.setRight(value);
padding.setTop(value);
padding.setBottom(value);
} catch (NumberFormatException exception) {
transData.log("Discarding attribute \"" + attribute.getName() + "\" since its value could not be parsed correctly.");
}
}
} else {
transformAttribute(parent, attribute, transData);
}
return null;
}
};
for (Statement statement : statements) {
statementSwitch.doSwitch(statement);
}
}
use of org.eclipse.elk.core.math.KVector in project elk by eclipse.
the class InteractiveCrossingMinimizer method getPos.
/**
* Determine a vertical position for the given node.
*
* @param node a node
* @param horizPos the horizontal position at which to measure (relevant for edges)
* @return the vertical position used for sorting
*/
private double getPos(final LNode node, final double horizPos) {
switch(node.getType()) {
case LONG_EDGE:
LEdge edge = (LEdge) node.getProperty(InternalProperties.ORIGIN);
// reconstruct the original bend points from the node annotations
KVectorChain bendpoints = edge.getProperty(InternalProperties.ORIGINAL_BENDPOINTS);
if (bendpoints == null) {
bendpoints = new KVectorChain();
} else if (edge.getProperty(InternalProperties.REVERSED)) {
bendpoints = KVectorChain.reverse(bendpoints);
}
// Check if we can determine the position just by using the source point, if we can determine it
LPort source = node.getProperty(InternalProperties.LONG_EDGE_SOURCE);
if (source != null) {
KVector sourcePoint = source.getAbsoluteAnchor();
if (horizPos <= sourcePoint.x) {
return sourcePoint.y;
}
bendpoints.addFirst(sourcePoint);
}
// Check if we can determine the position just by using the target point
LPort target = node.getProperty(InternalProperties.LONG_EDGE_TARGET);
if (target != null) {
KVector targetPoint = target.getAbsoluteAnchor();
if (targetPoint.x <= horizPos) {
return targetPoint.y;
}
bendpoints.addLast(targetPoint);
}
// Find the two points along the edge that the horizontal point lies between
if (bendpoints.size() >= 2) {
Iterator<KVector> pointIter = bendpoints.iterator();
KVector point1 = pointIter.next();
KVector point2 = pointIter.next();
while (point2.x < horizPos && pointIter.hasNext()) {
point1 = point2;
point2 = pointIter.next();
}
return point1.y + (horizPos - point1.x) / (point2.x - point1.x) * (point2.y - point1.y);
}
break;
case NORTH_SOUTH_PORT:
// Get one of the ports the dummy node was created for, and its original node
LPort originPort = (LPort) node.getPorts().get(0).getProperty(InternalProperties.ORIGIN);
LNode originNode = originPort.getNode();
switch(originPort.getSide()) {
case NORTH:
// by respecting node successor constraints.
return originNode.getPosition().y;
case SOUTH:
// Use the position of the node's southern side
return originNode.getPosition().y + originNode.getSize().y;
}
break;
}
// the fallback solution is to take the previous position of the node's anchor point
return node.getInteractiveReferencePoint().y;
}
Aggregations