// tree.java import java.applet.Applet; import java.awt.*; import java.awt.event.*; import java.util.Random; public class tree extends Applet implements Runnable { class msL extends MouseAdapter { public void mouseReleased(MouseEvent e) {_mDn = false; } public void mousePressed (MouseEvent e) { _mX = e.getX(); _mY = e.getY(); _mDn = true; } } class mmL extends MouseMotionAdapter { public void mouseMoved (MouseEvent e) {_mX = e.getX(); _mY = e.getY();} public void mouseDragged(MouseEvent e) {_mX = e.getX(); _mY = e.getY();} } class c { public void DBG (String s) {System.out.println (s);} public void clear (int r, int g, int b) // clear parent gfx to rgb and _bm* to rgb*_r1 { tree.this._gfx.setColor (new Color (r, g, b)); tree.this._gfx.fillRect (0, 0, _w, _h); for (_y = 0; _y < _h; _y++) for (_x = 0; _x < _w; _x++) { _bmR[_x][_y] = (short)(_r1 * (double)r); _bmG[_x][_y] = (short)(_r1 * (double)g); _bmB[_x][_y] = (short)(_r1 * (double)b); } } public void fillq (double x1, double y1, double x2, double y2, int r, int g, int b, double q) { if (q > 1D) {fill2 (x1, y1, x2, y2, r, g, b, q); return;} double dx = x2 - x1; double dy = y2 - y1; double h = Math.sqrt (dx * dx + dy * dy); dx /= h; dy /= h; for (int i = 0; (double)i < h; i++, x1 += dx, y1 += dy) dotq (x1, y1, r, g, b, q); } public void fill2 (double x1, double y1, double x2, double y2, int r, int g, int b, double d) { double dx = x2 - x1; double dy = y1 - y2; double h = Math.sqrt (dy * dy + dx * dx); dy /= h; dx /= h; d--; double d1 = -d / 2D; int i1 = (int)(d * _r2); if (i1 < 2) i1 = 2; double d2 = d / (double)i1; for (int i = 0; i <= i1; i++) { double da = d1 + d2 * (double)i; double db = Math.sqrt(d1 * d1 - da * da); do4c ((x1 + dy*da) - dx*db, (y1 + dx*da) + dy*db, (x2 + dy*da) + dx*db, (y2 + dx*da) - dy*db, r, g, b); } } public void do4c (double x1, double y1, double x2, double y2, int r, int g, int b) { double dx = x2 - x1; double dy = y2 - y1; double h = Math.sqrt (dx * dx + dy * dy); dx /= h; dy /= h; for (int i = 0; (double)i < h; i++, x1 += dx, y1 += dy) dot (x1, y1, r, g, b); } public void dot (double x, double y, int r, int g, int b) { if (x <= 0D || x >= (double)(_w - 1) || // clip y <= 0D || y >= (double)(_h - 1)) return; r = (int)((double)r * _r1); g = (int)((double)g * _r1); b = (int)((double)b * _r1); // calc 4 new pixels int ix = (int)x, jx = ix + 1; int iy = (int)y, jy = iy + 1; double fx = (double)jx - x, gx = 1.0D - fx; double fy = (double)jy - y, gy = 1.0D - fy; double fs = fx * fy, gs = 1.0D - fs; _bmR[ix][iy] = (short)(fs * (double)r + gs * (double)_bmR[ix][iy]); _bmG[ix][iy] = (short)(fs * (double)g + gs * (double)_bmG[ix][iy]); _bmB[ix][iy] = (short)(fs * (double)b + gs * (double)_bmB[ix][iy]); fs = gx * fy; gs = 1.0D - fs; _bmR[jx][iy] = (short)(fs * (double)r + gs * (double)_bmR[jx][iy]); _bmG[jx][iy] = (short)(fs * (double)g + gs * (double)_bmG[jx][iy]); _bmB[jx][iy] = (short)(fs * (double)b + gs * (double)_bmB[jx][iy]); fs = fx * gy; gs = 1.0D - fs; _bmR[ix][jy] = (short)(fs * (double)r + gs * (double)_bmR[ix][jy]); _bmG[ix][jy] = (short)(fs * (double)g + gs * (double)_bmG[ix][jy]); _bmB[ix][jy] = (short)(fs * (double)b + gs * (double)_bmB[ix][jy]); fs = gx * gy; gs = 1.0D - fs; _bmR[jx][jy] = (short)(fs * (double)r + gs * (double)_bmR[jx][jy]); _bmG[jx][jy] = (short)(fs * (double)g + gs * (double)_bmG[jx][jy]); _bmB[jx][jy] = (short)(fs * (double)b + gs * (double)_bmB[jx][jy]); // plot the 4 new pixels onto parent gfx tree.this._gfx.setColor (new Color ( (short)(_r3 * (double)_bmR[ix][iy]), (short)(_r3 * (double)_bmG[ix][iy]), (short)(_r3 * (double)_bmB[ix][iy]))); tree.this._gfx.drawLine (ix, iy, ix, iy); tree.this._gfx.setColor (new Color ( (short)(_r3 * (double)_bmR[jx][iy]), (short)(_r3 * (double)_bmG[jx][iy]), (short)(_r3 * (double)_bmB[jx][iy]))); tree.this._gfx.drawLine (jx, iy, jx, iy); tree.this._gfx.setColor (new Color ( (short)(_r3 * (double)_bmR[ix][jy]), (short)(_r3 * (double)_bmG[ix][jy]), (short)(_r3 * (double)_bmB[ix][jy]))); tree.this._gfx.drawLine (ix, jy, ix, jy); tree.this._gfx.setColor (new Color ( (short)(_r3 * (double)_bmR[jx][jy]), (short)(_r3 * (double)_bmG[jx][jy]), (short)(_r3 * (double)_bmB[jx][jy]))); tree.this._gfx.drawLine (jx, jy, jx, jy); } public void dotq (double x, double y, int r, int g, int b, double q) { if (x <= 0D || x >= (double)(_w - 1) || // clip y <= 0D || y >= (double)(_h - 1)) return; r = (int)((double)r * _r1); g = (int)((double)g * _r1); b = (int)((double)b * _r1); // calc 4 new pixels int ix = (int)x, jx = ix + 1; int iy = (int)y, jy = iy + 1; double fx = (double)jx - x, gx = 1.0D - fx; double fy = (double)jy - y, gy = 1.0D - fy; if (fx > 0D) fx = 0.35D + 0.65D*fx; if (gx > 0D) gx = 0.35D + 0.65D*gx; if (fy > 0D) fy = 0.35D + 0.65D*fy; if (gy > 0D) gy = 0.35D + 0.65D*gy; double fs = fx * fy * q, gs = 1.0D - fs; _bmR[ix][iy] = (short)(fs * (double)r + gs * (double)_bmR[ix][iy]); _bmG[ix][iy] = (short)(fs * (double)g + gs * (double)_bmG[ix][iy]); _bmB[ix][iy] = (short)(fs * (double)b + gs * (double)_bmB[ix][iy]); fs = gx * fy * q; gs = 1.0D - fs; _bmR[jx][iy] = (short)(fs * (double)r + gs * (double)_bmR[jx][iy]); _bmG[jx][iy] = (short)(fs * (double)g + gs * (double)_bmG[jx][iy]); _bmB[jx][iy] = (short)(fs * (double)b + gs * (double)_bmB[jx][iy]); fs = fx * gy * q; gs = 1.0D - fs; _bmR[ix][jy] = (short)(fs * (double)r + gs * (double)_bmR[ix][jy]); _bmG[ix][jy] = (short)(fs * (double)g + gs * (double)_bmG[ix][jy]); _bmB[ix][jy] = (short)(fs * (double)b + gs * (double)_bmB[ix][jy]); fs = gx * gy * q; gs = 1.0D - fs; _bmR[jx][jy] = (short)(fs * (double)r + gs * (double)_bmR[jx][jy]); _bmG[jx][jy] = (short)(fs * (double)g + gs * (double)_bmG[jx][jy]); _bmB[jx][jy] = (short)(fs * (double)b + gs * (double)_bmB[jx][jy]); // plot the 4 new pixels onto parent gfx tree.this._gfx.setColor (new Color ( (short)(_r3 * (double)_bmR[ix][iy]), (short)(_r3 * (double)_bmG[ix][iy]), (short)(_r3 * (double)_bmB[ix][iy]))); tree.this._gfx.drawLine (ix, iy, ix, iy); tree.this._gfx.setColor (new Color ( (short)(_r3 * (double)_bmR[jx][iy]), (short)(_r3 * (double)_bmG[jx][iy]), (short)(_r3 * (double)_bmB[jx][iy]))); tree.this._gfx.drawLine (jx, iy, jx, iy); tree.this._gfx.setColor (new Color ( (short)(_r3 * (double)_bmR[ix][jy]), (short)(_r3 * (double)_bmG[ix][jy]), (short)(_r3 * (double)_bmB[ix][jy]))); tree.this._gfx.drawLine (ix, jy, ix, jy); tree.this._gfx.setColor (new Color ( (short)(_r3 * (double)_bmR[jx][jy]), (short)(_r3 * (double)_bmG[jx][jy]), (short)(_r3 * (double)_bmB[jx][jy]))); tree.this._gfx.drawLine (jx, jy, jx, jy); } protected short _bmR [][], _bmG [][], _bmB [][]; protected int _w, _h, _x, _y; double _r1, _r2, _r3; public c (int w, int h) { _r1 = 128.49803921568628D; _r2 = 3.0D; _r3 = 0.007782219916379284D; _w = w; _h = h; _bmR = new short [_w][_h]; _bmG = new short [_w][_h]; _bmB = new short [_w][_h]; } } public void DBG (String s) {System.out.println (s);} public tree () {_on = false; _mDn = false; _mX = 0; _mY = 0; _rp = 0;} public void init () { String s; _w = getWidth (); _h = getHeight (); _lf = getParameter ("leaf"); if (_lf == null) _lf = "y"; _ln = getParameter ("line"); if (_ln == null) _ln = "n"; _cs = getParameter ("colorSky"); if (_cs == null) _cs = "D0E8FF"; _cw = getParameter ("colorWood"); if (_cw == null) _cw = "804820"; _md = ((s = getParameter ("maxDepth" )) == null) ? 100 : Integer.parseInt (s); _mb = ((s = getParameter ("maxBranch" )) == null) ? 2 : Integer.parseInt (s); _lt = ((s = getParameter ("scaleTrunk" )) == null) ? .042 : Integer.parseInt (s) * 0.01; _pb = ((s = getParameter ("probaBranch" )) == null) ? .23 : Integer.parseInt (s) * 0.01; _sb = ((s = getParameter ("scaleBranch" )) == null) ? .90 : Integer.parseInt (s) * 0.01; _ss = ((s = getParameter ("scaleStraight")) == null) ? .95 : Integer.parseInt (s) * 0.01; _sn = ((s = getParameter ("scaleNoise" )) == null) ? .15 : Integer.parseInt (s) * 0.01; _ab = ((s = getParameter ("angleBranch" )) == null) ? 18 : Integer.parseInt (s); _an = ((s = getParameter ("angleNoise" )) == null) ? 5 : Integer.parseInt (s); _ab *= (2D*PI/360D); // degree to radian _an *= (2D*PI/360D); _cwR = Integer.parseInt (_cw.substring (0, 2), 16); // split RGB _cwG = Integer.parseInt (_cw.substring (2, 4), 16); _cwB = Integer.parseInt (_cw.substring (4, 6), 16); _csR = Integer.parseInt (_cs.substring (0, 2), 16); _csG = Integer.parseInt (_cs.substring (2, 4), 16); _csB = Integer.parseInt (_cs.substring (4, 6), 16); _wd = new Color (_cwR, _cwG, _cwB); _img = createImage (_w, _h); _gfx = _img.getGraphics (); _on = true; _c = new c (_w, _h); addMouseListener (new msL()); addMouseMotionListener (new mmL()); repaint (); } public void update (Graphics g) {paint (g);} public void paint (Graphics g) {if (_on) g.drawImage (_img, 0, 0, this);} public void start () { if (_thr == null) {_thr = new Thread (this); _thr.start ();} } public void run () { while (true) { int seed = (int)(1000000D * Math.random ()); _c.clear (_csR, _csG, _csB); _rnd = new Random (seed); part ('b', 1, _w/2, _h-1, -PI/2, _h * _lt); if (! _lf.equals ("n")) { _rnd = new Random (seed); part ('l', 1, _w/2, _h-1, -PI/2, _h * _lt); } while (! _mDn) { repaint (); try {Thread.sleep (50L);} catch (InterruptedException interruptedexception) { } } } } public void part (char bl, int dep, double x1, double y1, double ang, double len) { //DBG("part bl="+bl+" dep="+dep+" x1="+x1+" y1="+y1+" ang="+ang+" len="+len); // done w recursion when len decs to 1 or depth goes too far if ((len <= 1) || (dep > _md)) return; // calc branch end via good ole polar coords double x = x1 + len * Math.cos (ang); double y = y1 + len * Math.sin (ang); // draw branch or leaf? if (bl == 'b') { if (_ln.equals ("n")) { double t = len / 5D; t *= t; _c.fillq (x1, y1, x, y, _cwR, _cwG, _cwB, t); } else { _gfx.setColor (_wd); _gfx.drawLine ((int)x1, (int)y1, (int)x, (int)y); } } else if (len < 3D) { // only do a leaf if we're at len<3 double x2 = x + 10D * Math.random () - 5D; // rand spot a bit +-5 double y2 = y + 10D * Math.random () - 5D; if (_ln.equals ("n")) _c.dotq (x2, y2, (int)( 150D*Math.random ()), // 0,50,0 to (int)(50D + 200D*Math.random ()), // 149,249,149 (int)( 150D*Math.random ()), 0.23D); else { _gfx.setColor (new Color ((int)( 150D*Math.random ()), (int)(50D + 200D*Math.random ()), (int)( 150D*Math.random ()))); _gfx.drawLine ((int)x2, (int)y2, (int)x2, (int)y2); } } // branch out or just continue the limb if (_rnd.nextDouble () < _pb) { int nb = 2 + (int)(_rnd.nextDouble()*(_mb-2)); for (int b = 0; b < nb; b++) part ( bl, dep+1, x, y, (ang - _ab + b*_ab*2/(nb-1)) + _an*(2D*_rnd.nextDouble() - 1D), len * (_sb + _sn*(2D*_rnd.nextDouble() - 1D)) ); } else { part ( bl, dep+1, x, y, ang + _an*(2D*_rnd.nextDouble() - 1D), len * _ss ); } _rp++; if (_rp >= 1000) {_rp = 0; repaint ();} } int _w, _h; Image _img; Graphics _gfx; Thread _thr; boolean _mDn; int _mX, _mY; Random _rnd; boolean _on; c _c; int _rp; String _ln, _lf, _cs, _cw; int _md, _mb, _csR, _csG, _csB, _cwR, _cwG, _cwB; double _lt, _pb, _sb, _ss, _sn, _ab, _an; Color _wd; public static final double PI = 3.1415927; }