KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > CLSFractal


1 /*
2  * @(#)CLSFractal.java 1.14 06/02/22
3  *
4  * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * -Redistribution of source code must retain the above copyright notice, this
10  * list of conditions and the following disclaimer.
11  *
12  * -Redistribution in binary form must reproduce the above copyright notice,
13  * this list of conditions and the following disclaimer in the documentation
14  * and/or other materials provided with the distribution.
15  *
16  * Neither the name of Sun Microsystems, Inc. or the names of contributors may
17  * be used to endorse or promote products derived from this software without
18  * specific prior written permission.
19  *
20  * This software is provided "AS IS," without a warranty of any kind. ALL
21  * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
22  * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
23  * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN")
24  * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
25  * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
26  * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
27  * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
28  * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
29  * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
30  * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31  *
32  * You acknowledge that this software is not designed, licensed or intended
33  * for use in the design, construction, operation or maintenance of any
34  * nuclear facility.
35  */

36
37 /*
38  * @(#)CLSFractal.java 1.14 06/02/22
39  */

40
41 import java.awt.Graphics JavaDoc;
42 import java.util.Stack JavaDoc;
43 import java.util.Vector JavaDoc;
44 import java.awt.event.*;
45
46 /**
47  * A (not-yet) Context sensitive L-System Fractal applet class.
48  *
49  * The rules for the Context L-system are read from the java.applet.Applet's
50  * attributes and then the system is iteratively applied for the
51  * given number of levels, possibly drawing each generation as it
52  * is generated. Note that the ContextLSystem class does not yet
53  * handle the lContext and rContext attributes, although this
54  * class is already designed to parse the '[' and ']' characters
55  * typically used in Context sensitive L-Systems.
56  *
57  * @author Jim Graham
58  * @version 1.1f, 27 Mar 1995
59  */

60 public class CLSFractal
61     extends java.applet.Applet JavaDoc
62     implements Runnable JavaDoc, MouseListener {
63     Thread JavaDoc kicker;
64     ContextLSystem cls;
65     int fractLevel = 1;
66     int repaintDelay = 50;
67     boolean incrementalUpdates;
68     float startAngle = 0;
69     float rotAngle = 45;
70     float Xmin;
71     float Xmax;
72     float Ymin;
73     float Ymax;
74     int border;
75     boolean normalizescaling;
76
77     public void init() {
78     String JavaDoc s;
79     cls = new ContextLSystem(this);
80     s = getParameter("level");
81     if (s != null) fractLevel = Integer.parseInt(s);
82     s = getParameter("incremental");
83     if (s != null) incrementalUpdates = s.equalsIgnoreCase("true");
84     s = getParameter("delay");
85     if (s != null) repaintDelay = Integer.parseInt(s);
86     s = getParameter("startAngle");
87     if (s != null) startAngle = Float.valueOf(s).floatValue();
88     s = getParameter("rotAngle");
89     if (s != null) rotAngle = Float.valueOf(s).floatValue();
90     rotAngle = rotAngle / 360 * 2 * 3.14159265358f;
91     s = getParameter("border");
92     if (s != null) border = Integer.parseInt(s);
93     s = getParameter("normalizescale");
94     if (s != null) normalizescaling = s.equalsIgnoreCase("true");
95     addMouseListener(this);
96     }
97
98     public void destroy() {
99         removeMouseListener(this);
100     }
101
102     public void run() {
103     Thread JavaDoc me = Thread.currentThread();
104     boolean needsRepaint = false;
105     while (kicker == me && cls.getLevel() < fractLevel) {
106         cls.generate();
107         if (kicker == me && incrementalUpdates) {
108         repaint();
109         try {Thread.sleep(repaintDelay);} catch (InterruptedException JavaDoc e){}
110         } else {
111         needsRepaint = true;
112         }
113     }
114     if (kicker == me) {
115         kicker = null;
116         if (needsRepaint) {
117         repaint();
118         }
119     }
120     }
121
122     public void start() {
123     kicker = new Thread JavaDoc(this);
124     kicker.start();
125     }
126
127     public void stop() {
128     kicker = null;
129     }
130
131       /*1.1 event handling */
132     public void mouseClicked(MouseEvent e) {
133     }
134
135     public void mousePressed(MouseEvent e) {
136     }
137
138     public void mouseReleased(MouseEvent e) {
139         cls = new ContextLSystem(this);
140         savedPath = null;
141         start();
142         e.consume();
143     }
144
145     public void mouseEntered(MouseEvent e) {
146     }
147
148     public void mouseExited(MouseEvent e) {
149     }
150
151     String JavaDoc savedPath;
152
153     public void paint(Graphics JavaDoc g) {
154     String JavaDoc fractalPath = cls.getPath();
155     if (fractalPath == null) {
156         super.paint(g);
157         return;
158     }
159     if (savedPath == null || !savedPath.equals(fractalPath)) {
160         savedPath = fractalPath;
161         render(null, fractalPath);
162     }
163
164     for (int i = 0; i < border; i++) {
165         g.draw3DRect(i, i, getSize().width - i * 2, getSize().height - i * 2,false);
166     }
167     render(g, fractalPath);
168     }
169
170     void render(Graphics JavaDoc g, String JavaDoc path) {
171     Stack JavaDoc turtleStack = new Stack JavaDoc();
172     CLSTurtle turtle;
173
174     if (g == null) {
175         Xmin = 1E20f;
176         Ymin = 1E20f;
177         Xmax = -1E20f;
178         Ymax = -1E20f;
179         turtle = new CLSTurtle(startAngle, 0, 0, 0, 0, 1, 1);
180     } else {
181         float frwidth = Xmax - Xmin;
182         if (frwidth == 0)
183         frwidth = 1;
184         float frheight = Ymax - Ymin;
185         if (frheight == 0)
186         frheight = 1;
187         float xscale = (getSize().width - border * 2 - 1) / frwidth;
188         float yscale = (getSize().height - border * 2 - 1) / frheight;
189         int xoff = border;
190         int yoff = border;
191         if (normalizescaling) {
192         if (xscale < yscale) {
193             yoff += ((getSize().height - border * 2)
194                  - ((Ymax - Ymin) * xscale)) / 2;
195             yscale = xscale;
196         } else if (yscale < xscale) {
197             xoff += ((getSize().width - border * 2)
198                  - ((Xmax - Xmin) * yscale)) / 2;
199             xscale = yscale;
200         }
201         }
202         turtle = new CLSTurtle(startAngle, 0 - Xmin, 0 - Ymin,
203                    xoff, yoff, xscale, yscale);
204     }
205
206     for (int pos = 0; pos < path.length(); pos++) {
207         switch (path.charAt(pos)) {
208         case '+':
209         turtle.rotate(rotAngle);
210         break;
211         case '-':
212         turtle.rotate(-rotAngle);
213         break;
214         case '[':
215         turtleStack.push(turtle);
216         turtle = new CLSTurtle(turtle);
217         break;
218         case ']':
219         turtle = (CLSTurtle) turtleStack.pop();
220         break;
221         case 'f':
222         turtle.jump();
223         break;
224         case 'F':
225         if (g == null) {
226             includePt(turtle.X, turtle.Y);
227             turtle.jump();
228             includePt(turtle.X, turtle.Y);
229         } else {
230             turtle.draw(g);
231         }
232         break;
233         default:
234         break;
235         }
236     }
237     }
238
239     void includePt(float x, float y) {
240     if (x < Xmin)
241         Xmin = x;
242     if (x > Xmax)
243         Xmax = x;
244     if (y < Ymin)
245         Ymin = y;
246     if (y > Ymax)
247         Ymax = y;
248     }
249
250   public String JavaDoc getAppletInfo() {
251     return "Title: CLSFractal 1.1f, 27 Mar 1995 \nAuthor: Jim Graham \nA (not yet) Context Sensitive L-System production rule. \nThis class encapsulates a production rule for a Context Sensitive\n L-System \n(pred, succ, lContext, rContext). The matches() method, however, does not \n(yet) verify the lContext and rContext parts of the rule.";
252   }
253
254   public String JavaDoc[][] getParameterInfo() {
255     String JavaDoc[][] info = {
256       {"level", "int", "Maximum number of recursions. Default is 1."},
257       {"incremental","boolean","Whether or not to repaint between recursions. Default is true."},
258       {"delay","integer","Sets delay between repaints. Default is 50."},
259       {"startAngle","float","Sets the starting angle. Default is 0."},
260       {"rotAngle","float","Sets the rotation angle. Default is 45."},
261       {"border","integer","Width of border. Default is 2."},
262       {"normalizeScale","boolean","Whether or not to normalize the scaling. Default is true."},
263       {"pred","String","Initializes the rules for Context Sensitive L-Systems."},
264       {"succ","String","Initializes the rules for Context Sensitive L-Systems."},
265       {"lContext","String","Initializes the rules for Context Sensitive L-Systems."},
266       {"rContext","String","Initializes the rules for Context Sensitive L-Systems."}
267     };
268     return info;
269   }
270 }
271
272 /**
273  * A Logo turtle class designed to support Context sensitive L-Systems.
274  *
275  * This turtle performs a few basic maneuvers needed to support the
276  * set of characters used in Context sensitive L-Systems "+-fF[]".
277  *
278  * @author Jim Graham
279  * @version 1.1f, 27 Mar 1995
280  */

281 class CLSTurtle {
282     float angle;
283     float X;
284     float Y;
285     float scaleX;
286     float scaleY;
287     int xoff;
288     int yoff;
289
290     public CLSTurtle(float ang, float x, float y,
291              int xorg, int yorg, float sx, float sy) {
292     angle = ang;
293     scaleX = sx;
294     scaleY = sy;
295     X = x * sx;
296     Y = y * sy;
297     xoff = xorg;
298     yoff = yorg;
299     }
300
301     public CLSTurtle(CLSTurtle turtle) {
302     angle = turtle.angle;
303     X = turtle.X;
304     Y = turtle.Y;
305     scaleX = turtle.scaleX;
306     scaleY = turtle.scaleY;
307     xoff = turtle.xoff;
308     yoff = turtle.yoff;
309     }
310
311     public void rotate(float theta) {
312     angle += theta;
313     }
314
315     public void jump() {
316     X += (float) Math.cos(angle) * scaleX;
317     Y += (float) Math.sin(angle) * scaleY;
318     }
319
320     public void draw(Graphics JavaDoc g) {
321     float x = X + (float) Math.cos(angle) * scaleX;
322     float y = Y + (float) Math.sin(angle) * scaleY;
323     g.drawLine((int) X + xoff, (int) Y + yoff,
324            (int) x + xoff, (int) y + yoff);
325     X = x;
326     Y = y;
327     }
328 }
329
330 /**
331  * A (non-)Context sensitive L-System class.
332  *
333  * This class initializes the rules for Context sensitive L-Systems
334  * (pred, succ, lContext, rContext) from the given java.applet.Applet's attributes.
335  * The generate() method, however, does not (yet) apply the lContext
336  * and rContext parts of the rules.
337  *
338  * @author Jim Graham
339  * @version 1.1f, 27 Mar 1995
340  */

341 class ContextLSystem {
342     String JavaDoc axiom;
343     Vector JavaDoc rules = new Vector JavaDoc();
344     int level;
345
346     public ContextLSystem(java.applet.Applet JavaDoc app) {
347     axiom = app.getParameter("axiom");
348     int num = 1;
349     while (true) {
350         String JavaDoc pred = app.getParameter("pred"+num);
351         String JavaDoc succ = app.getParameter("succ"+num);
352         if (pred == null || succ == null) {
353         break;
354         }
355         rules.addElement(new CLSRule(pred, succ,
356                      app.getParameter("lContext"+num),
357                      app.getParameter("rContext"+num)));
358         num++;
359     }
360     currentPath = new StringBuffer JavaDoc(axiom);
361     level = 0;
362     }
363
364     public int getLevel() {
365     return level;
366     }
367
368     StringBuffer JavaDoc currentPath;
369
370     public synchronized String JavaDoc getPath() {
371     return ((currentPath == null) ? null : currentPath.toString());
372     }
373
374     private synchronized void setPath(StringBuffer JavaDoc path) {
375     currentPath = path;
376     level++;
377     }
378
379     public void generate() {
380     StringBuffer JavaDoc newPath = new StringBuffer JavaDoc();
381     int pos = 0;
382     while (pos < currentPath.length()) {
383         CLSRule rule = findRule(pos);
384         if (rule == null) {
385         newPath.append(currentPath.charAt(pos));
386         pos++;
387         } else {
388         newPath.append(rule.succ);
389         pos += rule.pred.length();
390         }
391     }
392     setPath(newPath);
393     }
394
395     public CLSRule findRule(int pos) {
396     for (int i = 0; i < rules.size(); i++) {
397         CLSRule rule = (CLSRule) rules.elementAt(i);
398         if (rule.matches(currentPath, pos)) {
399         return rule;
400         }
401     }
402     return null;
403     }
404 }
405
406 /**
407  * A Context sensitive L-System production rule.
408  *
409  * This class encapsulates a production rule for a Context sensitive
410  * L-System (pred, succ, lContext, rContext).
411  * The matches() method, however, does not (yet) verify the lContext
412  * and rContext parts of the rule.
413  *
414  * @author Jim Graham
415  * @version 1.1f, 27 Mar 1995
416  */

417 class CLSRule {
418     String JavaDoc pred;
419     String JavaDoc succ;
420     String JavaDoc lContext;
421     String JavaDoc rContext;
422
423     public CLSRule(String JavaDoc p, String JavaDoc d, String JavaDoc l, String JavaDoc r) {
424     pred = p;
425     succ = d;
426     lContext = l;
427     rContext = r;
428     }
429
430     public boolean matches(StringBuffer JavaDoc sb, int pos) {
431     if (pos + pred.length() > sb.length()) {
432         return false;
433     }
434     char cb[] = new char[pred.length()];
435     sb.getChars(pos, pos + pred.length(), cb, 0);
436     return pred.equals(new String JavaDoc(cb));
437     }
438 }
439
Popular Tags