xxxxxxxxxx
168
let turtle
let commands = []
let theta = 0
let points = []
let index = 0
let speed = 5
let transVec;
let scl = 2
let order
const mouse = () => createVector(mouseX, mouseY)
const pmouse = () => createVector(pmouseX, pmouseY)
const vecLine = (a, b) => {
line(a.x, a.y, b.x, b.y);
}
class LSystem {
constructor(axiom, rules, order, size, angle) {
this.axiom = axiom
this.rules = rules
this.order = order;
this.angle = angle
this.size = size
this.turtle = new Turtle(0, 0, 0)
this.generate()
this.index = 0
this.speed = 150
}
generate() {
let sentence = this.axiom
for (let i = 0; i < this.order; i++) {
let nextSentence = ""
for (const current of sentence) {
let found = false
for (const index in this.rules) {
if (current == index) {
nextSentence += this.rules[index]
found = true
break;
}
}
if (!found) {
nextSentence += current
}
}
sentence = nextSentence
}
sentence += "F"
for (const op of sentence) {
if (op == "F") this.turtle.forward(this.size)
else if (op == "+") this.turtle.right(this.angle)
else if (op == "-") this.turtle.left(this.angle)
}
}
show() {
for (let i = 1; i < this.turtle.points.length; i++) {
let a = this.turtle.points[i - 1]
let b = this.turtle.points[i]
const hu = 360 * (i / this.turtle.points.length)
stroke(hu % 360, 100, 100);
vecLine(a, b);
}
}
animate(){
for (let i = 1; i < this.index; i++) {
let a = this.turtle.points[i - 1]
let b = this.turtle.points[i]
const hu = 360 * (i / this.index)
stroke(hu % 360, 100, 100);
vecLine(a, b);
}
this.index += min(this.speed, this.turtle.points.length-this.index)
}
}
let systems = [];
function setup() {
createCanvas(800, 700).parent("canvas-content")
colorMode(HSB, 360, 100, 100);
background(0);
// gosper curve
systems.push(new LSystem(
"A", {
A: 'A+BF++BF-FA--FAFA-BF+',
B: '-FA+BFBF++BF+FA--FA-B'
}, 5, 2, 60))
// dragon curve
systems.push(new LSystem(
"FX",
{
X: "X+YF+",
Y: "-FX-Y"
}, 13, 2, 90))
// hilbert curve
systems.push(new LSystem(
"A",
{
A: '-BF+AFA+FB-',
B: '+AF-BFB-FA+'
}, 7, 2, 90))
transVec = createVector();
}
////////////////////////////////////////////////////////////////////////
// DRAW
////////////////////////////////////////////////////////////////////////
function keyPressed(){
index = (index + 1)%systems.length
}
function draw() {
translate(width / 2, height / 2);
translate(transVec.x, transVec.y);
scale(scl);
strokeWeight(.5);
background(0);
systems[index].show();
// animateCurve()
}
function mouseWheel(event) {
var e = Math.sign(-event.delta);
scl += 0.1 * e
scl = max(scl, .1)
}
function mouseDragged() {
if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) {
const dif = p5.Vector.sub(pmouse(), mouse());
transVec.add(dif.mult(-1));
}
}
function gosper_curve(order, size, is_A = true) {
const gosper_op_map = {
"-": () => turtle.right(60),
"+": () => turtle.left(60),
}
if (order == 0) {
turtle.forward(size)
return
}
const opString = is_A ? "A-B--B+A++AA+B-" : "+A-BB--B-A++A+B"
for (const op of opString) {
if (op == "A") gosper_curve(order - 1, size, true)
else if (op == "B") gosper_curve(order - 1, size, false)
else {
gosper_op_map[op]()
}
}
}