Search in sources :

Example 6 with FGraph

use of org.eclipse.elk.alg.force.graph.FGraph in project elk by eclipse.

the class ComponentsProcessor method recombine.

// ///////////////////////////////////////////////////////////////////////////////////////////
// Recombination
/**
 * Pack the given components into a single graph.
 *
 * @param components a list of components.
 * @return a single graph that contains all components.
 */
public FGraph recombine(final List<FGraph> components) {
    if (components.size() == 1) {
        return components.get(0);
    } else if (components.size() <= 0) {
        return new FGraph();
    }
    // assign priorities and sizes
    for (FGraph graph : components) {
        int priority = 0;
        double minx = Integer.MAX_VALUE, miny = Integer.MAX_VALUE, maxx = Integer.MIN_VALUE, maxy = Integer.MIN_VALUE;
        for (FNode node : graph.getNodes()) {
            priority += node.getProperty(ForceOptions.PRIORITY);
            // careful: the (x,y) of an FNode refers to its center
            minx = Math.min(minx, node.getPosition().x - node.getSize().x / 2);
            miny = Math.min(miny, node.getPosition().y - node.getSize().y / 2);
            maxx = Math.max(maxx, node.getPosition().x + node.getSize().x / 2);
            maxy = Math.max(maxy, node.getPosition().y + node.getSize().y / 2);
        }
        graph.setProperty(ForceOptions.PRIORITY, priority);
        graph.setProperty(InternalProperties.BB_UPLEFT, new KVector(minx, miny));
        graph.setProperty(InternalProperties.BB_LOWRIGHT, new KVector(maxx, maxy));
    }
    // sort the components by their priority and size
    Collections.sort(components, new Comparator<FGraph>() {

        public int compare(final FGraph graph1, final FGraph graph2) {
            int prio = graph2.getProperty(ForceOptions.PRIORITY) - graph1.getProperty(ForceOptions.PRIORITY);
            if (prio == 0) {
                KVector size1 = graph1.getProperty(InternalProperties.BB_LOWRIGHT).clone().sub(graph1.getProperty(InternalProperties.BB_UPLEFT));
                KVector size2 = graph2.getProperty(InternalProperties.BB_LOWRIGHT).clone().sub(graph2.getProperty(InternalProperties.BB_UPLEFT));
                return Double.compare(size1.x * size1.y, size2.x * size2.y);
            }
            return prio;
        }
    });
    FGraph result = new FGraph();
    result.copyProperties(components.get(0));
    // determine the maximal row width by the maximal box width and the total area
    double maxRowWidth = 0.0f;
    double totalArea = 0.0f;
    for (FGraph graph : components) {
        KVector size = graph.getProperty(InternalProperties.BB_LOWRIGHT).clone().sub(graph.getProperty(InternalProperties.BB_UPLEFT));
        maxRowWidth = Math.max(maxRowWidth, size.x);
        totalArea += size.x * size.y;
    }
    maxRowWidth = Math.max(maxRowWidth, (float) Math.sqrt(totalArea) * result.getProperty(ForceOptions.ASPECT_RATIO));
    double spacing = result.getProperty(ForceOptions.SPACING_NODE_NODE).doubleValue();
    // place nodes iteratively into rows
    double xpos = 0, ypos = 0, highestBox = 0, broadestRow = spacing;
    for (FGraph graph : components) {
        KVector size = graph.getProperty(InternalProperties.BB_LOWRIGHT).clone().sub(graph.getProperty(InternalProperties.BB_UPLEFT));
        if (xpos + size.x > maxRowWidth) {
            // place the graph into the next row
            xpos = 0;
            ypos += highestBox + spacing;
            highestBox = 0;
        }
        moveGraph(result, graph, xpos, ypos);
        broadestRow = Math.max(broadestRow, xpos + size.x);
        highestBox = Math.max(highestBox, size.y);
        xpos += size.x + spacing;
    }
    return result;
}
Also used : FNode(org.eclipse.elk.alg.force.graph.FNode) FGraph(org.eclipse.elk.alg.force.graph.FGraph) KVector(org.eclipse.elk.core.math.KVector) FBendpoint(org.eclipse.elk.alg.force.graph.FBendpoint)

Example 7 with FGraph

use of org.eclipse.elk.alg.force.graph.FGraph in project elk by eclipse.

the class ComponentsProcessor method split.

// ///////////////////////////////////////////////////////////////////////////////////////////
// Splitting
/**
 * Split the given graph into its connected components.
 *
 * @param graph an input graph.
 * @return a list of components that can be processed one by one.
 */
public List<FGraph> split(final FGraph graph) {
    Boolean separate = graph.getProperty(ForceOptions.SEPARATE_CONNECTED_COMPONENTS);
    if (separate == null || separate.booleanValue()) {
        boolean[] visited = new boolean[graph.getNodes().size()];
        List<FEdge>[] incidence = buildIncidenceLists(graph);
        // perform DFS starting on each node, collecting connected components
        List<FGraph> components = new LinkedList<FGraph>();
        for (FNode node : graph.getNodes()) {
            FGraph comp = dfs(node, null, null, visited, incidence);
            if (comp != null) {
                comp.copyProperties(graph);
                components.add(comp);
            }
        }
        // redistribute identifier numbers to each component
        if (components.size() > 1) {
            for (FGraph comp : components) {
                int id = 0;
                for (FNode node : comp.getNodes()) {
                    node.id = id++;
                }
            }
        }
        return components;
    }
    return Lists.newArrayList(graph);
}
Also used : FNode(org.eclipse.elk.alg.force.graph.FNode) FGraph(org.eclipse.elk.alg.force.graph.FGraph) List(java.util.List) LinkedList(java.util.LinkedList) LinkedList(java.util.LinkedList) FBendpoint(org.eclipse.elk.alg.force.graph.FBendpoint)

Example 8 with FGraph

use of org.eclipse.elk.alg.force.graph.FGraph in project elk by eclipse.

the class ElkGraphImporter method importGraph.

// /////////////////////////////////////////////////////////////////////////////
// Transformation KGraph -> FGraph
@Override
public FGraph importGraph(final ElkNode kgraph) {
    FGraph fgraph = new FGraph();
    // copy the properties of the KGraph to the force graph
    fgraph.copyProperties(kgraph);
    // TODO Find another way to do this kind of bounds checking
    // fgraph.checkProperties(Properties.SPACING, Properties.ASPECT_RATIO, Properties.TEMPERATURE,
    // Properties.ITERATIONS, Properties.REPULSION);
    fgraph.setProperty(InternalProperties.ORIGIN, kgraph);
    // keep a list of created nodes in the force graph
    Map<ElkNode, FNode> elemMap = new HashMap<ElkNode, FNode>();
    // transform everything
    transformNodes(kgraph, fgraph, elemMap);
    transformEdges(kgraph, fgraph, elemMap);
    return fgraph;
}
Also used : ElkNode(org.eclipse.elk.graph.ElkNode) HashMap(java.util.HashMap) FNode(org.eclipse.elk.alg.force.graph.FNode) FGraph(org.eclipse.elk.alg.force.graph.FGraph)

Example 9 with FGraph

use of org.eclipse.elk.alg.force.graph.FGraph in project elk by eclipse.

the class StressLayoutProvider method layout.

@Override
public void layout(final ElkNode layoutGraph, final IElkProgressMonitor progressMonitor) {
    progressMonitor.begin("ELK Stress", 1);
    // calculate initial coordinates
    if (!layoutGraph.getProperty(StressOptions.INTERACTIVE)) {
        new ForceLayoutProvider().layout(layoutGraph, progressMonitor.subTask(1));
    } else {
        // Note that for the non-interactive case (above) this will be taken care of by the force layout provider
        if (!layoutGraph.getProperty(StressOptions.OMIT_NODE_MICRO_LAYOUT)) {
            NodeMicroLayout.forGraph(layoutGraph).execute();
        }
    }
    // transform the input graph
    IGraphImporter<ElkNode> graphImporter = new ElkGraphImporter();
    FGraph fgraph = graphImporter.importGraph(layoutGraph);
    // split the input graph into components
    List<FGraph> components = componentsProcessor.split(fgraph);
    // perform the actual layout
    for (FGraph subGraph : components) {
        if (subGraph.getNodes().size() <= 1) {
            continue;
        }
        stressMajorization.initialize(subGraph);
        stressMajorization.execute();
        // Note that contrary to force itself, labels are not considered during stress layout.
        // Hence, all we can do here is to place the labels at reasonable positions after layout has finished.
        subGraph.getLabels().forEach(label -> label.refreshPosition());
    }
    // pack the components back into one graph
    fgraph = componentsProcessor.recombine(components);
    // apply the layout results to the original graph
    graphImporter.applyLayout(fgraph);
    progressMonitor.done();
}
Also used : ForceLayoutProvider(org.eclipse.elk.alg.force.ForceLayoutProvider) ElkNode(org.eclipse.elk.graph.ElkNode) ElkGraphImporter(org.eclipse.elk.alg.force.ElkGraphImporter) FGraph(org.eclipse.elk.alg.force.graph.FGraph)

Aggregations

FGraph (org.eclipse.elk.alg.force.graph.FGraph)9 FNode (org.eclipse.elk.alg.force.graph.FNode)3 ElkNode (org.eclipse.elk.graph.ElkNode)3 Test (org.junit.Test)3 ComponentsProcessor (org.eclipse.elk.alg.force.ComponentsProcessor)2 FBendpoint (org.eclipse.elk.alg.force.graph.FBendpoint)2 HashMap (java.util.HashMap)1 LinkedList (java.util.LinkedList)1 List (java.util.List)1 ElkGraphImporter (org.eclipse.elk.alg.force.ElkGraphImporter)1 ForceLayoutProvider (org.eclipse.elk.alg.force.ForceLayoutProvider)1 FEdge (org.eclipse.elk.alg.force.graph.FEdge)1 KVector (org.eclipse.elk.core.math.KVector)1