📄 annealinglayoutalgorithm.java
字号:
/*----------------AQUIRATION OF RUNTIME CONSTANTS----------------*/
jgraph = graph;
presetConfig = configuration;
cellList = new ArrayList();
edgeList = new ArrayList();
applyCellList = new ArrayList();
loadConfiguration(CONFIG_KEY_RUN);
getNodes(jgraph,applyToAll);
if( applyCellList.size() == 0 )
return;
if( isLayoutUpdateEnabled )
jgraph.getModel().addGraphModelListener(this);
/*------------------------AQUIRATION DONE------------------------*/
initProgressValue = 0;
dlgProgress.setValue(initProgressValue);
dlgProgress.setVisible(true);
/*------------------------ALGORITHM START------------------------*/
init(true);
boolean isCancled = run();
/*-------------------------ALGORITHM END-------------------------*/
//if this algorithm isn't a optimization add-on of another algorithm
if( !isCancled ){
moveGraphToNW();//moves the graph to the upper left corner
applyChanges(); // making temporary positions to real positions
removeTemporaryData(); // remove temporary positions
}
dlgProgress.setVisible(false);
isRunning = false;
}
/******************************************************************************/
/**
* Runs the Algorithm as a optimization Algorithm of another Algorithm
* @param applyList List of all Cells, a new Layout should be found for.
* @param allCellList List of all Cells of the Graph
* @param allEdgeList List of all Edges of the Graph
* @param dialog Progress Dialog of the Algorithm, this Algorithm is a
* Optimizer for.
* @return when Cancel is pressed during the optimization, the method returns
* <code><b>true</b></code>, else, for a successfull run,
* <code><b>false</b></code>.
*/
public boolean performOptimization(ArrayList applyList, ArrayList allCellList, ArrayList allEdgeList, Properties config, ProgressDialog dialog){
cellList = allCellList;
applyCellList = applyList;
edgeList = allEdgeList;
presetConfig = config;
dlgProgress = dialog;
initProgressValue = dialog.getValue();
loadConfiguration(CONFIG_KEY_RUN);
init(false);
boolean isCancled = run();
return isCancled;
}
/******************************************************************************/
/**
* Loads the initial Values from the configuration.
*
* @param configSwitch Determines which configurationvalues have to be loaded
* Possible values are {@link #CONFIG_KEY_RUN} and
* {@link #CONFIG_KEY_LAYOUT_UPDATE}
*/
private void loadConfiguration(int configSwitch){
isLayoutUpdateEnabled = isTrue((String)presetConfig.get(AnnealingLayoutController.KEY_LAYOUT_UPDATE_ENABLED));
//load config for normal runs
if( configSwitch == CONFIG_KEY_RUN ){
initTemperature = Double.parseDouble((String)presetConfig.get(AnnealingLayoutController.KEY_INIT_TEMPERATURE));
minTemperature = Double.parseDouble((String)presetConfig.get(AnnealingLayoutController.KEY_MIN_TEMPERATURE));
minDistance = Double.parseDouble((String)presetConfig.get(AnnealingLayoutController.KEY_MIN_DISTANCE));
tempScaleFactor = Double.parseDouble((String)presetConfig.get(AnnealingLayoutController.KEY_TEMP_SCALE_FACTOR));
maxRounds = Integer.parseInt((String)presetConfig.get(AnnealingLayoutController.KEY_MAX_ROUNDS));
triesPerCell = Integer.parseInt((String)presetConfig.get(AnnealingLayoutController.KEY_TRIES_PER_CELL));
ArrayList lambda = (ArrayList) presetConfig.get(AnnealingLayoutController.KEY_LAMBDA);
lambdaList = new double[AnnealingLayoutController.COUT_COSTFUNCTION];
for( int i = 0; i < lambdaList.length; i++ )
lambdaList[i] = ((Double)lambda.get(i)).doubleValue();
bounds = (Rectangle) presetConfig.get(AnnealingLayoutController.KEY_BOUNDS);
costFunctionConfig = Integer.parseInt((String)presetConfig.get(AnnealingLayoutController.KEY_COST_FUNCTION_CONFIG),2);
computePermutation = isTrue((String)presetConfig.get(AnnealingLayoutController.KEY_COMPUTE_PERMUTATION));
uphillMovesAllowed = isTrue((String)presetConfig.get(AnnealingLayoutController.KEY_IS_UPHILL_MOVE_ALLOWED));
}
//load config for layout updates
else if( configSwitch == CONFIG_KEY_LAYOUT_UPDATE ){
initTemperature = Double.parseDouble((String)presetConfig.get(AnnealingLayoutController.KEY_LAYOUT_UPDATE_INIT_TEMPERATURE));
minTemperature = Double.parseDouble((String)presetConfig.get(AnnealingLayoutController.KEY_LAYOUT_UPDATE_MIN_TEMPERATURE));
minDistance = Double.parseDouble((String)presetConfig.get(AnnealingLayoutController.KEY_LAYOUT_UPDATE_MIN_DISTANCE));
tempScaleFactor = Double.parseDouble((String)presetConfig.get(AnnealingLayoutController.KEY_LAYOUT_UPDATE_TEMP_SCALE_FACTOR));
maxRounds = Integer.parseInt((String)presetConfig.get(AnnealingLayoutController.KEY_LAYOUT_UPDATE_MAX_ROUNDS));
triesPerCell = Integer.parseInt((String)presetConfig.get(AnnealingLayoutController.KEY_LAYOUT_UPDATE_TRIES_PER_CELL));
ArrayList lambda = (ArrayList) presetConfig.get(AnnealingLayoutController.KEY_LAYOUT_UPDATE_LAMBDA);
lambdaList = new double[AnnealingLayoutController.COUT_COSTFUNCTION];
for( int i = 0; i < lambdaList.length; i++ )
lambdaList[i] = ((Double)lambda.get(i)).doubleValue();
bounds = (Rectangle) presetConfig.get(AnnealingLayoutController.KEY_LAYOUT_UPDATE_BOUNDS);
costFunctionConfig = Integer.parseInt((String)presetConfig.get(AnnealingLayoutController.KEY_LAYOUT_UPDATE_COST_FUNCTION_CONFIG),2);
computePermutation = isTrue((String)presetConfig.get(AnnealingLayoutController.KEY_LAYOUT_UPDATE_COMPUTE_PERMUTATION));
uphillMovesAllowed = isTrue((String)presetConfig.get(AnnealingLayoutController.KEY_LAYOUT_UPDATE_IS_UPHILL_MOVE_ALLOWED));
luRecursionDepth = Integer.parseInt((String)presetConfig.get(AnnealingLayoutController.KEY_LAYOUT_UPDATE_METHOD_NEIGHBORS_DEPTH));
luPerimeterRadius = Double.parseDouble((String)presetConfig.get(AnnealingLayoutController.KEY_LAYOUT_UPDATE_METHOD_PERIMETER_RADIUS));
luPerimeterRadiusInc = Double.parseDouble((String)presetConfig.get(AnnealingLayoutController.KEY_LAYOUT_UPDATE_METHOD_PERIMETER_RADIUS_INCREASE));
luMethod = (String)presetConfig.get(AnnealingLayoutController.KEY_LAYOUT_UPDATE_METHOD);
isClusteringEnabled = isTrue((String)presetConfig.get(AnnealingLayoutController.KEY_LAYOUT_UPDATE_CLUSTERING_ENABLED));
clusteringFactor = Double.parseDouble((String)presetConfig.get(AnnealingLayoutController.KEY_LAYOUT_UPDATE_CLUSTERING_FACTOR));
clusterMoveScaleFactor = Double.parseDouble((String)presetConfig.get(AnnealingLayoutController.KEY_LAYOUT_UPDATE_CLUSTERING_MOVE_SCALE));
}
loadAdditionalConfiguration(configSwitch);
}
/******************************************************************************/
/**
* Method of classes extending this class, that want to load their initial
* values from the configuration.
*
* @param configSwitch Determines which configurationvalues have to be loaded
* Possible values are {@link #CONFIG_KEY_RUN} and
* {@link #CONFIG_KEY_LAYOUT_UPDATE}
* @see #loadConfiguration(int)
*/
protected void loadAdditionalConfiguration(int configSwitch){
}
/******************************************************************************/
/**
* Helper-method. Transforms a String into a Boolean Value. The String has to
* Contain the characters "true" or "false". upper case writings of some letters
* doesn't matter. if the String doesn't contain "true" or "false" the method
* returns false (easier to handle than throwing an exception).
*/
private boolean isTrue(String boolValue){
if( boolValue != null ){
if( "TRUE".equals(boolValue.toUpperCase()) ){
return true;
}
else if( "FALSE".equals(boolValue.toUpperCase()) ){
return false;
}
}
return false;
}
/******************************************************************************/
/**
* Extracts all cells, all edges and all cells, the algorithm should run for,
* from JGraph. After calling this Method {@link #cellList},
* {@link #applyCellList} and {@link #edgeList} is filled.
*
* @param jgraph A instanz from JGraph, the Cells will be extract from.
* @param applyToAll Determines, if the Algorithm should run for all Cells or
* only for the selected. In the first case, the contense of {@link #cellList}
* is the same as of {@link #applyCellList}
*/
private void getNodes(JGraph jgraph, boolean applyToAll){
Object[] cells = jgraph.getRoots();
Object[] selectedCells = jgraph.getSelectionCells();
CellView[] view = jgraph.getGraphLayoutCache().getMapping(cells,false);
CellView[] selectedView = jgraph.getGraphLayoutCache().getMapping(selectedCells,false);
for (int i = 0; i < view.length; i++)
if (view[i] instanceof VertexView){
if( !cellList.contains(view[i]) )
cellList.add(view[i]);
if( applyToAll )
if( !applyCellList.contains(view) )
applyCellList.add(view[i]);
}
else if( view[i] instanceof EdgeView && view[i] != null ){
if( !edgeList.contains(view[i]) )
edgeList.add(view[i]);
}
if( !applyToAll )
for( int i = 0; i < selectedView.length; i++ )
if( view[i] instanceof VertexView )
if( !applyCellList.contains(selectedView[i]) )
applyCellList.add(selectedView[i]);
}
/******************************************************************************/
/**
* Makes the changed Positions of the Cells of the graph visible. This is like
* a "commit". Before this Method runs, nothing has change is the visible
* representation of the graph. After this method, the Layout for the Cells
* of the graph is applied.
*/
private void applyChanges(){
Map viewMap = new Hashtable();
for( int i = 0; i < applyCellList.size(); i++ ){
CellView view = (CellView)applyCellList.get(i);
Point2D.Double pos = getPosition(view);
Rectangle r = view.getBounds();
r.x = (int) (pos.getX() - ((double)r.getWidth() /2.0));
r.y = (int) (pos.getY() - ((double)r.getHeight()/2.0));
Object cell = ((CellView) applyCellList.get(i)).getCell();
Map attributes = GraphConstants.createMap();
GraphConstants.setBounds(attributes, r);
viewMap.put(cell, attributes);
}
jgraph.getGraphLayoutCache().edit(viewMap,null,null,null);
}
/******************************************************************************/
/**
* Removes the temporary Data from the Cells of the graph. During the run of the
* Algorithm there has been plenty of Data stored in the Cells. These are
* removed here, if the Algorithm is canceled or finished.
*/
private void removeTemporaryData(){
for( int i = 0; i < applyCellList.size(); i++ )
((CellView)applyCellList.get(i)).getAttributes().clear();
}
/******************************************************************************/
/**
* Initialises the Algorithm. This is the step right before running the
* Algorithm. Letting this method set the initial Positions for all cells is
* only necessary when the Algorithm makes a normal run. Otherwise the initial
* Positions are allready set, by
* {@link #arrangeLayoutUpdateInsertPlacement(CellView[])
* arrangeLayoutUpdateInsertPlacement(...)}.
* @param setInitPositions Determines, if the initial Positions of the cells
* should be set or not. Initial Positions are calculated by random.
*/
private void init(boolean setInitPositions){
if( setInitPositions ){
for( int i = 0; i < applyCellList.size(); i++ )
if( !((CellView)applyCellList.get(i)).getAttributes().containsKey(KEY_POSITION) )
setPosition(i,
(Math.random()*bounds.getWidth()) +bounds.getX(),
(Math.random()*bounds.getHeight())+bounds.getY());
for( int i = 0; i < cellList.size(); i++ )
if( !((CellView)cellList.get(i)).getAttributes().containsKey(KEY_POSITION) )
setPosition((CellView)cellList.get(i),
(Math.random()*bounds.getWidth()) +bounds.getX(),
(Math.random()*bounds.getHeight())+bounds.getY());
}
temperature = initTemperature;
maxRounds = Math.min(100 * applyCellList.size(),
getMaxRoundsByTemperature(temperature));
round = 0;
}
/******************************************************************************/
/**
* Runs the Algorithm until {@link #temperature} is lower than
* {@link #minTemperature} or cancel on the progressdialog is pressed.
*
* @return When the Algorithm is Canceled, the Method breaks and returns
* <code><b>true</b></code>.
*/
private boolean run(){
boolean isCancled = false;
while( round <= maxRounds && !isCancled)
isCancled = performRound();
return isCancled;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -