// Medusa is a graph viewer which allows interactive editing of networks
// (edges and nodes) and also connects to databases.
//
// Copyright (C) 2006 Sean Hooper
//
// This program is free software; you can redistribute it and/or modify 
// it under the terms of the GNU General Public License as published by 
// the Free Software Foundation; either version 2 of the License, or (at 
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but 
// WITHOUT ANY WARRANTY; without even the implied warranty of 
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 
// Public License for more details.
//
// You should have received a copy of the GNU General Public License along 
// with this program; if not, write to the 
// Free Software Foundation, Inc., 
// 59 Temple Place, Suite 330, 
// Boston, MA 02111-1307 USA

package medusa.display;

import java.util.Iterator;
import medusa.graph.Graph;
import medusa.graph.Node;
import medusa.graph.UniqueEdge;

/*
 * An implementation of the Fruchterman Reingold
 * graph layout algorithm
 * Coded by Sean Hooper for STRING 2003
 */

/* This class will assign new positions for the nodes
 * depending on the energy constraints
 */

public class FRspring implements Runnable{
    private int width;
    private int height;
    private double critXDistance;
    private double critYDistance;

    private int area;
    private double k;
    private Graph g;
    
    
    
    private double temp;
    private Thread me;
    private boolean done=true;

    private static final double LIMIT=1e-10;
    

    public FRspring (int width, int height){
	// for now, assume 5 nodes
	//me=new Thread(this);
	this.width = width;
	this.height = height;
	area = width*height;
	temp = width/10;
	critXDistance = width*3/4;
	critYDistance = height*3/4;
	//System.out.println(width+" "+height);
    }

    public FRspring (Graph g,int width, int height){
	
	this.g=g;
	this.width = width;
	this.height = height;
	area = width*height;
	temp = width/10;
	critXDistance = width*3/4;
	critYDistance = height*3/4;
	setK();
	//System.out.println(width+" "+height);
	//System.out.println("optimal length: "+k);
    }

    

    private void setK(){
	k = 0.8*Math.sqrt(area / this.g.getNodeSize());
	//k=0.1;
    }
    //static final double MAX_STEP=0.05;

    private double[] attractDistance(Node aNode, Node bNode){
	double xDelta = aNode.getX() - bNode.getX();
	double yDelta = aNode.getY() - bNode.getY();
	//System.out.println("attract"+a.x+" "+b.x);
	double delta =  Math.sqrt((xDelta * xDelta) + (yDelta * yDelta));
	double result[] = new double[2];
	delta = Math.max(delta,LIMIT);
	double force = delta*delta/k;
	result[0] = xDelta / delta*force;
	result[1]= yDelta / delta*force;
	return result;
    }

    private double[] repelDistance(Node aNode, Node bNode){
	double xDelta = aNode.getX() - bNode.getX();
	double yDelta = aNode.getY() - bNode.getY();
	
		if (xDelta > critXDistance) // repel over the x border right
		    xDelta = aNode.getX() - bNode.getX() - width; 
		if (xDelta < -critXDistance) // repel over the x border left
		    xDelta = aNode.getX() - bNode.getX() + width; 

		if (yDelta > critYDistance)// repel over the y border down
		    yDelta = aNode.getY() - bNode.getY() - height;
		if (yDelta < -critYDistance)// repel over the y border up
		    yDelta = aNode.getY() - bNode.getY() + height;

	//System.out.println("repel "+a.x+" "+b.x);
	double delta =  Math.sqrt((xDelta * xDelta) + (yDelta * yDelta));
	delta = Math.max(delta, LIMIT);
	double result[] = new double[2];
	double force = k*k/delta;
	result[0] = xDelta / delta*force;
	result[1] = yDelta / delta*force;
	return result;
    }

    
    static int MAX_ITERATIONS=300;
    private int iterations=0;
    
    public void iterateAll(){
	done=false;
	for (int i=0; i width) {
                    node.setX(width - borderSize - 10*Math.random());
                }
                if (node.getX() < borderSize) {
                    node.setX(borderSize + 10*Math.random()); 
                }
                if (node.getY() > height) {
                    node.setY(height - borderSize - 10*Math.random());
                }
                if (node.getY() < (borderSize+10)) {
                    // remember that the label also needs space
                    node.setY(2*borderSize + 10*Math.random());
                }
            }
        }
	// decrease the temperature
	//System.out.println("temp: "+temp);
	cool();
    }

    int borderSize=20;
    
    // for setting the border size
    public void setBorderSize(int borderSize){
	this.borderSize=borderSize;
    }
    
    private void cool(){
	temp*=1-(double)iterations/(double)MAX_ITERATIONS;
    }


    public static void main (String [] args){
	FRspring frSpring = new FRspring(400,400);
	
	frSpring.setK();
	for (int i=0; i<18;i++){
	    System.out.println("move "+i);
	    frSpring.moveNodes();
	}
    }

}

 

Ads help maintain this website.