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

📄 gemlayoutalgorithm.java

📁 用JGraph编的软件
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
        if( avoidOverlapping ){
        
            Rectangle viewBounds = new Rectangle(
                                             (int)pos.x,
                                             (int)pos.y,
                                             (int)view.getBounds().getWidth(),
                                             (int)view.getBounds().getHeight());
            Rectangle viewBorder = new Rectangle(
                        (int)(viewBounds.getX()-overlapDetectWidth),
                        (int)(viewBounds.getY()-overlapDetectWidth),
                        (int)(viewBounds.getWidth()+(2.0*overlapDetectWidth)),
                        (int)(viewBounds.getHeight()+(2.0*overlapDetectWidth)));
                                             
            for( int i = 0; i < cellList.size(); i++ ){
            
                Point2D.Double uPos = getPosition(i,cellList);            
                Rectangle uBounds = new Rectangle(
                      (int)uPos.x,
                      (int)uPos.y,
                      (int)((CellView)cellList.get(i)).getBounds().getWidth(),
                      (int)((CellView)cellList.get(i)).getBounds().getHeight());
            
                if( view != cellList.get(i) &&
                    viewBorder.intersects(uBounds) ){
                
                
                    Dimension viewSize = viewBounds.getSize();
                    Dimension uSize    = uBounds.getSize();
                
                    double minDistance = 
                        (Math.max(viewSize.getWidth(),viewSize.getHeight())/2.0)+
                        (Math.max(uSize.getWidth(),uSize.getHeight())/2.0)+overlapPrefDistance;
                
                    double deltaX = (double)(pos.x - uPos.x);
                    double deltaY = (double)(pos.y - uPos.y);
/*                  
                    if( isCellACluster ){
                        deltaX -= view.getBounds().getWidth() / 2.0;
                        deltaY -= view.getBounds().getHeight()/ 2.0;
                    }
                    if( isCluster((CellView)cellList.get(i))){
                        deltaX -= ((CellView)cellList.get(i)).getBounds().getWidth() / 2.0;
                        deltaY -= ((CellView)cellList.get(i)).getBounds().getHeight()/ 2.0;
                    }*/
                
                    if( deltaX < equalsNull && deltaX >= 0.0 ){
                        deltaX = equalsNull;
                    }
                    else if( deltaX > -equalsNull && deltaX <= 0.0 ){
                        deltaX = -equalsNull;
                    }
                    if( deltaY < equalsNull && deltaY >= 0.0 ){
                        deltaY = equalsNull;
                    }
                    else if( deltaY > -equalsNull && deltaY <= 0.0 ){
                        deltaY = -equalsNull;
                    }
                
                
                    double absDelta = MathExtensions.abs(deltaX,deltaY);
                
                    Point2D.Double force = new Point2D.Double(
                          deltaX*(minDistance*minDistance)/(absDelta*absDelta),
                          deltaY*(minDistance*minDistance)/(absDelta*absDelta));
//                System.out.println("Overlapping Nodes: ("+pos.x+"|"+pos.y+") and ("+uPos.x+"|"+uPos.y+") -> Distance = "+absDelta+" -> Force = "+force);
                    forcesByOverlapping.add(force);
                }
            }
        }
        
        //for classes that extend this algorithm
        ArrayList additionalForce = getAdditionalForces((VertexView)view);
        
        //adding the forces
        impulse = add(impulse,gravitationForce);
        impulse = add(impulse,randomImpulse);
        
        for( int i = 0; i < repulsiveForce.size(); i++ )
            impulse = add(impulse,(Point2D.Double)  repulsiveForce.get(i) );
        for( int i = 0; i < attractiveForce.size(); i++ )
            impulse = sub(impulse,(Point2D.Double) attractiveForce.get(i) );
        for( int i = 0; i < forcesByOverlapping.size(); i++ )
            impulse = add(impulse,(Point2D.Double) forcesByOverlapping.get(i));
        for( int i = 0; i < additionalForce.size(); i++ )
            impulse = add(impulse,(Point2D.Double) additionalForce.get(i) );
        
        return impulse;            
    }
    
/******************************************************************************/
/**
 * Updating the position of the given cell, by taking the direction of the
 * current impulse and the length of the temperature of the cell. After this
 * temperature will fall, when the last impulse and the current impulse are
 * part of a rotation or a oscillation, temperature of the cell will be 
 * decreased.
 * 
 * @param view Cell that should be updated
 */
    private void updatePosAndTemp(CellView view){
        
        Point2D.Double impulse     = (Point2D.Double) view.getAttributes().get(KEY_CURRENT_IMPULSE);
        Point2D.Double lastImpulse = (Point2D.Double) view.getAttributes().get(KEY_LAST_IMPULSE);
        Point2D.Double position    = getPosition(view);
        double localTemperature = ((Double) view.getAttributes().get(KEY_TEMPERATURE)).doubleValue();
        double skewGauge        = ((Double) view.getAttributes().get(KEY_SKEWGAUGE)).doubleValue();
        double absImpulse     = MathExtensions.abs(impulse);
        double absLastImpulse = MathExtensions.abs(lastImpulse);
        
        if( absImpulse > equalsNull ){ //if impulse != 0
            //scaling with temperature
            if( isCluster(view) ){
                impulse.setLocation( 
                    impulse.getX() * localTemperature * clusterForceScalingFactor / absImpulse,
                    impulse.getY() * localTemperature * clusterForceScalingFactor / absImpulse);                
            }
            else {
                impulse.setLocation( 
                                impulse.getX() * localTemperature / absImpulse,
                                impulse.getY() * localTemperature / absImpulse);
            }
                                 
            view.getAttributes().put(KEY_CURRENT_IMPULSE,impulse);
            position.setLocation(position.getX()+impulse.getX(),
                                 position.getY()+impulse.getY());
            view.getAttributes().put(KEY_POSITION,position);
/*            if( isDebugging ){
                check(impulse,"impulse12");
                check(position,"position12");
            }*/
        }
        if( absLastImpulse > equalsNull ){
            
            //beta = angle between new and last impulse
            double beta = MathExtensions.angleBetween(impulse,lastImpulse);
            
            double sinBeta = Math.sin(beta);
            double cosBeta = Math.cos(beta);
            
            //detection for rotations
            if( Math.abs(sinBeta) >= Math.sin((Math.PI/2.0)+(alphaRot/2.0)) )
                skewGauge += sigmaRot * MathExtensions.sgn(sinBeta);            
                
            //detection for oscillation
            if( cosBeta < Math.cos(Math.PI+(alphaOsc/2.0)) )
                localTemperature *= sigmaOsc * Math.abs(cosBeta);            
            
            localTemperature *= 1.0 - Math.abs(skewGauge);
            localTemperature = Math.min(localTemperature,maxTemperature);
        }
        
        //applying changes
        view.getAttributes().put(KEY_TEMPERATURE,new Double(localTemperature));
        view.getAttributes().put(KEY_POSITION   ,position);
        view.getAttributes().put(KEY_SKEWGAUGE  ,new Double(skewGauge));
        view.getAttributes().put(KEY_LAST_IMPULSE,new Point2D.Double(
                                                               impulse.getX(),
                                                               impulse.getY()));
/*        if( isDebugging )
            checkCellList();*/
    }

/******************************************************************************/
/**
 * Adding two forces.
 * @param v1 Force that should be added with v2
 * @param v2 Force that should be added with v1
 * @return Sum of both forces.
 */
    private Point2D.Double add(Point2D.Double v1, Point2D.Double v2){
        return new Point2D.Double(v1.getX()+v2.getX(),v1.getY()+v2.getY());        
    }

/******************************************************************************/
/**
 * Subtracing two forces.
 * @param v1 Force, v2 should be subtracted from
 * @param v2 Force, that should be subtracted from v1.
 */
    private Point2D.Double sub(Point2D.Double v1, Point2D.Double v2){
        return new Point2D.Double(v1.getX()-v2.getX(),v1.getY()-v2.getY());
    }

/******************************************************************************/
/**
 * Returns all Cells, that have a direct connection with the given cell and are
 * a member of the given list.
 * 
 * @param list List of some cells, that should contain some relatives from view
 * @param view Cell, the relatives are requested from
 * @return List of all relatives that are in list.
 * @see #getRelatives(CellView)
 */
    private 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;
    }
        
/******************************************************************************/
/**
 * Returns a list of all cells, that have a direct connection with the given
 * cell via a edge. At the end of this method, the result is stored in the given
 * cell, so it will be available the next time, the method runs. This temporary
 * stored data will stay there, until the algorithm finishes 
 * (successfull or not). 
 * 
 * @param view Cell, the relatives requested from.
 * @return List of all cells, that have a direct connection with a edge to
 * the given cell. 
 */
    private ArrayList getRelatives(CellView view){    

        if( !(view instanceof VertexView) ) {
            new Exception("getRelatives 1").printStackTrace();
            return null;
        }
        
        if( view.getAttributes().containsKey(KEY_RELATIVES) )
            return (ArrayList) view.getAttributes().get(KEY_RELATIVES);
            
        ArrayList relatives = new ArrayList();
                    
        //if view is a cluster, then all clustered cells are extracted and
        //getRelatives is called for every cell again. the resulting relatives
        //are checked, if they are in the same cluster or another cluster.
        //if the last condition is the case, the cluster is added, else the
        //vertex is added to the list of relatives, iff he isn't already in the
        //list
        if( isCluster(view) ){
            ArrayList clusteredVertices = (ArrayList) 
                               view.getAttributes().get(KEY_CLUSTERED_VERTICES);
            for( int i = 0; i < clusteredVertices.size(); i++ ){
                ArrayList vertexRelatives = getRelatives(
                                            (CellView)clusteredVertices.get(i));
                for( int j = 0; j < vertexRelatives.size(); j++ ){
                    CellView relative = (CellView) vertexRelatives.get(j);
                    if( !clusteredVertices.contains(relative) ){
/*                      if( relative.getAttributes().containsKey(KEY_CLUSTER) ){
                relative = (CellView) relative.getAttributes().get(KEY_CLUSTER);
                        }*/
                        if( !relatives.contains(relative))
                            relatives.add(relative);
                    }
                }
            }
        }
        else {        
            
            //runs only for vertices. finds all ports of the vertex. every
            //edge in every port is checked on their source and target.
            //the one, that isn't the vertex, we are searching the relatives of,
            //is added to the list of relatives.
            
            ArrayList portsCells = new ArrayList();
        
            VertexView vertexView = (VertexView)view;
            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), true);
                    relatives.add(nextVertex);
                }
            }
        }
        view.getAttributes().put(KEY_RELATIVES,relatives);
        return relatives;                
    }

/******************************************************************************/
/**
 * This is a rating method for the cells. It is used during 
 * {@link #computeImpulse(CellView)} scale some forces. 
 * 
 * @param view Cell, the weight is of interest.
 */

//TODO: method doesn't work right for clusters

    private double getNodeWeight(CellView view){
        
        if( view.getAttributes().containsKey(KEY_MASSINDEX) )
            return ((Double)view.getAttributes().get(KEY_MASSINDEX)).
                                                                  doubleValue();

⌨️ 快捷键说明

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