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