Bird Nest
Recreation of a birds nest with eggs inside, draws the nest using parameterized rectangles. Egg curve function from mathcurve.com/courbes2d.gb/oeuf/oeuf.shtml.
Log in to post a comment.
const stick_count = 300; // min = 100 max = 500 step = 1
const radius_min = 50; // min = 10 max = 50 step = 1
const radius_range = 40; // min = 10 max = 50 step = 1
const height_rand = 8;
const height_scale = 0.7;
const width_rand = .4;
const width_scale = 0.02;
const egg_scale = 2.6; // min = 0.5 max = 3 step = 0.1
const egg_randomness = 0.5; // min = 0 max = 2 step = 0.1
const turtle = new Turtle();
class Rectangle {
constructor(h, w, x_center, y_center, rot) {
this.h = h
this.w = w
this.x_center = x_center
this.y_center = y_center
this.rot = rot
this.x1 = x_center + w/2 * Math.cos(rot) - h/2 * Math.sin(rot);
this.y1 = y_center + w/2 * Math.sin(rot) + h/2 * Math.cos(rot);
this.x2 = x_center - w/2 * Math.cos(rot) - h/2 * Math.sin(rot);
this.y2 = y_center - w/2 * Math.sin(rot) + h/2 * Math.cos(rot);
this.x3 = x_center - w/2 * Math.cos(rot) + h/2 * Math.sin(rot);
this.y3 = y_center - w/2 * Math.sin(rot) - h/2 * Math.cos(rot);
this.x4 = x_center + w/2 * Math.cos(rot) + h/2 * Math.sin(rot);
this.y4 = y_center + w/2 * Math.sin(rot) - h/2 * Math.cos(rot);
}
inside(x_pos, y_pos) {
let pal1 = this.point_above_line(this.x1, this.y1, this.x2, this.y2, x_pos, y_pos);
let pal2 = this.point_above_line(this.x2, this.y2, this.x3, this.y3, x_pos, y_pos);
let pal3 = this.point_above_line(this.x3, this.y3, this.x4, this.y4, x_pos, y_pos);
let pal4 = this.point_above_line(this.x4, this.y4, this.x1, this.y1, x_pos, y_pos);
return(((pal1 && !pal3) || (!pal1 && pal3)) && ((pal2 && !pal4) || (!pal2 && pal4)));
}
point_above_line(x1, y1, x2, y2, xp, yp) {
return(yp > (((y2-y1)/(x2-x1)) * (xp - x1) + y1));
}
draw() {
line(this.x1, this.y1, this.x2, this.y2);
line(this.x2, this.y2, this.x3, this.y3);
line(this.x3, this.y3, this.x4, this.y4);
line(this.x4, this.y4, this.x1, this.y1);
}
}
class Circle {
constructor(radius, steps, x_center, y_center) {
this.radius = radius
this.steps = steps
this.x_center = x_center
this.y_center = y_center
}
inside(x_pos, y_pos) {
return(Math.sqrt((x_pos-this.x_center)*(x_pos-this.x_center) + (y_pos-this.y_center)*(y_pos-this.y_center)) <= this.radius)
}
draw() {
let theta = Math.PI * 2 / this.steps;
turtle.penup();
turtle.goto(this.x_center + this.radius * Math.cos(theta * 0), this.y_center + this.radius * Math.sin(theta * 0))
turtle.pendown();
for(let i = 0; i <= this.steps; i++) {
let x = this.x_center + this.radius * Math.cos(theta * i);
let y = this.y_center + this.radius * Math.sin(theta * i);
turtle.goto(x,y);
}
}
}
function line(x1,y1,x2,y2) {
turtle.penup();
turtle.goto(x1, y1);
turtle.pendown();
turtle.goto(x2, y2);
}
function egg(steps, x_center, y_center, a, b, d, theta) {
let t = Math.PI * 2 / steps;
turtle.penup();
for(i = 0; i <= steps; i++) {
if(i == 1) {
turtle.pendown();
}
x = (Math.sqrt(a*a - d*d*Math.sin(t*i)*Math.sin(t*i)) + d*Math.cos(t*i))*Math.cos(t*i);
y = b*Math.sin(t*i);
x_r = x_center + Math.cos(theta)*x - Math.sin(theta)*y;
y_r = y_center + Math.sin(theta)*x + Math.cos(theta)*y;
turtle.goto(x_r,y_r);
}
}
egg_location_list = [];
for(let i = 0; i < 15; i++) {
let pos_radius = Math.random()*radius_min - egg_scale*5;
let pos_angle = Math.random()*Math.PI*2;
let x_center = Math.cos(pos_angle)*pos_radius;
let y_center = Math.sin(pos_angle)*pos_radius;
let rotation = Math.random()*Math.PI*2;
let to_draw = true;
for(let j = 0; j < egg_location_list.length; j++) {
let distance_between_eggs = Math.sqrt(Math.pow(egg_location_list[j][0]-x_center, 2) + Math.pow(egg_location_list[j][1]-y_center, 2));
if(distance_between_eggs < 14*egg_scale) {
to_draw = false;
}
}
if(to_draw) {
egg_location_list.push([x_center, y_center])
let a = 7.5*egg_scale + Math.random()*egg_randomness - egg_randomness;
let b = 5.1*egg_scale + Math.random()*egg_randomness - egg_randomness;
let d = 1.8*egg_scale + Math.random()*egg_randomness - egg_randomness;
egg(50, x_center, y_center, a, b, d, rotation);
}
}
for(let i = 0; i < stick_count; i++) {
let pos_radius = Math.random()*radius_range+radius_min;
let pos_angle = Math.random()*Math.PI*2;
let x_center = Math.cos(pos_angle)*pos_radius;
let y_center = Math.sin(pos_angle)*pos_radius;
let height = Math.random()*height_rand+pos_radius*height_scale;
let width = Math.random()*width_rand+pos_radius*width_scale;
let rotation = Math.atan(y_center/x_center) + Math.random()*0.1 - 0.05;
let rect1 = new Rectangle(height, width, x_center, y_center, rotation);
rect1.draw();
}