home *** CD-ROM | disk | FTP | other *** search
/ Java 1.2 How-To / JavaHowTo.iso / 3rdParty / Bluette / Plastic / demo / Graph.java < prev    next >
Text File  |  1997-09-03  |  12KB  |  333 lines

  1. /*
  2.  * This program was generated by PLASTIC
  3.  *
  4.  * Author : Min-Kyu Lee
  5.  * Title : Graph Layout
  6.  * Generated Date : 97-09-04
  7.  */
  8.  
  9.  
  10. import java.util.*;
  11. import java.awt.*;
  12. import java.applet.Applet;
  13.  
  14. /**
  15.  * @(#)Graph.java    1.3 96/12/06
  16.  * Copyright (c) 1994-1996 Sun Microsystems, Inc. All Rights 
  17.  * Reserved.
  18.  */
  19.  
  20. class Node extends Object {
  21.         double x;
  22.         double y;
  23.         double dx;
  24.         double dy;
  25.         boolean fixed;
  26.         String lbl;
  27. }
  28.  
  29. class Edge extends Object {
  30.         int from;
  31.         int to;
  32.         double len;
  33. }
  34.  
  35. class GraphPanel extends Panel implements Runnable {
  36.         Node[] nodes = new Node[100]; // aggregation
  37.         Edge[] edges = new Edge[200]; // aggregation
  38.         Thread relaxer; // reference
  39.         Graph graph;
  40.         int nnodes;
  41.         int nedges;
  42.         boolean stress;
  43.         boolean random;
  44.         Node pick;
  45.         boolean pickfixed;
  46.         Image offscreen;
  47.         Dimension offscreensize;
  48.         Graphics offgraphics;
  49.         final Color fixedColor = Color.red;
  50.         final Color selectColor = Color.pink;
  51.         final Color edgeColor = Color.black;
  52.         final Color nodeColor = new Color(250, 220, 100);
  53.         final Color stressColor = Color.darkGray;
  54.         final Color arcColor1 = Color.black;
  55.         final Color arcColor2 = Color.pink;
  56.         final Color arcColor3 = Color.red;
  57.         GraphPanel(Graph graph) {
  58.                 this.graph = graph;
  59.         }
  60.         int findNode(String lbl) {
  61.                 for (int i = 0 ; i < nnodes ; i++) {
  62.                     if (nodes[i].lbl.equals(lbl)) {
  63.                         return i;
  64.                     }
  65.                 }
  66.                 return addNode(lbl);
  67.         }
  68.         int addNode(String lbl) {
  69.                 Node n = new Node();
  70.                 n.x = 10 + 380*Math.random();
  71.                 n.y = 10 + 380*Math.random();
  72.                 n.lbl = lbl;
  73.                 nodes[nnodes] = n;
  74.                 return nnodes++;
  75.         }
  76.         void addEdge(String from, String to, int len) {
  77.                 Edge e = new Edge();
  78.                 e.from = findNode(from);
  79.                 e.to = findNode(to);
  80.                 e.len = len;
  81.                 edges[nedges++] = e;
  82.         }
  83.         public void run() {
  84.                 while (true) {
  85.                     relax();
  86.                     if (random && (Math.random() < 0.03)) {
  87.                     Node n = nodes[(int)(Math.random() * nnodes)];
  88.                     if (!n.fixed) {
  89.                         n.x += 100*Math.random() - 50;
  90.                         n.y += 100*Math.random() - 50;
  91.                     }
  92.                     graph.play(graph.getCodeBase(), "audio/drip.au");
  93.                     }
  94.                     try {
  95.                     Thread.sleep(100);
  96.                     } catch (InterruptedException e) {
  97.                     break;
  98.                     }
  99.                 }
  100.         }
  101.         synchronized void relax() {
  102.                 for (int i = 0 ; i < nedges ; i++) {
  103.                     Edge e = edges[i];
  104.                     double vx = nodes[e.to].x - nodes[e.from].x;
  105.                     double vy = nodes[e.to].y - nodes[e.from].y;
  106.                     double len = Math.sqrt(vx * vx + vy * vy);
  107.                     double f = (edges[i].len - len) / (len * 3);
  108.                     double dx = f * vx;
  109.                     double dy = f * vy;
  110.                 
  111.                     nodes[e.to].dx += dx;
  112.                     nodes[e.to].dy += dy;
  113.                     nodes[e.from].dx += -dx;
  114.                     nodes[e.from].dy += -dy;
  115.                 }
  116.                 
  117.                 for (int i = 0 ; i < nnodes ; i++) {
  118.                     Node n1 = nodes[i];
  119.                     double dx = 0;
  120.                     double dy = 0;
  121.                 
  122.                     for (int j = 0 ; j < nnodes ; j++) {
  123.                     if (i == j) {
  124.                         continue;
  125.                     }
  126.                     Node n2 = nodes[j];
  127.                     double vx = n1.x - n2.x;
  128.                     double vy = n1.y - n2.y;
  129.                     double len = vx * vx + vy * vy;
  130.                     if (len == 0) {
  131.                         dx += Math.random();
  132.                         dy += Math.random();
  133.                     } else if (len < 100*100) {
  134.                         dx += vx / len;
  135.                         dy += vy / len;
  136.                     }
  137.                     }
  138.                     double dlen = dx * dx + dy * dy;
  139.                     if (dlen > 0) {
  140.                     dlen = Math.sqrt(dlen) / 2;
  141.                     n1.dx += dx / dlen;
  142.                     n1.dy += dy / dlen;
  143.                     }
  144.                 }
  145.                 
  146.                 Dimension d = size();
  147.                 for (int i = 0 ; i < nnodes ; i++) {
  148.                     Node n = nodes[i];
  149.                     if (!n.fixed) {
  150.                     n.x += Math.max(-5, Math.min(5, n.dx));
  151.                     n.y += Math.max(-5, Math.min(5, n.dy));
  152.                         // System.out.println("v= " + n.dx + "," + n.dy);
  153.                     if (n.x < 0) {
  154.                         n.x = 0;
  155.                     } else if (n.x > d.width) {
  156.                         n.x = d.width;
  157.                     }
  158.                     if (n.y < 0) {
  159.                         n.y = 0;
  160.                     } else if (n.y > d.height) {
  161.                         n.y = d.height;
  162.                     }
  163.                     }
  164.                     n.dx /= 2;
  165.                     n.dy /= 2;
  166.                 }
  167.                 repaint();
  168.         }
  169.         public void paintNode(Graphics g, Node n, FontMetrics fm) {
  170.                 int x = (int)n.x;
  171.                 int y = (int)n.y;
  172.                 g.setColor((n == pick) ? selectColor : (n.fixed ? fixedColor : nodeColor));
  173.                 int w = fm.stringWidth(n.lbl) + 10;
  174.                 int h = fm.getHeight() + 4;
  175.                 g.fillRect(x - w/2, y - h / 2, w, h);
  176.                 g.setColor(Color.black);
  177.                 g.drawRect(x - w/2, y - h / 2, w-1, h-1);
  178.                 g.drawString(n.lbl, x - (w-10)/2, (y - (h-4)/2) + fm.getAscent());
  179.         }
  180.         public synchronized void update(Graphics g) {
  181.                 Dimension d = size();
  182.                 if ((offscreen == null) || (d.width != offscreensize.width) || (d.height != offscreensize.height)) {
  183.                     offscreen = createImage(d.width, d.height);
  184.                     offscreensize = d;
  185.                     offgraphics = offscreen.getGraphics();
  186.                     offgraphics.setFont(getFont());
  187.                 }
  188.                 
  189.                 offgraphics.setColor(getBackground());
  190.                 offgraphics.fillRect(0, 0, d.width, d.height);
  191.                 for (int i = 0 ; i < nedges ; i++) {
  192.                     Edge e = edges[i];
  193.                     int x1 = (int)nodes[e.from].x;
  194.                     int y1 = (int)nodes[e.from].y;
  195.                     int x2 = (int)nodes[e.to].x;
  196.                     int y2 = (int)nodes[e.to].y;
  197.                     int len = (int)Math.abs(Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)) - e.len);
  198.                     offgraphics.setColor((len < 10) ? arcColor1 : (len < 20 ? arcColor2 : arcColor3)) ;
  199.                     offgraphics.drawLine(x1, y1, x2, y2);
  200.                     if (stress) {
  201.                     String lbl = String.valueOf(len);
  202.                     offgraphics.setColor(stressColor);
  203.                     offgraphics.drawString(lbl, x1 + (x2-x1)/2, y1 + (y2-y1)/2);
  204.                     offgraphics.setColor(edgeColor);
  205.                     }
  206.                 }
  207.                 
  208.                 FontMetrics fm = offgraphics.getFontMetrics();
  209.                 for (int i = 0 ; i < nnodes ; i++) {
  210.                     paintNode(offgraphics, nodes[i], fm);
  211.                 }
  212.                 
  213.                 g.drawImage(offscreen, 0, 0, null);
  214.         }
  215.         public synchronized boolean mouseDown(Event evt, int x, int y) {
  216.                 double bestdist = Double.MAX_VALUE;
  217.                 for (int i = 0 ; i < nnodes ; i++) {
  218.                     Node n = nodes[i];
  219.                     double dist = (n.x - x) * (n.x - x) + (n.y - y) * (n.y - y);
  220.                     if (dist < bestdist) {
  221.                     pick = n;
  222.                     bestdist = dist;
  223.                     }
  224.                 }
  225.                 pickfixed = pick.fixed;
  226.                 pick.fixed = true;
  227.                 pick.x = x;
  228.                 pick.y = y;
  229.                 repaint();
  230.                 return true;
  231.         }
  232.         public synchronized boolean mouseDrag(Event evt, int x, int y) {
  233.                 pick.x = x;
  234.                 pick.y = y;
  235.                 repaint();
  236.                 return true;
  237.         }
  238.         public synchronized boolean mouseUp(Event evt, int x, int y) {
  239.                 pick.x = x;
  240.                 pick.y = y;
  241.                 pick.fixed = pickfixed;
  242.                 pick = null;
  243.                 repaint();
  244.                 return true;
  245.         }
  246.         public void start() {
  247.                 relaxer = new Thread(this);
  248.                 relaxer.start();
  249.         }
  250.         public void stop() {
  251.                 relaxer.stop();
  252.         }
  253. }
  254.  
  255. public class Graph extends Applet {
  256.         GraphPanel panel; // reference
  257.         public void init() {
  258.                 setLayout(new BorderLayout());
  259.                 panel = new GraphPanel(this);
  260.                 add("Center", panel);
  261.                 Panel p = new Panel();
  262.                 add("South", p);
  263.                 p.add(new Button("Scramble"));
  264.                 p.add(new Button("Shake"));
  265.                 p.add(new Checkbox("Stress"));
  266.                 p.add(new Checkbox("Random"));
  267.                 String edges = getParameter("edges");
  268.                 for (StringTokenizer t = new StringTokenizer(edges, ",") ; t.hasMoreTokens() ; ) {
  269.                     String str = t.nextToken();
  270.                     int i = str.indexOf('-');
  271.                     if (i > 0) {
  272.                         int len = 50;
  273.                         int j = str.indexOf('/');
  274.                         if (j > 0) {
  275.                             len = Integer.valueOf(str.substring(j+1)).intValue();
  276.                             str = str.substring(0, j);
  277.                         }
  278.                         panel.addEdge(str.substring(0,i), str.substring(i+1), len);
  279.                     }
  280.                 }
  281.                 Dimension d = size();
  282.                 String center = getParameter("center");
  283.                 if (center != null){
  284.                     Node n = panel.nodes[panel.findNode(center)];
  285.                     n.x = d.width / 2;
  286.                     n.y = d.height / 2;
  287.                     n.fixed = true;
  288.                 }
  289.         }
  290.         public void start() {
  291.                 panel.start();
  292.         }
  293.         public void stop() {
  294.                 panel.stop();
  295.         }
  296.         public boolean action(Event evt, Object arg) {
  297.                 if (arg instanceof Boolean) {
  298.                     if (((Checkbox)evt.target).getLabel().equals("Stress")) {
  299.                     panel.stress = ((Boolean)arg).booleanValue();
  300.                     } else {
  301.                     panel.random = ((Boolean)arg).booleanValue();
  302.                     }
  303.                     return true;
  304.                 } 
  305.                 if ("Scramble".equals(arg)) {
  306.                     play(getCodeBase(), "audio/computer.au");
  307.                     Dimension d = size();
  308.                     for (int i = 0 ; i < panel.nnodes ; i++) {
  309.                     Node n = panel.nodes[i];
  310.                     if (!n.fixed) {
  311.                         n.x = 10 + (d.width-20)*Math.random();
  312.                         n.y = 10 + (d.height-20)*Math.random();
  313.                     }
  314.                     }
  315.                     return true;
  316.                 }
  317.                 if ("Shake".equals(arg)) {
  318.                     play(getCodeBase(), "audio/gong.au");
  319.                     Dimension d = size();
  320.                     for (int i = 0 ; i < panel.nnodes ; i++) {
  321.                     Node n = panel.nodes[i];
  322.                     if (!n.fixed) {
  323.                         n.x += 80*Math.random() - 40;
  324.                         n.y += 80*Math.random() - 40;
  325.                     }
  326.                     }
  327.                     return true;
  328.                 }
  329.                 return false;
  330.         }
  331. }
  332.  
  333.