Crossfire JXClient, Trunk
CLSFractal.java
Go to the documentation of this file.
1 /*
2  * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * - Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * - Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * - Neither the name of Oracle nor the names of its
16  * contributors may be used to endorse or promote products derived
17  * from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /*
33  * This source code is provided to illustrate the usage of a given feature
34  * or technique and has been deliberately simplified. Additional steps
35  * required for a production-quality application, such as security checks,
36  * input validation and proper error handling, might not be present in
37  * this sample code.
38  */
39 
40 
41 
42 import java.awt.Graphics;
43 import java.util.Stack;
44 import java.awt.event.*;
45 import java.util.ArrayList;
46 import java.util.List;
47 
48 
62 @SuppressWarnings("serial")
63 public class CLSFractal
64  extends java.applet.Applet
65  implements Runnable, MouseListener {
66 
67  Thread kicker;
68  ContextLSystem cls;
69  int fractLevel = 1;
70  int repaintDelay = 50;
71  boolean incrementalUpdates;
72  float startAngle = 0;
73  float rotAngle = 45;
74  float Xmin;
75  float Xmax;
76  float Ymin;
77  float Ymax;
78  int border;
79  boolean normalizescaling;
80 
81  @Override
82  public void init() {
83  String s;
84  cls = new ContextLSystem(this);
85  s = getParameter("level");
86  if (s != null) {
87  fractLevel = Integer.parseInt(s);
88  }
89  s = getParameter("incremental");
90  if (s != null) {
91  incrementalUpdates = s.equalsIgnoreCase("true");
92  }
93  s = getParameter("delay");
94  if (s != null) {
95  repaintDelay = Integer.parseInt(s);
96  }
97  s = getParameter("startAngle");
98  if (s != null) {
99  startAngle = Float.valueOf(s).floatValue();
100  }
101  s = getParameter("rotAngle");
102  if (s != null) {
103  rotAngle = Float.valueOf(s).floatValue();
104  }
105  rotAngle = rotAngle / 360 * 2 * 3.14159265358f;
106  s = getParameter("border");
107  if (s != null) {
108  border = Integer.parseInt(s);
109  }
110  s = getParameter("normalizescale");
111  if (s != null) {
112  normalizescaling = s.equalsIgnoreCase("true");
113  }
114  addMouseListener(this);
115  }
116 
117  @Override
118  public void destroy() {
119  removeMouseListener(this);
120  }
121 
122  @Override
123  public void run() {
124  Thread me = Thread.currentThread();
125  boolean needsRepaint = false;
126  while (kicker == me && cls.getLevel() < fractLevel) {
127  cls.generate();
128  if (kicker == me && incrementalUpdates) {
129  repaint();
130  try {
131  Thread.sleep(repaintDelay);
132  } catch (InterruptedException ignored) {
133  }
134  } else {
135  needsRepaint = true;
136  }
137  }
138  if (kicker == me) {
139  kicker = null;
140  if (needsRepaint) {
141  repaint();
142  }
143  }
144  }
145 
146  @Override
147  public void start() {
148  kicker = new Thread(this);
149  kicker.start();
150  }
151 
152  @Override
153  public void stop() {
154  kicker = null;
155  }
156 
157  /*1.1 event handling */
158  @Override
159  public void mouseClicked(MouseEvent e) {
160  }
161 
162  @Override
163  public void mousePressed(MouseEvent e) {
164  }
165 
166  @Override
167  public void mouseReleased(MouseEvent e) {
168  cls = new ContextLSystem(this);
169  savedPath = null;
170  start();
171  e.consume();
172  }
173 
174  @Override
175  public void mouseEntered(MouseEvent e) {
176  }
177 
178  @Override
179  public void mouseExited(MouseEvent e) {
180  }
181  String savedPath;
182 
183  @Override
184  public void paint(Graphics g) {
185  String fractalPath = cls.getPath();
186  if (fractalPath == null) {
187  super.paint(g);
188  return;
189  }
190  if (savedPath == null || !savedPath.equals(fractalPath)) {
191  savedPath = fractalPath;
192  render(null, fractalPath);
193  }
194 
195  for (int i = 0; i < border; i++) {
196  g.draw3DRect(i, i, getSize().width - i * 2, getSize().height - i * 2,
197  false);
198  }
199  render(g, fractalPath);
200  }
201 
202  void render(Graphics g, String path) {
203  Stack<CLSTurtle> turtleStack = new Stack<CLSTurtle>();
204  CLSTurtle turtle;
205 
206  if (g == null) {
207  Xmin = 1E20f;
208  Ymin = 1E20f;
209  Xmax = -1E20f;
210  Ymax = -1E20f;
211  turtle = new CLSTurtle(startAngle, 0, 0, 0, 0, 1, 1);
212  } else {
213  float frwidth = Xmax - Xmin;
214  if (frwidth == 0) {
215  frwidth = 1;
216  }
217  float frheight = Ymax - Ymin;
218  if (frheight == 0) {
219  frheight = 1;
220  }
221  float xscale = (getSize().width - border * 2 - 1) / frwidth;
222  float yscale = (getSize().height - border * 2 - 1) / frheight;
223  int xoff = border;
224  int yoff = border;
225  if (normalizescaling) {
226  if (xscale < yscale) {
227  yoff += ((getSize().height - border * 2)
228  - ((Ymax - Ymin) * xscale)) / 2;
229  yscale = xscale;
230  } else if (yscale < xscale) {
231  xoff += ((getSize().width - border * 2)
232  - ((Xmax - Xmin) * yscale)) / 2;
233  xscale = yscale;
234  }
235  }
236  turtle = new CLSTurtle(startAngle, 0 - Xmin, 0 - Ymin,
237  xoff, yoff, xscale, yscale);
238  }
239 
240  for (int pos = 0; pos < path.length(); pos++) {
241  switch (path.charAt(pos)) {
242  case '+':
243  turtle.rotate(rotAngle);
244  break;
245  case '-':
246  turtle.rotate(-rotAngle);
247  break;
248  case '[':
249  turtleStack.push(turtle);
250  turtle = new CLSTurtle(turtle);
251  break;
252  case ']':
253  turtle = turtleStack.pop();
254  break;
255  case 'f':
256  turtle.jump();
257  break;
258  case 'F':
259  if (g == null) {
260  includePt(turtle.X, turtle.Y);
261  turtle.jump();
262  includePt(turtle.X, turtle.Y);
263  } else {
264  turtle.draw(g);
265  }
266  break;
267  default:
268  break;
269  }
270  }
271  }
272 
273  void includePt(float x, float y) {
274  if (x < Xmin) {
275  Xmin = x;
276  }
277  if (x > Xmax) {
278  Xmax = x;
279  }
280  if (y < Ymin) {
281  Ymin = y;
282  }
283  if (y > Ymax) {
284  Ymax = y;
285  }
286  }
287 
288  @Override
289  public String getAppletInfo() {
290  return "Title: CLSFractal 1.1f, 27 Mar 1995 \nAuthor: Jim Graham \nA "
291  + "(not yet) Context Sensitive L-System production rule. \n"
292  + "This class encapsulates a production rule for a Context "
293  + "Sensitive\n L-System \n(pred, succ, lContext, rContext)."
294  + " The matches() method, however, does not \n(yet) verify "
295  + "the lContext and rContext parts of the rule.";
296  }
297 
298  @Override
299  public String[][] getParameterInfo() {
300  String[][] info = {
301  { "level", "int", "Maximum number of recursions. Default is 1." },
302  { "incremental", "boolean", "Whether or not to repaint between "
303  + "recursions. Default is true." },
304  { "delay", "integer", "Sets delay between repaints. Default is 50." },
305  { "startAngle", "float", "Sets the starting angle. Default is 0." },
306  { "rotAngle", "float", "Sets the rotation angle. Default is 45." },
307  { "border", "integer", "Width of border. Default is 2." },
308  { "normalizeScale", "boolean", "Whether or not to normalize "
309  + "the scaling. Default is true." },
310  { "pred", "String",
311  "Initializes the rules for Context Sensitive L-Systems." },
312  { "succ", "String",
313  "Initializes the rules for Context Sensitive L-Systems." },
314  { "lContext", "String",
315  "Initializes the rules for Context Sensitive L-Systems." },
316  { "rContext", "String",
317  "Initializes the rules for Context Sensitive L-Systems." }
318  };
319  return info;
320  }
321 }
322 
323 
332 class CLSTurtle {
333 
334  float angle;
335  float X;
336  float Y;
337  float scaleX;
338  float scaleY;
339  int xoff;
340  int yoff;
341 
342  public CLSTurtle(float ang, float x, float y,
343  int xorg, int yorg, float sx, float sy) {
344  angle = ang;
345  scaleX = sx;
346  scaleY = sy;
347  X = x * sx;
348  Y = y * sy;
349  xoff = xorg;
350  yoff = yorg;
351  }
352 
353  public CLSTurtle(CLSTurtle turtle) {
354  angle = turtle.angle;
355  X = turtle.X;
356  Y = turtle.Y;
357  scaleX = turtle.scaleX;
358  scaleY = turtle.scaleY;
359  xoff = turtle.xoff;
360  yoff = turtle.yoff;
361  }
362 
363  public void rotate(float theta) {
364  angle += theta;
365  }
366 
367  public void jump() {
368  X += (float) Math.cos(angle) * scaleX;
369  Y += (float) Math.sin(angle) * scaleY;
370  }
371 
372  public void draw(Graphics g) {
373  float x = X + (float) Math.cos(angle) * scaleX;
374  float y = Y + (float) Math.sin(angle) * scaleY;
375  g.drawLine((int) X + xoff, (int) Y + yoff,
376  (int) x + xoff, (int) y + yoff);
377  X = x;
378  Y = y;
379  }
380 }
381 
382 
393 class ContextLSystem {
394 
395  String axiom;
396  List<CLSRule> rules = new ArrayList<CLSRule>();
397  int level;
398 
399  public ContextLSystem(java.applet.Applet app) {
400  axiom = app.getParameter("axiom");
401  int num = 1;
402  while (true) {
403  String pred = app.getParameter("pred" + num);
404  String succ = app.getParameter("succ" + num);
405  if (pred == null || succ == null) {
406  break;
407  }
408  rules.add(new CLSRule(pred, succ,
409  app.getParameter("lContext" + num),
410  app.getParameter("rContext" + num)));
411  num++;
412  }
413  currentPath = new StringBuffer(axiom);
414  level = 0;
415  }
416 
417  public int getLevel() {
418  return level;
419  }
420  StringBuffer currentPath;
421 
422  public synchronized String getPath() {
423  return ((currentPath == null) ? null : currentPath.toString());
424  }
425 
426  private synchronized void setPath(StringBuffer path) {
427  currentPath = path;
428  level++;
429  }
430 
431  public void generate() {
432  StringBuffer newPath = new StringBuffer();
433  int pos = 0;
434  while (pos < currentPath.length()) {
435  CLSRule rule = findRule(pos);
436  if (rule == null) {
437  newPath.append(currentPath.charAt(pos));
438  pos++;
439  } else {
440  newPath.append(rule.succ);
441  pos += rule.pred.length();
442  }
443  }
444  setPath(newPath);
445  }
446 
447  public CLSRule findRule(int pos) {
448  for (int i = 0; i < rules.size(); i++) {
449  CLSRule rule = rules.get(i);
450  if (rule.matches(currentPath, pos)) {
451  return rule;
452  }
453  }
454  return null;
455  }
456 }
457 
458 
469 class CLSRule {
470 
471  String pred;
472  String succ;
473  String lContext;
474  String rContext;
475 
476  public CLSRule(String p, String d, String l, String r) {
477  pred = p;
478  succ = d;
479  lContext = l;
480  rContext = r;
481  }
482 
483  public boolean matches(StringBuffer sb, int pos) {
484  if (pos + pred.length() > sb.length()) {
485  return false;
486  }
487  char cb[] = new char[pred.length()];
488  sb.getChars(pos, pos + pred.length(), cb, 0);
489  return pred.equals(new String(cb));
490  }
491 }
CLSFractal.getAppletInfo
String getAppletInfo()
Definition: CLSFractal.java:289
CLSFractal
Definition: CLSFractal.java:63
CLSFractal.getParameterInfo
String[][] getParameterInfo()
Definition: CLSFractal.java:299
CLSFractal.mouseClicked
void mouseClicked(MouseEvent e)
Definition: CLSFractal.java:159
CLSFractal.mouseEntered
void mouseEntered(MouseEvent e)
Definition: CLSFractal.java:175
CLSFractal.destroy
void destroy()
Definition: CLSFractal.java:118
CLSFractal.stop
void stop()
Definition: CLSFractal.java:153
CLSFractal.mouseReleased
void mouseReleased(MouseEvent e)
Definition: CLSFractal.java:167
CLSFractal.paint
void paint(Graphics g)
Definition: CLSFractal.java:184
CLSFractal.init
void init()
Definition: CLSFractal.java:82
CLSFractal.mouseExited
void mouseExited(MouseEvent e)
Definition: CLSFractal.java:179
CLSFractal.start
void start()
Definition: CLSFractal.java:147
CLSFractal.mousePressed
void mousePressed(MouseEvent e)
Definition: CLSFractal.java:163
CLSFractal.run
void run()
Definition: CLSFractal.java:123