Blame tree.c

e5cc64
e5cc64
#include <stdlib.h></stdlib.h>
e5cc64
#include <math.h></math.h>
e5cc64
#include <helianthus.h></helianthus.h>
e5cc64
e5cc64
e5cc64
e5cc64
e5cc64
int seed;
e5cc64
double t;
e5cc64
e5cc64
const double segmentLength = 5;
e5cc64
const double segmentWidth = 0.05;
e5cc64
const double minWidth = 0.5;
e5cc64
const double branchesPerSegment = 0.2;
e5cc64
const double leafSize = 200;
e5cc64
const double leafPerBranch = 1;
e5cc64
const double leafThreshold = 1 + 200/5*0.05/4*0.5;
e5cc64
e5cc64
e5cc64
double randomRange(double min, double max)
e5cc64
  { return randomFloat()*(max - min) + min; }
e5cc64
e5cc64
double randomIncrement(double deviation)
e5cc64
  { return randomRange(-deviation, deviation); }
e5cc64
e5cc64
double randomAmplifier(double deviation)
e5cc64
  { return randomRange(1 - deviation, 1 + deviation); }
e5cc64
e5cc64
e5cc64
void leaf(double x, double y, double size) {
e5cc64
  double r = 0.5*size;//*randomAmplifier(0.5);
e5cc64
  saveState();
e5cc64
  noStroke();
e5cc64
  circle(x, y, r);
e5cc64
  restoreState();
e5cc64
}
e5cc64
e5cc64
e5cc64
void branch(double x, double y, double angle, double width) {
e5cc64
  double da = sin(t*randomRange(0.5, 1) + randomIncrement(PI));
e5cc64
e5cc64
  saveState();
e5cc64
  while(TRUE) {
e5cc64
    double length = segmentLength * randomAmplifier(0.1);
e5cc64
e5cc64
    double s = sin(angle/180*PI);
e5cc64
    double c = cos(angle/180*PI);
e5cc64
    double nx = x + c*length;
e5cc64
    double ny = y + s*length;
e5cc64
    double nw = width - segmentWidth;
e5cc64
    strokeWidth(width);
e5cc64
    line(x, y, nx, ny);
e5cc64
e5cc64
    if (width > leafThreshold && nw <= leafThreshold && randomFloat() < leafPerBranch && y > leafSize/2) {
e5cc64
      double dl = randomRange(0, length);
e5cc64
      leaf(x + c*dl, y + s*dl, leafSize);
e5cc64
    }
e5cc64
e5cc64
    if (width < minWidth || ny < 0)
e5cc64
      break;
e5cc64
e5cc64
    x = nx;
e5cc64
    y = ny;
e5cc64
    s += randomRange(0, 0.2);
e5cc64
    c += randomIncrement(0.15);
e5cc64
    angle = atan2(s, c)/PI*180;
e5cc64
    width -= segmentWidth;
e5cc64
e5cc64
    translate(x, y);
e5cc64
    rotate(da*pow(minWidth/width, 2));
e5cc64
    translate(-x, -y);
e5cc64
e5cc64
    if (randomFloat() < branchesPerSegment) {
e5cc64
      double k = randomRange(0.1, 0.3);
e5cc64
      double w = sqrt(width*width*k);
e5cc64
      if (w > minWidth) {
e5cc64
        width = sqrt(width*width*(1-k));
e5cc64
        double a = randomNumber(0, 1) ? angle - 90 + randomRange(0, 45)
e5cc64
                                      : angle + 90 - randomRange(0, 45);
e5cc64
        branch(x, y, a, w);
e5cc64
      }
e5cc64
    }
e5cc64
  }
e5cc64
  restoreState();
e5cc64
}
e5cc64
e5cc64
e5cc64
void tree(int seed, double x, double y, double width) {
e5cc64
  srand(seed);
e5cc64
  double angle = 90 + randomIncrement(30);
e5cc64
  width *= randomAmplifier(0.5);
e5cc64
  int s = randomNumber(0, 1000000);
e5cc64
e5cc64
  saveState();
e5cc64
  noStroke();
e5cc64
  srand(s);
e5cc64
  branch(x, y, angle, width);
e5cc64
  restoreState();
e5cc64
e5cc64
  saveState();
e5cc64
  noFill();
e5cc64
  srand(s);
e5cc64
  branch(x, y, angle, width);
e5cc64
  restoreState();
e5cc64
}
e5cc64
e5cc64
e5cc64
void init() {
e5cc64
  seed = randomNumber(0, 1000000);
e5cc64
}
e5cc64
e5cc64
e5cc64
void draw() {
ef1455
  double w = windowGetWidth();
ef1455
  double h = windowGetHeight();
ef1455
  t += windowGetFrameTime();
e5cc64
e5cc64
  if (keyWentDown("space")) seed = randomNumber(0, 1000000);
e5cc64
e5cc64
  saveState();
e5cc64
  translate(w/2, h*0.9);
e5cc64
  scale(1, -1);
e5cc64
e5cc64
  fill(colorByName("green"));
e5cc64
  stroke(colorByName("black"));
e5cc64
  tree(seed, 0, 0, 20);
e5cc64
e5cc64
  restoreState();
e5cc64
}
e5cc64
e5cc64
e5cc64
int main() {
ef1455
  windowSetVariableFrameRate();
ef1455
  windowSetResizable(TRUE);
ef1455
  windowSetInit(&init);
ef1455
  windowSetDraw(&draw);
ef1455
  windowRun();
e5cc64
}