/*--------------------------------------------------------------------------- File: Animation.java Package: JAWAA Beta Version 0.1 Author: Will Pierson (wcp@acpub.duke.edu) Description of Contents: Contains routines which draw animation. --------------------------------------------------------------------------*/ /* * Susan H. Rodger, Will Pierson * Computer Science Department * Duke University * December 1996 * * Copyright (c) 1996 * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the author. The name of the author may not be used to * endorse or promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ import java.awt.*; import java.util.*; public class Animation{ GraphicStore GS = new GraphicStore(); int s, totalSteps; AnimClass parent; public boolean started; Graphics dbuffer; Dimension r; public Animation(Dimension rd, Image offscreen, AnimClass p){ r = rd; dbuffer = offscreen.getGraphics(); dbuffer.setColor(Color.lightGray); dbuffer.fillRect(0,0, r.width, r.height); parent = p; } public void pause(int i){ try{ Thread.sleep(i); }catch(InterruptedException e){ } } public void draw(GraphicObject go){ switch(go.type){ case GraphicStore.NODE: dbuffer.setColor(go.col2); dbuffer.fillArc(go.x, go.y, go.aux[0] , go.aux[0], 0, 365); dbuffer.setColor(go.col); dbuffer.drawArc(go.x, go.y, go.aux[0], go.aux[0], 0, 365); dbuffer.drawString(String.valueOf(go.name), (int)(go.x + go.aux[0]/2 - (go.name.length()-1)*4 -3), (int)(go.y + go.aux[0]/2 +4)); break; case GraphicStore.ARC: dbuffer.setColor(go.col); dbuffer.drawLine(go.x, go.y, go.aux[0], go.aux[1]); double ratio = - (go.daux[0] / go.daux[1]); dbuffer.drawLine(go.aux[0], go.aux[1], (int)(go.aux[0] - go.daux[0] - .5*go.daux[1]), (int)(go.aux[1] - go.daux[1] + .5*go.daux[0])); dbuffer.drawLine(go.aux[0], go.aux[1], (int)(go.aux[0] - go.daux[0] + .5*go.daux[1]), (int)(go.aux[1] - go.daux[1] - .5*go.daux[0])); break; case GraphicStore.MARKER: dbuffer.setColor(go.col2); dbuffer.fillArc(go.x, go.y, go.aux[0], go.aux[0], 0, 365); dbuffer.setColor(go.col); dbuffer.drawArc(go.x, go.y, go.aux[0], go.aux[0], 0, 365); break; case GraphicStore.CIRCLE: dbuffer.setColor(go.col2); if (go.col2.getRGB() != -5544) dbuffer.fillArc(go.x, go.y, go.aux[0], go.aux[0], 0, 365); dbuffer.setColor(go.col); dbuffer.drawArc(go.x, go.y, go.aux[0],go.aux[0], 0, 365); break; case GraphicStore.LINE: dbuffer.setColor(go.col); dbuffer.drawLine(go.x, go.y, go.aux[0], go.aux[1]); break; case GraphicStore.POLYGON: int yPoints[] = new int[go.x]; int i = 0; if (go.col2.getRGB() != -5544){ dbuffer.setColor(go.col2); for(;i < go.x; i++){ yPoints[i] = (int)go.daux[i]; } dbuffer.fillPolygon(go.aux, yPoints, go.x); } dbuffer.setColor(go.col); dbuffer.drawPolygon(go.aux, yPoints, go.x); break; case GraphicStore.RECTANGLE: dbuffer.setColor(go.col2); if (go.col2.getRGB() != -5544) dbuffer.fillRect(go.x, go.y, go.aux[0], go.aux[1]); if (go.col.getRGB() == -5544) break; dbuffer.setColor(go.col); if (go.as[0] != null){ dbuffer.drawString(go.as[0], go.x+5, go.y+15); } dbuffer.drawRect(go.x, go.y, go.aux[0], go.aux[1]); break; case GraphicStore.TEXT: dbuffer.setColor(go.col); dbuffer.drawString(go.as[0], go.x, go.y); break; case GraphicStore.STACK: dbuffer.setColor(go.col); int length = (int)go.daux[0]; int sL = (int)go.daux[1] * 10; dbuffer.drawLine(go.x, go.y, go.x + 10, go.y); dbuffer.drawLine(go.x + 10, go.y, go.x + 10, go.y + 15*length); dbuffer.drawLine(go.x +10, go.y +15*length, go.x + 15 + sL, go.y +15*length); dbuffer.drawLine(go.x + 15 + sL, go.y+ 15*length, go.x + 15 + sL, go.y); dbuffer.drawLine(go.x + 15 +sL, go.y, go.x + 25 + sL, go.y); dbuffer.setColor(go.col2); int j = 0; for (i = length-1; i >=0; i--, j++){ dbuffer.drawString(go.as[i], go.x+14, go.y+10+j*15); } break; case GraphicStore.QUEUE: dbuffer.setColor(go.col); int l = (int)go.daux[0]; int strL = go.aux[0]; dbuffer.drawLine(go.x, go.y, go.x + 6*l + strL*9, go.y); dbuffer.drawLine(go.x, go.y+25, go.x + 6*l + strL*9, go.y+25); dbuffer.setColor(go.col2); int nextx = go.x+1; for (i = 0;i < l; i++){ dbuffer.drawString(go.as[i], nextx, go.y+17); nextx = nextx +5 + go.as[i].length()*9; } break; case GraphicStore.ARRAY: break; case GraphicStore.GROUP: break; case GraphicStore.TREE: break; case GraphicStore.GRAPH: break; default: System.out.println("Could not find GraphicObject type"+go.type); } } //when applet is exposed, must redraw everything that has happened //to this point, run through all current graphic objects and draw them public void redraw(){ dbuffer.setColor(Color.lightGray); dbuffer.fillRect(0,0,r.width, r.height); GraphicObject go; while(true){ go = GS.getObj(); if (go == null){ return; } if (go.x >= 0){ // System.out.println(go.name); draw(go); } } } // standard graphic object methods, draws object and puts it into array public void node(String name, int x, int y, int radius, Color col, Color bkgcol){ int arr[] = new int[5]; double darr[] = new double[2]; arr[0] = radius; String[] as = new String[2]; GS.add(name, x, y, GraphicStore.NODE, as, arr, darr, bkgcol, col); } public void setCircleBkgd(String name, Color bkg){ GraphicObject temp = new GraphicObject(); temp = GS.getObj(name); temp.col2 = bkg; } public void text(String name, int x, int y, String s, Color col){ int aux[] = new int[2]; double daux[] = new double[2]; Color col2 = Color.red; String[] as = new String[3]; as[0] = s; GS.add(name, x, y, GraphicStore.TEXT, as, aux, daux, col2, col); } public void connectNodes(String name, String node1Name, String node2Name, Color col, boolean animateDraw){ double node1_angle, node2_angle, x1_adj=0, y1_adj=0, x2_adj=0, y2_adj=0; double start_x=0, start_y=0, end_x=0, end_y=0; GraphicObject node1, node2; node1 = GS.getObj(node1Name); node2 = GS.getObj(node2Name); int rad1 = node1.aux[0]/2; int rad2 = node2.aux[0]/2; int x1 = node1.x + node1.aux[0]/2; int y1 = node1.y + node1.aux[0]/2; int x2 = node2.x + node2.aux[0]/2; int y2 = node2.y + node2.aux[0]/2; double x_diff = x1 - x2; double y_diff = -(y1 - y2); if (y_diff == 0) y_diff = -.0001; if (x_diff == 0) x_diff = .0001; if (x_diff >= 0){ if (y_diff >= 0){ node1_angle = Math.atan(y_diff/x_diff); node2_angle = Math.atan(x_diff/y_diff); x1_adj = -Math.cos(node1_angle); y1_adj = Math.sin(node1_angle); x2_adj = Math.sin(node2_angle); y2_adj = -Math.cos(node2_angle); } else{ node1_angle = Math.atan(x_diff/y_diff); node2_angle = Math.atan(y_diff/x_diff); x1_adj = Math.sin(node1_angle); y1_adj = -Math.cos(node1_angle); x2_adj = Math.cos(node2_angle); y2_adj = -Math.sin(node2_angle); } } else{ if (y_diff >= 0){ node1_angle = Math.atan(x_diff/y_diff); node2_angle = Math.atan(y_diff/x_diff); x1_adj = -Math.sin(node1_angle); y1_adj = Math.cos(node1_angle); x2_adj = -Math.cos(node2_angle); y2_adj = Math.sin(node2_angle); } else{ node1_angle = Math.atan(y_diff/x_diff); node2_angle = Math.atan(x_diff/y_diff); x1_adj = Math.cos(node1_angle); y1_adj = -Math.sin(node1_angle); x2_adj = -Math.sin(node2_angle); y2_adj = Math.cos(node2_angle); } } start_x = x1 + x1_adj * rad1; start_y = y1 + y1_adj *rad1; end_x = x2 + x2_adj * rad2; end_y = y2 + y2_adj * rad2; double temp_x = start_x; double temp_y = start_y; int arr[] = new int[5]; arr[0] = (int)start_x; arr[1] = (int)start_y; String as[] = new String[5]; as[0] = node1Name; as[1] = node2Name; double darr[] = new double[5]; darr[0] = x1_adj * 10; darr[1] = y1_adj* 10; Color col2 = Color.red; if(animateDraw){ GS.add(name, (int)start_x, (int)start_y, GraphicStore.ARC, as, arr, darr, col2, col); GraphicObject newArc = GS.getObj(name); while((Math.abs(temp_x - end_x) > 4) ||(Math.abs(temp_y - end_y) > 4)){ temp_x = temp_x + x1_adj*5; temp_y = temp_y + y1_adj*5; newArc.aux[0] = (int)temp_x; newArc.aux[1] = (int)temp_y; parent.ac.repaint(); try{ Thread.sleep(parent.delay/4); }catch(InterruptedException e){ } } newArc.aux[0] = (int)end_x; newArc.aux[1] = (int)end_y; } else{ arr[0] = (int)end_x; arr[1] = (int)end_y; GS.add(name, (int)start_x, (int)start_y, GraphicStore.ARC, as, arr, darr, col2, col); } } public void marker(String name, String nodeName, int radius, Color col, Color bkgd){ int arr[] = new int[5]; double darr[] = new double[5]; arr[0] = radius; GraphicObject node = GS.getObj(nodeName); int x = node.x +node.aux[0]/2 - radius/2; int y = node.y +node.aux[0]/2 - radius/2; String[] as = new String[5]; as[0] = nodeName; GS.add(name, x, y, GraphicStore.MARKER, as, arr, darr, bkgd, col); } public void moveMarker(String name, String node1Name, String node2Name, String arcName, Color col, Color bkgd){ GraphicObject node1 = GS.getObj(node1Name); GraphicObject node2 = GS.getObj(node2Name); GraphicObject arc = GS.getObj(arcName); GraphicObject newLoz = GS.getObj(name); double end_x = node2.x+node2.aux[0]/2 - newLoz.aux[0]/2; double end_y = node2.y+node2.aux[0]/2 - newLoz.aux[0]/2; double x_const = arc.daux[0]; double y_const = arc.daux[1]; if (arc.as[0].equals(node2Name)){ x_const = -x_const; y_const = -y_const; } newLoz.col2 = bkgd; double temp_x = newLoz.x; double temp_y = newLoz.y; while((Math.abs(temp_x - end_x) > 4) ||(Math.abs(temp_y - end_y) > 4)){ temp_x = temp_x + .4*x_const; temp_y = temp_y + .4*y_const; newLoz.x = (int)temp_x; newLoz.y = (int)temp_y; try{ Thread.sleep(parent.delay/8); }catch(InterruptedException e){ } parent.ac.repaint(); } newLoz.as[0] = node2Name; newLoz.x = node2.x + node2.aux[0]/2 - newLoz.aux[0]/2; newLoz.y = node2.y + node2.aux[0]/2 - newLoz.aux[0]/2; parent.ac.repaint(); } public void line(String name, int x1, int y1, int x2, int y2, Color col){ int arr[] = new int[5]; arr[0] = x2; arr[1] = y2; double darr[] = new double[1]; String[] as = new String[1]; GS.add(name, x1, y1, GraphicStore.LINE, as, arr, darr, col, col); } public void rectangle(String name, int x1, int y1, int x2, int y2, Color col, Color bkgd){ int arr[] = new int[5]; arr[0] = x2; arr[1] = y2; double darr[] = new double[1]; String[] as = new String[1]; GS.add(name, x1, y1, GraphicStore.RECTANGLE, as, arr, darr, bkgd, col); } public void polygon(String name, int points, int Xcoords[], int Ycoords[], Color col, Color bkgd){ double darr[] = new double[20]; for(int i = 0; i < points; i++){ darr[i] = Ycoords[i]; } String[] as = new String[1]; GS.add(name, points, 0, GraphicStore.POLYGON, as, Xcoords, darr, col, bkgd); } public void circle(String name, int x, int y, int radius, Color col, Color bkgcol){ int arr[] = new int[5]; double darr[] = new double[2]; arr[0] = radius; String[] as = new String[2]; GS.add(name, x, y, GraphicStore.CIRCLE, as, arr, darr, bkgcol, col); } public void stack(String name, int x, int y, int length, String values[], Color col, Color numCol){ int arr[] = new int[2]; double darr[] = new double[5]; darr[0] = length; darr[1] = 0; for (int i = 0; i < length; i++){ if (darr[1] < values[i].length()){ darr[1] = values[i].length(); } } GS.add(name, x, y, GraphicStore.STACK, values, arr, darr, numCol, col); } public void pop(String name){ GraphicObject go = GS.getObj(name); if (--go.daux[0] < 0){ System.out.println("ERROR: stack popped when empty"); } go.daux[1] = 0; for (int i = 0; i < go.daux[0]; i++){ if (go.daux[1] < go.as[i].length()){ go.daux[1] = go.as[i].length(); } } } public void push(String name, String value){ GraphicObject go = GS.getObj(name); go.as[(int)go.daux[0]] = value; go.daux[0]++; if (go.daux[1] < value.length()){ go.daux[1] = value.length(); } } public void queue(String name, int x, int y, int length, String values[], Color col, Color numCol){ int arr[] = new int[2]; double darr[] = new double[5]; darr[0] = length; int strLength = 0; for (int i = 0; i < length; i++){ strLength += values[i].length(); } arr[0] = strLength; GS.add(name, x, y, GraphicStore.QUEUE, values, arr, darr, numCol, col); } public void dequeue(String name){ GraphicObject go = GS.getObj(name); if (--go.daux[0] < 0){ System.out.println("ERROR: queue dequeued when empty"); } for (int i = 0; i < go.daux[0]; i++){ go.as[i] = go.as[i+1]; } int strLength = 0; for (int i = 0; i < go.daux[0]; i++){ strLength += go.as[i].length(); } go.aux[0] = strLength; } public void enqueue(String name, String value){ GraphicObject go = GS.getObj(name); go.as[(int)go.daux[0]] = value; go.daux[0]++; int strLength =0; for (int i = 0; i < go.daux[0]; i++){ strLength += go.as[i].length(); } go.aux[0] = strLength; } public void changeParam(String name, String paramName, String newValue){ GraphicObject go = GS.getObj(name); if (paramName.equals("color")){ Color newColor = new Color(Interpreter.findRGB(newValue)); go.col = newColor; } else if (paramName.equals("bkgrd")){ Color newColor = new Color(Interpreter.findRGB(newValue)); go.col2 = newColor; } else if (paramName.equals("text")){ GraphicObject oldText = new GraphicObject(); GraphicStore.goCopy(oldText, go); oldText.col = Color.lightGray; oldText.col2 = Color.lightGray; go.as[0] = newValue; } } public void array(String name, int x, int y, int length, String values[], String orient, Color col, Color col2){ double darr[] = new double[2]; int arr[] = new int[2]; arr[0] = length; String cellName; int cellLength, x_length = 0; //create array from rectangle objects if (orient.equals("horz")){ for(int i = 0; i < length; i++){ int cellArr[] = new int[4]; String cellAs[] = new String[2]; cellAs[0] = values[i]; cellName = name + "[" +i+"]"; cellLength = 10 + 8*(values[i].length()); cellArr[0] = cellLength; cellArr[1] = 20; GS.add(cellName, x + x_length, y, GraphicStore.RECTANGLE, cellAs, cellArr, darr, col2, col); x_length += cellLength + 1; } } else{ int longest = 0; for(int i = 0; i< length; i++){ if (values[i].length() > longest){ longest = values[i].length(); } } int y_length = 0; for(int i = 0; i < length; i++){ int cellArr[] = new int[4]; String cellAs[] = new String[2]; cellAs[0] = values[i]; cellName = name + "[" +i +"]"; cellArr[0] = 10 + 8*longest; cellArr[1] = 20; GS.add(cellName, x, y+y_length, GraphicStore.RECTANGLE, cellAs, cellArr, darr, col2, col); y_length += 21; } } GS.add(name, x, y, GraphicStore.ARRAY, values, arr, darr, col2, col); } public int[] sizeTree (int rootNode, int start[], int end[], int nodeNum){ int i = 0; int left[] = new int[2]; int right[] = new int[2]; int ret[] = new int[2]; left[0] = right[1] = 0; while(i < nodeNum){ if (start[i] == rootNode){ left = sizeTree(end[i], start, end, nodeNum); left[0] += 1; i++; break; } i++; } while(i < nodeNum){ if (start[i] == rootNode){ right = sizeTree(end[i], start, end, nodeNum); right[1] += 1; break; } i++; } ret[0] = left[0]; ret[1] = right[1]; return (ret); } public void makeTree(int rootNode, int x, int y, int nodeNum, int leftBorder, int rightBorder, int start[], int end[]){ node(String.valueOf(rootNode), x, y, 20, Color.black, Color.lightGray); int i = 0; int r = 0, left, right, total; int size[][] = new int[2][2]; int cnode[] = new int[2]; int isLeaf = 1; while(i < nodeNum && start[i] > -1){ if (start[i] == rootNode){ cnode[r] = end[i]; size[r++] = sizeTree(end[i], start, end, nodeNum); isLeaf = 0; } i++; } if (isLeaf == 1) return; left = size[0][0] + size[0][1]; right = size[1][0] + size[1][1]; total = left + right; int midBorder, cx1, cx2; int width = rightBorder - leftBorder; if (total == 0){ cx1 = leftBorder + width/4; midBorder = width/2 + leftBorder; cx2 = rightBorder - width/4; if (cnode[1] == 0){ cx1 = leftBorder + width/8; midBorder = width/4 + leftBorder; } } else if (left == 0){ cx1 = leftBorder + width/6; midBorder = leftBorder; cx2 = rightBorder - (width/3); } else if (right == 0){ cx2 = rightBorder - width/8; midBorder = rightBorder; cx1 = leftBorder + (3*width/8); } else{ int leftW = (int)(((float)left/(float)total) * width); int rightW = width - leftW; cx2 = rightBorder - rightW/2; midBorder = rightBorder - rightW; cx1 = leftBorder + leftW/2; } makeTree(cnode[0], cx1, y + 40, nodeNum, leftBorder, midBorder, start, end); if (cnode[1] > 0){ makeTree(cnode[1], cx2, y + 40, nodeNum, midBorder, rightBorder, start, end); } connectNodes(rootNode+"-"+cnode[0], String.valueOf(rootNode), String.valueOf(cnode[0]), Color.black, false); if (cnode[1] >0){ connectNodes(rootNode+"-"+cnode[1], String.valueOf(rootNode), String.valueOf(cnode[1]), Color.black, false); } } public void tree(String name, int x, int y, int width, int start[], int end[]){ double darr[] = new double[30]; int arr[] = new int[30]; String as[] = new String[2]; Color col, col2; col = col2 = Color.black; arr[0] = getNodes(start,end, new int[100]); if (arr[0] == 0) arr[0]++; darr[0] = width; int leftBorder = x; int rightBorder = x + width; for(int j = 1; j < arr[0]; j++){ arr[j] = start[j-1]; darr[j] = end[j-1]; } GS.add(name, x, y, GraphicStore.TREE, as, arr, darr, col2, col); makeTree(1,x+width/2, y, arr[0], leftBorder, rightBorder, start, end); } public int getNodes(int start[], int end[], int node[]){ int nodei = 0; int i = 0; boolean founds, founde; while (start[i] >0 ){ founds = false; founde = false; nodei = 0; while(node[nodei] >0){ if (node[nodei] == start[i]){ founds = true; } if (node[nodei] == end[i]){ founde = true; } nodei++; } if (!founds){ node[nodei] = start[i]; // System.out.println(start[i]); nodei++; } if (!founde && end[i] > 0){ node[nodei] = end[i]; // System.out.println(end[i]); } i++; } return nodei; } public void addNode(String name, int startNode, int endNode){ int end[] = new int[30]; int start[] = new int[30]; int node[] = new int[30]; GraphicObject go = GS.getObj(name); int width = (int)go.daux[0]; if (go.type == GraphicStore.TREE){ go.aux[go.aux[0]] = startNode; go.daux[go.aux[0]] = endNode; go.aux[0]++; } else if (go.type == GraphicStore.GRAPH){ int i; for(i = 0;go.aux[i] > 0;i++){ } go.aux[i] = startNode; go.daux[i] = -1; go.aux[0]++; } int j = 1; while(go.aux[j] >0){ end[j-1] = (int)go.daux[j]; start[j-1] = go.aux[j]; j++; } int leftBorder = go.x; int rightBorder = go.x + width; if (go.type == GraphicStore.TREE){ GS.add(name, go.x, go.y, GraphicStore.TREE, go.as, go.aux, go.daux, go.col2, go.col); makeTree(1, go.x + width/2,go.y,go.aux[0], leftBorder, rightBorder, start, end); } else if (go.type == GraphicStore.GRAPH){ GS.add(name, go.x, go.y, GraphicStore.GRAPH, go.as, go.aux, go.daux, go.col2, go.col); getNodes(start, end, node); if (go.as[0].equals("NORMAL")){ makeGraph(go.x, go.y, go.aux[0], leftBorder, rightBorder, start, end, node); } else if (go.as[0].equals("CIRCLE")){ makeCircleGraph(node[0], go.x ,go.y, go.aux[0], leftBorder, rightBorder, start, end, node); } } } public void addEdge(String name, int startNode, int endNode){ int end[] = new int[30]; int start[] = new int[30]; int node[] = new int[30]; GraphicObject go = GS.getObj(name); int j = 0; while(go.aux[j] > 0 ){ j++; } go.aux[j] = startNode; go.daux[j] = endNode; if (GS.getObj(String.valueOf(startNode)) == null){ go.aux[0]++; } if (GS.getObj(String.valueOf(endNode)) == null){ go.aux[0]++; } j = 1; while(go.aux[j] >0){ end[j-1] = (int)go.daux[j]; start[j-1] = go.aux[j]; j++; } getNodes(start, end, node); int width = (int)go.daux[0]; int leftBorder = go.x; int rightBorder = go.x + width; GS.add(name, go.x, go.y, GraphicStore.GRAPH, go.as, go.aux, go.daux, go.col2, go.col); if (go.as[0].equals("NORMAL")){ makeGraph(go.x, go.y, go.aux[0], leftBorder, rightBorder, start, end, node); } else if (go.as[0].equals("CIRCLE")){ makeCircleGraph(node[0], go.x ,go.y, go.aux[0], leftBorder, rightBorder, start, end, node); } } public void makeCircleGraph(int rootNode, int x, int y, int nodeNum, int leftBorder, int rightBorder, int start[], int end[], int node[]){ int nodex, nodey; int interval = 360/nodeNum; int width = rightBorder - leftBorder; int midx = x + width/2; int midy = y + width/2; boolean found = false; node(String.valueOf(rootNode), midx, y, 20, Color.black, Color.lightGray); int i = 1; int angle = 0; while(node[i] > 0){ angle += interval; nodex = (int)(Math.sin(angle/57.3) * width/2) + midx; nodey = -(int)(Math.cos(angle/57.3) * width/2) + midy; node(String.valueOf(node[i]), nodex, nodey, 20, Color.black, Color.lightGray); i++; } i = 0; while(end[i] != 0){ if(end[i] > 0){ connectNodes(start[i]+"-"+end[i], String.valueOf(start[i]), String.valueOf(end[i]), Color.black, false); } i++; } } public int BFS(int root, int start[], int end[], Stack order[]){ int i, node, level = 0; Vector adj1 = new Vector(); Vector adj2 = new Vector(); Vector visited = new Vector(); visited.addElement(new Integer(root)); adj1.addElement(new Integer(root)); while(!adj1.isEmpty()){ level++; order[level] = new Stack(); while(!adj1.isEmpty()){ node = ((Integer)adj1.firstElement()).intValue(); order[level].push(new String(String.valueOf(node))); adj1.removeElementAt(0); i = 0; while(start[i] > 0){ if (start[i] == node){ if (end[i] >0&&!visited.contains(new Integer(end[i]))){ visited.addElement(new Integer(end[i])); adj2.addElement(new Integer(end[i])); } } i++; } i = 0; while(end[i] > 0){ if (end[i] == node){ if (!visited.contains(new Integer(start[i]))){ visited.addElement(new Integer(start[i])); adj2.addElement(new Integer(start[i])); } } i++; } } adj1 = (Vector)adj2.clone(); adj2.removeAllElements(); } return level; } public int gridDistance(int x1, int y1, int x2, int y2){ int dist = 0 , d1; d1 = (x2 - x1)* (x2 - x1) + (y2 - y1)*(y2 - y1); dist = (int)Math.sqrt(d1); return dist; } public boolean cross(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4){ //calculate bounding box - from CLR p889 int rx1 = Math.min(x1, x2); int ry1 = Math.max(y1, y2); int rx2 = Math.max(x1, x2); int ry2 = Math.min(y1, y2); int rx3 = Math.min(x3, x4); int ry3 = Math.max(y3, y4); int rx4 = Math.max(x3, x4); int ry4 = Math.min(y3, y4); if ((rx2 >= rx3) && (rx4 >= rx1) && (ry2 <= ry3) && (ry4 <= ry1)){ // straddle test int v1 = (x3 - x1) * (y2 - y1) - (y3 - y1) * (x2 - x1); int v2 = (x4 - x1) * (y2 - y1) - (y4 - y1) * (x2 - x1); if (v1*v2 <= 0) return true; else return false; } else return false; } public Vector findNeighbors(int node, int start[], int end[]){ Vector neighbors = new Vector(); for(int i = 0; start[i] > 0; i++){ if (start[i] == node && end[i] > 0){ neighbors.addElement(new String(String.valueOf(end[i]))); } else if (end[i] == node){ neighbors.addElement(new String(String.valueOf(start[i]))); } } return neighbors; } public int incGraphCost(String nodeName, int start[], int end[], Vector placedNodes){ int d = 0; int wa = 1; int wr = 310000000; int wc = 80000; int repulsion = 0; int attraction = 0; int crossing = 0; GraphicObject go1, go2, go3; GraphicObject node = GS.getObj(nodeName); String tempNode; // calculate repulsion cost for (Enumeration e = placedNodes.elements() ; e.hasMoreElements() ;) { tempNode = (String)e.nextElement(); go1 = GS.getObj(tempNode); if (tempNode != nodeName){ d = gridDistance(node.x, node.y, go1.x, go1.y); if (d != 0) repulsion += wr/(d*d); } } // calculate attraction and crossing cost for(int i = 0; start[i] > 0; i++){ if (start[i] == Integer.valueOf(nodeName).intValue() && placedNodes.contains(String.valueOf(end[i]))){ go1 = GS.getObj(String.valueOf(String.valueOf(end[i]))); d = gridDistance(node.x, node.y, go1.x, go1.y); attraction += wa*d*d; for(int j = 0; start[j] > 0; j++){ if(j != i && placedNodes.contains(String.valueOf(end[j])) && placedNodes.contains(String.valueOf(start[j]))){ go2 = GS.getObj(String.valueOf(String.valueOf(start[j]))); go3 =GS.getObj(String.valueOf(String.valueOf(end[j]))); if (cross(node.x, node.y, go1.x, go1.y, go2.x, go2.y, go3.x, go3.y)) crossing += wc; } } } else if (end[i] == Integer.valueOf(nodeName).intValue() && placedNodes.contains(String.valueOf(start[i]))){ go1 = GS.getObj(String.valueOf(String.valueOf(start[i]))); d = gridDistance(node.x, node.y,go1.x,go1.y); attraction += wa*d*d; for(int j = 0; start[j] > 0; j++){ if(j != i && placedNodes.contains(String.valueOf(end[j])) && placedNodes.contains(String.valueOf(start[j]))){ go2 = GS.getObj(String.valueOf(String.valueOf(start[j]))); go3 =GS.getObj(String.valueOf(String.valueOf(end[j]))); if (cross(node.x, node.y, go1.x, go1.y, go2.x, go2.y, go3.x, go3.y)) crossing += wc; } } } } // System.out.println("ATT: "+attraction); // System.out.println("REP: "+repulsion); // System.out.println("CROSS: "+crossing); return attraction + repulsion + crossing; } public void makeGraph(int x, int y, int nodeNum, int leftBorder, int rightBorder, int start[], int end[], int node[]){ Stack leastOrder[] = new Stack[30]; Stack order[]; int cellSize = 30; try{ Thread.sleep(200); }catch(InterruptedException e){ } int width = rightBorder - leftBorder; int sideLength = width/cellSize; BitSet bitmap[] = new BitSet[sideLength]; for (int i = 0; i < sideLength; i++){ bitmap[i] = new BitSet(sideLength); } int rootNode, i = 0; int path, leastPath = 1000; while(node[i] > 0){ order = new Stack[30]; path = BFS(node[i], start, end, order); // System.out.println("NODE: "+node[i]+" "+path); if (path < leastPath){ leastPath = path; for(int j =1; j <= path; j++){ leastOrder[j] = (Stack)order[j].clone(); } } i++; } int mid = sideLength/2; String name, temp; int totalx, totaly, tempx, tempy, ptx, pty, places,neighborsPlaced; int baryx, baryy; Vector placedNodes = new Vector(); GraphicObject tempNode; name = (String)leastOrder[1].pop(); bitmap[mid].set(mid); // System.out.println("Placed "+name+" at "+mid+","+mid); // System.out.println(bitmap[mid].get(mid)); node(name, cellSize*mid+5+x, cellSize*mid+5+y, 20,Color.black, Color.lightGray); placedNodes.addElement(name); for(i = 2; i <= leastPath; i++){ while(!leastOrder[i].empty()){ totalx = totaly = places = neighborsPlaced = 0; int placex[] = new int[300]; int placey[] = new int[300]; Vector neighbors = new Vector(); name = (String)leastOrder[i].pop(); // System.out.println("Placing: "+name); neighbors = findNeighbors(Integer.valueOf(name).intValue(), start, end); for (Enumeration e =neighbors.elements();e.hasMoreElements();){ temp = (String)e.nextElement(); if (placedNodes.contains(temp)){ neighborsPlaced++; tempNode = GS.getObj(temp); tempx = tempNode.x / cellSize; tempy = tempNode.y / cellSize; totalx += tempx; totaly += tempy; for(int k = -1; k <= 1; k++){ for(int l = -1; l <= 1; l++){ ptx = tempx +k; pty = tempy+l; if(ptx >= 0 && ptx < sideLength && pty >= 0 && pty < sideLength && !bitmap[ptx].get(pty)){ placex[places] = ptx; placey[places] = pty; places++; } ptx = tempx +k*3; pty = tempy+l*3; if(ptx >= 0 && ptx < sideLength && pty >= 0 && pty < sideLength && !bitmap[ptx].get(pty)){ placex[places] = ptx; placey[places] = pty; places++; } } } if (neighborsPlaced > 1){ baryx = totalx/neighborsPlaced; baryy = totaly/neighborsPlaced; for(int k = -1; k <= 1; k++){ for(int l = -1; l <= 1; l++){ ptx = baryx +k; pty = baryy+l; if(ptx >= 0 && ptx < sideLength && pty >= 0 && pty < sideLength && !bitmap[ptx].get(pty)){ placex[places] = ptx; placey[places] = pty; places++; } ptx = baryx +k*3; pty = baryy + l*3; if(ptx >= 0 && ptx < sideLength && pty >= 0 && pty < sideLength && !bitmap[ptx].get(pty)){ placex[places] = ptx; placey[places] = pty; places++; } } } } } } int cost, leastCost = 10000000; int leastx = 1; int leasty = 1; for(; places >= 0; places--){ node(name, placex[places]*cellSize+5 +x, placey[places]*cellSize+5 +y , 20, Color.black, Color.lightGray); cost = incGraphCost(name, start, end, placedNodes); if (cost < leastCost){ leastCost = cost; leastx = placex[places]; leasty = placey[places]; } } // System.out.println("Placed "+name+" at "+leastx+","+leasty); placedNodes.addElement(name); node(name, leastx*cellSize +5+ x, leasty*cellSize+5+y, 20, Color.black, Color.lightGray); bitmap[leastx].set(leasty); for(int j = 0; start[j] > 0; j++){ if(start[j] == Integer.valueOf(name).intValue() && placedNodes.contains(String.valueOf(end[j]))){ connectNodes(start[j]+"-"+end[j], String.valueOf(start[j]), String.valueOf(end[j]), Color.black, false); } else if(end[j] == Integer.valueOf(name).intValue() && placedNodes.contains(String.valueOf(start[j]))){ connectNodes(start[j]+"-"+end[j], String.valueOf(start[j]), String.valueOf(end[j]), Color.black, false); } } } } } public void graph(String name, int x, int y, String type, int width, int start[], int end[]){ int nodeNum; int node[] = new int[30]; double darr[] = new double[30]; int arr[] = new int[30]; String as[] = new String[2]; Color col, col2; col = col2 = Color.black; int j = 0; while (start[j] > 0){ arr[j+1] = start[j]; darr[j+1] = end[j]; j++; } nodeNum = getNodes(start, end, node); arr[0] = nodeNum; darr[0] = width; as[0] = type; int leftBorder = x; int rightBorder = x + width; GS.add(name, x, y, GraphicStore.GRAPH, as, arr, darr, col2, col); Thread.currentThread().yield(); if (type.equals("NORMAL")){ makeGraph(x, y, nodeNum, leftBorder, rightBorder, start, end,node); } else if (type.equals("CIRCLE")){ makeCircleGraph(node[0], x, y, nodeNum, leftBorder, rightBorder, start, end, node); } } public void delete(String name){ GraphicObject go = GS.getObj(name); if (go.type == GraphicStore.ARRAY){ for (int i = 0; i < go.aux[0]; i++){ GS.remove(name + "[" +i +"]"); } } GS.remove(name); } public void moveRelative(String name, int x, int y, boolean animate){ GraphicObject objs[] = new GraphicObject[10]; GraphicObject go = GS.getObj(name); double x_const, y_const, ratio, temp_x = 0, temp_y = 0; int start_x[] = new int[6]; int start_y[] = new int[6]; int length; if (go.type == GraphicStore.GROUP){ length = go.x; for (int i = 0; i < length; i++){ objs[i] = GS.getObj(go.as[i]); start_x[i] = objs[i].x; start_y[i] = objs[i].y; } } else{ length = 1; objs[0] = go; start_x[0] = objs[0].x; start_y[0] = objs[0].y; } if (Math.abs(x) > Math.abs(y)){ ratio = Math.abs(((double)y)/x); x_const = 3; y_const = x_const * ratio; if (x < 0) x_const *= -1; if (y < 0) y_const *= -1; } else{ ratio = Math.abs(((double)x)/y); y_const = 3; x_const = y_const * ratio; if (y < 0) y_const *= -1; if (x < 0) x_const *= -1; } while((Math.abs(temp_x - x) > 4) ||(Math.abs(temp_y - y) > 4)){ temp_x += x_const; temp_y += y_const; for (int i = 0; i < length; i++){ objs[i].x = (int)(temp_x + start_x[i]); objs[i].y = (int)(temp_y + start_y[i]); } // System.out.println("x "+temp_x+" y "+temp_y); parent.ac.repaint(); try{ Thread.sleep(parent.delay/8); }catch(InterruptedException e){ } } for (int i = 0; i < length; i++){ objs[i].x = start_x[i] + x; objs[i].y = start_y[i] + y; } parent.ac.repaint(10); } public void groupObjects(String name, int num, String objs[]){ int arr[] = new int[2]; double darr[] = new double[2]; int x = num; for(int i = 0; i < num; i++){ if(GS.getObj(objs[i]) == null){ System.out.println("ERROR: could not add "+objs[i]+" to group"); return; } } GS.add(name, x, x, GraphicStore.GROUP, objs, arr, darr, Color.red, Color.red); parent.repaint(); } }