📄 annealinglayoutalgorithm.java
字号:
* @param view CellView, that stores the attribute
* @param key The attribute is stored in the CellView with this key
* @return Object stored with the given key in the given CellView
*/
private Object getAttribute(CellView view, String key){
return view.getAttributes().get(key);
}
/******************************************************************************/
/**
* After the calculation of the new Layout for a graph, the cells of the graph
* are positioned somewhere on the drawing space. They even might have negative
* coordinates. To prevent from this, this method is called, everytime before
* {@link #applyChanges()} is called. This method moves the whole graph to the
* upper left corner. No cell will have negative x- or y-coordinates.
*/
private void moveGraphToNW(){
Point2D.Double firstPos = getPosition((CellView)cellList.get(0));
double minX = firstPos.x;
double minY = firstPos.y;
double maxX = minX;
double maxY = minY;
for( int i = 0; i < cellList.size(); i++ ){
CellView view = (CellView) cellList.get(i);
Point2D.Double viewPos = getPosition((CellView)cellList.get(i));
Rectangle viewBounds = new Rectangle(view.getBounds());
if( viewPos.getX() < minX ){
minX = viewPos.getX();
}
else if( viewPos.getX()+viewBounds.getWidth() > maxX ){
maxX = viewPos.getX()+viewBounds.getWidth();
}
if( viewPos.getY() < minY ){
minY = viewPos.getY();
}
else if( viewPos.getY()+viewBounds.getHeight() > maxY ){
maxY = viewPos.getY()+viewBounds.getHeight();
}
}
minX -= 50;
minY -= 50;
for( int i = 0; i < cellList.size(); i++ ){
CellView view = (CellView) cellList.get(i);
Point2D.Double pos = getPosition(view);
setPosition(view,new Point2D.Double(pos.x-minX,
pos.y-minY));
}
}
/******************************************************************************/
/**
* Retrieves the Cells that are directly connected to the given Cell and
* member of the given list.
* @param list Only relatives from this List are allowed
* @param view Relatives from this view are requested
* @return Relatives from view that are in the list
* @see #getRelatives(CellView)
*/
protected ArrayList getRelativesFrom(ArrayList list, CellView view){
ArrayList relatives = getRelatives(view);
ArrayList result = new ArrayList();
for( int i = 0; i < relatives.size(); i++ )
if( list.contains(relatives.get(i)) )
result.add(relatives.get(i));
return result;
}
/******************************************************************************/
/**
* Retrieves all Cells that have an edge with the given Cell.
* @param view Cell, the relatives are requested from
* @return Relatives of view
*/
protected ArrayList getRelatives(CellView view){
if( view.getAttributes().containsKey(KEY_RELATIVES) )
return (ArrayList) view.getAttributes().get(KEY_RELATIVES);
ArrayList relatives = new ArrayList();
ArrayList portsCells = new ArrayList();
VertexView vertexView = (VertexView)view;
if( isCluster(view) ){
ArrayList clusteredVertices = (ArrayList) vertexView.getAttributes().get(KEY_CLUSTERED_VERTICES);
for( int i = 0; i < clusteredVertices.size(); i++ ){
ArrayList clusterRelatives = getRelatives((CellView)clusteredVertices.get(i));
for( int j = 0; j < clusterRelatives.size(); j++ )
if( !relatives.contains(clusterRelatives.get(j)) &&
!clusteredVertices.contains(clusterRelatives.get(j)) ){
relatives.add(clusterRelatives.get(j));
}
}
}
else {
GraphModel model = vertexView.getModel();
CellMapper mapper = vertexView.getMapper() ;
Object vertexCell = vertexView.getCell() ;
for (int i = 0; i < model.getChildCount(vertexCell); i++){
Object portCell = model.getChild(vertexCell, i);
portsCells.add(portCell);
}
for( int i = 0; i < portsCells.size() ; i++ ){
Object portCell = portsCells.get(i);
Iterator edges = model.edges(portCell);
while (edges.hasNext() ){
Object edge = edges.next() ;
Object nextPort = null;
if( model.getSource(edge) != portCell ){
nextPort = model.getSource(edge);
}
else {
nextPort = model.getTarget(edge);
}
CellView nextVertex = mapper.getMapping(
model.getParent(nextPort), false);
relatives.add(nextVertex);
}
}
}
view.getAttributes().put(KEY_RELATIVES,relatives);
return relatives;
}
/******************************************************************************/
/**
* When Cells are inserted and a update of the layout is desired, this method
* defines the initial positions for all cells, the already layouted cells and
* the inserted. The already layouted cells get their previos calculated
* position, gained from their bounds. The inserted Cells are positioned
* recursivly. The inserted Cells, that have at least one relative in
* {@link #cellList} are placed in the barycenter of the relatives. After this,
* the inserted Cells, with a new position are added to {@link #cellList}.
* This is done, until all inserted Cells are in {@link #cellList}.
*
* @param viewList List of the inserted Cells
* @see #arrangeLayoutUpdateInsertedCellsPlacement(ArrayList)
*/
private void arrangeLayoutUpdateInsertPlacement(CellView[] viewList){
//preinitialisation - init positions for all known vertexViews
for( int i = 0; i < cellList.size(); i++ ){
CellView view = (CellView) cellList.get(i);
if( !view.getAttributes().containsKey(KEY_POSITION) ){
Point2D.Double pos = new Point2D.Double(
view.getBounds().getCenterX(),
view.getBounds().getCenterY());
view.getAttributes().put(KEY_POSITION,pos);
}
}
ArrayList placableCells = new ArrayList();
for( int i = 0; i < viewList.length; i++ )
placableCells.add(viewList[i]);
arrangeLayoutUpdateInsertedCellsPlacement(placableCells);
/*
//puts the view in the barycenter of the relatives, if there are any
for( int i = 0; i < viewList.length; i++ )
if( viewList[i] instanceof VertexView ){
ArrayList relatives = getRelativesFrom(cellList,viewList[i]);
if( relatives.size() != 0 ){
double sumX = 0.0;
double sumY = 0.0;
for( int j = 0; j < relatives.size(); j++ ){
Point2D.Double pos = (Point2D.Double)
((CellView)relatives.get(j)).
getAttributes().
get(KEY_POSITION);
sumX += pos.x;
sumY += pos.y;
}
Point2D.Double randomVector = new Point2D.Double(Math.cos(Math.random()*2.0*Math.PI)*10.0,
Math.sin(Math.random()*2.0*Math.PI)*10.0);
viewList[i].getAttributes().put(KEY_POSITION,
new Point2D.Double(
(sumX/(double)relatives.size())+randomVector.x,
(sumY/(double)relatives.size())+randomVector.y));
}
else {
viewList[i].getAttributes().put(KEY_POSITION,
new Point2D.Double(
0.0,
0.0));
}
}*/
}
/******************************************************************************/
/**
* Recursive method for finding the initial position for inserted cells. The
* inserted cells are checked, whether there is at leased one of the relatives
* in {@link #cellList}. If there is any, the cells are positioned in the
* barycenter of the relatives. If there is only one relative, this means, the
* inserted CellViews are positioned exactly on the position of the relative.
* Cells with no relative in {@link #cellList} are stored in a list. After all
* Cells are visited and checked, all positioned cells are added to
* {@link #cellList}. Then, while the list with the non positioned Cells is
* not empty, the method is called recursivly again. This is done, until all
* inserted cells are positioned or no relatives could be found for all left
* Cells (that causes that the left cells are positioned in the upper left
* corner).
*
* @param placableCells A List of CellViews, that have to be placed in the
* barycenter of their relatives
* @see #arrangeLayoutUpdateInsertPlacement(CellView[])
* @see #graphChanged(GraphModelEvent)
*/
private void arrangeLayoutUpdateInsertedCellsPlacement(ArrayList placableCells){
ArrayList notPlacedCells = new ArrayList();
for( int i = 0; i < placableCells.size(); i++ ){
CellView view = (CellView) placableCells.get(i);
if( view instanceof VertexView ){
ArrayList relatives = getRelativesFrom(cellList,view);
if( relatives.size() != 0 ){
double sumX = 0.0;
double sumY = 0.0;
for( int j = 0; j < relatives.size(); j++ ){
Point2D.Double pos = (Point2D.Double)
((CellView)relatives.get(j)).
getAttributes().
get(KEY_POSITION);
sumX += pos.x;
sumY += pos.y;
}
Point2D.Double randomVector = new Point2D.Double(Math.cos(Math.random()*2.0*Math.PI)*10.0,
Math.sin(Math.random()*2.0*Math.PI)*10.0);
view.getAttributes().put(KEY_POSITION,
new Point2D.Double(
(sumX/(double)relatives.size())+randomVector.x,
(sumY/(double)relatives.size())+randomVector.y));
}
else {
notPlacedCells.add(view);
}
}
}
for( int i = 0; i < placableCells.size(); i++ ){
if( placableCells.get(i) != null )
if( ((CellView) placableCells.get(i)).getAttributes() != null )
if( ((CellView) placableCells.get(i)).getAttributes().containsKey(KEY_POSITION) )
cellList.add(placableCells.get(i));
}
if( notPlacedCells.size() != placableCells.size() ){
arrangeLayoutUpdateInsertedCellsPlacement(notPlacedCells);
}
else {
for( int i = 0; i < notPlacedCells.size(); i++ ){
CellView view = (CellView) notPlacedCells.get(i);
if( !view.getAttributes().containsKey(KEY_POSITION) )
view.getAttributes().put(KEY_POSITION,
new Point2D.Double(0.0,0.0));
}
}
for( int i = 0; i < cellList.size(); i++ )
if( ((CellView)cellList.get(i)).getAttributes().get(KEY_POSITION) == null )
System.err.println("WHATCH OUT!!! NODE "+i+" == NULL");
}
/******************************************************************************/
/**
* Decides in a layout update process, what cells are member of
* {@link #applyCellList}. This depends on the configuration of the layout
* update method. First, regardless which layout update method was chosen, all
* inserted cells, gained a
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -