Penrose Tile
penrose-tile.pde
/**
* Penrose Tile L-System
* by Geraldine Sarmiento.
*
* This example was based on Patrick Dwyer's L-System class.
*/
struct LSystem {
int steps = 0;
std::string axiom;
std::string rule;
std::string production;
float startLength;
float drawLength;
float theta;
int generations = 0;
LSystem() {
axiom = "F";
rule = "F+F-F";
startLength = 190.0;
theta = radians(120.0);
reset();
}
void reset() {
production = axiom;
drawLength = startLength;
generations = 0;
}
int getAge() {
return generations;
}
void render() {
translate(width / 2, height / 2);
steps += 5;
if (steps > (int)production.length()) {
steps = production.length();
}
for (int i = 0; i < steps; i++) {
char step = production[i];
if (step == 'F') {
rect(0, 0, -drawLength, -drawLength);
noFill();
translate(0, -drawLength);
} else if (step == '+') {
rotate(theta);
} else if (step == '-') {
rotate(-theta);
} else if (step == '[') {
pushMatrix();
} else if (step == ']') {
popMatrix();
}
}
}
void simulate(int gen) {
while (getAge() < gen) {
production = iterate(production, rule);
}
}
virtual std::string iterate(std::string prod_, std::string rule_) {
drawLength = drawLength * 0.6;
generations++;
std::string result = "";
for (char c : prod_) {
if (c == 'F') result += rule_;
else result += c;
}
return result;
}
virtual ~LSystem() {}
};
struct PenroseLSystem : public LSystem {
int steps = 0;
float somestep = 0.1;
std::string ruleW;
std::string ruleX;
std::string ruleY;
std::string ruleZ;
PenroseLSystem() {
axiom = "[X]++[X]++[X]++[X]++[X]";
ruleW = "YF++ZF4-XF[-YF4-WF]++";
ruleX = "+YF--ZF[3-WF--XF]+";
ruleY = "-WF++XF[+++YF++ZF]-";
ruleZ = "--YF++++WF[+ZF++++XF]--XF";
startLength = 460.0;
theta = radians(36);
reset();
}
void useRule(std::string r_) { rule = r_; }
void useAxiom(std::string a_) { axiom = a_; }
void useLength(float l_) { startLength = l_; }
void useTheta(float t_) { theta = radians(t_); }
void reset() {
production = axiom;
drawLength = startLength;
generations = 0;
}
int getAge() { return generations; }
void render() {
translate(width / 2, height / 2);
int pushes = 0;
int repeats = 1;
steps += 12;
if (steps > (int)production.length()) {
steps = production.length();
}
for (int i = 0; i < steps; i++) {
char step = production[i];
if (step == 'F') {
stroke(255, 60);
for (int j = 0; j < repeats; j++) {
line(0, 0, 0, -drawLength);
noFill();
translate(0, -drawLength);
}
repeats = 1;
} else if (step == '+') {
for (int j = 0; j < repeats; j++) { rotate(theta); }
repeats = 1;
} else if (step == '-') {
for (int j = 0; j < repeats; j++) { rotate(-theta); }
repeats = 1;
} else if (step == '[') {
pushes++;
pushMatrix();
} else if (step == ']') {
popMatrix();
pushes--;
} else if (step >= 48 && step <= 57) {
repeats = (int)step - 48;
}
}
while (pushes > 0) { popMatrix(); pushes--; }
}
std::string iterate(std::string prod_, std::string rule_) override {
std::string newProduction = "";
for (int i = 0; i < (int)prod_.size(); i++) {
char step = prod_[i];
if (step == 'W') newProduction += ruleW;
else if (step == 'X') newProduction += ruleX;
else if (step == 'Y') newProduction += ruleY;
else if (step == 'Z') newProduction += ruleZ;
else if (step != 'F') newProduction += step;
}
drawLength = drawLength * 0.5;
generations++;
return newProduction;
}
};
PenroseLSystem ds;
void setup() {
size(640, 360);
ds = PenroseLSystem();
ds.simulate(4);
}
void draw() {
background(0);
ds.render();
}