xxxxxxxxxx
95
class Spirograph {
constructor(R, r, d) {
this.R = int(random(25,200)); // this is the Radius of the conventionally bigger and outer circle (but this can ofc change depending on the random values or of vector addition / subtraction)
this.r = int(random(25,100)); // this is the radius of the conventionally smaller and inner circle
this.d = int(random(5,150)); // d is the distance of the point in the inner/smaller circle --> this is what is drawing the design
this.angle = 0; // to keep updating the design / generating the pattern each frame
// current position
this.x = 0;
this.y = 0;
// calculate appropriate values needed
this.choice = int(random(N));
this.calculate();
this.style = int(random(2));
// to store previous positon
this.prevX = this.y;
this.prevY = this.x;
}
calculate() {
// print(this.choice);
// various deign choices / parameters
// each equation is a slightly modified version of the base spirograph formula as in the blog post
// could'nt find a more generative way of applying sin or cosine functions randomly as we were discussing in the previous class so this is the next best alternative I found
// within each equation too, the pattern is not fixed but generative, depending on the values of R, r and d
if (this.choice == 0) {
this.x = (this.R+this.r)*(cos(this.angle)*2)-this.d*tan((this.R+this.r)/this.r*this.angle/2);
this.y = (this.R-this.r*2)*(tan(this.angle))-this.d*cos((this.R-this.r)/this.r*this.angle);
}
if (this.choice == 1) {
this.x = (this.r+this.r)*(sin(this.angle))-this.d*0.41*tan((this.R-this.r)/this.r*this.angle*2);
this.y = (this.R-this.r)*tan(sin(this.angle*1.8))+this.d*0.57*tan((this.R+this.r)/this.r*this.angle);
}
if (this.choice == 2) {
this.x = (this.r+this.r)*(tan(this.angle))-this.d*0.41*tan((this.R-this.r)/this.r*this.angle*2);
this.y = (this.R-this.r)*tan(sin(this.angle*1.8))+this.d*0.57*cos((this.R+this.r)/this.r*this.angle);
}
if (this.choice == 3) {
this.x = (this.R+this.r)*(cos(this.angle))-this.d*cos((this.R+this.r)/this.r*this.angle);
this.y = (this.R+this.r)*(sin(this.angle))-this.d*sin((this.R+this.r)/this.r*this.angle);
}
if (this.choice == 4) {
this.x = (this.R-this.r)*(cos(this.angle)*2)-this.d*sin((this.R-this.r)/this.r*this.angle);
this.y = (this.R-this.r*2)*(cos(this.angle))+this.d*sin((this.R-this.r)/this.r*this.angle);
}
if (this.choice == 5) {
this.x = (this.R+this.r)*(cos(this.angle)*2)-this.d*tan((this.R-this.r)/this.r*this.angle/2);
this.y = (this.R-this.r*2)*(cos(this.angle))+this.d*tan((this.R-this.r)/this.r*this.angle);
}
}
draw() {
this.calculate(); // calculate the correct values needed to plot the design based on choice
// choose whether to draw lines or dots:
if (this.style == 0) {
//draw conventional dots
stroke(0);
point(this.x, this.y);
}
else { // draw lines
// modification for the pen plotter design
// this is so that I am not drawing lines across the screen whenver the points takes a large jump. this ruined the aesthetics / design of the pattern so added a constraint for the plotter
if (dist(this.x, this.y, this.prevX, this.prevY) > width/4) {
this.prevX = this.x; // do not draw from previous very far away point, but start a new line here
this.prevY = this.y; // draw from same position, previous reset to current
}
// draw the line
stroke(0,50);
line(this.x, this.y, this.prevX, this.prevY);
}
// update values each frame
this.prevX = this.x;
this.prevY = this.y;
this.angle += 0.02;
}
regenerate() {
background(255); // clear the screen
this.choice = int(random(N)); // choose values again
this.style = int(random(2));
}
}