⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 annealinglayoutalgorithm.java

📁 用JGraph编的软件
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
package org.jgraph.layout;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Rectangle;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;

import org.jgraph.JGraph;
import org.jgraph.event.GraphModelEvent;
import org.jgraph.event.GraphModelListener;
import org.jgraph.graph.CellMapper;
import org.jgraph.graph.CellView;
import org.jgraph.graph.EdgeView;
import org.jgraph.graph.GraphConstants;
import org.jgraph.graph.GraphModel;
import org.jgraph.graph.VertexView;
import org.jgraph.utils.MathExtensions;


/**
 * <h1>Simulated Annealing Layout Algorithm</h1><p>
 * Implemented from the paper: "Drawing Graphs Nicely Using Simulated Annealing"
 * from Ron Davidson and David Harel. ACM Transactions on Graphics, Vol. 15, 
 * No. 4, October 1996, Pages 301-331.
 * @author winkler
 * @version 1.0
 * Date of creation: 11.04.2003 - 12:39:58
 */
public class AnnealingLayoutAlgorithm implements LayoutAlgorithm, GraphModelListener {

    public final static String KEY_CAPTION   = "Annealing Layoutalgorithm Attributes";    
    public final static String KEY_POSITION  = "Position";
    public final static String KEY_RELATIVES = "Relatives";
    
    public final static String CF_KEY_EDGE_DISTANCE_RELEVANT_EDGES = "costfunction edge distance key for relevant edges";
    
    /**
     * Key used only with clusters. Under this key a cluster has an ArrayList.
     * This list is filled with the clustered vertices.
     * @see #clusterGraph()
     * @see #moveVerticeToCluster(CellView,CellView)
     */
    public final static String KEY_CLUSTERED_VERTICES = "Clustered Vertices";
    /**
     * Key used only with clusters. Under this key vertices have the cluster
     * they belong to.
     * @see #clusterGraph()
     * @see #moveVerticeToCluster(CellView,CellView)
     */
    public final static String KEY_CLUSTER            = "Cluster";
    /**
     * Key used only with clusters. Under this key a cluster has a boolean value
     * indicating that this vertice is a cluster (clusters are 
     * VertexView-instances like every other cell).
     * @see #clusterGraph() 
     * @see #isCluster()
     */
    public final static String KEY_IS_CLUSTER         = "is Cluster";
    /**
     * Key used only with clusters. Under this key every cluster has a position,
     * which represents the position of the cluster, right after the clustering
     * process. After the layout update process is finished, the move, resulting
     * of subtracting the position under {@link #KEY_POSITION} from the 
     * position under this value, will be performed to all vertices in the 
     * cluster. By holding the initial position here clustering becomes 
     * possible.
     * 
     * @see #clusterGraph()
     * @see #declusterGraph()
     */
    public final static String KEY_CLUSTER_INIT_POSITION = "initial Position of the Cluster";
    
    /**
     * Key for loading configuration values. Indicates to load values for a
     * normal run.
     */
    protected final static int CONFIG_KEY_RUN           = 0;
    /**
     * Key for loading configuration values. Indicates to load values for a
     * layout update.
     */
    protected final static int CONFIG_KEY_LAYOUT_UPDATE = 1;

    /**
     * actual temperature
     */
    private double    temperature;
    /**
     * starting temperature
     */
    private double    initTemperature;
    /**
     * when {@link #temperature} reaches this value, the algorithm finishes its
     * calculation.
     */
    private double    minTemperature;
    /**
     * value for costfunctions {@link #getNodeDistribution()} and
     * {@link #getEdgeDistribution()}. Determines, how long the edges have to
     * be.
     */
    private double    minDistance;
    /**
     * {@link #temperature} will be multiplied with this value every round
     */
    private double    tempScaleFactor;
    /**
     * maximum number of rounds, if algorithm doesn't stop earlier, by 
     * temperature decreasement.
     */
    private int        maxRounds;
    /**
     * normalizing and priority factors for the costfunctions
     */
    protected double[]  lambdaList;
    /**
     * the drawing area, the graph should be layouted in.
     */
    private Rectangle bounds;
    /**
     * determines, if the cells of the graph are computed every time in the
     * same order or a random order, calculated every round.
     */
    private boolean   computePermutation;
    /**
     * determines, if the only allowed moves for cells of the graph are moves, 
     * that cost less. 
     */
    private boolean   uphillMovesAllowed;
    /**
     * Indicates, if the algorithm should also run on Updates in the graph.
     */
    private boolean   isLayoutUpdateEnabled;
    
    /**
     * Indicates what costfunctions to use for calculating the costs of the 
     * graph. The bits of this Integer switches the functions. Possible Values
     * are <br>
     * <blockquote><blockquote>
     * {@link AnnealingLayoutAlgorithm#COSTFUNCTION_NODE_DISTRIBUTION 
     * COSTFUNCTION_NODE_DISTRIBUTION}<br>
     * {@link AnnealingLayoutAlgorithm#COSTFUNCTION_NODE_DISTANCE
     * COSTFUNCTION_NODE_DISTANCE}<br>
     * {@link AnnealingLayoutAlgorithm#COSTFUNCTION_BORDERLINE
     * COSTFUNCTION_BORDERLINE}<br>
     * {@link AnnealingLayoutAlgorithm#COSTFUNCTION_EDGE_DISTANCE
     * COSTFUNCTION_EDGE_DISTANCE}<br>
     * {@link AnnealingLayoutAlgorithm#COSTFUNCTION_EDGE_CROSSING
     * COSTFUNCTION_EDGE_CROSSING}<br>
     * {@link AnnealingLayoutAlgorithm#COSTFUNCTION_EDGE_DISTRIBUTION
     * COSTFUNCTION_EDGE_DISTRIBUTION}
     * </blockquote></blockquote>
     */
    private int       costFunctionConfig;
    
    /**
     * counts the rounds 
     */
    private int       round;
    /**
     * determines, in how many segments the circle around cells is divided,
     * to find a new position for the cell.
     */
    private int       triesPerCell;
    
    /**
     * the list of all cells of the graph
     */
    protected ArrayList cellList;
    /**
     * the list of all edges of the graph
     */
    protected ArrayList edgeList;
    /**
     * the list of all cells, a new layout should be calculated for
     */
    protected ArrayList applyCellList;
    
    /**
     * the JGraph
     */
    private JGraph    jgraph;
    
    /**
     * if this algorithm is a optimizing algorithm, this value indicates the
     * offset for the progress dialog, else it is 0
     */
    private int       initProgressValue = 0;
    
    /**
     * holds the configuration of the algorithm, gained by the controller
     */
    protected Properties presetConfig;
    
    /**
     * for debugging purpose. 
     */
    private long      time = 0;

    /**
     * the progress dialog
     */
    private ProgressDialog dlgProgress =
        new ProgressDialog((Frame) null, "Progress:", false);
        
    /**
     * for debugging purpose
     */
    private boolean isDebugging = false;
    /**
     * indicates if the algorihm is performing a calculation. this prevents from
     * entering the method {@link #graphChanged(GraphModelEvent) 
     * graphChanged(...)} more than once at a time.
     */
    private boolean isRunning   = false;
        
        
    /**
     * the number of edges, neighbors of inserted cells are away,
     * to be also layouted again.
     */   
    private int       luRecursionDepth;
    /**
     * if a cell has a lower distance to a inserted cell, after the cell gained 
     * its initial position, it will be layouted too
     */
    private double    luPerimeterRadius;
    /**
     * if more than one cell is inserted and the initial position of other 
     * inserted cells is inside {@link #luPerimeterRadius} around a initial
     * position of a inserted cell, than {@link #luPerimeterRadius} will be
     * increased by this value.
     */
    private double    luPerimeterRadiusInc;
    /**
     * determines how the neighborhood is handled, when a layout update
     * should be performed. Possible values are:<p>
     * <blockquote><blockquote>
     * {@link AnnealingLayoutController#KEY_LAYOUT_UPDATE_METHOD_NEIGHBORS_ONLY
     * KEY_LAYOUT_UPDATE_METHOD_NEIGHBORS_ONLY}<br>
     * {@link AnnealingLayoutController#KEY_LAYOUT_UPDATE_METHOD_PERIMETER
     * KEY_LAYOUT_UPDATE_METHOD_PERIMETER}<br>
     * </blockquote></blockquote>
     */
    private String    luMethod;
    
    /**
     * prevents from dividing with zero and from creating to high costs
     */
    private double equalsNull = 0.05;
    
    /**
     * Switches clustering for the layout update process on/off
     */
    private boolean         isClusteringEnabled;
    
    /**
     * Scales movement of clusters. It is recommendet to take
     * a value between 1.0 and 0.0. This garanties, that clusters move slower
     * than other cells. That rises the chance of getting a good looking layout
     * after the calculation.
     */
    private double          clusterMoveScaleFactor;
    
    /**
     * Effects, how many clusters are created, when the layout update process
     * starts. This affects the initial number of clusters, which is the number
     * of cells available minus the number of cells to layout. The result of
     * that term is divided by this factor, to get the maximum number of 
     * clusters. After this calculation, the clustering algorithm tries to
     * minimize the number of clusters, so there might be less clusters than 
     * the maximum number.
     */
    private double          clusteringFactor;

/******************************************************************************/
	/**
	 * Constructor for SimulatedAnnealingAlgorithm.
	 */
	public AnnealingLayoutAlgorithm() {
	}

/******************************************************************************/
	/**
     * Runs the Algorithm
	 * @see org.jgraph.layout.LayoutAlgorithm#perform(JGraph, boolean, Properties)
	 */
	public void perform(
		JGraph graph,
		boolean applyToAll,
		Properties configuration) {
            
        isRunning = true;
            
//        System.out.println("now running Simulated Annealing");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -