home *** CD-ROM | disk | FTP | other *** search
Java Source | 1996-07-10 | 8.6 KB | 358 lines |
- import java.awt.Graphics;
- import java.util.Stack;
- import java.util.Vector;
-
- /**
- * A (not-yet) Context sensitive L-System Fractal applet class.
- *
- * The rules for the Context L-system are read from the java.applet.Applet's
- * attributes and then the system is iteratively applied for the
- * given number of levels, possibly drawing each generation as it
- * is generated. Note that the ContextLSystem class does not yet
- * handle the lContext and rContext attributes, although this
- * class is already designed to parse the '[' and ']' characters
- * typically used in Context sensitive L-Systems.
- *
- * @author Jim Graham
- * @version 1.1f, 27 Mar 1995
- */
- public class clsfractal extends java.applet.Applet implements Runnable {
- ContextLSystem cls;
- int fractLevel = 1;
- int repaintDelay = 50;
- boolean incrementalUpdates;
- float startAngle;
- float rotAngle;
- float Xmin;
- float Xmax;
- float Ymin;
- float Ymax;
- int border;
- boolean normalizescaling;
-
- public void init() {
- String s;
- cls = new ContextLSystem(this);
- s = getParameter("level");
- if (s != null) fractLevel = Integer.parseInt(s);
- s = getParameter("incremental");
- if (s != null) incrementalUpdates = s.equals("true");
- s = getParameter("delay");
- if (s != null) repaintDelay = Integer.parseInt(s);
- s = getParameter("startAngle");
- if (s != null) startAngle = Float.valueOf(s).floatValue();
- s = getParameter("rotAngle");
- if (s != null) rotAngle = Float.valueOf(s).floatValue();
- rotAngle = rotAngle / 360 * 2 * 3.14159265358f;
- s = getParameter("border");
- if (s != null) border = Integer.parseInt(s);
- s = getParameter("normalizescale");
- if (s != null) normalizescaling = s.equals("true");
- }
-
- Thread kicker;
-
- public void run() {
- Thread me = Thread.currentThread();
- boolean needsRepaint = false;
- while (kicker == me && cls.getLevel() < fractLevel) {
- cls.generate();
- if (kicker == me && incrementalUpdates) {
- repaint();
- try {Thread.sleep(repaintDelay);} catch (InterruptedException e){}
- } else {
- needsRepaint = true;
- }
- }
- if (kicker == me) {
- kicker = null;
- if (needsRepaint) {
- repaint();
- }
- }
- }
-
- public void start() {
- kicker = new Thread(this);
- kicker.start();
- }
-
- public void stop() {
- kicker = null;
- }
-
- public boolean mouseUp(java.awt.Event evt, int x, int y) {
- cls = new ContextLSystem(this);
- savedPath = null;
- start();
- return true;
- }
-
- String savedPath;
-
- public void paint(Graphics g) {
- String fractalPath = cls.getPath();
- if (fractalPath == null) {
- super.paint(g);
- return;
- }
- if (savedPath == null || !savedPath.equals(fractalPath)) {
- savedPath = fractalPath;
- render(null, fractalPath);
- }
-
- for (int i = 0; i < border; i++) {
- g.draw3DRect(i, i, size().width - i * 2, size().height - i * 2,false);
- }
- render(g, fractalPath);
- }
-
- void render(Graphics g, String path) {
- Stack turtleStack = new Stack();
- CLSTurtle turtle;
-
- if (g == null) {
- Xmin = 1E20f;
- Ymin = 1E20f;
- Xmax = -1E20f;
- Ymax = -1E20f;
- turtle = new CLSTurtle(startAngle, 0, 0, 0, 0, 1, 1);
- } else {
- float frwidth = Xmax - Xmin;
- if (frwidth == 0)
- frwidth = 1;
- float frheight = Ymax - Ymin;
- if (frheight == 0)
- frheight = 1;
- float xscale = (size().width - border * 2 - 1) / frwidth;
- float yscale = (size().height - border * 2 - 1) / frheight;
- int xoff = border;
- int yoff = border;
- if (normalizescaling) {
- if (xscale < yscale) {
- yoff += ((size().height - border * 2)
- - ((Ymax - Ymin) * xscale)) / 2;
- yscale = xscale;
- } else if (yscale < xscale) {
- xoff += ((size().width - border * 2)
- - ((Xmax - Xmin) * yscale)) / 2;
- xscale = yscale;
- }
- }
- turtle = new CLSTurtle(startAngle, 0 - Xmin, 0 - Ymin,
- xoff, yoff, xscale, yscale);
- }
-
- for (int pos = 0; pos < path.length(); pos++) {
- switch (path.charAt(pos)) {
- case '+':
- turtle.rotate(rotAngle);
- break;
- case '-':
- turtle.rotate(-rotAngle);
- break;
- case '[':
- turtleStack.push(turtle);
- turtle = new CLSTurtle(turtle);
- break;
- case ']':
- turtle = (CLSTurtle) turtleStack.pop();
- break;
- case 'f':
- turtle.jump();
- break;
- case 'F':
- if (g == null) {
- includePt(turtle.X, turtle.Y);
- turtle.jump();
- includePt(turtle.X, turtle.Y);
- } else {
- turtle.draw(g);
- }
- break;
- default:
- break;
- }
- }
- }
-
- void includePt(float x, float y) {
- if (x < Xmin)
- Xmin = x;
- if (x > Xmax)
- Xmax = x;
- if (y < Ymin)
- Ymin = y;
- if (y > Ymax)
- Ymax = y;
- }
- }
-
- /**
- * A Logo turtle class designed to support Context sensitive L-Systems.
- *
- * This turtle performs a few basic maneuvers needed to support the
- * set of characters used in Context sensitive L-Systems "+-fF[]".
- *
- * @author Jim Graham
- * @version 1.1f, 27 Mar 1995
- */
- class CLSTurtle {
- float angle;
- float X;
- float Y;
- float scaleX;
- float scaleY;
- int xoff;
- int yoff;
-
- public CLSTurtle(float ang, float x, float y,
- int xorg, int yorg, float sx, float sy) {
- angle = ang;
- scaleX = sx;
- scaleY = sy;
- X = x * sx;
- Y = y * sy;
- xoff = xorg;
- yoff = yorg;
- }
-
- public CLSTurtle(CLSTurtle turtle) {
- angle = turtle.angle;
- X = turtle.X;
- Y = turtle.Y;
- scaleX = turtle.scaleX;
- scaleY = turtle.scaleY;
- xoff = turtle.xoff;
- yoff = turtle.yoff;
- }
-
- public void rotate(float theta) {
- angle += theta;
- }
-
- public void jump() {
- X += (float) Math.cos(angle) * scaleX;
- Y += (float) Math.sin(angle) * scaleY;
- }
-
- public void draw(Graphics g) {
- float x = X + (float) Math.cos(angle) * scaleX;
- float y = Y + (float) Math.sin(angle) * scaleY;
- g.drawLine((int) X + xoff, (int) Y + yoff,
- (int) x + xoff, (int) y + yoff);
- X = x;
- Y = y;
- }
- }
-
- /**
- * A (non-)Context sensitive L-System class.
- *
- * This class initializes the rules for Context sensitive L-Systems
- * (pred, succ, lContext, rContext) from the given java.applet.Applet's attributes.
- * The generate() method, however, does not (yet) apply the lContext
- * and rContext parts of the rules.
- *
- * @author Jim Graham
- * @version 1.1f, 27 Mar 1995
- */
- class ContextLSystem {
- String axiom;
- Vector rules = new Vector();
- int level;
-
- public ContextLSystem(java.applet.Applet app) {
- axiom = app.getParameter("axiom");
- int num = 1;
- while (true) {
- String pred = app.getParameter("pred"+num);
- String succ = app.getParameter("succ"+num);
- if (pred == null || succ == null) {
- break;
- }
- rules.addElement(new CLSRule(pred, succ,
- app.getParameter("lContext"+num),
- app.getParameter("rContext"+num)));
- num++;
- }
- currentPath = new StringBuffer(axiom);
- level = 0;
- }
-
- public int getLevel() {
- return level;
- }
-
- StringBuffer currentPath;
-
- public synchronized String getPath() {
- return ((currentPath == null) ? null : currentPath.toString());
- }
-
- private synchronized void setPath(StringBuffer path) {
- currentPath = path;
- level++;
- }
-
- public void generate() {
- StringBuffer newPath = new StringBuffer();
- int pos = 0;
- while (pos < currentPath.length()) {
- CLSRule rule = findRule(pos);
- if (rule == null) {
- newPath.append(currentPath.charAt(pos));
- pos++;
- } else {
- newPath.append(rule.succ);
- pos += rule.pred.length();
- }
- }
- setPath(newPath);
- }
-
- public CLSRule findRule(int pos) {
- for (int i = 0; i < rules.size(); i++) {
- CLSRule rule = (CLSRule) rules.elementAt(i);
- if (rule.matches(currentPath, pos)) {
- return rule;
- }
- }
- return null;
- }
- }
-
- /**
- * A Context sensitive L-System production rule.
- *
- * This class encapsulates a production rule for a Context sensitive
- * L-System (pred, succ, lContext, rContext).
- * The matches() method, however, does not (yet) verify the lContext
- * and rContext parts of the rule.
- *
- * @author Jim Graham
- * @version 1.1f, 27 Mar 1995
- */
- class CLSRule {
- String pred;
- String succ;
- String lContext;
- String rContext;
-
- public CLSRule(String p, String d, String l, String r) {
- pred = p;
- succ = d;
- lContext = l;
- rContext = r;
- }
-
- public boolean matches(StringBuffer sb, int pos) {
- if (pos + pred.length() > sb.length()) {
- return false;
- }
- char cb[] = new char[pred.length()];
- sb.getChars(pos, pos + pred.length(), cb, 0);
- return pred.equals(new String(cb));
- }
- }
-