import java.applet.*; import java.awt.*; import java.awt.event.*; import java.util.*; import java.lang.*; import java.io.*; import Cursor; /** 2-D L-System Applet * LSystem.java * @author J Scott Cameron */ public class LSystem extends Applet implements ActionListener{ Button Draw = new Button("Draw"); TextField nText = new TextField(); Label nLabel = new Label("n"); TextField angleText = new TextField(); Label angleLabel = new Label("angle"); TextField initText = new TextField(); Label initLabel = new Label("init"); TextArea grammarText = new TextArea(); Label grammarLabel = new Label("grammar"); Dimension size; Image buffer; Graphics bufferGraphics; int xMin, xMax, yMin, yMax; int width,height; int n; float angle; String init, grammar, finalPath; /** Initializes the components of the applet */ public void init() { setLayout(null); /* initialize awt components */ Draw.setBounds(405,5,80,20); Draw.addActionListener(this); nText.setBounds(460,30,50,20); nText.setText("5"); nLabel.setBounds(405,30,50,20); angleText.setBounds(460,55,50,20); angleText.setText("25.7"); angleLabel.setBounds(405,55,50,20); initText.setBounds(460,80,135,20); initText.setText("F"); initLabel.setBounds(405,80,50,20); grammarText.setBounds(405,130,180,200); grammarText.setText("F=F[+F]F[-F]F"); grammarLabel.setBounds(405,105,60,20); add(Draw); add(nText); add(nLabel); add(angleText); add(angleLabel); add(initText); add(initLabel); add(grammarText); add(grammarLabel); size = new Dimension(800,410); buffer = createImage(400, 400); bufferGraphics = buffer.getGraphics(); width=height=400; xMin=yMin=-10; xMax=yMax=10; } /** sets the scale so that the applet shows the whole Lsystem graphic * @param finalPath the final string that the cursor will move through * @param angle the angle the cursor turns for "+" and "-" symbols */ public void getScale(String finalPath, double angle) { double xMax = 0, xMin =0, yMin=0, yMax=0; Cursor cursor = new Cursor(); Cursor newCursor = new Cursor(); Stack cursorStack = new Stack(); int c; StringReader pathReader = new StringReader(finalPath); try { /* moves through the L-System the same as if it were * being drawn to determine what the bounds of the * L-System will be */ for(int i=0; i xMax) xMax = cursor.x; else if(cursor.x < xMin) xMin = cursor.x; cursor.y += Math.sin(cursor.angle); if(cursor.y > yMax) yMax = cursor.y; else if(cursor.y < yMin) yMin = cursor.y; break; case('+'): /*rotate cursor*/ cursor.angle+=angle; while(cursor.angle >= (2*Math.PI)) cursor.angle-=(2*Math.PI); break; case('-'): /*rotate cursor*/ cursor.angle-=angle; while(cursor.angle < 0) cursor.angle+=(2*Math.PI); break; case('['): /* push down on the stack */ cursorStack.push(new Cursor(cursor)); break; case(']'): /* pop off the stack */ cursor = (Cursor)cursorStack.pop(); default: break; } } } catch(IOException e) {} double size = (xMax-xMin); if(size < (yMax-yMin) ) size = (yMax-yMin); /* calculate the proper bounds */ this.xMax=(int)( ((xMax+xMin)/2) + (size/2))+1; this.xMin=(int)( ((xMax+xMin)/2) - (size/2))-1; this.yMax=(int)( ((yMax+yMin)/2) + (size/2))+1; this.yMin=(int)( ((yMax+yMin)/2) - (size/2))-1; } /** maps an LSystem x value to a screen x-coordinate * @param x The x value to be mapped * @return the appropriate x-coordinate for the screen */ public int getXCoord(double x) { float p = ((float)width)/((float)(xMax-xMin)); return (int) ((x-xMin)*p); } /** maps an LSystem y value to a screen y-coordinate * * @return the appropriate x-coordinate for the screen * @param y The y value to be mapped */ public int getYCoord(double y) { float p = ((float)width)/((float)(yMax-yMin)); return (int) ((y-yMin)*p); } /** draws the expanded LSystem string to the screen * @param finalPath expanded LSYstem string * @param angle angle the cursor will rotate for "+,=" symbols * @param graphics Graphics object to draw to. */ public void drawPath(String finalPath, double angle, Graphics graphics) { Cursor cursor = new Cursor(); Cursor newCursor = new Cursor(); /* create a stack to keep track of cursors */ Stack cursorStack = new Stack(); int c; StringReader pathReader = new StringReader(finalPath); try{ /* checks each character */ for(int i=0; i= (2*Math.PI)) cursor.angle-=(2*Math.PI); break; case('-'): /* rotates cursor */ cursor.angle-=angle; while(cursor.angle < 0) cursor.angle+=(2*Math.PI); break; case('['): /* pushes cursor state down on the stack*/ cursorStack.push(new Cursor(cursor)); break; case(']'): /* pops the stack and * sets cursor to that value*/ cursor = (Cursor)cursorStack.pop(); default: break; } } } catch(IOException e) {} } /** expands an Lsystem grammar * @param init The initial string for the LSystem * @param grammar The string containing the rules for the LSystem of format: * =\n * @param depth number of times the LSystem should recurse * @return the expanded string */ public String expandPath(String init, String grammar, int depth) { /* if the grammar isn't to be expanded, simply return the * initial string */ if(depth <= 0) { return init; } String expandedPath; StringWriter sw = new StringWriter(); Properties props = new Properties(); try{ /* Big-time cheat that uses the Java property loader to * parse the rules */ props.load(new ByteArrayInputStream(grammar.getBytes())); StringReader initReader = new StringReader(init); int c; /* replaces all characters that have associated rules * with the appropriate string */ for(int i=0;i0) { return expandPath(sw.toString(),grammar, depth-1); } else return sw.toString(); } /** Overload of update(Graphics) * calls paint() * @param g Graphics object to be updated */ public void update(Graphics g) { paint(g); } /** repaints the main window * @param g Graphics object to be repainted */ public void paint(Graphics g) { /* clears drawing area, draws outline*/ bufferGraphics.setColor(this.getBackground()); bufferGraphics.fillRect(0,0, 399, 399); bufferGraphics.setColor(Color.black); bufferGraphics.drawLine(0,0,399,0); bufferGraphics.drawLine(399,0,399,399); bufferGraphics.drawLine(399,399,0,399); bufferGraphics.drawLine(0,399,0,0); bufferGraphics.setColor(Color.blue); /*Get the expanded path from the initText and rules Fields*/ String expandedPath = expandPath(initText.getText(), grammarText.getText(), Integer.parseInt(nText.getText())); /*Find/set range for drawing area and draw L-System*/ try{ getScale(expandedPath, (Double.valueOf( angleText.getText())).doubleValue()/(180/Math.PI)); drawPath(expandedPath, (Double.valueOf( angleText.getText())).doubleValue()/(180/Math.PI), bufferGraphics); } catch(NumberFormatException e) {} g.drawImage(buffer,5,5,this); } /** sends button pressed events to appropriate handlers * @param evt description of event */ public void actionPerformed(ActionEvent evt) { Button theItem = (Button) evt.getSource(); if (theItem == Draw) DrawPressed(); } /** Redraws the LSystem, based upon data in the applet's fields. */ public void DrawPressed() { paint(this.getGraphics()); } }