Package lupos.gui.operatorgraph.arrange

Source Code of lupos.gui.operatorgraph.arrange.Sugiyama

/**
* Copyright (c) 2013, Institute of Information Systems (Sven Groppe and contributors of LUPOSDATE), University of Luebeck
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
*   - Redistributions of source code must retain the above copyright notice, this list of conditions and the following
*     disclaimer.
*   - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
*     following disclaimer in the documentation and/or other materials provided with the distribution.
*   - Neither the name of the University of Luebeck nor the names of its contributors may be used to endorse or promote
*     products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package lupos.gui.operatorgraph.arrange;

import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedList;

import lupos.gui.operatorgraph.GraphBox;
import lupos.gui.operatorgraph.GraphWrapperIDTuple;
import lupos.gui.operatorgraph.OperatorGraph;
import lupos.gui.operatorgraph.graphwrapper.GraphWrapper;

/**
* The class Sugiyama implements the Sudiyama - Algorithm
* which is used in the LUPOSDATE- Project
*
* @author Tobias Bielfeld
*
*/
public final class Sugiyama {
 
  /**
   * Method gets a HashMap with the levels of the layout as keys
   * and lists of GraphWrapper which belong to the level
   *
   * @param operatorgraph    all nodes of the graph
   * @return  HashMap with layout-levels and their nodes
   */
  protected static LinkedHashMap<Integer, LinkedList<GraphWrapper>> fillAllLevels(
      final OperatorGraph operatorgraph) {
   
    final HashMap<GraphWrapper, Integer> levels = new HashMap<GraphWrapper, Integer>();
    // compute for every layout-level the nodes
    // start with roots
    HashSet<GraphWrapper> visited = new HashSet<GraphWrapper>();
    for (final GraphWrapper gw : operatorgraph.getRootList(false)) {
      computeLevel(visited,
          new HashSet<GraphWrapper>(), gw, 0, operatorgraph, levels);
    }

   
    // get a HashMap for every Level in the list
    final LinkedHashMap<Integer, LinkedList<GraphWrapper>> graphWrapperOfLevel = new LinkedHashMap<Integer, LinkedList<GraphWrapper>>();
    final HashMap<GraphWrapper, GraphBox> boxes = operatorgraph.getBoxes();

    // iterate over all GraphWrapper, which have a GraphBox
    for (final GraphWrapper gw : boxes.keySet()) {
      // get level of current node
      final int currentLevel = levels.get(gw);
     
      // get a list of GraphWrapper-objects of current level
      LinkedList<GraphWrapper> lgw = graphWrapperOfLevel
          .get(currentLevel);

      if (lgw == null) { // if list is empty
        lgw = new LinkedList<GraphWrapper>(); // initiate a new one
      }

      lgw.add(gw); // add current GraphWrapper to list

      // add GraphWrapper list to current level in HashMap
      graphWrapperOfLevel.put(currentLevel, lgw);
    }
   
    return graphWrapperOfLevel;
  }
 
  /**
   * Method computes recursively the level
   * of a node and his children by depth-search
   **/
  protected static void computeLevel(
      final HashSet<GraphWrapper> visited,
      final HashSet<GraphWrapper> visitedNotCloned,
      final GraphWrapper op, final int level,
      final OperatorGraph operatorgraph,
      final HashMap<GraphWrapper, Integer> levels) {

    // if a node is visited
    if (visited.contains(op)) {
      return; // abort
    }

    visited.add(op); // set the current node visited
   
    levels.put(op, level);

    // visit all children and compute their level recursive

    for (final GraphWrapperIDTuple child : op.getSucceedingElements()) {
      computeLevel(visited,
          visitedNotCloned, child.getOperator(), level+1,
          operatorgraph, levels);
    }
  }

  /**
   * Method uses the barycenter-method to compute new positions for nodes in the graph
   * and minimizes edge-crossings.
   * @param levels  HashMap with layout levels and their nodes
   * @param level    current level
   */
  protected static int baryCenter (LinkedHashMap <Integer, LinkedList<GraphWrapper>>levels,
                   int level) {
    int moves = 0;
    LinkedList<NodeWrapper> positions = new LinkedList<NodeWrapper>();
    LinkedList<GraphWrapper> newPlaced = new LinkedList<GraphWrapper>();
    LinkedList<GraphWrapper> currentLevel = levels.get(level);
   
    if (level == 0) {
      newPlaced = currentLevel;
    }
    else{
   
      // iterate over all nodes in the level
      for (int currentIndex = 0; currentIndex < currentLevel.size(); currentIndex++) {
        GraphWrapper currentNode = currentLevel.get(currentIndex);
        int gridPositionsSum = 0; // Sum of positions of ancestors of current node
        int nodeAmount = 0;    // Amount of ancestors of current node     
        // List of all ancestors of the current node
        LinkedList <GraphWrapper> ancestors = currentNode.getPrecedingElements();
           
        // iterate over all ancestors
        for (int i = 0; i < ancestors.size();i++) {
          GraphWrapper ancestor = ancestors.get(i);

          gridPositionsSum += getGridPosition(levels, ancestor, level-1);

          // if current level is root-level
          if (gridPositionsSum < 0) return moves;
          nodeAmount++;
        }
     
        if (nodeAmount > 0) {
        // compute new position level
          double newPosition = gridPositionsSum/nodeAmount;
          NodeWrapper node = new NodeWrapper(currentNode, newPosition);
          positions.add(node);
        }
      }
   
   
      while (positions.size() != 0) {
        NodeWrapper smallestPos = positions.getFirst();
        for (int i = 1; i < positions.size(); i++) {
          NodeWrapper temp = positions.get(i);
          if (smallestPos.getGridPosition() > temp.getGridPosition())
            smallestPos = temp;
        }
        newPlaced.add(smallestPos.get_Node());
        positions.remove(smallestPos);
      }
    }
    levels.put(level, newPlaced);   
   
    return moves;
  }
 
  /**
   * Method gets the position of a node in his level
   * @param levels  HashMap with layout levels and their nodes
   * @param a      node to get position
   * @param level    the level to the node belongs
   * @return      position of the node or -1, if node isn't in the level
   */
  protected static int getGridPosition (LinkedHashMap <Integer, LinkedList<GraphWrapper>>levels,
                    GraphWrapper a, int level) {
    LinkedList<GraphWrapper> levelKnoten = levels.get(level);
   
    if (levelKnoten == null )
      return -1;
   
    int pos = levelKnoten.indexOf(a);
    return pos;
  }
 
 
  public static void arrange(final OperatorGraph operatorgraph){

    //long time1 = System.currentTimeMillis();
   
   
    LinkedList<GraphRow> rows = new LinkedList<GraphRow>();
    HashMap<GraphWrapper, GraphBox> boxes = operatorgraph.getBoxes();
   
    LinkedHashMap<Integer, LinkedList<GraphWrapper>> levels = fillAllLevels(operatorgraph);
   
    int moves = -1;

    while (moves != 0){
      moves = 0;
      for (int level = 0; level < levels.size(); level++) {
        moves += baryCenter(levels, level);
      }       
    }

    int level = 0;
    int y = (int)Math.ceil(operatorgraph.PADDING);
    while (levels.get(level) != null) {
      GraphRow row = new GraphRow(operatorgraph, y, levels.get(level).size());
      rows.add(row);

      row.addAllWithoutUpdatingParentsSize(levels.get(level), boxes);
      y += row.getHeight()+operatorgraph.SPACING_Y;
      level++;
    }
   
    int largestWidth = 0;
    for (GraphRow row : rows){
      if (row.getWidth() > largestWidth)
        largestWidth = row.getWidth();
    }
    for (GraphRow row : rows) {
      row.center(largestWidth/2);
    }   
    //time1 = System.currentTimeMillis() - time1;
    //System.out.println("Laufzeit = " + time1 + " ms");
  }   
}

TOP

Related Classes of lupos.gui.operatorgraph.arrange.Sugiyama

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.