use of org.eclipse.elk.alg.layered.options.GreedySwitchType 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.alg.layered.options.GreedySwitchType in project elk by eclipse.
the class GraphConfigurator method getPhaseIndependentLayoutProcessorConfiguration.
/**
* Returns an intermediate processing configuration with processors not tied to specific phases.
*
* @param lgraph the layered graph to be processed. The configuration may vary depending on certain
* properties of the graph.
* @return intermediate processing configuration. May be {@code null}.
*/
private LayoutProcessorConfiguration<LayeredPhases, LGraph> getPhaseIndependentLayoutProcessorConfiguration(final LGraph lgraph) {
Set<GraphProperties> graphProperties = lgraph.getProperty(InternalProperties.GRAPH_PROPERTIES);
// Basic configuration
LayoutProcessorConfiguration<LayeredPhases, LGraph> configuration = LayoutProcessorConfiguration.createFrom(BASELINE_PROCESSING_CONFIGURATION);
// Hierarchical layout.
// Note that the recursive graph layout engine made sure that at this point
// 'INCLUDE_CHILDREN' has been propagated to all parent nodes with 'INHERIT'.
// Thus, every lgraph of the hierarchical lgraph structure is configured with the following additions.
HierarchyHandling hierarchyHandling = lgraph.getProperty(LayeredOptions.HIERARCHY_HANDLING);
if (hierarchyHandling == HierarchyHandling.INCLUDE_CHILDREN) {
configuration.addAll(HIERARCHICAL_ADDITIONS);
}
// Port side processor, put to first slot only if requested and routing is orthogonal
if (lgraph.getProperty(LayeredOptions.FEEDBACK_EDGES)) {
configuration.addBefore(LayeredPhases.P1_CYCLE_BREAKING, IntermediateProcessorStrategy.PORT_SIDE_PROCESSOR);
} else {
configuration.addBefore(LayeredPhases.P3_NODE_ORDERING, IntermediateProcessorStrategy.PORT_SIDE_PROCESSOR);
}
// If the graph has a label manager, so add label management additions
if (lgraph.getProperty(LabelManagementOptions.LABEL_MANAGER) != null) {
configuration.addAll(LABEL_MANAGEMENT_ADDITIONS);
}
// If the graph should be laid out interactively, add the layers and positions to the nodes.
if (lgraph.getProperty(LayeredOptions.INTERACTIVE_LAYOUT)) {
configuration.addAfter(LayeredPhases.P5_EDGE_ROUTING, IntermediateProcessorStrategy.CONSTRAINTS_POSTPROCESSOR);
}
// graph transformations for unusual layout directions
switch(lgraph.getProperty(LayeredOptions.DIRECTION)) {
case LEFT:
case DOWN:
case UP:
configuration.addBefore(LayeredPhases.P1_CYCLE_BREAKING, IntermediateProcessorStrategy.DIRECTION_PREPROCESSOR).addAfter(LayeredPhases.P5_EDGE_ROUTING, IntermediateProcessorStrategy.DIRECTION_POSTPROCESSOR);
break;
default:
// don't need any processors here
break;
}
// Additional dependencies
if (graphProperties.contains(GraphProperties.COMMENTS)) {
configuration.addBefore(LayeredPhases.P1_CYCLE_BREAKING, IntermediateProcessorStrategy.COMMENT_PREPROCESSOR).addBefore(LayeredPhases.P4_NODE_PLACEMENT, IntermediateProcessorStrategy.COMMENT_NODE_MARGIN_CALCULATOR).addAfter(LayeredPhases.P5_EDGE_ROUTING, IntermediateProcessorStrategy.COMMENT_POSTPROCESSOR);
}
// Node-Promotion application for reduction of dummy nodes after layering
if (lgraph.getProperty(LayeredOptions.LAYERING_NODE_PROMOTION_STRATEGY) != NodePromotionStrategy.NONE) {
configuration.addBefore(LayeredPhases.P3_NODE_ORDERING, IntermediateProcessorStrategy.NODE_PROMOTION);
}
// Preserve certain partitions during layering
if (graphProperties.contains(GraphProperties.PARTITIONS)) {
configuration.addBefore(LayeredPhases.P1_CYCLE_BREAKING, IntermediateProcessorStrategy.PARTITION_PREPROCESSOR);
configuration.addBefore(LayeredPhases.P2_LAYERING, IntermediateProcessorStrategy.PARTITION_MIDPROCESSOR);
configuration.addBefore(LayeredPhases.P3_NODE_ORDERING, IntermediateProcessorStrategy.PARTITION_POSTPROCESSOR);
}
// Additional horizontal compaction depends on orthogonal edge routing
if (lgraph.getProperty(LayeredOptions.COMPACTION_POST_COMPACTION_STRATEGY) != GraphCompactionStrategy.NONE && lgraph.getProperty(LayeredOptions.EDGE_ROUTING) != EdgeRouting.POLYLINE) {
configuration.addAfter(LayeredPhases.P5_EDGE_ROUTING, IntermediateProcessorStrategy.HORIZONTAL_COMPACTOR);
}
// Move trees of high degree nodes to separate layers
if (lgraph.getProperty(LayeredOptions.HIGH_DEGREE_NODES_TREATMENT)) {
configuration.addBefore(LayeredPhases.P3_NODE_ORDERING, IntermediateProcessorStrategy.HIGH_DEGREE_NODE_LAYER_PROCESSOR);
}
// Introduce in-layer constraints to preserve the order of regular nodes
if (lgraph.getProperty(LayeredOptions.CROSSING_MINIMIZATION_SEMI_INTERACTIVE)) {
configuration.addBefore(LayeredPhases.P3_NODE_ORDERING, IntermediateProcessorStrategy.SEMI_INTERACTIVE_CROSSMIN_PROCESSOR);
}
// ElkLayered#reviewAndCorrectHierarchicalProcessors(...)
if (activateGreedySwitchFor(lgraph)) {
final GreedySwitchType greedySwitchType;
if (isHierarchicalLayout(lgraph)) {
greedySwitchType = lgraph.getProperty(LayeredOptions.CROSSING_MINIMIZATION_GREEDY_SWITCH_HIERARCHICAL_TYPE);
} else {
greedySwitchType = lgraph.getProperty(LayeredOptions.CROSSING_MINIMIZATION_GREEDY_SWITCH_TYPE);
}
IntermediateProcessorStrategy internalGreedyType = (greedySwitchType == GreedySwitchType.ONE_SIDED) ? IntermediateProcessorStrategy.ONE_SIDED_GREEDY_SWITCH : IntermediateProcessorStrategy.TWO_SIDED_GREEDY_SWITCH;
configuration.addBefore(LayeredPhases.P4_NODE_PLACEMENT, internalGreedyType);
}
// Wrapping of graphs
switch(lgraph.getProperty(LayeredOptions.WRAPPING_STRATEGY)) {
case SINGLE_EDGE:
configuration.addBefore(LayeredPhases.P4_NODE_PLACEMENT, IntermediateProcessorStrategy.SINGLE_EDGE_GRAPH_WRAPPER);
break;
case MULTI_EDGE:
configuration.addBefore(LayeredPhases.P3_NODE_ORDERING, IntermediateProcessorStrategy.BREAKING_POINT_INSERTER).addBefore(LayeredPhases.P4_NODE_PLACEMENT, IntermediateProcessorStrategy.BREAKING_POINT_PROCESSOR).addAfter(LayeredPhases.P5_EDGE_ROUTING, IntermediateProcessorStrategy.BREAKING_POINT_REMOVER);
break;
// OFF
default:
}
if (lgraph.getProperty(LayeredOptions.CONSIDER_MODEL_ORDER_STRATEGY) != OrderingStrategy.NONE) {
configuration.addBefore(LayeredPhases.P3_NODE_ORDERING, IntermediateProcessorStrategy.SORT_BY_INPUT_ORDER_OF_MODEL);
}
return configuration;
}
use of org.eclipse.elk.alg.layered.options.GreedySwitchType in project elk by eclipse.
the class GraphConfigurator method activateGreedySwitchFor.
/**
* Greedy switch may be activated if the following holds.
*
* <h3>Hierarchical layout</h3>
* <ol>
* <li>the {@link LayeredOptions#CROSSING_MINIMIZATION_GREEDY_SWITCH_HIERARCHICAL_TYPE} is set to something
* different than OFF</li>
* </ol>
*
* <h3>Non-hierarchical layout</h3>
* <ol>
* <li>no interactive crossing minimization is performed</li>
* <li>the {@link LayeredOptions#CROSSING_MINIMIZATION_GREEDY_SWITCH_TYPE} option is set to something different
* than OFF</li>
* <li>the activationThreshold is larger than or equal to the graph's number of nodes (or '0')</li>
* </ol>
* @return {@code true} if above condition holds, {@code false} otherwise.
*/
public static boolean activateGreedySwitchFor(final LGraph lgraph) {
// First, check the hierarchical case
if (isHierarchicalLayout(lgraph)) {
// (and thus doesn't have to be checked here).
return lgraph.getParentNode() == null && lgraph.getProperty(LayeredOptions.CROSSING_MINIMIZATION_GREEDY_SWITCH_HIERARCHICAL_TYPE) != GreedySwitchType.OFF;
}
// Second, if not hierarchical, check the slightly more complex non-hierarchical case
GreedySwitchType greedySwitchType = lgraph.getProperty(LayeredOptions.CROSSING_MINIMIZATION_GREEDY_SWITCH_TYPE);
boolean interactiveCrossMin = lgraph.getProperty(LayeredOptions.CROSSING_MINIMIZATION_SEMI_INTERACTIVE) || lgraph.getProperty(LayeredOptions.CROSSING_MINIMIZATION_STRATEGY) == CrossingMinimizationStrategy.INTERACTIVE;
int activationThreshold = lgraph.getProperty(LayeredOptions.CROSSING_MINIMIZATION_GREEDY_SWITCH_ACTIVATION_THRESHOLD);
int graphSize = lgraph.getLayerlessNodes().size();
return !interactiveCrossMin && greedySwitchType != GreedySwitchType.OFF && (activationThreshold == 0 || activationThreshold > graphSize);
}
Aggregations