📄 annealinglayoutalgorithm.java
字号:
energy += lambda * ( (1.0/(t*t)) + (1.0/(l*l)) + (1.0/(b*b)) + (1.0/(r*r)) );
}
// System.out.println("Borderline : "+energy);
return energy;
}
/******************************************************************************/
/**
* Costfunction. This criterion tries to shorten the edges to a necessary
* minimum without causing the entire graph to become to tightly packed.
* This function penalizes long edges.
*
* @param lambda An appropriate normalizing factor. Increasing lamda relative
* to the lambdas of other costfunctions will result in shorter Edges.
* Decreasing brings up very different length of the edges.
* @return costs of this criterion
*/
private double getEdgeLength(double lambda ){
double energy = 0.0;
Line2D.Double[] lineList = getEdgeLines(edgeList);
for( int i = 0; i < lineList.length; i++ ){
Point2D p1 = lineList[i].getP1();
Point2D p2 = lineList[i].getP2();
double edgeLength = p1.distance(p2);
energy += lambda * edgeLength * edgeLength;
}
// System.out.println("EdgeLength : "+energy);
return energy;
}
/******************************************************************************/
/**
* Costfunction. A constant penalty value is added for every two edges that
* cross.
* @param lambda Normalizing factor. Increasing lambda means attributing more
* importance to the elimination of edge crossings, and results in pictures
* with fewer crossings on average. However, this may be at the expense of other
* aesthetics.
* @return costs of this criterion.
*/
private double getEdgeCrossing(double f, double lambda){
int n = 0; // counts edgecrossings around vertex[i]
Line2D.Double[] lineList = getEdgeLines(edgeList);
for( int i = 0; i < lineList.length; i++ )
for( int j = i; j < lineList.length; j++ )
if( j != i )
if( lineList[i].intersectsLine(lineList[j]) ){
if( ((lineList[i].getP1().getX() != lineList[j].getP1().getX()) && (lineList[i].getP1().getY() != lineList[j].getP1().getY())) &&
((lineList[i].getP1().getX() != lineList[j].getP2().getX()) && (lineList[i].getP1().getY() != lineList[j].getP2().getY())) &&
((lineList[i].getP2().getX() != lineList[j].getP1().getX()) && (lineList[i].getP2().getY() != lineList[j].getP1().getY())) &&
((lineList[i].getP2().getX() != lineList[j].getP2().getX()) && (lineList[i].getP2().getY() != lineList[j].getP2().getY())) ){
n++;
}
}
// System.out.println("EdgeCrossings : "+n);
return lambda * f * (double) n;
}
/******************************************************************************/
/**
* Costfunction. This method calculates the distance between Cells and Edges.
* A small distance brings up higher costs while great distances generates lower
* costs. Costs for the distance between Cells and Edges are always computed
* by the method. If the distance is smaller than {@link #minDistance}
* additional costs are added. This method is suggested for finetuning and other
* short running calculations. Its the slowest of all costfunctions implemented
* here.
*
* @param lamda A normalizing factor for this function. Drawings with a
* relativ increase lambda will have greater distances between nodes and
* edges, by the expense of other aesthetics.
*/
private double getEdgeDistance(double lambda){
double energy = 0.0;
for( int i = 0; i < applyCellList.size(); i++ ){
double h = 0.0;
CellView view = (CellView) applyCellList.get(i);
ArrayList relevantEdges = null;
if( view.getAttributes().containsKey(CF_KEY_EDGE_DISTANCE_RELEVANT_EDGES) ){
relevantEdges = (ArrayList) view.getAttributes().get(CF_KEY_EDGE_DISTANCE_RELEVANT_EDGES);
}
else {
relevantEdges = getRelevantEdges(view);
view.getAttributes().put(CF_KEY_EDGE_DISTANCE_RELEVANT_EDGES,relevantEdges);
}
Line2D.Double[] lineList = getEdgeLines(getRelevantEdges(view));
for( int j = 0; j < lineList.length; j++ ){
double distance = lineList[j].ptSegDist(getPosition(view));
//prevents from dividing with Zero
if( Math.abs(distance) < equalsNull )
distance = equalsNull;
if( distance != 0.0 )
h += lambda / ( distance * distance );
if( distance < minDistance )
h += lambda / ( minDistance * minDistance );
}
energy += h;
}
// System.out.println("EdgeDistance : "+energy);
return energy;
}
/******************************************************************************/
/**
* Costfunction. This is a extension to the original Algorithm. This method
* evaluates the distances between cells. When the distance is lower than
* {@link #minDistance} or the cells are overlapping the costs from this
* function increase.
*
* @param lambda Normalizing value for this function. Increasing this value
* brings up less overlapping pairs of cells, by the expense of other
* aesthetics.
* @return costs of this criterion.
*/
private double getNodeDistance(double lambda){
double energy = 0.0;
double radiusInc = 30.0;
int overlapCount = 0;
for( int i = 0; i < applyCellList.size(); i++ ){
Point2D.Double pos = (Point2D.Double)((CellView)applyCellList.get(i)).getAttributes().get(KEY_POSITION);
Rectangle vertex = ((CellView)applyCellList.get(i)).getBounds();
for( int j = 0; j < cellList.size(); j++ ){
if( applyCellList.get(i) != cellList.get(j) ){
Point2D.Double uPos = (Point2D.Double)((CellView)cellList.get(j)).getAttributes().get(KEY_POSITION);
Rectangle uVertex = ((CellView)cellList.get(j)).getBounds();
double minDist = Math.max((2.0 * radiusInc) +
(Math.max(vertex.getWidth(),vertex.getHeight())/2.0) +
(Math.max(uVertex.getWidth(),uVertex.getHeight())/2.0),
minDistance);
double distance = Math.abs(pos.distance(uPos));
//prevents from dividing with Zero
if( Math.abs(distance) < equalsNull )
distance = equalsNull;
if( distance < minDist ){
energy += lambda / (distance * distance);
overlapCount++;
}
}
}
}
return energy;
}
/******************************************************************************/
/**
* Transforms the Edges stored in a given List of edges into an array of lines.
* This is usefull, to get the Positions of the Edges.
* @param edges List containing only EdgeViews
* @return Array of Lines representing the edges of the graph.
*/
private Line2D.Double[] getEdgeLines(ArrayList edges){
Line2D.Double[] lines = new Line2D.Double[edges.size()];
for( int i = 0; i < edges.size(); i++ ){
EdgeView edge = (EdgeView) edges.get(i);
GraphModel model = edge.getModel();
CellMapper mapper = edge.getMapper();
CellView source = edge.getSource().getParentView();
CellView target = edge.getTarget().getParentView();
lines[i] = new Line2D.Double(getPosition(source),
getPosition(target));
}
return lines;
}
/******************************************************************************/
/**
* Returns all Edges that are connected with cells, member of
* {@link #applyCellList}, except the edges connected the the given cell.
* @param except Edges connected to this cell are not of interest
* @return List of all interesting Edges
*/
private ArrayList getRelevantEdges(CellView except){
ArrayList relevantEdgeList = new ArrayList();
for( int i = 0; i < edgeList.size(); i++ ){
CellView view = ((EdgeView)edgeList.get(i)).getSource().getParentView();
if( view != except &&
applyCellList.contains(view) ){
relevantEdgeList.add(edgeList.get(i));
}
else {
view = ((EdgeView)edgeList.get(i)).getTarget().getParentView();
if( view != except &&
applyCellList.contains(view) ){
relevantEdgeList.add(edgeList.get(i));
}
}
}
return relevantEdgeList;
}
/******************************************************************************/
/**
* Computes a random Vector with a random direction and a given length.
*/
public Point2D.Double getRandomVector(double maxLength){
double alpha = Math.random()*Math.PI*2;
double length = Math.random()*maxLength;
return new Point2D.Double(length*Math.cos(alpha),
length*Math.sin(alpha));
}
/******************************************************************************/
/**
* Sets the position of a CellView to the given Position
*
* @param view The CellView, the position should be set
* @param pos New Position
* @see #setAttribute(CellView,String,Object)
*/
private void setPosition(CellView view, Point2D.Double pos){
setAttribute(view,KEY_POSITION,pos);
}
/******************************************************************************/
/**
* Sets the position of a CellView member of {@link #applyCellList} to the given
* position.
*
* @param index ID of the CellView in {@link #applyCellList}
* @param x X-Coordinate of the new position
* @param y Y-Coordinate of the new position
* @see #setPosition(CellView,double,double)
*/
private void setPosition(int index, double x, double y){
setPosition((CellView)applyCellList.get(index),x,y);
}
/******************************************************************************/
/**
* Sets the position of a CellView to the given Position
*
* @param view The CellView, the position should be set
* @param x X-Coordinate of the new position
* @param y Y-Coordinate of the new position
* @see #setPosition(CellView,Point2D.Double)
*/
private void setPosition(CellView view, double x, double y){
setPosition(view,new Point2D.Double(x,y));
}
/******************************************************************************/
/**
* Returns the Position of a CellView
*
* @param view CellView, the position is requested
* @return Position of the CellView
* @see #getAttribute(CellView,String)
*/
private Point2D.Double getPosition(CellView view){
return (Point2D.Double) getAttribute(view,KEY_POSITION);
}
/******************************************************************************/
/**
* Sets an attribute in a CellView
*
* @param view CellView, the attribute should be set
* @param key The attribute will be stored in the CellView under that key.
* @param obj Object representing the attribute, that should be stored.
*/
private void setAttribute(CellView view,String key, Object obj){
if( view.getAttributes() == null )
view.setAttributes(new Hashtable());
Map attributes = view.getAttributes();
attributes.put(key,obj);
}
/******************************************************************************/
/**
* Returns an attribute from a CellView
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -