Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/demo/applets/Fractal/CLSFractal.java
38827 views
/*1* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.2*3* Redistribution and use in source and binary forms, with or without4* modification, are permitted provided that the following conditions5* are met:6*7* - Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9*10* - Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* - Neither the name of Oracle nor the names of its15* contributors may be used to endorse or promote products derived16* from this software without specific prior written permission.17*18* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS19* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,20* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR21* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR22* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,23* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,24* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR25* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF26* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING27* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS28* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.29*/3031/*32* This source code is provided to illustrate the usage of a given feature33* or technique and has been deliberately simplified. Additional steps34* required for a production-quality application, such as security checks,35* input validation and proper error handling, might not be present in36* this sample code.37*/38394041import java.awt.Graphics;42import java.util.Stack;43import java.awt.event.*;44import java.util.ArrayList;45import java.util.List;464748/**49* A (not-yet) Context sensitive L-System Fractal applet class.50*51* The rules for the Context L-system are read from the java.applet.Applet's52* attributes and then the system is iteratively applied for the53* given number of levels, possibly drawing each generation as it54* is generated. Note that the ContextLSystem class does not yet55* handle the lContext and rContext attributes, although this56* class is already designed to parse the '[' and ']' characters57* typically used in Context sensitive L-Systems.58*59* @author Jim Graham60*/61@SuppressWarnings("serial")62public class CLSFractal63extends java.applet.Applet64implements Runnable, MouseListener {6566Thread kicker;67ContextLSystem cls;68int fractLevel = 1;69int repaintDelay = 50;70boolean incrementalUpdates;71float startAngle = 0;72float rotAngle = 45;73float Xmin;74float Xmax;75float Ymin;76float Ymax;77int border;78boolean normalizescaling;7980@Override81public void init() {82String s;83cls = new ContextLSystem(this);84s = getParameter("level");85if (s != null) {86fractLevel = Integer.parseInt(s);87}88s = getParameter("incremental");89if (s != null) {90incrementalUpdates = s.equalsIgnoreCase("true");91}92s = getParameter("delay");93if (s != null) {94repaintDelay = Integer.parseInt(s);95}96s = getParameter("startAngle");97if (s != null) {98startAngle = Float.valueOf(s).floatValue();99}100s = getParameter("rotAngle");101if (s != null) {102rotAngle = Float.valueOf(s).floatValue();103}104rotAngle = rotAngle / 360 * 2 * 3.14159265358f;105s = getParameter("border");106if (s != null) {107border = Integer.parseInt(s);108}109s = getParameter("normalizescale");110if (s != null) {111normalizescaling = s.equalsIgnoreCase("true");112}113addMouseListener(this);114}115116@Override117public void destroy() {118removeMouseListener(this);119}120121@Override122public void run() {123Thread me = Thread.currentThread();124boolean needsRepaint = false;125while (kicker == me && cls.getLevel() < fractLevel) {126cls.generate();127if (kicker == me && incrementalUpdates) {128repaint();129try {130Thread.sleep(repaintDelay);131} catch (InterruptedException ignored) {132}133} else {134needsRepaint = true;135}136}137if (kicker == me) {138kicker = null;139if (needsRepaint) {140repaint();141}142}143}144145@Override146public void start() {147kicker = new Thread(this);148kicker.start();149}150151@Override152public void stop() {153kicker = null;154}155156/*1.1 event handling */157@Override158public void mouseClicked(MouseEvent e) {159}160161@Override162public void mousePressed(MouseEvent e) {163}164165@Override166public void mouseReleased(MouseEvent e) {167cls = new ContextLSystem(this);168savedPath = null;169start();170e.consume();171}172173@Override174public void mouseEntered(MouseEvent e) {175}176177@Override178public void mouseExited(MouseEvent e) {179}180String savedPath;181182@Override183public void paint(Graphics g) {184String fractalPath = cls.getPath();185if (fractalPath == null) {186super.paint(g);187return;188}189if (savedPath == null || !savedPath.equals(fractalPath)) {190savedPath = fractalPath;191render(null, fractalPath);192}193194for (int i = 0; i < border; i++) {195g.draw3DRect(i, i, getSize().width - i * 2, getSize().height - i * 2,196false);197}198render(g, fractalPath);199}200201void render(Graphics g, String path) {202Stack<CLSTurtle> turtleStack = new Stack<CLSTurtle>();203CLSTurtle turtle;204205if (g == null) {206Xmin = 1E20f;207Ymin = 1E20f;208Xmax = -1E20f;209Ymax = -1E20f;210turtle = new CLSTurtle(startAngle, 0, 0, 0, 0, 1, 1);211} else {212float frwidth = Xmax - Xmin;213if (frwidth == 0) {214frwidth = 1;215}216float frheight = Ymax - Ymin;217if (frheight == 0) {218frheight = 1;219}220float xscale = (getSize().width - border * 2 - 1) / frwidth;221float yscale = (getSize().height - border * 2 - 1) / frheight;222int xoff = border;223int yoff = border;224if (normalizescaling) {225if (xscale < yscale) {226yoff += ((getSize().height - border * 2)227- ((Ymax - Ymin) * xscale)) / 2;228yscale = xscale;229} else if (yscale < xscale) {230xoff += ((getSize().width - border * 2)231- ((Xmax - Xmin) * yscale)) / 2;232xscale = yscale;233}234}235turtle = new CLSTurtle(startAngle, 0 - Xmin, 0 - Ymin,236xoff, yoff, xscale, yscale);237}238239for (int pos = 0; pos < path.length(); pos++) {240switch (path.charAt(pos)) {241case '+':242turtle.rotate(rotAngle);243break;244case '-':245turtle.rotate(-rotAngle);246break;247case '[':248turtleStack.push(turtle);249turtle = new CLSTurtle(turtle);250break;251case ']':252turtle = turtleStack.pop();253break;254case 'f':255turtle.jump();256break;257case 'F':258if (g == null) {259includePt(turtle.X, turtle.Y);260turtle.jump();261includePt(turtle.X, turtle.Y);262} else {263turtle.draw(g);264}265break;266default:267break;268}269}270}271272void includePt(float x, float y) {273if (x < Xmin) {274Xmin = x;275}276if (x > Xmax) {277Xmax = x;278}279if (y < Ymin) {280Ymin = y;281}282if (y > Ymax) {283Ymax = y;284}285}286287@Override288public String getAppletInfo() {289return "Title: CLSFractal 1.1f, 27 Mar 1995 \nAuthor: Jim Graham \nA "290+ "(not yet) Context Sensitive L-System production rule. \n"291+ "This class encapsulates a production rule for a Context "292+ "Sensitive\n L-System \n(pred, succ, lContext, rContext)."293+ " The matches() method, however, does not \n(yet) verify "294+ "the lContext and rContext parts of the rule.";295}296297@Override298public String[][] getParameterInfo() {299String[][] info = {300{ "level", "int", "Maximum number of recursions. Default is 1." },301{ "incremental", "boolean", "Whether or not to repaint between "302+ "recursions. Default is true." },303{ "delay", "integer", "Sets delay between repaints. Default is 50." },304{ "startAngle", "float", "Sets the starting angle. Default is 0." },305{ "rotAngle", "float", "Sets the rotation angle. Default is 45." },306{ "border", "integer", "Width of border. Default is 2." },307{ "normalizeScale", "boolean", "Whether or not to normalize "308+ "the scaling. Default is true." },309{ "pred", "String",310"Initializes the rules for Context Sensitive L-Systems." },311{ "succ", "String",312"Initializes the rules for Context Sensitive L-Systems." },313{ "lContext", "String",314"Initializes the rules for Context Sensitive L-Systems." },315{ "rContext", "String",316"Initializes the rules for Context Sensitive L-Systems." }317};318return info;319}320}321322323/**324* A Logo turtle class designed to support Context sensitive L-Systems.325*326* This turtle performs a few basic maneuvers needed to support the327* set of characters used in Context sensitive L-Systems "+-fF[]".328*329* @author Jim Graham330*/331class CLSTurtle {332333float angle;334float X;335float Y;336float scaleX;337float scaleY;338int xoff;339int yoff;340341public CLSTurtle(float ang, float x, float y,342int xorg, int yorg, float sx, float sy) {343angle = ang;344scaleX = sx;345scaleY = sy;346X = x * sx;347Y = y * sy;348xoff = xorg;349yoff = yorg;350}351352public CLSTurtle(CLSTurtle turtle) {353angle = turtle.angle;354X = turtle.X;355Y = turtle.Y;356scaleX = turtle.scaleX;357scaleY = turtle.scaleY;358xoff = turtle.xoff;359yoff = turtle.yoff;360}361362public void rotate(float theta) {363angle += theta;364}365366public void jump() {367X += (float) Math.cos(angle) * scaleX;368Y += (float) Math.sin(angle) * scaleY;369}370371public void draw(Graphics g) {372float x = X + (float) Math.cos(angle) * scaleX;373float y = Y + (float) Math.sin(angle) * scaleY;374g.drawLine((int) X + xoff, (int) Y + yoff,375(int) x + xoff, (int) y + yoff);376X = x;377Y = y;378}379}380381382/**383* A (non-)Context sensitive L-System class.384*385* This class initializes the rules for Context sensitive L-Systems386* (pred, succ, lContext, rContext) from the given java.applet.Applet's attributes.387* The generate() method, however, does not (yet) apply the lContext388* and rContext parts of the rules.389*390* @author Jim Graham391*/392class ContextLSystem {393394String axiom;395List<CLSRule> rules = new ArrayList<CLSRule>();396int level;397398public ContextLSystem(java.applet.Applet app) {399axiom = app.getParameter("axiom");400int num = 1;401while (true) {402String pred = app.getParameter("pred" + num);403String succ = app.getParameter("succ" + num);404if (pred == null || succ == null) {405break;406}407rules.add(new CLSRule(pred, succ,408app.getParameter("lContext" + num),409app.getParameter("rContext" + num)));410num++;411}412currentPath = new StringBuffer(axiom);413level = 0;414}415416public int getLevel() {417return level;418}419StringBuffer currentPath;420421public synchronized String getPath() {422return ((currentPath == null) ? null : currentPath.toString());423}424425private synchronized void setPath(StringBuffer path) {426currentPath = path;427level++;428}429430public void generate() {431StringBuffer newPath = new StringBuffer();432int pos = 0;433while (pos < currentPath.length()) {434CLSRule rule = findRule(pos);435if (rule == null) {436newPath.append(currentPath.charAt(pos));437pos++;438} else {439newPath.append(rule.succ);440pos += rule.pred.length();441}442}443setPath(newPath);444}445446public CLSRule findRule(int pos) {447for (int i = 0; i < rules.size(); i++) {448CLSRule rule = rules.get(i);449if (rule.matches(currentPath, pos)) {450return rule;451}452}453return null;454}455}456457458/**459* A Context sensitive L-System production rule.460*461* This class encapsulates a production rule for a Context sensitive462* L-System (pred, succ, lContext, rContext).463* The matches() method, however, does not (yet) verify the lContext464* and rContext parts of the rule.465*466* @author Jim Graham467*/468class CLSRule {469470String pred;471String succ;472String lContext;473String rContext;474475public CLSRule(String p, String d, String l, String r) {476pred = p;477succ = d;478lContext = l;479rContext = r;480}481482public boolean matches(StringBuffer sb, int pos) {483if (pos + pred.length() > sb.length()) {484return false;485}486char cb[] = new char[pred.length()];487sb.getChars(pos, pos + pred.length(), cb, 0);488return pred.equals(new String(cb));489}490}491492493