package caida.otter;
import java.awt.*;
import java.util.Random;
import java.lang.Math;
import caida.tools.PsGenerator;
/**************************************************************************
* File: Node.java Class: Node
* Goal: A self contained class that will maintain its own
* way of being draw, size, color, selected color,
* location x,y, name.
*
* Written: Bradley Huffaker (12/17/97)
*
* Modified: Jaeyeon Jung (2/13/93)
* Modified: R. Benjamin Shapiro (Oct 2000)
* getDomain: ipaddress which doesn't have domain name will
* be returned as unknown
*
* For:Cooperative Association for Internet Data Analysis
***************************************************************************
***************************************************************************
By accessing this software, NODE, you are duly informed of and
agree to be bound by the conditions described below in this notice:
This software product, NODE, is developed by Bradley Huffaker and
Jaeyeon Jung, and copyrighted(C) 1998 by the University of California,
San Diego (UCSD), with all rights reserved. UCSD administers the NSF
grant to CAIDA, number NCR-9711092, under which this code was developed.
There is no charge for NODE 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. NODE 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 NODE
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
9500 Gilman Dr., MS-0505
La Jolla, CA 92093 - 0505 USA
Or contact INFO@CAIDA.ORG
**************************************************************************/
public class Node extends DisplayObject
{
String name;
long ip;
static final Color NODE_DEFAULT_COLOR = Color.white;
static final Color outline_color = Color.black;
static final Color root_color = Color.red;
boolean highlighted = false;
// Drawing Name Stuff
// Will have it draw it's name CHANGE HERE IF ANIMATION IMAGE !
boolean show_name = false;
static final int NORTH_EAST = 0;
static final int NORTH = 1;
static final int NORTH_WEST = 2;
static final int WEST = 3;
static final int SOUTH_WEST = 4;
static final int SOUTH = 5;
static final int SOUTH_EAST = 6;
static final int EAST = 7;
int name_location = SOUTH;
DList links = new DList();
Node[] children;
Node[] dir_children = new Node[5];
int num_dir_children = 0;
// Keeps track of weather it is a root or not
boolean root = false;
boolean setXY = false;
// This is needed for animation. A Group of nodes is compressed
// into a single node across files.
Node animatorNode;
// This is used in placement Algorthim for a breathfirst search
Node[] neighbors = new Node[10];
int num_neighbors = 0;
// This hidden flag is controlled by the site that this
// node is connected to
boolean hiddenBySite = false;
// This is the Site node if it exists
Node site = null;
// This is to allow for color by domain Names
public static final String[] FIELDS = {"Level 1", "Level 2",
"Level 3", "Full Name"};
public static final ValuesGroup DOMAIN_NAMES =
new ValuesGroup("Domain Names", ValuesGroup.STRING,
FIELDS);
String[] domains = new String[FIELDS.length];
/**************************** Path Stuff *******************/
DisplayObject[] paths = new DisplayObject[10];
int[] path_x = null;
int[] path_y = null;
int num_paths = 0;
public Node(String name_input, int x_input, int y_input)
{
size = 3;
little_size = 4;
color = default_color;
default_color = NODE_DEFAULT_COLOR;
name = name_input;
/*
SetDomains();
*/
x = x_input;
y = y_input;
}
/*********************************************************
* Purpose: To have a contructor what works with IOHandler
* to have a node create that has a file assotionated with it
**********************************************************/
public Node(String name_input, int x_input, int y_input,
int fileIndex, int num_files_input)
{
this(name_input, x_input,y_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 Node))
return true;
char[] mine = name.toCharArray();
char[] other= ((Node)object).name.toCharArray();
int shortest = mine.length;
if (shortest > other.length)
shortest = other.length;
for (int index =0; index < shortest; index++)
{
if (mine[index] > other[index])
return true;
else if (mine[index] < other[index])
return false;
}
if (mine.length != shortest)
return true;
return false;
}
public void hideAll()
{
super.hideAll();
for(int i=0; i < num_paths; i++)
paths[i].hideAll();
links.reset();
while (!links.end())
links.next().hideAll();
}
public void hideIfLinksHide()
{
boolean all_hidden = true;
int i=0;
while (i < num_paths && all_hidden)
{
if (!paths[i].hidden())
all_hidden = false;
i++;
}
links.reset();
while (!links.end() && all_hidden)
if(!links.next().hidden())
all_hidden = false;
if (all_hidden)
hide();
}
public void hideBySite()
{
hiddenBySite = true;
}
public void showBySite()
{
hiddenBySite = false;
}
/**************************************************
* 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_input, int y_input)
{
if (hidden || hiddenBySite)
return -1;
int delta_x = x_input - x;
int delta_y = y_input - y;
double Z = delta_x*delta_x + delta_y*delta_y;
if (Z > size*size)
return -1;
return Z;
}
//public void setAnimatorNode(Node node) { animatorNode = node; }
//public Node getAnimatorNode() { return animatorNode;}
public void setName(String input)
{
name = input;
//SetDomains();
}
public String getName() { return name; }
public void setIP(long input) { ip = input;}
public long getIP() {return ip; }
protected void SetDomains()
{
if (true) return;
char[] buffer = name.toCharArray();
int end = buffer.length;
int start = end-1;
int domain_index = 0;
boolean all_number = true;
if (buffer[start] == ')')
{
while (start > 0 && buffer[start] != '(')
start--;
if (start == 0)
return;
end = start;
start--;
}
while (domain_index < domains.length-1)
{
while (start > 0 && buffer[start] != '.')
{
if (all_number &&
buffer[start] > '9' || buffer[start] < '0')
all_number = false;
start--;
}
if (all_number)
while(domain_index < domains.length)
domains[domain_index++] = "unknown";
else
{
domains[domain_index++]
= new String(buffer,start,end-start);
if (start > 0)
start--;
}
}
domains[domains.length-1] = name;
addValues(DOMAIN_NAMES,domains);
}
public void setSite(Node node)
{
site = node;
setGeo(node.getLatitude(),node.getLongitude(),"unknown");
}
public void setHighlight(boolean input) { highlighted = input; }
public boolean isHighlighted() { return highlighted; }
public void selectTree(boolean input,DList dlist)
{
if (input)
dlist.enqueue(this);
else
dlist.drop(this);
selected = input;
if (children != null)
for (int index=0; index < children.length; index++)
children[index].selectTree(input,dlist);
}
public void setRoot(boolean input) { root = input; }
public boolean isRoot() { return root; }
public void swapRoot() { root = !root; }
public void showName() { show_name = true; }
public void hideName() { show_name = false; }
public void setNameLocation(double degree)
{
while (degree < 0)
degree += 2*Math.PI;
degree = degree % (Math.PI*2);
final double FOURTH = Math.PI/4;
degree += FOURTH;
if (degree <= FOURTH)
name_location = EAST;
else if (degree <= 2*FOURTH || degree > 7*FOURTH)
name_location = NORTH_EAST;
else if (degree <= 3*FOURTH)
name_location = NORTH;
else if (degree <= 4*FOURTH)
name_location = NORTH_WEST;
else if (degree <= 5*FOURTH)
name_location = WEST;
else if (degree <= 6*FOURTH)
name_location = SOUTH_WEST;
else
name_location = SOUTH;
}
public void nameClockWise()
{
name_location = (name_location+1)%8;
}
public void nameCounterClock()
{
if (name_location <= 0)
name_location = 7;
else
name_location--;
}
public void draw(Graphics g, int x_shift, int y_shift,
int x_scale, int y_scale, Dimension dim, double[] latlon,
boolean drawing_postscript)
{
draw(g,(double)x_shift,(double)y_shift,(double)x_scale,
(double)y_scale,dim,latlon,drawing_postscript);
}
public void draw(Graphics g, double x_shift, double y_shift,
double x_scale, double y_scale, Dimension dim, double[] latlon,
boolean drawing_postscript)
{
// if (!exists || hidden || hiddenBySite || size < 1)
if (!exists || hidden || hiddenBySite)
return;
// We use this offset to accomodate for long names at the sides
if (!drawing_postscript) {
x_shift += ShiftImage.getXShift();
y_shift += ShiftImage.getYShift();
}
double local_x =( (x * x_scale)+x_shift);
double local_y =( (y * y_scale)+y_shift);
if (g instanceof PsGenerator) {
if (local_x < 0) {
local_x = 0;
}
if (local_y < 0) {
local_y = 0;
}
}
g.setColor(outline_color);
if (show_name)
drawName(g, local_x, local_y);
if (little && false)
{
if (selected || highlighted)
g.setColor(selected_color);
else if (root && !colored)
g.setColor(root_color);
if (g instanceof PsGenerator){
((PsGenerator)g).fillRect((local_x-(little_size)/2.0),
(local_y-(little_size)/2.0),
little_size,little_size);
}else
g.fillRect((int)(local_x-(little_size)/2),
(int)(local_y-(little_size)/2),
little_size,little_size);
}
else
{
if (selected || highlighted)
g.setColor(selected_color);
else
if (root && !colored)
g.setColor(root_color);
//else if (!isSetXY())
// g.setColor(Color.green);
else
g.setColor(color);
if (g instanceof PsGenerator)
((PsGenerator)g).fillRect((local_x-(size)/2),( local_y-(size)/2),
size,size);
else g.fillRect((int)(local_x-(size)/2),(int)( local_y-(size)/2),
size,size);
g.setColor(outline_color);
if (g instanceof PsGenerator)
((PsGenerator)g).drawRect((local_x-(size)/2),( local_y-(size)/2),
size, size);
else g.drawRect((int)(local_x-(size)/2),(int)( local_y-(size)/2),
size, size);
}
// Now let's see if we must arrange the links to/from the node
if (prevPaintCounter != currentPaintCounter) {
// Arrange links
arrangeLinks();
}
}
public void drawname(Graphics g, int name_x, int name_y)
{
drawName(g,(double)name_x,(double)name_y);
}
public void drawName(Graphics g, double name_x, double name_y)
{
Font smallFont;
FontMetrics fmSmall;
if (g instanceof PsGenerator) {
smallFont = ((PsGenerator) g).getFont();
fmSmall = ((PsGenerator) g).getFontMetrics(smallFont);
} else {
smallFont = g.getFont();
fmSmall = g.getFontMetrics(smallFont);
}
int stringHeight = fmSmall.getHeight();
int stringWidth = fmSmall.stringWidth(name);
int halfSize = size;
if (name.equals(" ")) {
return;
}
switch(name_location)
{
case NORTH_EAST:
name_x -= stringWidth+halfSize;
name_y -= halfSize;
break;
case NORTH:
name_x -= stringWidth/2;
name_y -= halfSize;
break;
case NORTH_WEST:
name_x += halfSize;
name_y -= halfSize-stringHeight;
break;
case WEST:
name_x += halfSize;
name_y += stringHeight/2;
break;
case SOUTH_WEST:
name_x += halfSize;
name_y += halfSize+stringHeight;
break;
case SOUTH:
name_x -= stringWidth/2;
name_y += halfSize+stringHeight;
break;
case SOUTH_EAST:
name_x -= stringWidth + halfSize;
name_y += halfSize+ stringHeight;
break;
case EAST:
name_x -= stringWidth + halfSize;
name_y += stringHeight/2;
break;
}
// white color and draw box
g.setColor(Color.white);
if (g instanceof PsGenerator) {
((PsGenerator)g).fillRect(name_x-1, name_y-stringHeight+5, stringWidth, stringHeight-4);
} else {
g.fillRect((int)name_x-1, (int)name_y-stringHeight+5, stringWidth+1, stringHeight-4);
}
// Set font and color
g.setColor(Color.black);
g.setFont(smallFont);
if (g instanceof PsGenerator){
((PsGenerator)g).drawString(name, name_x, name_y);
}else{
g.drawString(name, (int) name_x, (int) name_y);
}
}
public DisplayObject[] remove()
{
DisplayObject[] objects = new DisplayObject[links.count()];
int index = 0;
while (!links.empty())
objects[index++] = links.pop();
return objects;
}
public void removeObject(DisplayObject object)
{
links.drop(object);
}
public Node[] getChildren() { return children; }
public void setChildren(Node[] input) { children = input; }
/************************ Path Stuff ******************************/
public int addPath(Node last, Node next, DisplayObject object)
{
if (last != null)
{
addNeighbor(last);
if (object.getDirection() == DisplayObject.DIR_TWO)
addDirChild(last);
}
if (next != null)
{
addNeighbor(next);
addDirChild(next);
}
if (num_paths == paths.length)
{
DisplayObject[] temp = paths;
//int[] temp_x = path_x;
//int[] temp_y = path_y;
int new_size = (int)(num_paths*1.5);
paths = new DisplayObject[new_size];
//path_x = new int[new_size];
//path_y = new int[new_size];
for(int i=0; i < num_paths;i++)
{
paths[i] = temp[i];
//path_x[i] = temp_x[i];
//path_y[i] = temp_y[i];
}
}
paths[num_paths] = object;
return num_paths++;
}
public void finished()
{
path_x = new int[num_paths];
path_y = new int[num_paths];
}
public int getPathX(int which)
{
if (true) return x;
return path_x[which];
}
public int getPathY(int which)
{
if (true) return y;
return path_y[which];
}
public String getInfo()
{
String answer = name;
/*
if (root)
answer = answer + " (root)" ;
if (!setXY )
answer = answer + " !setXY" ;
*/
if (current_group != null && current_values != null)
{
if (current_group.getType() == ValuesGroup.DOUBLE)
answer = answer +" (" + (float)double_value +")";
else
answer = answer +" (" + string_value +")";
}
return answer;
}
public void unSetXY() { setXY = false; }
public void setXY() { setXY = true; }
public boolean isSetXY() { return setXY; }
public void setXY(int x_input, int y_input) //throws Throwable
{
//if (1==1) throw (new Throwable());
x = x_input;
y = y_input;
double radius = size*.7;
//if (radius < 3)
//radius = 3;
//ystem.out.println("radius:"+radius);
for(int i=0; i < num_paths;i++)
{
double angle = (i*2*Math.PI)/num_paths;
path_x[i] = (int)(radius* Math.cos(angle))+x;
path_y[i] = (int)(radius* Math.sin(angle))+y;
//System.out.println(name + " " + path_x[i]+","+x +" "+ path_y[i]+","+y);
}
setXY = true;
}
public void setXY(int[] xy) {
setXY(xy[0],xy[1]);
}
public int getX() { return x; }
public int getY() { return y; }
public void changeXY(int delta_x, int delta_y)
{
int temp_x = x + delta_x;
int temp_y = y + delta_y;
setXY(temp_x,temp_y);
}
public void changeChildXY(int delta_x, int delta_y)
{
changeXY(delta_x,delta_y);
if (children != null)
for (int index=0; index < children.length; index++)
children[index].changeChildXY(delta_x,delta_y);
}
public void scaleXY(double scalarX, double scalarY)
{
double temp_x = x*scalarX;
double temp_y = y*scalarY;
setXY((int)temp_x,(int)temp_y);
}
public void scale(double scaler)
{
scaleXY(scaler, scaler);
}
public void addLink(DisplayObject link)
{
links.push(link);
Node node = (Node) link.getParent();
if (node == this)
{
node = (Node) link.getChild();
addDirChild(node);
}
else if (link.getDirection() == DisplayObject.DIR_TWO)
addDirChild(node);
addNeighbor(node);
}
public void removeLink(DisplayObject link) { links.drop(link); }
public int countLink() { return links.count(); }
public DList getLink() {return links;}
public DisplayObject getParent() { return new Node("",0,0); }
public DisplayObject getChild() { return new Node("",0,0); }
public int getNumNeighbors()
{
return num_neighbors;
}
public Node[] getNeighbors()
{
Node[] temp = new Node[num_neighbors];
for (int i=0; i < num_neighbors;i++)
temp[i] = neighbors[i];
return temp;
}
public void addNeighbor(Node node)
{
if (node == null)
return;
int i=0;
while (i < num_neighbors && neighbors[i] != node)
i++;
if (i == num_neighbors)
{
if (i == neighbors.length)
{
Node[] temp = neighbors;
neighbors = new Node[(int)(i*1.5)];
for (i=0;i < num_neighbors;i++)
neighbors[i] = temp[i];
}
neighbors[i] = node;
num_neighbors++;
}
}
// ************ This is used by Value Based formating *********
public int getNumDirChildren()
{
return num_dir_children;
}
public Node[] getDirChildren()
{
Node[] temp = new Node[num_dir_children];
for (int i=0; i < num_dir_children;i++)
temp[i] = dir_children[i];
return temp;
}
public int getMinX()
{
int retval=this.getX();
return retval;
}
public int getMaxX()
{
int retval=this.getX()+this.getSize();
return retval;
}
public int getMinY()
{
int retval=this.getY();
return retval;
}
public int getMaxY()
{
int retval=this.getY()+this.getSize();
return retval;
}
public void addDirChild(Node node)
{
if (node == null)
return;
int i=0;
while (i < num_dir_children && dir_children[i] != node)
i++;
if (i == num_dir_children)
{
if (i == dir_children.length)
{
if (dir_children == null)
{
dir_children = new Node[5];
}
else
{
Node[] temp = dir_children;
if (i < 2)
i = 4;
dir_children = new Node[(int)(i*1.5)];
for (i=0;i < num_dir_children;i++)
dir_children[i] = temp[i];
}
}
dir_children[i] = node;
num_dir_children++;
}
}
private void arrangeLinks() {
/* Sort all links in the 4 categories described
by the following functions where C1 = y-x and C2 = x+y
x,y are coordinates of this node. Below x,y are coordinates of
to point.
a) x + C1 < y
b) x + C1 >= y
c) -x + C2 < y
d) -x + C2 >= y
\ 0 / Section 0: satisfies b && d
\ / Section 1: satisfies b && c
\ / Section 2: satisfies a && c
3 X 1 Section 3: satisfies a && d
/ \
/ \
/ 2 \
After this we see how many links are in each section. Links are
arranged in the following way:
1 link : The link is drawn from the center of the node
2 links: Each link has a corner of the node
3 links: 2 links at either corner and one in the middle
x links: x > 3, links are arranged on either of the 2 corners.
|
V
+---+ <--
|###|
|###|
+---+ <--
^ ^ ^
| | |
The decision for a link to be on a particular side is made by
dividing the section in 2 halves straight down the center of the
section.
*/
int fromX, fromY, toX, toY, c1, c2;
int count0 = 0;
int count1 = 0;
int count2 = 0;
int count3 = 0;
DList[] sortLinks = new DList[4];
sortLinks[0] = new DList();
sortLinks[1] = new DList();
sortLinks[2] = new DList();
sortLinks[3] = new DList();
links.reset();
while (!links.end()) {
Link current = (Link) links.next();
if (current.from == this) {
fromX = current.from.x;
fromY = current.from.y;
toX = current.to.x;
toY = current.to.y;
} else {
fromX = current.to.x;
fromY = current.to.y;
toX = current.from.x;
toY = current.from.y;
}
// Determine category C1 = y-x and C2 = x+y
c1 = fromY - fromX;
c2 = fromX + fromY;
if ((toX + c1) < toY) {
if (((-1 * toX) + c2) < toY) {
// Section 2
sortLinks[2].enqueue(current);
count2++;
} else {
// Section 3
sortLinks[3].enqueue(current);
count3++;
}
} else {
if (((-1 * toX) + c2) < toY) {
// Section 1
sortLinks[1].enqueue(current);
count1++;
} else {
// Section 0
sortLinks[0].enqueue(current);
count0++;
}
}
}
if (count0 > 0) {
arrangeLinksS0(sortLinks[0], count0);
}
if (count1 > 0) {
arrangeLinksS1(sortLinks[1], count1);
}
if (count2 > 0) {
arrangeLinksS2(sortLinks[2], count2);
}
if (count3 > 0) {
arrangeLinksS3(sortLinks[3], count3);
}
prevPaintCounter = currentPaintCounter;
currentPaintCounter++;
}
private void arrangeLinksS0(DList list, int count) {
// Depeding on the number of links in the list determine the
// location of the links on the node
// Section 0 is top of the node. coordinates are
// x1 = node.x - (size/2);
// x2 = node.x + (size/2);
// y1 = node.y - (size/2);
Link[] link;
int x1 = x - (size/2);
int x2 = x + (size/2);
int y1 = y - (size/2);
if (count == 0) {
return;
} else if (count == 1) {
// Put that link in the center of the node
Link current = (Link) list.top();
if (current.from == this) {
current.setFromXY(x, y1);
} else {
current.setToXY(x, y1);
}
} else if (count == 2) {
// Put links at either side of the node
link = new Link[2];
link[0] = (Link) list.pop();
link[1] = (Link) list.pop();
// Check which node is further to left then other
int n1x, n2x;
boolean from1, from2;
if (link[0].from == this) {
from1 = true;
n1x = link[0].to.x;
} else {
from1 = false;
n1x = link[0].from.x;
}
if (link[1].from == this) {
from2 = true;
n2x = link[1].to.x;
} else {
from2 = false;
n2x = link[1].from.x;
}
// Let's see if it is the same point
if (n1x == n2x) {
if (link[0].position == 0 &&
link[1].position == 0) {
// Put up arrow on the right
if (from1) {
link[0].position = 2;
link[1].position = 1;
} else {
link[0].position = 1;
link[1].position = 2;
}
}
if (link[0].position < link[1].position) {
if (from1) {
link[0].setFromXY(x1, y1);
} else {
link[0].setToXY(x1, y1);
}
if (from2) {
link[1].setFromXY(x2, y1);
} else {
link[1].setToXY(x2, y1);
}
} else {
if (from1) {
link[0].setFromXY(x2, y1);
} else {
link[0].setToXY(x2, y1);
}
if (from2) {
link[1].setFromXY(x1, y1);
} else {
link[1].setToXY(x1, y1);
}
}
} else if (n1x < n2x) {
if (from1) {
link[0].setFromXY(x1, y1);
} else {
link[0].setToXY(x1, y1);
}
if (from2) {
link[1].setFromXY(x2, y1);
} else {
link[1].setToXY(x2, y1);
}
} else {
if (from1) {
link[0].setFromXY(x2, y1);
} else {
link[0].setToXY(x2, y1);
}
if (from2) {
link[1].setFromXY(x1, y1);
} else {
link[1].setToXY(x1, y1);
}
}
} else {
// Put links with the same end point in the same
// array. Put up arrows to the left and down arrows
// to the right. spread the nodes on the same plane with N
// pixels in between.
int i = 0;
int j = 0;
DList[] sortList = new DList[count];
Node common = null;
list.reset();
while (!list.end()) {
Link current = (Link) list.next();
if (current.to == this) {
common = current.from;
} else {
common = current.to;
}
// Find the common in the array
if (i == 0) {
// First entry
sortList[0] = new DList();
sortList[0].enqueue(current);
i++;
} else {
boolean found = false;
for (j=0; j < i;j++) {
if (((Link) sortList[j].top()).from == common ||
((Link) sortList[j].top()).to == common) {
sortList[j].enqueue(current);
found = true;
break;
}
}
if (!found) {
sortList[i] = new DList();
sortList[i].enqueue(current);
i++;
}
}
}
// Determine the positions of the i entries.
int small_entry;
int smallX;
for (int k=0; k < i; k++) {
DList temp = null;
small_entry = k;
smallX = 999999;
for (int l=k; l < i; l++) {
if (((Link) sortList[l].top()).to == this) {
if (((Link) sortList[l].top()).from.x < smallX) {
small_entry = l;
smallX = ((Link) sortList[l].top()).from.x;
}
} else {
if (((Link) sortList[l].top()).to.x < smallX) {
small_entry = l;
smallX = ((Link) sortList[l].top()).to.x;
}
}
}
// swap small_entry with k entry
if (small_entry != k) {
temp = sortList[k];
sortList[k] = sortList[small_entry];
sortList[small_entry] = temp;
}
}
// So now the links are nicely in a row.
// Determine the offset for each of the links on the
// x-axis.
int lsize = sortList[0].top().size+2;
for (int k=0; k < i; k++) {
DList list2 = sortList[k];
int size2 = list2.count();
int pos = 1;
if (((Link) list2.top()).position == 0) {
// Arrange these links so up arrow is right
DList down = new DList();
DList up = new DList();
list2.reset();
while (!list2.end()) {
Link current = (Link) list2.next();
if (current.to == this) {
// Down arrow
down.enqueue(current);
} else {
// Up arrow
up.enqueue(current);
}
}
list2 = new DList();
up.reset();
while(!up.end()) {
Link current = (Link) up.next();
current.position = pos;
pos++;
list2.enqueue(current);
}
down.reset();
while(!down.end()) {
Link current = (Link) down.next();
current.position = pos;
pos++;
list2.enqueue(current);
}
}
int offset;
if (count > 6) {
// offset = -1 * ((lsize * 2) / 2);
offset = 0;
lsize = 0;
} else {
offset = -1 * ((lsize * count) / 2);
}
list2.reset();
while (!list2.end()) {
Link current = (Link) list2.next();
if (current.to == this) {
current.setToXY(x+offset+(lsize*current.position), y1);
} else {
current.setFromXY(x+offset+(lsize*current.position), y1);
}
}
if (count <= 6) {
offset += lsize*size2;
}
}
}
}
private void arrangeLinksS1(DList list, int count) {
// Section 1 is the right side of the node. coordinates are
// x1 = node.x + (size/2);
// y1 = node.y - (size/2);
// y2 = node.y + (size/2);
Link[] link;
int x1 = x + (size/2);
int y1 = y - (size/2);
int y2 = y + (size/2);
if (count == 0) {
return;
} else if (count == 1) {
// Put that link in the center of the node
Link current = (Link) list.top();
if (current.from == this) {
current.setFromXY(x1, y);
} else {
current.setToXY(x1, y);
}
} else if (count == 2) {
// Put links at either side of the node
link = new Link[2];
link[0] = (Link) list.pop();
link[1] = (Link) list.pop();
// Check which node is further to up then other
int n1x, n2x;
boolean from1, from2;
if (link[0].from == this) {
from1 = true;
n1x = link[0].to.x;
} else {
from1 = false;
n1x = link[0].from.x;
}
if (link[1].from == this) {
from2 = true;
n2x = link[1].to.x;
} else {
from2 = false;
n2x = link[1].from.x;
}
// Let's see if it is the same point
if (n1x == n2x) {
if (link[0].position == 0 &&
link[1].position == 0) {
// Put left arrow on the top
if (from1) {
link[0].position = 2;
link[1].position = 1;
} else {
link[0].position = 1;
link[1].position = 2;
}
}
if (link[0].position < link[1].position) {
if (from1) {
link[0].setFromXY(x1, y1);
} else {
link[0].setToXY(x1, y1);
}
if (from2) {
link[1].setFromXY(x1, y2);
} else {
link[1].setToXY(x1, y2);
}
} else {
if (from1) {
link[0].setFromXY(x1, y2);
} else {
link[0].setToXY(x1, y2);
}
if (from2) {
link[1].setFromXY(x1, y1);
} else {
link[1].setToXY(x1, y1);
}
}
} else if (n1x < n2x) {
if (from1) {
link[0].setFromXY(x1, y1);
} else {
link[0].setToXY(x1, y1);
}
if (from2) {
link[1].setFromXY(x1, y2);
} else {
link[1].setToXY(x1, y2);
}
} else {
if (from1) {
link[0].setFromXY(x1, y2);
} else {
link[0].setToXY(x1, y2);
}
if (from2) {
link[1].setFromXY(x1, y1);
} else {
link[1].setToXY(x1, y1);
}
}
} else {
// Put links with the same end point in the same
// array. Put left arrows above and right arrows
// at the bottom. spread the nodes on the same plane with N
// pixels in between.
int i = 0;
int j = 0;
DList[] sortList = new DList[count];
Node common = null;
list.reset();
while (!list.end()) {
Link current = (Link) list.next();
if (current.to == this) {
common = current.from;
} else {
common = current.to;
}
// Find the common in the array
if (i == 0) {
// First entry
sortList[0] = new DList();
sortList[0].enqueue(current);
i++;
} else {
boolean found = false;
for (j=0; j < i;j++) {
if (((Link) sortList[j].top()).from == common ||
((Link) sortList[j].top()).to == common) {
sortList[j].enqueue(current);
found = true;
break;
}
}
if (!found) {
sortList[i] = new DList();
sortList[i].enqueue(current);
i++;
}
}
}
// Determine the positions of the i entries.
int small_entry;
int smallX;
int smallY;
for (int k=0; k < i; k++) {
DList temp = null;
small_entry = k;
smallX = 999999;
smallY = 999999;
for (int l=k; l < i; l++) {
if (((Link) sortList[l].top()).to == this) {
if (((Link) sortList[l].top()).from.y == smallY &&
((Link) sortList[l].top()).from.x < smallX) {
small_entry = l;
smallX = ((Link) sortList[l].top()).from.x;
smallY = ((Link) sortList[l].top()).from.y;
} else
if (((Link) sortList[l].top()).from.y < smallY) {
small_entry = l;
smallX = ((Link) sortList[l].top()).from.x;
smallY = ((Link) sortList[l].top()).from.y;
}
} else {
if (((Link) sortList[l].top()).to.y == smallY &&
((Link) sortList[l].top()).to.x < smallX) {
small_entry = l;
smallX = ((Link) sortList[l].top()).to.x;
smallY = ((Link) sortList[l].top()).to.y;
} else if (((Link) sortList[l].top()).to.y < smallY) {
small_entry = l;
smallX = ((Link) sortList[l].top()).to.x;
smallY = ((Link) sortList[l].top()).to.y;
}
}
}
// swap small_entry with k entry
if (small_entry != k) {
temp = sortList[k];
sortList[k] = sortList[small_entry];
sortList[small_entry] = temp;
}
}
// So now the links are nicely in a row.
// Determine the offset for each of the links on the
// y-axis.
int lsize = sortList[0].top().size+2;
for (int k=0; k < i; k++) {
DList list2 = sortList[k];
int size2 = list2.count();
int pos = 1;
if (((Link) list2.top()).position == 0) {
// Arrange these links so left arrow is above
DList right = new DList();
DList left = new DList();
list2.reset();
while (!list2.end()) {
Link current = (Link) list2.next();
if (current.to == this) {
// left arrow
left.enqueue(current);
} else {
// right arrow
right.enqueue(current);
}
}
list2 = new DList();
left.reset();
while(!left.end()) {
Link current = (Link) left.next();
current.position = pos;
pos++;
list2.enqueue(current);
}
right.reset();
while(!right.end()) {
Link current = (Link) right.next();
current.position = pos;
pos++;
list2.enqueue(current);
}
}
int offset;
if (count > 6) {
// offset = -1 * ((lsize * 2) / 2);
offset = 0;
lsize = 0;
} else {
offset = -1 * ((lsize * count) / 2);
}
list2.reset();
while (!list2.end()) {
Link current = (Link) list2.next();
if (current.to == this) {
current.setToXY(x1,y+offset+(lsize*current.position));
} else {
current.setFromXY(x1,y+offset+(lsize*current.position));
}
}
if (count <= 6) {
offset += lsize*size2;
}
}
}
}
private void arrangeLinksS2(DList list, int count) {
// location of the links on the node
// Section 2 is the bottom of the node. coordinates are
// x1 = node.x - (size/2);
// x2 = node.x + (size/2);
// y1 = node.y + (size/2);
Link[] link;
int x1 = x - (size/2);
int x2 = x + (size/2);
int y1 = y + (size/2);
if (count == 0) {
return;
} else if (count == 1) {
// Put that link in the center of the node
Link current = (Link) list.top();
if (current.from == this) {
current.setFromXY(x, y1);
} else {
current.setToXY(x, y1);
}
} else if (count == 2) {
// Put links at either side of the node
link = new Link[2];
link[0] = (Link) list.pop();
link[1] = (Link) list.pop();
// Check which node is further to left then other
int n1x, n2x;
boolean from1, from2;
if (link[0].from == this) {
from1 = true;
n1x = link[0].to.x;
} else {
from1 = false;
n1x = link[0].from.x;
}
if (link[1].from == this) {
from2 = true;
n2x = link[1].to.x;
} else {
from2 = false;
n2x = link[1].from.x;
}
// Let's see if it is the same point
if (n1x == n2x) {
if (link[0].position == 0 &&
link[1].position == 0) {
// Put up arrow on the right
if (from1) {
link[0].position = 1;
link[1].position = 2;
} else {
link[0].position = 2;
link[1].position = 1;
}
}
if (link[0].position < link[1].position) {
if (from1) {
link[0].setFromXY(x1, y1);
} else {
link[0].setToXY(x1, y1);
}
if (from2) {
link[1].setFromXY(x2, y1);
} else {
link[1].setToXY(x2, y1);
}
} else {
if (from1) {
link[0].setFromXY(x2, y1);
} else {
link[0].setToXY(x2, y1);
}
if (from2) {
link[1].setFromXY(x1, y1);
} else {
link[1].setToXY(x1, y1);
}
}
} else if (n1x < n2x) {
if (from1) {
link[0].setFromXY(x1, y1);
} else {
link[0].setToXY(x1, y1);
}
if (from2) {
link[1].setFromXY(x2, y1);
} else {
link[1].setToXY(x2, y1);
}
} else {
if (from1) {
link[0].setFromXY(x2, y1);
} else {
link[0].setToXY(x2, y1);
}
if (from2) {
link[1].setFromXY(x1, y1);
} else {
link[1].setToXY(x1, y1);
}
}
} else {
// Put links with the same end point in the same
// array. Put up arrows to the left and down arrows
// to the right. spread the nodes on the same plane with N
// pixels in between.
int i = 0;
int j = 0;
DList[] sortList = new DList[count];
Node common = null;
list.reset();
while (!list.end()) {
Link current = (Link) list.next();
if (current.to == this) {
common = current.from;
} else {
common = current.to;
}
// Find the common in the array
if (i == 0) {
// First entry
sortList[0] = new DList();
sortList[0].enqueue(current);
i++;
} else {
boolean found = false;
for (j=0; j < i;j++) {
if (((Link) sortList[j].top()).from == common ||
((Link) sortList[j].top()).to == common) {
sortList[j].enqueue(current);
found = true;
break;
}
}
if (!found) {
sortList[i] = new DList();
sortList[i].enqueue(current);
i++;
}
}
}
// Determine the positions of the i entries.
int small_entry;
int smallX;
for (int k=0; k < i; k++) {
DList temp = null;
small_entry = k;
smallX = 999999;
for (int l=k; l < i; l++) {
if (((Link) sortList[l].top()).to == this) {
if (((Link) sortList[l].top()).from.x < smallX) {
small_entry = l;
smallX = ((Link) sortList[l].top()).from.x;
}
} else {
if (((Link) sortList[l].top()).to.x < smallX) {
small_entry = l;
smallX = ((Link) sortList[l].top()).to.x;
}
}
}
// swap small_entry with k entry
if (small_entry != k) {
temp = sortList[k];
sortList[k] = sortList[small_entry];
sortList[small_entry] = temp;
}
}
// So now the links are nicely in a row.
// Determine the offset for each of the links on the
// x-axis.
int lsize = sortList[0].top().size+2;
for (int k=0; k < i; k++) {
DList list2 = sortList[k];
int size2 = list2.count();
int pos = 1;
if (((Link) list2.top()).position == 0) {
// Arrange these links so up arrow is right
DList down = new DList();
DList up = new DList();
list2.reset();
while (!list2.end()) {
Link current = (Link) list2.next();
if (current.to == this) {
// Down arrow
down.enqueue(current);
} else {
// Up arrow
up.enqueue(current);
}
}
list2 = new DList();
up.reset();
while(!up.end()) {
Link current = (Link) up.next();
current.position = pos;
pos++;
list2.enqueue(current);
}
down.reset();
while(!down.end()) {
Link current = (Link) down.next();
current.position = pos;
pos++;
list2.enqueue(current);
}
}
int offset;
if (count > 6) {
// offset = -1 * ((lsize * 2) / 2);
offset = 0;
lsize = 0;
} else {
offset = -1 * ((lsize * count) / 2);
}
list2.reset();
while (!list2.end()) {
Link current = (Link) list2.next();
if (current.to == this) {
current.setToXY(x+offset+(lsize*current.position), y1);
} else {
current.setFromXY(x+offset+(lsize*current.position), y1);
}
}
if (count <= 6) {
offset += lsize*size2;
}
}
}
}
private void arrangeLinksS3(DList list, int count) {
// location of the links on the node
// Section 3 is the left of the node. coordinates are
// x1 = node.x - (size/2);
// y1 = node.y - (size/2);
// y2 = node.y + (size/2);
Link[] link;
int x1 = x - (size/2);
int y1 = y - (size/2);
int y2 = y + (size/2);
if (count == 0) {
return;
} else if (count == 1) {
// Put that link in the center of the node
Link current = (Link) list.top();
if (current.from == this) {
current.setFromXY(x1, y);
} else {
current.setToXY(x1, y);
}
} else if (count == 2) {
// Put links at either side of the node
link = new Link[2];
link[0] = (Link) list.pop();
link[1] = (Link) list.pop();
// Check which node is further to up then other
int n1x, n2x;
boolean from1, from2;
if (link[0].from == this) {
from1 = true;
n1x = link[0].to.x;
} else {
from1 = false;
n1x = link[0].from.x;
}
if (link[1].from == this) {
from2 = true;
n2x = link[1].to.x;
} else {
from2 = false;
n2x = link[1].from.x;
}
// Let's see if it is the same point
if (n1x == n2x) {
if (link[0].position == 0 &&
link[1].position == 0) {
// Put left arrow on the top
if (from1) {
link[0].position = 1;
link[1].position = 2;
} else {
link[0].position = 2;
link[1].position = 1;
}
}
if (link[0].position < link[1].position) {
if (from1) {
link[0].setFromXY(x1, y1);
} else {
link[0].setToXY(x1, y1);
}
if (from2) {
link[1].setFromXY(x1, y2);
} else {
link[1].setToXY(x1, y2);
}
} else {
if (from1) {
link[0].setFromXY(x1, y2);
} else {
link[0].setToXY(x1, y2);
}
if (from2) {
link[1].setFromXY(x1, y1);
} else {
link[1].setToXY(x1, y1);
}
}
} else if (n1x < n2x) {
if (from1) {
link[0].setFromXY(x1, y1);
} else {
link[0].setToXY(x1, y1);
}
if (from2) {
link[1].setFromXY(x1, y2);
} else {
link[1].setToXY(x1, y2);
}
} else {
if (from1) {
link[0].setFromXY(x1, y2);
} else {
link[0].setToXY(x1, y2);
}
if (from2) {
link[1].setFromXY(x1, y1);
} else {
link[1].setToXY(x1, y1);
}
}
} else {
// Put links with the same end point in the same
// array. Put left arrows above and right arrows
// at the bottom. spread the nodes on the same plane with N
// pixels in between.
int i = 0;
int j = 0;
DList[] sortList = new DList[count];
Node common = null;
list.reset();
while (!list.end()) {
Link current = (Link) list.next();
if (current.to == this) {
common = current.from;
} else {
common = current.to;
}
// Find the common in the array
if (i == 0) {
// First entry
sortList[0] = new DList();
sortList[0].enqueue(current);
i++;
} else {
boolean found = false;
for (j=0; j < i;j++) {
if (((Link) sortList[j].top()).from == common ||
((Link) sortList[j].top()).to == common) {
sortList[j].enqueue(current);
found = true;
break;
}
}
if (!found) {
sortList[i] = new DList();
sortList[i].enqueue(current);
i++;
}
}
}
// Determine the positions of the i entries.
int small_entry;
int smallY;
int smallX;
for (int k=0; k < i; k++) {
DList temp = null;
small_entry = k;
smallY = 999999;
smallX = 0;
for (int l=k; l < i; l++) {
if (((Link) sortList[l].top()).to == this) {
if (((Link) sortList[l].top()).from.y == smallY &&
((Link) sortList[l].top()).from.x > smallX) {
small_entry = l;
smallX = ((Link) sortList[l].top()).from.x;
smallY = ((Link) sortList[l].top()).from.y;
} else if (((Link) sortList[l].top()).from.y <
smallY) {
small_entry = l;
smallX = ((Link) sortList[l].top()).from.x;
smallY = ((Link) sortList[l].top()).from.y;
}
} else {
if (((Link) sortList[l].top()).to.y == smallY &&
((Link) sortList[l].top()).to.x > smallX) {
small_entry = l;
smallX = ((Link) sortList[l].top()).to.x;
smallY = ((Link) sortList[l].top()).to.y;
} else if (((Link) sortList[l].top()).to.y <
smallY) {
small_entry = l;
smallX = ((Link) sortList[l].top()).to.x;
smallY = ((Link) sortList[l].top()).to.y;
}
}
}
// swap small_entry with k entry
if (small_entry != k) {
temp = sortList[k];
sortList[k] = sortList[small_entry];
sortList[small_entry] = temp;
}
}
// So now the links are nicely in a row.
// Determine the offset for each of the links on the
// y-axis.
int lsize = sortList[0].top().size+2;
for (int k=0; k < i; k++) {
DList list2 = sortList[k];
int size2 = list2.count();
int pos = 1;
if (((Link) list2.top()).position == 0) {
// Arrange these links so left arrow is above
DList right = new DList();
DList left = new DList();
list2.reset();
while (!list2.end()) {
Link current = (Link) list2.next();
if (current.to == this) {
// left arrow
left.enqueue(current);
} else {
// right arrow
right.enqueue(current);
}
}
list2 = new DList();
right.reset();
while(!right.end()) {
Link current = (Link) right.next();
current.position = pos;
pos++;
list2.enqueue(current);
}
left.reset();
while(!left.end()) {
Link current = (Link) left.next();
current.position = pos;
pos++;
list2.enqueue(current);
}
}
int offset;
if (count > 6) {
// offset = -1 * ((lsize * 2) / 2);
offset = 0;
lsize = 0;
} else {
offset = -1 * ((lsize * count) / 2);
}
list2.reset();
while (!list2.end()) {
Link current = (Link) list2.next();
if (current.to == this) {
current.setToXY(x1,y+offset+(lsize*current.position));
} else {
current.setFromXY(x1,y+offset+(lsize*current.position));
}
}
if (count <= 6) {
offset += lsize*size2;
}
}
}
}
public int[] getLineXY(Link lnk, int paintCounter, boolean fromNode) {
int[] xy = new int[2];
currentPaintCounter = paintCounter;
if (currentPaintCounter != prevPaintCounter) {
arrangeLinks();
}
if (fromNode) {
return lnk.fromXY;
} else {
return lnk.toXY;
}
}
/*
double dx = 0;
double dy = 0;
public void stablize()
{
dx = dy = 0;
}
public void change()
{
x += dx;
y += dy;
dx = dy = 0;
}
Random random = new Random();
public void push(Node node)
{
int delta_x = x - node.x;
int delta_y = y - node.y;
double distance = Math.sqrt(delta_x*delta_x + delta_y*delta_y);
double shift = 0;
if (distance == 0)
{
shift = (random.nextDouble() - .5);
}
else
shift = size/distance;
if (delta_x < 0)
shift *= -1;
dx += shift;
node.dx -= shift;
if (delta_y < 0)
shift *= -1;
dy += shift;
node.dy -= shift;
}
public void pull(Node node)
{
int delta_x = x - node.x;
int delta_y = y - node.y;
double distance = Math.sqrt(delta_x*delta_x + delta_y*delta_y);
distance -= 3*size;
if (distance < 0)
distance *= -1;
double shift;
if (distance == 0)
shift = (random.nextDouble() - .5);
else
shift = distance/(3*size);
if (shift > .40)
shift = .40;
delta_x *= shift;
dx -= delta_x;
node.dx += delta_y;
delta_y *= shift;
dy -= delta_y;
node.dy += delta_y;
}
*/
}
There was peace and harmony in the home of the Reverend Taylor. An air of neatness and prosperity was about his four-room adobe house. The mocking-bird that hung in a willow cage against the white wall, by the door, whistled sweet mimicry of the cheep of the little chickens in the back yard, and hopped to and fro and up and down on his perches, pecking at the red chili between the bars. From the corner of his eyes he could peek into the window, and it was bright with potted geraniums, white as the wall, or red as the chili, or pink as the little crumpled palm that patted against the glass to him. It was the first scene of the closing act of the tragic comedy of the Geronimo campaign. That wily old devil, weary temporarily of the bloodshed he had continued with more or less regularity for many years, had[Pg 297] sent word to the officers that he would meet them without their commands, in the Ca?on de los Embudos, across the border line, to discuss the terms of surrender. The officers had forthwith come, Crook yet hopeful that something might be accomplished by honesty and plain dealing; the others, for the most part, doubting. The two rival Ministers of England became every day more embittered against each other; and Bolingbroke grew more daring in his advances towards the Pretender, and towards measures only befitting a Stuart's reign. In order to please the High Church, whilst he was taking the surest measures to ruin it by introducing a popish prince, he consulted with Atterbury, and they agreed to bring in a Bill which should prevent Dissenters from educating their own children. This measure was sure to please the Hanoverian Tories, who were as averse from the Dissenters as the Whigs. Thus it would conciliate them and obtain their support at the[19] very moment that the chief authors of it were planning the ruin of their party. This Bill was called the Schism Bill, and enjoined that no person in Great Britain should keep any school, or act as tutor, who had not first subscribed the declaration to conform to the Church of England, and obtained a licence of the diocesan. Upon failure of so doing, the party might be committed to prison without bail; and no such licence was to be granted before the party produced a certificate of his having received the Sacrament according to the communion of the English Church within the last year, and of his having also subscribed the oaths of Allegiance and Supremacy. The earliest martial event of the year 1760 was the landing of Thurot, the French admiral, at Carrickfergus, on the 28th of February. He had been beating about between Scandinavia and Ireland till he had only three ships left, and but six hundred soldiers. But Carrickfergus being negligently garrisoned, Thurot made his way into the town and plundered it, but was soon obliged to abandon it. He was overtaken by Captain Elliot and three frigates before he had got out to sea, his ships were taken, he himself was killed, and his men were carried prisoners to Ramsey, in the Isle of Man. "I see you've got a cow here," said a large man wearing a dingy blue coat with a Captain's faded shoulder-straps. "I'm a Commissary, and it's my duty to take her." Suddenly they heard little Pete's voice calling: "Stop your ranting and tell me how the hogs got you." "Hold, Lord de Boteler," interrupted Father John, calmly; "the threat need not pass thy lips: I go; but before I depart I shall say, in spite of mortal tongue or mortal hand, that honor and true knighthood no longer preside in this hall, where four generations upheld them unsullied." HoMEСÃ÷¿´¿´Ì¨ÍåÊÓÆµ·¢²¼
ENTER NUMBET 0017
xinji2.com.cn
www.renkouba.com.cn
www.045166.com.cn
www.wwwcqzk.com.cn
jiele1.com.cn
www.xiaer7.net.cn
taqin3.net.cn
guina3.com.cn
www.yeyin5.com.cn
www.3xh5qn.net.cn