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

📄 graphpanel.java

📁 一个p2p仿真软件
💻 JAVA
字号:
/*
 * @(#)GraphPanel.java	ver 1.2  6/20/2005
 *
 * Modified by Weishuai Yang (wyang@cs.binghamton.edu). 
 * This file is based on NED from Tatiana Kichkaylo at NYU
 * 
 */


package gps.gui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;

import javax.swing.JPanel;

import gps.network.graph.Graph;
import gps.network.graph.Link;
import gps.network.graph.Node;
import gps.protocol.Agent;

/**
 * This panel visualize network topology and agents informaiton.
 * This file is based on NED from Tatiana Kichkaylo at NYU
 */
public class GraphPanel extends JPanel {

    private Graph graph = null;
    private Graphics bufferGraphics = null;  //Graphics context for double buffer
    private Rectangle r = new Rectangle(0,0,0,0); //Bounding box for double buffer
    private Image bufferImage = null;

    private double RTX, RTY, /*right top*/ LBX, LBY /*left bottom*/;
    private int vMargin=0, hMargin=0;
    
	private Node[] nodes=null;
	private Link[] links=null;

    private static Color linkColor[] = { Color.lightGray, Color.cyan, Color.red };
    private float scale = 5;
    private boolean showNodeId=false;

    private boolean[] matrix = null;
    private int minimum = 25, minimum2 = 100;


	/**
	 * distance for ss, ts, tt
	 */
    public static double dist[] = { 7, 20, 55 };
	/**
	 * coefficient
	 */
    public static double coef[] = { 1, 1, 1 };
    
    /**
     * dummy constructor
     *
     */
    public GraphPanel() {
    	super();
    }

    
    
    /**
     * graph panel size
     */
    public Dimension size = new Dimension( 480, 480 );
    /**
     * gets graph panel size
     * @return size
     */
    public Dimension getPreferredSize() { return size; }
    /**
     * gets minimum graph panel size
     * @return size
     */
    public Dimension getMinimumSize() { return size; }
    
    /**
     * sets graph to be displayed
     * @param g graph
     */
    public void setGraph(Graph g){
        graph=g;
        if(g==null) 
            return;
        
    	nodes = graph.getAllNodes();
    	links = graph.getAllLinks();
    	initLinkMatrix();


		for ( int i=0; i<links.length; i++ ) {
		    
		    int f=links[i].fromNode();
		    int t=links[i].toNode();
		    
		    int type = 0;
		    // link type: 0=S-S, 1=S-T, 2=T-T
            
		    if((nodes[f].getProperties().getType()==16)&&(nodes[t].getProperties().getType()==16)){
		        type=2;
		    }
		    else if((nodes[f].getProperties().getType()==16)||(nodes[t].getProperties().getType()==16)){
		        type=1;
		    }

	        links[i].getProperties().setType(type);
		}
    }
    /**
     * gets graph being displayed
     * @return Graph object
     */
    public Graph getGraph(){
        return graph;
    }

    /*
    public GraphPanel( GraphMouseListener list ) {
		super();
		addMouseMotionListener( (MouseMotionListener) list );
		addMouseListener ( (MouseListener) list );
    }
    */
    
    /**
     * sets flag for showing id or not
     * @param b flag
     */
	public void setShowNodeId(boolean b){
		showNodeId=b;
	}
    /**
     * gets current flag for showing id or not
     * @return flag
     */
	public boolean getShowNodeId(){
		return showNodeId;
	}
	
	
	/**
	 * paint graphical area
	 * @param g Graphics handle
	 */
    public void paint( Graphics g ) {
        update( g );
    }
    
    /**
     * update graphical area
     * @param g Graphics handle
     */
    
    public void update( Graphics g ) {
		if (r.width != getBounds().width || r.height != getBounds().height) {
		    bufferImage    = createImage(getBounds().width, getBounds().height);
		    bufferGraphics = bufferImage.getGraphics(); //*Whenever applet changes size*
			r = getBounds();                               //*create a new double buffer, and*
		}
		render(bufferGraphics); //*We ask application program to render to the buffer*
	    g.drawImage(bufferImage,0,0,this); //*And then paste in the rendered buffer.*
	}
    

    	
	/**
	 * relax links between nodes, make them looks more clear
	 */
    public void relax() {
     	double[] fx, fy;
        fx=new double[nodes.length];
        fy=new double[nodes.length];
    	// clean all
    	for ( int i=0; i<nodes.length; i++ ) {
    	    fx[i] = 0; fy[i] = 0;
    	}
    	linkShrink(fx, fy);
    	nodeRepulse(fx, fy);
    	linkNodeRepulse(fx, fy);

    	// move all
    	for ( int i=0; i<nodes.length; i++ ) {
    	    double c = 0.1;
    	    
    	    //System.out.println( nodes[i].getProperties().getX()+":"+nodes[i].getProperties().getY()+" "+fx[i]+":"+fy[i] );
    	    
    	    double newx=nodes[i].getProperties().getX() + c*fx[i];
    	    double newy=nodes[i].getProperties().getY() + c*fy[i];
    	    nodes[i].getProperties().setX(newx);
       	    nodes[i].getProperties().setY(newy);

    	}
    	
    } 
    
    //*****************************************************************************

    private void initLinkMatrix() {
    	//initialize link matrix between nodes
        matrix = new boolean[nodes.length*nodes.length];
    	for ( int i=0; i<nodes.length*nodes.length; i++ ) 
    	    matrix[i]=false;
    	for ( int i=0; i<links.length; i++ ) {
    	    matrix[ links[i].fromNode()*nodes.length+links[i].toNode() ] = true;
    	    matrix[ links[i].toNode()*nodes.length+links[i].fromNode() ] = true;
    	}
    }

    private void render( Graphics g ) {

        if(graph==null||!graph.isValid()) {
    		super.paint( g );
            return;
        }
		compSize();
		g.setColor( Color.white);
		g.fillRect( 0, 0, r.width, r.height );

		//draw links

		for ( int i=0; i<links.length; i++ ) {
		    
		    int f=links[i].fromNode();
		    int x1 = (int)((nodes[f].getProperties().getX()-LBX)*scale)+vMargin;
		    int y1 = (int)((nodes[f].getProperties().getY()-LBY)*scale)+hMargin;
		    int t=links[i].toNode();
		    int x2 = (int)((nodes[t].getProperties().getX()-LBX)*scale)+vMargin;
		    int y2 = (int)((nodes[t].getProperties().getY()-LBY)*scale)+hMargin;
		    
		    int type=links[i].getProperties().getType();
		    // link type: 0=S-S, 1=S-T, 2=T-T
	        
		    g.setColor( linkColor[type] );
		    g.drawLine( x1, y1, x2, y2 );
		    
			links[i].getBandwidthManager().bandwidthDraw(g,(x1+x2)/2,(y1+y2)/2);
		}

		//draw nodes
		for ( int i=0; i<nodes.length; i++ ) {
		    int x = (int)((nodes[i].getProperties().getX()-LBX)*scale)+vMargin;
		    int y = (int)((nodes[i].getProperties().getY()-LBY)*scale)+hMargin;
		    
		    //transit is 16
			if ( nodes[i].getProperties().getType()==16 ){ 
			    g.setColor( Color.red );
			    g.drawOval( x-6, y-6, 12, 12 );
			    g.drawOval( x-5, y-5, 10, 10 );
			}
			//stub is 8
			else if ( nodes[i].getProperties().getType()==8 ) {
		        g.setColor( Color.blue );
		        g.drawOval( x-4, y-4, 8, 8 );
			}
			else{ 
			    g.setColor( Color.black );
			    g.drawOval( x-4, y-4, 8, 8 );
			}

			if(showNodeId)
				g.drawString(""+i,x-15,y );
			
			//add agent specific drawing

			int s=nodes[i].getAgentList().size();
			if(s!=0){
				for(int m=0;m<s;m++)
					((Agent)(nodes[i].getAgentList().get(m))).agentDraw(g,x,y);
					//System.out.println("rander called for node "+i+" size "+nodes[i].getAgentList().size()+" with agent "+ (Agent)(nodes[i].getAgentList().get(0)));
					//System.out.println("agentDraw called to node"+i);	
			}
		}
	    
    }
    
    private void compSize() {
    	//maximum size
        RTX = 0; RTY = 0;
    	for (int i=0; i<nodes.length; i++ ) {
    	    if ( nodes[i].getProperties().getX()>RTX ) 
    	        RTX = nodes[i].getProperties().getX();
    	    if ( nodes[i].getProperties().getY()>RTY ) 
    	        RTY = nodes[i].getProperties().getY();
    	}
    	//minimum size
    	LBX = RTX; LBY = RTY;
    	for (int i=0; i<nodes.length; i++ ) {
    	    if ( nodes[i].getProperties().getX() <LBX ) 
    	        LBX = nodes[i].getProperties().getX();
    	    if ( nodes[i].getProperties().getY() <LBY ) 
    	        LBY = nodes[i].getProperties().getY();
    	}
    	//// System.out.println( RTX+":"+RTY+" "+LBX+":"+LBY );
    	scale = (r.width-60)/(float)( RTX - LBX );
    	vMargin=30;
    	hMargin=(int)(r.height-( RTY - LBY )*scale)/2;
    	if ( (r.height-60)/(float)( RTY - LBY ) < scale ) {
    	    scale = (r.height-60)/(float)( RTY - LBY );
    	    hMargin=30;
    	    vMargin=(int)(r.width-( RTX - LBX )*scale)/2;
    	}
    }

    private void linkShrink(double[] fx, double[] fy) {
		for ( int i=0; i<links.length; i++ ) {
		    // link type: 0=S-S, 1=S-T, 2=T-T

		    int type = links[i].getProperties().getType();
		    int f=links[i].fromNode();
		    int t=links[i].toNode();
		    
		    // current distance
		    double x1 = nodes[f].getProperties().getX();
		    double y1 = nodes[f].getProperties().getY();
		    double x2 = nodes[t].getProperties().getX();
		    double y2 = nodes[t].getProperties().getY();
		    double d = Math.sqrt( (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2) );
	
		    //System.out.println( dist[type]+":"+d );
	
		    double s = (dist[type]-d)/d;
		    //s = s*s;
		    fx[ f ] += (x1-x2)*s;
		    fy[ f ] += (y1-y2)*s;
		    fx[ t ] -= (x1-x2)*s;
		    fy[ t ] -= (y1-y2)*s;
		}
    }

    
    private void nodeRepulse(double[] fx, double[] fy) {
		for ( int i=0; i<nodes.length; i++ ) 
		    for ( int j=i+1; j<nodes.length; j++ ) {
		    // if there is a link, do not do anything
		    if ( matrix[ i*nodes.length+j ] ) continue;
	
		    // real distance
		    double xx = nodes[i].getProperties().getX() - nodes[j].getProperties().getX();
		    double yy = nodes[i].getProperties().getY() - nodes[j].getProperties().getY();
		    double d = Math.sqrt( xx*xx+yy*yy );
	
		    // desired distance
		    double m = minimum;
		    if ( (nodes[i].getProperties().getType()==16) && (nodes[j].getProperties().getType()==16))
		        m = minimum2;
		    if ( d<m ) {
				double c = 0.2;
				double s;
				if ( d>0.1 ) 
				    s = (m-d)/d;
				else 
				    s = 5;
				s = s*s;
		 //System.out.println( m+"->"+d+" "+(c*s) );
				fx[i] += c*xx*s;
				fy[i] += c*yy*s;
				fx[j] -= c*xx*s;
				fy[j] -= c*yy*s;
		    }
		}
    }


    private static class Geom {
        //********************************************************************************
        // line equasion is coef[0]*X + coef[1]*Y + coef[2] = 0
        public static void lineCoef( double x1, double y1, double x2, double y2, double[] coef ) {
    	if ( x1==x2 ) { // vertical
    	    coef[0] = 1;
    	    coef[1] = 0;
    	    coef[2] = x1;
    	} else if ( y1==y2 ) { // horizontal
    	    coef[0] = 0;
    	    coef[1] = 1;
    	    coef[2] = y1;
    	} else {
    	    coef[0] = 1/(x2-x1);
    	    coef[1] = 1/(y1-y2);
    	    coef[2] = y1/(y2-y1) - x1/(x2-x1);

    	    coef[1] /= coef[0]; 
    	    coef[2] /= coef[0];
    	    coef[0] = 1;
    	}
    	////System.out.println( "Line coef "+x1+":"+y1+"-"+x2+":"+y2+" "+coef[0]+", "+coef[1]+", "+coef[2] );
        }
        //********************************************************************************
        public static boolean inSegment( double x1, double y1, double x2, double y2, double[] p ) {
    	double c = 0.01, t;
    	if ( x1>x2 ) { t = x1; x1 = x2; x2 = t; }
    	if ( y1>y2 ) { t = y1; y1 = y2; y2 = t; } 

    	boolean res = false;
    	if ( x2-x1>4*c && p[0]-x1>c && x2-p[0]>c ) res = true; 
    	if ( y2-y1>4*c && p[1]-y1>c && y2-p[1]>c ) res = true; 
    	////System.out.println( "Segment "+x1+":"+x+":"+x2+"  "+y1+":"+y+":"+y2+" "+res );
    	return res; 
        }
        //********************************************************************************
        public static void intersect( double[] l1, double[] l2, double[] p ) {
    	if ( l1[0]==0 ) {
    	    p[1] = -l1[2];
    	    p[0] = - ( l2[1]*p[1] + l2[2] );
    	} else if ( l2[0]==0 ) {
    	    p[1] = -l2[2];
    	    p[0] = -( l1[1]*p[1] + l1[2] );
    	} else {
    	    p[1] = - ( l1[2] - l2[2] )/( l1[1] - l2[1] );
    	    p[0] = - ( l1[1]*p[1] + l1[2] );
    	}
        } 
        //********************************************************************************
        public static void perpend( double[] line, double[] point, double[] perp ) {
    	// perp line eq: Bx - Ay + D = 0, where the original one is Ax + By + C = 0
    	perp[0] = line[1]; 
    	perp[1] = -line[0];
    	perp[2] = - (perp[0]*point[0] + perp[1]*point[1]); 
        }
        //********************************************************************************
        public static double distance( double[] p1, double[] p2 ) {
    	double x = p1[0]-p2[0], y = p1[1]-p2[1];
    	return Math.sqrt( x*x + y*y );
        }
    }

    private void linkNodeRepulse(double[] fx, double[] fy) {
		for ( int i=0; i<nodes.length; i++ ){ 
		    for ( int j=0; j<links.length; j++ ) {
			    // node does not belong to the link
		        int f=links[j].fromNode();
		        int t=links[j].toNode();
		        
			    if ( f==i || t==i ) continue;
		
			    double[] link = { 0, 0, 0 };
			    double[] node = { nodes[i].getProperties().getX(), nodes[i].getProperties().getY() };
			    double[] perp = { 0, 0, 0 };
			    double[] inter = { 0, 0 };
			    
			    Geom.lineCoef( nodes[f].getProperties().getX(), nodes[f].getProperties().getY(), nodes[t].getProperties().getX(), nodes[t].getProperties().getY(), link );
			    Geom.perpend( link, node, perp );
			    Geom.intersect( link, perp, inter );
		
			    // if intersection outside the link, do not worry
			    if ( !Geom.inSegment( nodes[f].getProperties().getX(), nodes[f].getProperties().getY(), nodes[t].getProperties().getX(), nodes[t].getProperties().getY(), inter) )
				continue;
		
			    double d = Geom.distance( node, inter );
			    double rate;
			    if ( Math.abs( d )<1 ) 
			        rate = 0.2;
			    else 
			        rate = 0.2/Math.sqrt(d);
		
			    // add repulsion along the distance vector
			    if ( d>0.01 ) {
					fx[ i ] -= rate* (inter[0]-node[0])/d;
					fy[ i ] -= rate* (inter[1]-node[1])/d;
			    } 
			    else {
					fx[ i ] -= 1;
					fy[ i ] -= 1; 
			    }
			}
		}
    }
    


    

    
}

⌨️ 快捷键说明

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