home *** CD-ROM | disk | FTP | other *** search
/ BUG 15 / BUGCD1998_06.ISO / aplic / jbuilder / jsamples.z / CLSFractal.java < prev    next >
Text File  |  1997-07-30  |  11KB  |  389 lines

  1. // $Header: z:/admin/metro_examples/java/demo/Fractal/rcs/CLSFractal.java 1.1 1997/02/06 00:29:56 IPGIntel-2 Exp $ 
  2. /*
  3.  * @(#)CLSFractal.java    1.2 96/12/06
  4.  *
  5.  * Copyright (c) 1994-1996 Sun Microsystems, Inc. All Rights Reserved.
  6.  *
  7.  * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
  8.  * modify and redistribute this software in source and binary code form,
  9.  * provided that i) this copyright notice and license appear on all copies of
  10.  * the software; and ii) Licensee does not utilize the software in a manner
  11.  * which is disparaging to Sun.
  12.  *
  13.  * This software is provided "AS IS," without a warranty of any kind. ALL
  14.  * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
  15.  * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
  16.  * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
  17.  * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
  18.  * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
  19.  * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
  20.  * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
  21.  * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
  22.  * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
  23.  * POSSIBILITY OF SUCH DAMAGES.
  24.  *
  25.  * This software is not designed or intended for use in on-line control of
  26.  * aircraft, air traffic, aircraft navigation or aircraft communications; or in
  27.  * the design, construction, operation or maintenance of any nuclear
  28.  * facility. Licensee represents and warrants that it will not use or
  29.  * redistribute the Software for such purposes.
  30.  */
  31.  
  32. import java.awt.Graphics;
  33. import java.util.Stack;
  34. import java.util.Vector;
  35.  
  36. /**
  37.  * A (not-yet) Context sensitive L-System Fractal applet class.
  38.  *
  39.  * The rules for the Context L-system are read from the java.applet.Applet's
  40.  * attributes and then the system is iteratively applied for the
  41.  * given number of levels, possibly drawing each generation as it
  42.  * is generated.  Note that the ContextLSystem class does not yet
  43.  * handle the lContext and rContext attributes, although this
  44.  * class is already designed to parse the '[' and ']' characters
  45.  * typically used in Context sensitive L-Systems.
  46.  *
  47.  * @author     Jim Graham
  48.  * @version     1.1f, 27 Mar 1995
  49.  */
  50. public class CLSFractal extends java.applet.Applet implements Runnable {
  51.     ContextLSystem cls;
  52.     int fractLevel = 1;
  53.     int repaintDelay = 50;
  54.     boolean incrementalUpdates;
  55.     float startAngle;
  56.     float rotAngle;
  57.     float Xmin;
  58.     float Xmax;
  59.     float Ymin;
  60.     float Ymax;
  61.     int border;
  62.     boolean normalizescaling;
  63.  
  64.     public void init() {
  65.     String s;
  66.     cls = new ContextLSystem(this);
  67.     s = getParameter("level");
  68.     if (s != null) fractLevel = Integer.parseInt(s);
  69.     s = getParameter("incremental");
  70.     if (s != null) incrementalUpdates = s.equals("true");
  71.     s = getParameter("delay");
  72.     if (s != null) repaintDelay = Integer.parseInt(s);
  73.     s = getParameter("startAngle");
  74.     if (s != null) startAngle = Float.valueOf(s).floatValue();
  75.     s = getParameter("rotAngle");
  76.     if (s != null) rotAngle = Float.valueOf(s).floatValue();
  77.     rotAngle = rotAngle / 360 * 2 * 3.14159265358f;
  78.     s = getParameter("border");
  79.     if (s != null) border = Integer.parseInt(s);
  80.     s = getParameter("normalizescale");
  81.     if (s != null) normalizescaling = s.equals("true");
  82.     }
  83.  
  84.     Thread kicker;
  85.  
  86.     public void run() {
  87.     Thread me = Thread.currentThread();
  88.     boolean needsRepaint = false;
  89.     while (kicker == me && cls.getLevel() < fractLevel) {
  90.         cls.generate();
  91.         if (kicker == me && incrementalUpdates) {
  92.         repaint();
  93.         try {Thread.sleep(repaintDelay);} catch (InterruptedException e){}
  94.         } else {
  95.         needsRepaint = true;
  96.         }
  97.     }
  98.     if (kicker == me) {
  99.         kicker = null;
  100.         if (needsRepaint) {
  101.         repaint();
  102.         }
  103.     }
  104.     }
  105.  
  106.     public void start() {
  107.     kicker = new Thread(this);
  108.     kicker.start();
  109.     }
  110.  
  111.     public void stop() {
  112.     kicker = null;
  113.     }
  114.  
  115.     public boolean mouseUp(java.awt.Event evt, int x, int y) {
  116.     cls = new ContextLSystem(this);
  117.     savedPath = null;
  118.     start();
  119.     return true;
  120.     }
  121.  
  122.     String savedPath;
  123.  
  124.     public void paint(Graphics g) {
  125.     String fractalPath = cls.getPath();
  126.     if (fractalPath == null) {
  127.         super.paint(g);
  128.         return;
  129.     }
  130.     if (savedPath == null || !savedPath.equals(fractalPath)) {
  131.         savedPath = fractalPath;
  132.         render(null, fractalPath);
  133.     }
  134.  
  135.     for (int i = 0; i < border; i++) {
  136.         g.draw3DRect(i, i, size().width - i * 2, size().height - i * 2,false);
  137.     }
  138.     render(g, fractalPath);
  139.     }
  140.  
  141.     void render(Graphics g, String path) {
  142.     Stack turtleStack = new Stack();
  143.     CLSTurtle turtle;
  144.  
  145.     if (g == null) {
  146.         Xmin = 1E20f;
  147.         Ymin = 1E20f;
  148.         Xmax = -1E20f;
  149.         Ymax = -1E20f;
  150.         turtle = new CLSTurtle(startAngle, 0, 0, 0, 0, 1, 1);
  151.     } else {
  152.         float frwidth = Xmax - Xmin;
  153.         if (frwidth == 0)
  154.         frwidth = 1;
  155.         float frheight = Ymax - Ymin;
  156.         if (frheight == 0)
  157.         frheight = 1;
  158.         float xscale = (size().width - border * 2 - 1) / frwidth;
  159.         float yscale = (size().height - border * 2 - 1) / frheight;
  160.         int xoff = border;
  161.         int yoff = border;
  162.         if (normalizescaling) {
  163.         if (xscale < yscale) {
  164.             yoff += ((size().height - border * 2)
  165.                  - ((Ymax - Ymin) * xscale)) / 2;
  166.             yscale = xscale;
  167.         } else if (yscale < xscale) {
  168.             xoff += ((size().width - border * 2)
  169.                  - ((Xmax - Xmin) * yscale)) / 2;
  170.             xscale = yscale;
  171.         }
  172.         }
  173.         turtle = new CLSTurtle(startAngle, 0 - Xmin, 0 - Ymin,
  174.                    xoff, yoff, xscale, yscale);
  175.     }
  176.  
  177.     for (int pos = 0; pos < path.length(); pos++) {
  178.         switch (path.charAt(pos)) {
  179.         case '+':
  180.         turtle.rotate(rotAngle);
  181.         break;
  182.         case '-':
  183.         turtle.rotate(-rotAngle);
  184.         break;
  185.         case '[':
  186.         turtleStack.push(turtle);
  187.         turtle = new CLSTurtle(turtle);
  188.         break;
  189.         case ']':
  190.         turtle = (CLSTurtle) turtleStack.pop();
  191.         break;
  192.         case 'f':
  193.         turtle.jump();
  194.         break;
  195.         case 'F':
  196.         if (g == null) {
  197.             includePt(turtle.X, turtle.Y);
  198.             turtle.jump();
  199.             includePt(turtle.X, turtle.Y);
  200.         } else {
  201.             turtle.draw(g);
  202.         }
  203.         break;
  204.         default:
  205.         break;
  206.         }
  207.     }
  208.     }
  209.  
  210.     void includePt(float x, float y) {
  211.     if (x < Xmin)
  212.         Xmin = x;
  213.     if (x > Xmax)
  214.         Xmax = x;
  215.     if (y < Ymin)
  216.         Ymin = y;
  217.     if (y > Ymax)
  218.         Ymax = y;
  219.     }
  220. }
  221.  
  222. /**
  223.  * A Logo turtle class designed to support Context sensitive L-Systems.
  224.  *
  225.  * This turtle performs a few basic maneuvers needed to support the
  226.  * set of characters used in Context sensitive L-Systems "+-fF[]".
  227.  *
  228.  * @author     Jim Graham
  229.  * @version     1.1f, 27 Mar 1995
  230.  */
  231. class CLSTurtle {
  232.     float angle;
  233.     float X;
  234.     float Y;
  235.     float scaleX;
  236.     float scaleY;
  237.     int xoff;
  238.     int yoff;
  239.  
  240.     public CLSTurtle(float ang, float x, float y,
  241.              int xorg, int yorg, float sx, float sy) {
  242.     angle = ang;
  243.     scaleX = sx;
  244.     scaleY = sy;
  245.     X = x * sx;
  246.     Y = y * sy;
  247.     xoff = xorg;
  248.     yoff = yorg;
  249.     }
  250.  
  251.     public CLSTurtle(CLSTurtle turtle) {
  252.     angle = turtle.angle;
  253.     X = turtle.X;
  254.     Y = turtle.Y;
  255.     scaleX = turtle.scaleX;
  256.     scaleY = turtle.scaleY;
  257.     xoff = turtle.xoff;
  258.     yoff = turtle.yoff;
  259.     }
  260.  
  261.     public void rotate(float theta) {
  262.     angle += theta;
  263.     }
  264.  
  265.     public void jump() {
  266.     X += (float) Math.cos(angle) * scaleX;
  267.     Y += (float) Math.sin(angle) * scaleY;
  268.     }
  269.  
  270.     public void draw(Graphics g) {
  271.     float x = X + (float) Math.cos(angle) * scaleX;
  272.     float y = Y + (float) Math.sin(angle) * scaleY;
  273.     g.drawLine((int) X + xoff, (int) Y + yoff,
  274.            (int) x + xoff, (int) y + yoff);
  275.     X = x;
  276.     Y = y;
  277.     }
  278. }
  279.  
  280. /**
  281.  * A (non-)Context sensitive L-System class.
  282.  *
  283.  * This class initializes the rules for Context sensitive L-Systems
  284.  * (pred, succ, lContext, rContext) from the given java.applet.Applet's attributes.
  285.  * The generate() method, however, does not (yet) apply the lContext
  286.  * and rContext parts of the rules.
  287.  *
  288.  * @author     Jim Graham
  289.  * @version     1.1f, 27 Mar 1995
  290.  */
  291. class ContextLSystem {
  292.     String axiom;
  293.     Vector rules = new Vector();
  294.     int level;
  295.  
  296.     public ContextLSystem(java.applet.Applet app) {
  297.     axiom = app.getParameter("axiom");
  298.     int num = 1;
  299.     while (true) {
  300.         String pred = app.getParameter("pred"+num);
  301.         String succ = app.getParameter("succ"+num);
  302.         if (pred == null || succ == null) {
  303.         break;
  304.         }
  305.         rules.addElement(new CLSRule(pred, succ,
  306.                      app.getParameter("lContext"+num),
  307.                      app.getParameter("rContext"+num)));
  308.         num++;
  309.     }
  310.     currentPath = new StringBuffer(axiom);
  311.     level = 0;
  312.     }
  313.  
  314.     public int getLevel() {
  315.     return level;
  316.     }
  317.  
  318.     StringBuffer currentPath;
  319.  
  320.     public synchronized String getPath() {
  321.     return ((currentPath == null) ? null : currentPath.toString());
  322.     }
  323.  
  324.     private synchronized void setPath(StringBuffer path) {
  325.     currentPath = path;
  326.     level++;
  327.     }
  328.  
  329.     public void generate() {
  330.     StringBuffer newPath = new StringBuffer();
  331.     int pos = 0;
  332.     while (pos < currentPath.length()) {
  333.         CLSRule rule = findRule(pos);
  334.         if (rule == null) {
  335.         newPath.append(currentPath.charAt(pos));
  336.         pos++;
  337.         } else {
  338.         newPath.append(rule.succ);
  339.         pos += rule.pred.length();
  340.         }
  341.     }
  342.     setPath(newPath);
  343.     }
  344.  
  345.     public CLSRule findRule(int pos) {
  346.     for (int i = 0; i < rules.size(); i++) {
  347.         CLSRule rule = (CLSRule) rules.elementAt(i);
  348.         if (rule.matches(currentPath, pos)) {
  349.         return rule;
  350.         }
  351.     }
  352.     return null;
  353.     }
  354. }
  355.  
  356. /**
  357.  * A Context sensitive L-System production rule.
  358.  *
  359.  * This class encapsulates a production rule for a Context sensitive
  360.  * L-System (pred, succ, lContext, rContext).
  361.  * The matches() method, however, does not (yet) verify the lContext
  362.  * and rContext parts of the rule.
  363.  *
  364.  * @author     Jim Graham
  365.  * @version     1.1f, 27 Mar 1995
  366.  */
  367. class CLSRule {
  368.     String pred;
  369.     String succ;
  370.     String lContext;
  371.     String rContext;
  372.  
  373.     public CLSRule(String p, String d, String l, String r) {
  374.     pred = p;
  375.     succ = d;
  376.     lContext = l;
  377.     rContext = r;
  378.     }
  379.  
  380.     public boolean matches(StringBuffer sb, int pos) {
  381.     if (pos + pred.length() > sb.length()) {
  382.         return false;
  383.     }
  384.     char cb[] = new char[pred.length()];
  385.     sb.getChars(pos, pos + pred.length(), cb, 0);
  386.     return pred.equals(new String(cb));
  387.     }
  388. }
  389.