/************************************************************************** * $Id: Link.java,v 1.1.1.1 2000/03/29 22:58:14 kkeys Exp $ * * File: Link.java Class: Link * Goal: A self contained class that will mantain its own * way of being draw, size, color, selected color, * location Child, Parnet, type :ONE, TWO * * Written: Bradley Huffaker (12/17/97) * Modified: Jaeyeon Jung (3/04/98) * * For:Cooperative Association for Internet Data Analysis *************************************************************************** *************************************************************************** By accessing this software, LINK, you are duly informed of and agree to be bound by the conditions described below in this notice: This software product, LINK, is developed by Bradley Huffaker, and Jaeyeon Jung copyrighted(C) 1998 by the University of California, San Diego (UCSD), with all rights reserved. UCSD administers the NLANR Cache grants, NCR-9796082 and NCR-9616602, under which most of this code was developed. There is no charge for LINK software. You can redistribute it and/or modify it under the terms of the GNU General Public License, v. 2 dated June 1991 which is incorporated by reference herein. LINK is distributed WITHOUT ANY WARRANTY, IMPLIED OR EXPRESS, OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE or that the use of it will not infringe on any third party's intellectual property rights. You should have received a copy of the GNU GPL along with the LINK program. Copies can also be obtained from http://www.gnu.org/copyleft/gpl.html or by writing to University of California, San Diego SDSC/CAIDA/NLANR 9500 Gilman Dr., MS-0505 La Jolla, CA 92093 - 0505 USA Or contact INFO@NLANR.NET **************************************************************************/ package bhuffake.plankton; import java.awt.*; public class Link extends DisplayObject { // The child and parent node to which it is connected Node parent; Node child; // When link is wrapped on the map boolean wrapped = false; Node pmirror; Node cmirror; // The direction to which this link relation is int direction; static final int ONE = 1; // Only parent -> child static final int TWO = 2; // parent <-> child static final Color DEFAULT_COLOR = Color.black; boolean selected = false; boolean removed = false; boolean highlighted = false; public Link(Node parent_input, Node child_input, int direction_input) { little_size = 1; size = 1; default_color = DEFAULT_COLOR; color = default_color; parent = parent_input; parent.addLink(this); child = child_input; child.addLink(this); direction = direction_input; } /**************************************************************** * Purpose: To allow for links to be created where they exists for * some files and have values that go with them each file ****************************************************************/ public Link(Node parent_input,Node child_input, int direction_input, int fileIndex, int num_files_input) { this(parent_input, child_input, direction_input); num_files = num_files_input; setUpFiles(); setExists(fileIndex); } /**************************************************** * Purpose: To have all nodes in order of their names * and after all lines *****************************************************/ public boolean greater(DisplayObject object) { if (!(object instanceof Link)) return false; return parent.greater(((Link)object).parent); } /************************************************** * Purpose: To find the squared distance from the center of the * object to the point. I use the squared to avoid needless * math (ie faster) * * Returns : the distance or -1 if distance is greater then size*size ***************************************************/ public double near(int x, int y, int pX, int pY, int cX, int cY) { int temp; int low_x = pX; int high_x = cX; if (low_x > high_x) { temp = low_x; low_x = high_x; high_x = temp; } int low_y = pY; int high_y = cY; if (low_y > high_y) { temp = low_y; low_y = high_y; high_y = temp; } if (low_x <= x && x <= high_x && low_y <= y && y <= high_y) { // REALLY STUPID HACK NO CLUE WHY IT IS NEEDED x -= pX; cX -= pX; pX -= pX; double Xn = pY - cY; double Yn = cX - pX; //jae thinks it's a bug //double Z = (y*Yn + x*Xn - pY*Yn - pX*Yn); double Z = (y*Yn + x*Xn - pY*Yn - pX*Xn); Z = (Z*Z)/(Xn*Xn + Yn*Yn); if (Z < (size+2)*(2+size)) return Z; } return -1; } public double near(int x, int y) { int[] xy = parent.getXY(); int pX = xy[0]; int pY = xy[1]; xy = child.getXY(); int cX = xy[0]; int cY = xy[1]; if (hidden) return -1; else if (!this.isOnMap()) return near(x,y,pX,pY,cX,cY); else { if(!this.isSetGeo()) return -1; else if (!wrapped) return near(x,y,pX,pY,cX,cY); else { xy = pmirror.getXY(); int pmX = xy[0]; int pmY = xy[1]; xy = cmirror.getXY(); int cmX = xy[0]; int cmY = xy[1]; double value1 = near(x,y,pmX,pmY,cX,cY); double value2 = near(x,y,pX,pY,cmX,cmY); if (value1 > 0 ) return value1; else return value2; } } } public void setSelect(boolean input) { if (direction == ONE) direction = TWO; else { Node temp = child; child = parent; parent = temp; direction = ONE; } } public boolean isSelected() { return false; } public void setHighlight(boolean input) { highlighted = input; } public boolean isHighlighted() { return highlighted; } public void setParent(Node node) { parent.removeObject(this); parent = node; parent.addLink(this); } public DisplayObject getParent() { return parent; } public int getDirection() {return direction;} public void setChild(Node node) { child.removeObject(this); child = node; child.addLink(this); } public DisplayObject getChild() { return child; } public void draw(Graphics g, Dimension dim, double[] latlon) { if (!exists || hidden) return; if (removed) { System.err.println("Link.draw() Attempt to draw a " + "removed link"); return; } if (selected || highlighted) g.setColor(selected_color); else g.setColor(color); int[] xy = parent.getXY(); int pX = xy[0]; int pY = xy[1]; xy = child.getXY(); int cX = xy[0]; int cY = xy[1]; wrapped = false; // When line is supposed to be drawn on the map if(this.isOnMap()) { if(!this.isSetGeo()) return; double plat = ((DisplayObject)parent).getLatitude(); double plon = ((DisplayObject)parent).getLongitude(); double clat = ((DisplayObject)child).getLatitude(); double clon = ((DisplayObject)child).getLongitude(); double[] pmlatlon = new double[2]; double[] cmlatlon = new double[2]; int delta_x = pX - cX; pmlatlon[0] = plat; cmlatlon[0] = clat; double top_lon = (latlon[1] + latlon[3])/2 - 180; double bot_lon = (latlon[1] + latlon[3])/2 + 180; //longitude should be adjusted to be larger than top_lon while ( plon < top_lon) plon += 360.0; while ( clon < top_lon) clon += 360.0; int top_x[] = ToMap(90,top_lon,latlon,dim); int bot_x[] = ToMap(90,bot_lon,latlon,dim); int width = bot_x[0] - top_x[0]; if(delta_x > width/2 ) { pmlatlon[1] = plon-360.0; cmlatlon[1] = clon+360.0; wrapped = true; } else if(delta_x < -width/2 ) { pmlatlon[1] = plon+360.0; cmlatlon[1] = clon-360.0; wrapped = true; } else { //g.drawLine(pX,pY,cX,cY); draw(g,pX,pY,cX,cY); return; } if(pmlatlon[1] > bot_lon) { pmlatlon[0] = pmlatlon[0] - (pmlatlon[0] - clat) * (pmlatlon[1] - bot_lon) / (pmlatlon[1] - clon); pmlatlon[1] = bot_lon; } if(pmlatlon[1] < top_lon) { pmlatlon[0] = pmlatlon[0] - (pmlatlon[0] - clat) * (pmlatlon[1] - top_lon) / (pmlatlon[1] - clon); pmlatlon[1] = top_lon; //System.err.println("2-1:" + "pX:" +pX+ " pY:"+ pY + " cX:"+cX+" cY:"+ cY); //System.err.println("2-2:" + "plat:" +plat+ " plon:"+ plon + " clat:"+clat+" clon:"+ clon); } if(cmlatlon[1] > bot_lon) { cmlatlon[0] = cmlatlon[0] - (cmlatlon[0] - plat) * (cmlatlon[1] - bot_lon) / (cmlatlon[1] - plon); cmlatlon[1] = bot_lon; } if(cmlatlon[1] < top_lon) { cmlatlon[0] = cmlatlon[0] - (cmlatlon[0] - plat) * (cmlatlon[1] - top_lon) / (cmlatlon[1] - plon); cmlatlon[1] = top_lon; } int[] pmXY = ToMap(pmlatlon[0],pmlatlon[1],latlon,dim); int[] cmXY = ToMap(cmlatlon[0],cmlatlon[1],latlon,dim); pmirror = new Node("parent_mirror",pmXY[0],pmXY[1]); cmirror = new Node("child_mirror",cmXY[0],cmXY[1]); //g.drawLine(pX,pY,cmXY[0],cmXY[1]); draw(g,pX,pY,cmXY[0],cmXY[1]); //g.drawLine(pmXY[0],pmXY[1],cX,cY); draw(g,pmXY[0],pmXY[1],cX,cY); return; } //g.drawLine(pX,pY,cX,cY); draw(g,pX,pY,cX,cY); if (little) return; double delta_x = pX - cX; double delta_y = pY - cY; // Normaling the detla's if (delta_x == 0 || delta_y == 0) { if (delta_x < 0) delta_x = -1; else if (delta_x > 0) delta_x = 1; if (delta_y < 0) delta_y = -1; else if (delta_y > 0) delta_y = 1; } else { if (delta_x*delta_x > delta_y*delta_y) { delta_y = delta_y / delta_x; delta_x = 1; } else { delta_x = delta_x / delta_y; delta_y = 1; } } //System.err.println("X:" + delta_x +" Y:" + delta_y); // Creates the default of one direction int[] x_array = {pX - (int)(size*delta_y), pX + (int)(size*delta_y), cX}; int[] y_array = {pY + (int)(size*delta_x), pY - (int)(size*delta_x), cY}; int num = 3; if (direction == TWO) { int[] x_temp = {pX - (int)(size*delta_y), pX + (int)(size*delta_y), cX + (int)(size*delta_y), cX - (int)(size*delta_y)}; int[] y_temp = {pY + (int)(size*delta_x), pY - (int)(size*delta_x), cY - (int)(size*delta_x), cY + (int)(size*delta_x)}; x_array = x_temp; y_array = y_temp; num = 4; } /**************** Debugging** g.drawLine(pX,pY,cX,cY); g.drawLine(x_array[0],y_array[0],x_array[1],y_array[1]); System.err.println("x[0]:"+ x_array[0] + " y[0]" + y_array[0] +" x[1]" + x_array[1] + " y[1]" + y_array[1]); ***************** End Debug**/ g.fillPolygon(x_array,y_array,num); } public void draw(Graphics g, int x1, int y1, int x2, int y2) { int x_diff = x1 - x2; x_diff *= x_diff; int y_diff = y1 - y2; y_diff *= y_diff; int x_shift = 0; int y_shift = 0; if (y_diff < x_diff) { x_shift = 0; y_shift = 1; } else { y_shift = 0; x_shift = 1; } g.drawLine(x1, y1, x2, y2); int shift = 1; for (int index = 1; index < size; index++) { g.drawLine(x1 - x_shift*shift, y1 -y_shift*shift, x2 - x_shift*shift, y2 - y_shift*shift); shift *= -1; if (shift >0) shift += 1; } } public int[] ToMap(double lat, double lon, double[] latlon, Dimension dim) { int height = dim.height; int width = dim.width; int[] xy = new int[2]; double boundary = (latlon[1] + latlon[3])/2 - 180; while (lon < boundary ) lon += 360.0; xy[0] = (int) ( ((lon - latlon[1]) * width) / (latlon[3] - latlon[1])); xy[1] = (int) ( ((latlon[0] - lat) * height) / (latlon[0] - latlon[2])); return xy; } public DisplayObject[] remove() { removed = true; parent.removeObject(this); child.removeObject(this); return new DisplayObject[0]; } public void removeObject(DisplayObject object) { removed = true; if (object == parent || object == child) remove(); } public String getString() { String middle = " -> "; if (direction != ONE) middle = " <-> "; if (isSetToHTTPColor()) return parent.getName() + middle + child.getName() + " " + getHTTPRequest() + " requests"; return parent.getString() + middle + child.getString(); } public void setXY(int x, int y) { // It is not allowed to setXY on links // You change it parent and child nodes. } public int[] getXY() { int[] xy = new int[4]; xy[0] = parent.x; xy[1] = parent.y; xy[2] = child.x; xy[3] = child.y; return xy; } public void changeXY(int delta_x, int delta_y) { // You are not allowed to change the XY of a link // YOu change it parent and child nodes. } // ------------------- Animation Stuff ------------------------- public boolean equals(Node server, Node client) { return server == parent && client == child; } }