Search in sources :

Example 1 with Node

use of org.knime.workbench.ui.layout.Graph.Node in project knime-core by knime.

the class SimpleLayouter method doLayout.

public void doLayout(final Graph g) throws RuntimeException {
    double x = 1;
    double y = 50;
    Node start = null;
    for (Node n : g.nodes()) {
        if (!n.inEdges().hasNext()) {
            start = n;
            break;
        }
    }
    if (start == null) {
        throw new RuntimeException("No start node found");
    }
    y = g.getY(start);
    while (start != null) {
        System.out.println("Node " + start + ": " + x + ", " + y);
        g.setCoordinates(start, x, y);
        x += NodeContainerFigure.WIDTH * 1.5;
        if (start.outEdges().hasNext()) {
            start = start.outEdges().next().target();
        } else {
            start = null;
        }
    }
}
Also used : Node(org.knime.workbench.ui.layout.Graph.Node)

Example 2 with Node

use of org.knime.workbench.ui.layout.Graph.Node in project knime-core by knime.

the class CrossingMinimizer method greedySwitch.

/**
 * perform a greedy switch going from first to last layer. In each layer,
 * switch consecutive nodes if crossing number is reduced. Fixed layers are
 * excluded by given offsets.
 *
 * @param sourceOffset
 * @param sinkOffset
 */
private void greedySwitch(final int sourceOffset, final int sinkOffset) {
    for (int i = sourceOffset; i < m_layers.size() - sinkOffset; i++) {
        ArrayList<Node> curLayer = m_layers.get(i);
        int oldCross = Integer.MAX_VALUE;
        int cross = numberOfCrossingsPrevLayer(i);
        int crossTemp = cross;
        do {
            for (int j = 0; j < curLayer.size() - 1; j++) {
                Node u = curLayer.get(j);
                Node v = curLayer.get(j + 1);
                switchNodes(u, v, curLayer, j);
                // if switch produces less crossings keep it
                // i.e., if switch produces equal or more crossings, switch
                // back
                int c = numberOfCrossingsPrevLayer(i);
                if (c >= crossTemp) {
                    switchNodes(v, u, curLayer, j);
                } else {
                    // crossing number is reduced -> store new crossing
                    // number
                    crossTemp = c;
                }
            }
            oldCross = cross;
            cross = numberOfCrossingsPrevLayer(i);
        } while (cross < oldCross);
        Collections.sort(curLayer, new Util.NodeByYComparator(m_g));
    }
}
Also used : Node(org.knime.workbench.ui.layout.Graph.Node)

Example 3 with Node

use of org.knime.workbench.ui.layout.Graph.Node in project knime-core by knime.

the class CrossingMinimizer method orderByMedian.

/**
 * order the current layer by means of the average median of neighbors of
 * each node in the previous layer.
 *
 * @param curLayer
 * @param prevLayer
 */
private void orderByMedian(final ArrayList<Node> curLayer, final ArrayList<Node> prevLayer) {
    for (Node v : curLayer) {
        // get sorted list of neighbors in the previous layer
        ArrayList<Node> neighbors = getNeighbors(v, prevLayer);
        Collections.sort(neighbors, new Util.NodeByYComparator(m_g));
        // set median position, or average of two medians if degree is even
        int size = neighbors.size();
        int m1 = (int) Math.ceil(size / 2.0) - 1;
        // needed for even degree
        int m2 = m1 + 1;
        if (size > 0) {
            // average median heuristic
            if (size % 2 == 1) {
                // odd degree
                m_g.setY(v, m_g.getY(neighbors.get(m1)));
            } else {
                // even degree
                double y1 = m_g.getY(neighbors.get(m1));
                double y2 = m_g.getY(neighbors.get(m2));
                m_g.setY(v, (y1 + y2) / 2);
            }
        }
    }
    // sort current layer by medians
    Collections.sort(curLayer, new LayerSortComparator(prevLayer));
    // set corresponding y-coordinates
    updateY(curLayer);
}
Also used : Node(org.knime.workbench.ui.layout.Graph.Node)

Example 4 with Node

use of org.knime.workbench.ui.layout.Graph.Node in project knime-core by knime.

the class CrossingMinimizer method copyLayering.

/**
 * copies the current layering.
 *
 * @return
 */
private ArrayList<ArrayList<Node>> copyLayering() {
    ArrayList<ArrayList<Node>> layers = new ArrayList<ArrayList<Node>>();
    for (ArrayList<Node> layer : m_layers) {
        ArrayList<Node> layerCopy = new ArrayList<Graph.Node>();
        layers.add(layerCopy);
        for (Node n : layer) {
            layerCopy.add(n);
        }
    }
    return layers;
}
Also used : Graph(org.knime.workbench.ui.layout.Graph) Node(org.knime.workbench.ui.layout.Graph.Node) ArrayList(java.util.ArrayList)

Example 5 with Node

use of org.knime.workbench.ui.layout.Graph.Node in project knime-core by knime.

the class SimpleLayeredLayouter method doLayout.

/**
 * computes an hierarchical layout of the given graph. If nodes are fixed by
 * means of the given map, they will end up on the first or last layer,
 * ordered by their original y-coordinate. Precondition: g must be a
 * directed acyclic graph!
 *
 * @param g the graph to perform layout on
 * @param fixedNodes node map containing true if the respective node should
 *            be fixed (only sources and sinks allowed)
 * @throws RuntimeException
 */
public void doLayout(final Graph g, final Map<Node, Boolean> fixedNodes) throws RuntimeException {
    // create lists for fixed sources and sinks if necessary
    ArrayList<Node> fixedSources = null;
    ArrayList<Node> fixedSinks = null;
    if (fixedNodes != null) {
        fixedSources = new ArrayList<Graph.Node>();
        fixedSinks = new ArrayList<Graph.Node>();
        for (Node n : g.nodes()) {
            if (fixedNodes.get(n)) {
                if (n.inDegree() == 0) {
                    fixedSources.add(n);
                } else if (n.outDegree() == 0) {
                    fixedSinks.add(n);
                }
            }
        }
        if (fixedSources.isEmpty()) {
            fixedSources = null;
        }
        if (fixedSinks.isEmpty()) {
            fixedSinks = null;
        }
    }
    // get layering of the graph
    Map<Node, Integer> nodeLayer = g.createIntNodeMap();
    ArrayList<ArrayList<Node>> layers = Layerer.assignLayers(g, nodeLayer, fixedSources, fixedSinks);
    // add dummy vertices for edges spanning several layers
    ArrayList<Edge> hiddenEdges = new ArrayList<Graph.Edge>();
    ArrayList<Node> dummyNodes = new ArrayList<Graph.Node>();
    ArrayList<Edge> dummyEdges = new ArrayList<Graph.Edge>();
    HashMap<Edge, ArrayList<Node>> hiddenEdgeToDummyVertices = new HashMap<Graph.Edge, ArrayList<Node>>();
    for (Edge e : g.edges()) {
        int startLayer = nodeLayer.get(e.source()).intValue();
        int endLayer = nodeLayer.get(e.target()).intValue();
        int span = endLayer - startLayer;
        if (span > 1) {
            hiddenEdges.add(e);
        }
    }
    // concurrent modification due to iterator
    for (Edge e : hiddenEdges) {
        // list for this edges dummy nodes
        ArrayList<Node> eDummyNodes = new ArrayList<Graph.Node>();
        int startLayer = nodeLayer.get(e.source()).intValue();
        int endLayer = nodeLayer.get(e.target()).intValue();
        int span = endLayer - startLayer;
        Node last = e.source();
        for (int i = 1; i < span; i++) {
            Node current = g.createNode("bend " + e + ", " + i, startLayer + i, g.getY(last));
            // add dummy to its layer
            nodeLayer.put(current, startLayer + i);
            layers.get(startLayer + i).add(current);
            // add dummy edge to graph
            Edge dEdge = g.createEdge(last, current);
            dummyEdges.add(dEdge);
            // add dummy vertex to the list of dummies for the original edge
            eDummyNodes.add(current);
            // proceed
            last = current;
        }
        // add last dummy edge
        g.createEdge(last, e.target());
        // store list of dummy nodes for original edge
        hiddenEdgeToDummyVertices.put(e, eDummyNodes);
        // add this edges dummy Nodes to the list of all dummy nodes
        dummyNodes.addAll(eDummyNodes);
    }
    // remove hidden edges
    for (Edge e : hiddenEdges) {
        g.removeEdge(e);
    }
    // set initial coordinates by layer
    int layer = 0;
    for (ArrayList<Node> currentLayer : layers) {
        // sort first and last layer by y-coordinate if fixed
        if (layer == 0 && fixedSources != null) {
            Collections.sort(currentLayer, new Util.NodeByYComparator(g));
        } else if (layer == layers.size() - 1 && fixedSinks != null) {
            Collections.sort(currentLayer, new Util.NodeByYComparator(g));
        } else {
            // here the ordering is shuffled, could also be done several
            // times in the crossing minimization phase.
            // I.e., every execution of the algorithm potentially yields
            // another result!
            Collections.shuffle(currentLayer, m_rnd);
        // ordering could also be initialized by the current ordering
        // from y-coordinates.
        // Collections.sort(currentLayer, new
        // Util.NodeByYComparator(g));
        }
        // set coordinates from 0,1,...,size of layer
        int verticalCoord = 0;
        for (Node n : currentLayer) {
            g.setCoordinates(n, layer, verticalCoord);
            verticalCoord++;
        }
        layer++;
    }
    /* Do crossing minimization */
    CrossingMinimizer cm = new CrossingMinimizer(g, layers, fixedSources, fixedSinks);
    cm.run();
    /* Do vertical placement */
    VerticalCoordinateAssigner vca = new VerticalCoordinateAssigner(g, layers, dummyNodes, dummyEdges);
    vca.setBalanceBranchings(m_balanceBranching);
    vca.run();
    /*
         * Reinsert hidden edges with bendpoints, and remove dummy nodes and
         * edges
         */
    for (Edge hEdge : hiddenEdges) {
        Edge e = g.reinsert(hEdge);
        for (Node n : hiddenEdgeToDummyVertices.get(hEdge)) {
            g.addBend(e, g.getX(n), g.getY(n));
            // also removes dummy edges!
            g.removeNode(n);
        }
    }
    // clean up unnecessary bend-points
    g.cleanBends();
}
Also used : HashMap(java.util.HashMap) Node(org.knime.workbench.ui.layout.Graph.Node) ArrayList(java.util.ArrayList) Graph(org.knime.workbench.ui.layout.Graph) Edge(org.knime.workbench.ui.layout.Graph.Edge)

Aggregations

Node (org.knime.workbench.ui.layout.Graph.Node)21 Edge (org.knime.workbench.ui.layout.Graph.Edge)5 ArrayList (java.util.ArrayList)4 Graph (org.knime.workbench.ui.layout.Graph)3 HashMap (java.util.HashMap)2 Point2D (java.awt.geom.Point2D)1 Point (org.eclipse.draw2d.geometry.Point)1 ConnectionID (org.knime.core.node.workflow.ConnectionID)1 ConnectionUIInformation (org.knime.core.node.workflow.ConnectionUIInformation)1 NodeID (org.knime.core.node.workflow.NodeID)1 NodeUIInformation (org.knime.core.node.workflow.NodeUIInformation)1 ConnectionContainerUI (org.knime.core.ui.node.workflow.ConnectionContainerUI)1 NodeContainerUI (org.knime.core.ui.node.workflow.NodeContainerUI)1 SimpleLayeredLayouter (org.knime.workbench.ui.layout.layeredlayout.SimpleLayeredLayouter)1