Package org.eclipse.zest.layouts.algorithms

Source Code of org.eclipse.zest.layouts.algorithms.SpringLayoutAlgorithm

/*******************************************************************************
* Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     The Chisel Group, University of Victoria
*******************************************************************************/
package org.eclipse.zest.layouts.algorithms;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.zest.layouts.LayoutStyles;
import org.eclipse.zest.layouts.dataStructures.DisplayIndependentRectangle;
import org.eclipse.zest.layouts.dataStructures.InternalNode;
import org.eclipse.zest.layouts.dataStructures.InternalRelationship;

/**
* The SpringLayoutAlgorithm has its own data repository and relation
* repository. A user can populate the repository, specify the layout
* conditions, do the computation and query the computed results.
* <p>
* Instructions for using SpringLayoutAlgorithm: <br>
* 1. Instantiate a SpringLayout object; <br>
* 2. Populate the data repository using {@link #add add(...)}; <br>
* 3. Populate the relation repository using
* {@link #addRelation addRelation(...)}; <br>
* 4. Execute {@link #compute compute()}; <br>
* 5. Execute {@link #fitWithinBounds fitWithinBounds(...)}; <br>
* 6. Query the computed results(node size and node position).
*
* @version 2.0
* @author Ian Bull
* @author Casey Best (version 1.0 by Jingwei Wu/Rob Lintern)
*/
public class SpringLayoutAlgorithm extends ContinuousLayoutAlgorithm {

    private final static boolean DEFAULT_ANCHOR = false;

    /**
     * The default value for the spring layout number of interations.
     */
    public static final int DEFAULT_SPRING_ITERATIONS = 1000;

    /**
     * the default value for the time algorithm runs.
     */
    public static final long MAX_SPRING_TIME = 10000;

    /**
     * The default value for positioning nodes randomly.
     */
    public static final boolean DEFAULT_SPRING_RANDOM = true;

    /**
     * The default value for ignoring unconnected nodes.
     */
    public static final boolean DEFAULT_SPRING_IGNORE_UNCON = true;

    /**
     * The default value for separating connected components.
     */
    public static final boolean DEFAULT_SPRING_SEPARATE_COMPONENTS = true;

    /**
     * The default value for the spring layout move-control.
     */
    public static final double DEFAULT_SPRING_MOVE = 1.0f;

    /**
     * The default value for the spring layout strain-control.
     */
    public static final double DEFAULT_SPRING_STRAIN = 1.0f;

    /**
     * The default value for the spring layout length-control.
     */
    public static final double DEFAULT_SPRING_LENGTH = 1.0f;

    /**
     * The default value for the spring layout gravitation-control.
     */
    public static final double DEFAULT_SPRING_GRAVITATION = 1.0f;

    /**
     * The variable can be customized to set the number of iterations used.
     */
    private static int sprIterations = DEFAULT_SPRING_ITERATIONS;

    /**
     * This variable can be customized to set the max number of MS the algorithm
     * should run
     */
    private static long maxTimeMS = MAX_SPRING_TIME;

    /**
     * The variable can be customized to set whether or not the spring layout
     * nodes are positioned randomly before beginning iterations.
     */
    private static boolean sprRandom = DEFAULT_SPRING_RANDOM;

    /**
     * Minimum distance considered between nodes
     */
    protected static final double MIN_DISTANCE = 0.001d;

    /**
     * An arbitrarily small value in mathematics.
     */
    protected static final double EPSILON = 0.001d;

    /**
     * The variable can be customerized to set the spring layout move-control.
     */
    private static double sprMove = DEFAULT_SPRING_MOVE;

    /**
     * The variable can be customized to set the spring layout strain-control.
     */
    private static double sprStrain = DEFAULT_SPRING_STRAIN;

    /**
     * The variable can be customized to set the spring layout length-control.
     */
    private static double sprLength = DEFAULT_SPRING_LENGTH;

    /**
     * The variable can be customized to set the spring layout
     * gravitation-control.
     */
    private static double sprGravitation = DEFAULT_SPRING_GRAVITATION;

    /**
     * The largest movement of all vertices that has occured in the most recent
     * iteration.
     */
    private double largestMovement = 0;


    /**
     * Maps a src and dest object to the number of relations between them. Key
     * is src.toString() + dest.toString(), value is an Integer
     */
    private Map srcDestToNumRelsMap;

    /**
     * Maps a src and dest object to the average weight of the relations between
     * them. Key is src.toString() + dest.toString(), value is a Double
     */
    private Map srcDestToRelsAvgWeightMap;

    /**
     * Maps a relationship type to a weight. Key is a string, value is a Double
     */
    private static Map relTypeToWeightMap = new HashMap();

    private int iteration;

    private int[][] srcDestToNumRels;

    private double[][] srcDestToRelsAvgWeight;

    private double[] tempLocationsX;

    private double[] tempLocationsY;

    private double[] forcesX;

    private double[] forcesY;

    private boolean[] anchors;
   
    private DisplayIndependentRectangle bounds = null;
   
    Date date = null;

    /**
     * Constructor.
     */
    public SpringLayoutAlgorithm( int styles ) {
        super( styles );
        srcDestToNumRelsMap = new HashMap();
        srcDestToRelsAvgWeightMap = new HashMap();
        date = new Date();
    }

   
    /**
     * Creates a sprint layout algoirthm with no style
     *
     */
    public SpringLayoutAlgorithm() {
      this( LayoutStyles.NONE );
  }
   
    public void setLayoutArea(double x, double y, double width, double height) {
        bounds = new DisplayIndependentRectangle(x,y,width,height);
    }

    /**
     * Sets the spring layout move-control.
     *
     * @param move
     *            The move-control value.
     */
    public void setSpringMove(double move) {
        sprMove = move;
    }

    /**
     * Returns the move-control value of this SpringLayoutAlgorithm in
     * double presion.
     *
     * @return The move-control value.
     */
    public double getSpringMove() {
        return sprMove;
    }

    /**
     * Sets the spring layout strain-control.
     *
     * @param strain
     *            The strain-control value.
     */
    public void setSpringStrain(double strain) {
        sprStrain = strain;
    }

    /**
     * Returns the strain-control value of this SpringLayoutAlgorithm in
     * double presion.
     *
     * @return The strain-control value.
     */
    public double getSpringStrain() {
        return sprStrain;
    }

    /**
     * Sets the spring layout length-control.
     *
     * @param length
     *            The length-control value.
     */
    public void setSpringLength(double length) {
        sprLength = length;
    }

    /**
     * Gets the max time this algorithm will run for
     *
     * @return
     */
    public long getSpringTimeout() {
        return maxTimeMS;
    }

    /**
     * Sets the spring timeout
     *
     * @param timeout
     */
    public void setSpringTimeout(long timeout) {
        maxTimeMS = timeout;
    }

    /**
     * Returns the length-control value of this SpringLayoutAlgorithm in
     * double presion.
     *
     * @return The length-control value.
     */
    public double getSpringLength() {
        return sprLength;
    }

    /**
     * Sets the spring layout gravitation-control.
     *
     * @param gravitation
     *            The gravitation-control value.
     */
    public void setSpringGravitation(double gravitation) {
        sprGravitation = gravitation;
    }

    /**
     * Returns the gravitation-control value of this SpringLayoutAlgorithm
     * in double presion.
     *
     * @return The gravitation-control value.
     */
    public double getSpringGravitation() {
        return sprGravitation;
    }

    /**
     * Sets the number of iterations to be used.
     *
     * @param gravitation
     *            The number of iterations.
     */
    public void setIterations(int iterations) {
        sprIterations = iterations;
    }

    /**
     * Returns the number of iterations to be used.
     *
     * @return The number of iterations.
     */
    public int getIterations() {
        return sprIterations;
    }

    /**
     * Sets whether or not this SpringLayoutAlgorithm will layout the
     * nodes randomly before beginning iterations.
     *
     * @param random
     *            The random placement value.
     */
    public void setRandom(boolean random) {
        sprRandom = random;
    }

    /**
     * Returns whether or not this SpringLayoutAlgorithm will layout the
     * nodes randomly before beginning iterations.
     */
    public boolean getRandom() {
        return sprRandom;
    }

    public void setWeight(String relType, double weight) {
        relTypeToWeightMap.put(relType, new Double(weight));
    }

    public double getWeight(String relType) {
        Double weight = (Double) relTypeToWeightMap.get(relType);
        return (weight == null) ? 1 : weight.doubleValue();
    }

    /**
     * Sets the default conditions.
     */
    public void setDefaultConditions() {
        // sprMove = DEFAULT_SPRING_MOVE;
        // sprStrain = DEFAULT_SPRING_STRAIN;
        // sprLength = DEFAULT_SPRING_LENGTH;
        // sprGravitation = DEFAULT_SPRING_GRAVITATION;
        // sprIterations = DEFAULT_SPRING_ITERATIONS;
    }

    /**
     * Clean up after done
     *
     * @param entitiesToLayout
     */
    private void reset(InternalNode[] entitiesToLayout) {
        tempLocationsX = null;
        tempLocationsY = null;
        forcesX = null;
        forcesY = null;
        anchors = null;
        setDefaultConditions();
        srcDestToNumRelsMap = new HashMap();
        srcDestToRelsAvgWeightMap = new HashMap();
        relTypeToWeightMap = new HashMap();
    }

    private long startTime = 0;

    protected void preLayoutAlgorithm(InternalNode[] entitiesToLayout, InternalRelationship[] relationshipsToConsider, double x, double y, double width, double height) {
        // TODO: Filter out any non-wanted entities and relationships
        // super.applyLayout(entitiesToLayout, relationshipsToConsider, x, y,
        // width, height);
        //InternalNode[] a_entitiesToLayout = (InternalNode[]) entitiesToLayout.toArray(new InternalNode[entitiesToLayout.size()]);
      bounds = new DisplayIndependentRectangle(x,y,width,height);
        tempLocationsX = new double[entitiesToLayout.length];
        tempLocationsY = new double[entitiesToLayout.length];
        forcesX = new double[entitiesToLayout.length];
        forcesY = new double[entitiesToLayout.length];
        anchors = new boolean[entitiesToLayout.length];
       
        for (int i = 0; i < entitiesToLayout.length; i++) {
            anchors[i] = DEFAULT_ANCHOR;
        }
        for (int i = 0; i < relationshipsToConsider.length; i++) {
            InternalRelationship layoutRelationship = relationshipsToConsider[i];
            addRelation(layoutRelationship);
        }

        // do the calculations
        preCompute(entitiesToLayout);
        startTime = date.getTime();
    }

    protected void postLayoutAlgorithm(InternalNode[] entitiesToLayout, InternalRelationship[] relationshipsToConsider) {
        reset(entitiesToLayout);
    }

    /**
     * Adds a simple relation between two nodes to the relation repository.
     *
     * @param layoutRelationship
     *            The simple relation to be added
     * @throws java.lang.NullPointerExcetption
     *             If <code>sr</code> is null
     * @see SimpleRelation
     */
    private void addRelation(InternalRelationship layoutRelationship) {
        if (layoutRelationship == null) {
            throw new IllegalArgumentException("The arguments can not be null!");
        } else {
            double weight = layoutRelationship.getWeight();
            weight = (weight <= 0 ? 0.1 : weight);
            String key1 = layoutRelationship.getSource().toString() + layoutRelationship.getDestination().toString();
            String key2 = layoutRelationship.getDestination().toString() + layoutRelationship.getSource().toString();
            String[] keys = { key1, key2 };
            for (int i = 0; i < keys.length; i++) {
                String key = keys[i];
                Integer count = (Integer) srcDestToNumRelsMap.get(key);
                Double avgWeight = (Double) srcDestToRelsAvgWeightMap.get(key);
                if (count == null) {
                    count = new Integer(1);
                    avgWeight = new Double(weight);
                } else {
                    int newCount = count.intValue() + 1;
                    double newAverage = (avgWeight.doubleValue() * count.doubleValue() + weight) / newCount;
                    avgWeight = new Double(newAverage);
                    count = new Integer(newCount);
                }
                srcDestToNumRelsMap.put(key, count);
                srcDestToRelsAvgWeightMap.put(key, avgWeight);
            }
        }
    }

    private void preCompute(InternalNode [] entitiesToLayout) {
        // count number of relationships between all nodes and the average
        // weight between them
        srcDestToNumRels = new int[entitiesToLayout.length][entitiesToLayout.length];
        srcDestToRelsAvgWeight = new double[entitiesToLayout.length][entitiesToLayout.length];

        for (int i = 0; i < entitiesToLayout.length - 1; i++) {
            InternalNode layoutEntity1 = entitiesToLayout[i];
            for (int j = i + 1; j < entitiesToLayout.length; j++) {
                InternalNode layoutEntity2 = entitiesToLayout[j];
                srcDestToNumRels[i][j] = numRelations(layoutEntity1, layoutEntity2);
                srcDestToNumRels[i][j] += numRelations(layoutEntity2, layoutEntity1);
                srcDestToRelsAvgWeight[i][j] = avgWeight(layoutEntity1, layoutEntity2);
            }
        }

        if (sprRandom)
            placeRandomly(entitiesToLayout); // put vertices in random places
        else
            convertToUnitCoordinates(entitiesToLayout);

        iteration = 1;
        largestMovement = Double.MAX_VALUE;
    }

    // TODO: This is a complete Clone! (and not in a good way)
    protected DisplayIndependentRectangle getLayoutBoundsTemp(InternalNode [] entitiesToLayout, boolean includeNodeSize) {
        double rightSide = Double.MIN_VALUE;
        double bottomSide = Double.MIN_VALUE;
        double leftSide = Double.MAX_VALUE;
        double topSide = Double.MAX_VALUE;
        for (int i = 0; i < entitiesToLayout.length; i++) {
            double x = tempLocationsX[i];
            double y = tempLocationsY[i];

            leftSide = Math.min(x, leftSide);
            topSide = Math.min(y, topSide);
            rightSide = Math.max(x, rightSide);
            bottomSide = Math.max(y, bottomSide);

        }
        return new DisplayIndependentRectangle(leftSide, topSide, rightSide - leftSide, bottomSide - topSide);
    }

    protected void convertNodePositionsBack(int i, InternalNode entityToConvert, double px, double py, double screenWidth, double screenHeight, DisplayIndependentRectangle layoutBounds) {
     
      // If the node selected is outside the screen, map it to the boarder
      if ( px > screenWidth ) px = screenWidth;
      if ( py > screenHeight ) py = screenHeight;
     
      if ( px < 0 ) px = 1;
      if ( py < 0 ) py = 1;
     
        double x = (px / screenWidth) * layoutBounds.width + layoutBounds.x;
        double y = (py / screenHeight) * layoutBounds.height + layoutBounds.y;
       
        tempLocationsX[i] = x;
        tempLocationsY[i] = y;
        //setTempLocation(entityToConvert, new DisplayIndependentPoint(x, y));

        if (entityToConvert.getInternalX() < 0) {
            // System.out.println("We have nodes less than 0 here!");
        }

    }

    private void checkPreferredLocation(InternalNode [] entitiesToLayout, DisplayIndependentRectangle realBounds) {
        // use 10% for the border - 5% on each side
        double borderWidth = Math.min(realBounds.width, realBounds.height) / 10.0;
        DisplayIndependentRectangle screenBounds = new DisplayIndependentRectangle(realBounds.x + borderWidth / 2.0, realBounds.y + borderWidth / 2.0, realBounds.width - borderWidth, realBounds.height - borderWidth);

        DisplayIndependentRectangle layoutBounds = getLayoutBoundsTemp(entitiesToLayout, false);
        for (int i = 0; i < entitiesToLayout.length; i++) {
            InternalNode layoutEntity = entitiesToLayout[i];
            if (layoutEntity.hasPreferredLocation()) {
                convertNodePositionsBack(i, layoutEntity, layoutEntity.getPreferredX(), layoutEntity.getPreferredY(), screenBounds.width, screenBounds.height, layoutBounds);
            }
        }
    }

    /**
     * Scales the current iteration counter based on how long the algorithm has
     * been running for. You can set the MaxTime in maxTimeMS!
     */
    private void setSprIterationsBasedOnTime() {
        if (maxTimeMS <= 0)
            return;

        long currentTime = date.getTime();
        double fractionComplete = (double) ((double) (currentTime - startTime) / ((double) maxTimeMS));
        int currentIteration = (int) (fractionComplete * sprIterations);
        if (currentIteration > iteration) {
            iteration = currentIteration;
        }

    }

    protected boolean performAnotherNonContinuousIteration() {
        setSprIterationsBasedOnTime();
        if (iteration <= sprIterations && largestMovement >= sprMove)
            return true;
        else
            return false;
    }

    protected int getCurrentLayoutStep() {
        return iteration;
    }

    protected int getTotalNumberOfLayoutSteps() {
        return sprIterations;
    }
   
    protected void computeOneIteration(InternalNode[] entitiesToLayout, InternalRelationship[] relationshipsToConsider, double x, double y, double width, double height) {
      if ( bounds == null )
        bounds = new DisplayIndependentRectangle(x,y,width,height);
        checkPreferredLocation(entitiesToLayout, bounds );
        computeForces(entitiesToLayout);
        largestMovement = Double.MAX_VALUE;
        computePositions(entitiesToLayout);
       
        for (int i = 0; i < entitiesToLayout.length; i++) {
            InternalNode layoutEntity = entitiesToLayout[i];
            layoutEntity.setInternalLocation(tempLocationsX[i], tempLocationsY[i]);
        }       
       
        defaultFitWithinBounds(entitiesToLayout, bounds);

        iteration++;
    }
       
    /**
     * Puts vertices in random places, all between (0,0) and (1,1).
     */
    public void placeRandomly(InternalNode[] entitiesToLayout) {
        // If only one node in the data repository, put it in the middle
        if (entitiesToLayout.length == 1) {
            // If only one node in the data repository, put it in the middle
            tempLocationsX[0] = 0.5;
            tempLocationsY[0] = 0.5;
        } else {
            for (int i = 0; i < entitiesToLayout.length; i++) {
                if (i == 0) {
                    tempLocationsX[i] = 0.0;
                    tempLocationsY[i] = 0.0;
                } else if (i == 1) {
                    tempLocationsX[i] = 1.0;
                    tempLocationsY[i] = 1.0;
                } else {
                    tempLocationsX[i] = Math.random();
                    tempLocationsY[i] = Math.random();
                }
            }
        }
    }

    // /////////////////////////////////////////////////////////////////
    // /// Protected Methods /////
    // /////////////////////////////////////////////////////////////////

    /**
     * Computes the force for each node in this SpringLayoutAlgorithm. The
     * computed force will be stored in the data repository
     */
    protected void computeForces(InternalNode[] entitiesToLayout) {

        // initialize all forces to zero
        for (int i = 0; i < entitiesToLayout.length; i++) {
            forcesX[i] = 0.0;
            forcesY[i] = 0.0;
        }

        // TODO: Again really really slow!

        for (int i = 0; i < entitiesToLayout.length - 1; i++) {
            InternalNode sourceEntity = entitiesToLayout[i];
           
            double srcLocationX = tempLocationsX[i];
            double srcLocationY = tempLocationsY[i];
            double fx = forcesX[i]; // force in x direction
            double fy = forcesY[i]; // force in y direction
           

            for (int j = i + 1; j < entitiesToLayout.length; j++) {
                InternalNode destinationEntity = entitiesToLayout[j];

                if (!destinationEntity.equals(sourceEntity)) {
                    double destLocationX = tempLocationsX[j];
                    double destLocationY = tempLocationsY[j];
                    double dx = srcLocationX - destLocationX;
                    double dy = srcLocationY- destLocationY;
                    double distance = Math.sqrt(dx * dx + dy * dy);
                    double distance_sq = distance * distance;
                    // make sure distance and distance squared not too small
                    distance = Math.max(MIN_DISTANCE, distance);

                    // If there are relationships between srcObj and destObj
                    // then decrease force on srcObj (a pull) in direction of destObj
                    // If no relation between srcObj and destObj then increase
                    // force on srcObj (a push) from direction of destObj.
                    int numRels = srcDestToNumRels[i][j];
                    double avgWeight = srcDestToRelsAvgWeight[i][j];
                    if (numRels > 0) {
                        // nodes are pulled towards each other
                        double f = sprStrain * Math.log(distance / sprLength) * numRels * avgWeight;
                       
                        fx = fx - (f * dx / distance);
                        fy = fy - (f * dy / distance);
                       
                    } else {
                        // nodes are repelled from each other
                        //double f = Math.min(100, sprGravitation / (distance*distance));
                        double f = sprGravitation / (distance_sq);
                        fx = fx + (f * dx / distance);
                        fy = fy + (f * dy / distance);
                    }

                    // According to Newton, "for every action, there is an equal
                    // and opposite reaction."
                    // so give the dest an opposite force
                    forcesX[j] = forcesX[j] - fx;
                    forcesY[j] = forcesY[j] - fy;
                }
            }

            /*
             * //make sure forces aren't too big if (fx > 0 ) fx = Math.min(fx,
             * 10*sprMove); else fx = Math.max(fx, -10*sprMove); if (fy > 0) fy =
             * Math.min(fy, 10*sprMove); else fy = Math.max(fy, -10*sprMove);
             */
            forcesX[i] = fx;
            forcesY[i] = fy;
            // Remove the src object from the list of destinations since
            // we've already calculated the force from it on all other
            // objects.
            // dests.remove(srcObj);

        }
    }

    /**
     * Computes the position for each node in this SpringLayoutAlgorithm.
     * The computed position will be stored in the data repository. position =
     * position + sprMove * force
     */
    protected void computePositions(InternalNode[] entitiesToLayout) {
        for (int i = 0; i < entitiesToLayout.length; i++) {
            if (!anchors[i] || entitiesToLayout[i].hasPreferredLocation() ) {
                double oldX = tempLocationsX[i];
                double oldY = tempLocationsY[i];
                double deltaX = sprMove * forcesX[i];
                double deltaY = sprMove * forcesY[i];

                // constrain movement, so that nodes don't shoot way off to the edge
                double maxMovement = 0.2d * sprMove;
                if (deltaX >= 0) {
                    deltaX = Math.min(deltaX, maxMovement);
                } else {
                    deltaX = Math.max(deltaX, -maxMovement);
                }
                if (deltaY >= 0) {
                    deltaY = Math.min(deltaY, maxMovement);
                } else {
                    deltaY = Math.max(deltaY, -maxMovement);
                }
               

                largestMovement = Math.max(largestMovement, Math.abs(deltaX));
                largestMovement = Math.max(largestMovement, Math.abs(deltaY));

                double newX = oldX + deltaX;
                double newY = oldY + deltaY;
                tempLocationsX[i] = newX;
                tempLocationsY[i] = newY;
            }
           
        }

    }

    /**
     * Converts the position for each node in this SpringLayoutAlgorithm
     * to unit coordinates in double precision. The computed positions will be
     * still stored in the data repository.
     */
    protected void convertToUnitCoordinates(InternalNode[] entitiesToLayout) {
        double minX = Double.MAX_VALUE;
        double maxX = Double.MIN_VALUE;
        double minY = Double.MAX_VALUE;
        double maxY = Double.MIN_VALUE;
        for (int i = 0; i < entitiesToLayout.length; i++) {
            InternalNode layoutEntity = entitiesToLayout[i];
            minX = Math.min(minX, layoutEntity.getInternalX());
            minY = Math.min(minY, layoutEntity.getInternalY());
            maxX = Math.max(maxX, layoutEntity.getInternalX());
            maxY = Math.max(maxY, layoutEntity.getInternalY());
        }

        double spanX = maxX - minX;
        double spanY = maxY - minY;
        double maxSpan = Math.max(spanX, spanY);

        if (maxSpan > EPSILON) {
            for (int i = 0; i < entitiesToLayout.length; i++) {
                InternalNode layoutEntity = entitiesToLayout[i];
                double x = (layoutEntity.getInternalX() - minX) / spanX;
                double y = (layoutEntity.getInternalY() - minY) / spanY;
                tempLocationsX[i] = x;
                tempLocationsY[i] = y;
            }
        } else {
            placeRandomly(entitiesToLayout);
        }
    }

    /**
     * Examines the number of specified relation between the <code>src</code>
     * and the <code>dest</code> that exist in this
     * SpringLayoutAlgorithm's relation repository.
     *
     * @param src
     *            The source part of the relaton to be examined.
     * @param dest
     *            The destination part of the relation to be examined.
     * @return The number of relations between src and dest.
     */
    private int numRelations(Object src, Object dest) {
        String key = src.toString() + dest.toString();
        Integer count = (Integer) srcDestToNumRelsMap.get(key);
        int intCount = (count == null) ? 0 : count.intValue();
        return intCount;
    }

    /**
     * Returns the average weight between a src and dest object.
     *
     * @param src
     * @param dest
     * @return The average weight between the given src and dest nodes
     */
    private double avgWeight(Object src, Object dest) {
        String key = src.toString() + dest.toString();
        Double avgWeight = (Double) srcDestToRelsAvgWeightMap.get(key);
        double doubleWeight = (avgWeight == null) ? 1 : avgWeight.doubleValue();
        return doubleWeight;
    }


    protected boolean isValidConfiguration(boolean asynchronous, boolean continueous) {
        if (asynchronous && continueous)
            return true;
        else if (asynchronous && !continueous)
            return true;
        else if (!asynchronous && continueous)
            return false;
        else if (!asynchronous && !continueous)
            return true;

        return false;
    }


}
TOP

Related Classes of org.eclipse.zest.layouts.algorithms.SpringLayoutAlgorithm

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.