Public
Edited
Mar 14, 2024
Insert cell
Insert cell
p5(s => {
class Triangle{
constructor(x1, y1, x2, y2, x3, y3, level){
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.x3 = x3;
this.y3 = y3;
this.level = level;
this.divided = false;
}

// return [longestEdgeVertex1X, longestEdgeVertex1Y, longestEdgeVertex2X, longestEdgeVertex2Y, oppositeVertexX, oppositeVertexY]
getLongest(){
let d12 = (this.x1 - this.x2) * (this.x1 - this.x2) + (this.y1 - this.y2) * (this.y1 - this.y2);
let d23 = (this.x3 - this.x2) * (this.x3 - this.x2) + (this.y3 - this.y2) * (this.y3 - this.y2);
let d13 = (this.x1 - this.x3) * (this.x1 - this.x3) + (this.y1 - this.y3) * (this.y1 - this.y3);
if (d12 > d23 && d12 > d13) {
return [this.x1, this.y1, this.x2, this.y2, this.x3, this.y3];
} else if (d23 > d13) {
return [this.x2, this.y2, this.x3, this.y3, this.x1, this.y1];
} else {
return [this.x1, this.y1, this.x3, this.y3, this.x2, this.y2];
}
}

divide(){
this.divided = true;
let longestEdge = this.getLongest();
let unchanged = [];
//divide the triangle with the middle point of the longest edge
let newX = (longestEdge[0] + longestEdge[2]) / 2;
let newY = (longestEdge[1] + longestEdge[3]) / 2;
return [new Triangle(longestEdge[0],longestEdge[1], newX, newY, longestEdge[4], longestEdge[5], this.level + 1),
new Triangle(longestEdge[2],longestEdge[3], newX, newY, longestEdge[4], longestEdge[5], this.level + 1)];
}
}
s.setup = function(){
s.createCanvas(400,400);
s.strokeWeight(0.5);
let tris = [new Triangle(0,0,400,0,0,400, 0), new Triangle(0,400,400,400,400,0,0)];
// loop over all the triangles to do the division
for (let i = 0; i < tris.length; ++i) {
const t = tris[i];
if (Math.random() > 0.1 && t.level < 10) tris.push(...t.divide());
}
//get rid of the divided ones
tris = tris.filter(t => !t.divided);
//draw
tris.forEach(t => s.triangle(t.x1, t.y1, t.x2, t.y2, t.x3, t.y3));
}
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
p5(s => {
class Triangle{
constructor(x1, y1, x2, y2, x3, y3, level){
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.x3 = x3;
this.y3 = y3;
this.level = level;
this.divided = false;
}

// pick the new point in the incircle of the triangle to avoid triangles that are too 'long'
incircle(){
let a = Math.sqrt((this.x2 - this.x1) * (this.x2 - this.x1) + (this.y2 - this.y1) * (this.y2 - this.y1));
let b = Math.sqrt((this.x3 - this.x2) * (this.x3 - this.x2) + (this.y3 - this.y2) * (this.y3 - this.y2));
let c = Math.sqrt((this.x3 - this.x1) * (this.x3 - this.x1) + (this.y3 - this.y1) * (this.y3 - this.y1));
let newX = (a * this.x3 + b * this.x1 + c * this.x2) / (a + b + c);
let newY = (a * this.y3 + b * this.y1 + c * this.y2) / (a + b + c);
let ss=(a+b+c)/2;
let area=Math.sqrt(ss*(ss-a)*(ss-b)*(ss-c));
let r = area/ss;
return [newX, newY, r]; //[x, y, r];
}

divide(){
this.divided = true;
let incircle = this.incircle();
let a = Math.random() * Math.PI * 2, r = Math.random() * incircle[2] * 0.5; // adjustment for more even division
let newP = [incircle[0] + Math.sin(a) * r, incircle[1] + Math.cos(a) * r];
return [
new Triangle(this.x1, this.y1, this.x2, this.y2, newP[0], newP[1], this.level + 1),
new Triangle(this.x1, this.y1, this.x3, this.y3, newP[0], newP[1], this.level + 1),
new Triangle(this.x2, this.y2, this.x3, this.y3, newP[0], newP[1], this.level + 1),
];
}
}

s.setup = function(){
s.createCanvas(400,400);
s.strokeWeight(.5);
s.noFill();
let tris = [new Triangle(200,0,400,400,0,400,0)];
// loop over all the triangles to do the division
for (let i = 0; i < tris.length; ++i) {
const t = tris[i];
// possibility based on level
if (Math.random() > 0.05 * (t.level + 1) && t.level < 5) tris.push(...t.divide());
}
//get rid of the divided ones
tris = tris.filter(t => !t.divided);
//draw
tris.forEach(t => s.triangle(t.x1, t.y1, t.x2, t.y2, t.x3, t.y3));
}
})
Insert cell
Insert cell
p5(s => {
class Triangle{
constructor(x1, y1, x2, y2, x3, y3, level){
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.x3 = x3;
this.y3 = y3;
this.level = level;
this.divided = false;
}

divide(){
this.divided = true;
let rand1 = Math.random() * 0.4 + 0.3, rand2 = Math.random() * 0.4 + 0.3, rand3 = Math.random() * 0.4 + 0.3;
let newP1 = [this.x1 + (this.x2 - this.x1) * rand1, this.y1 + (this.y2 - this.y1) * rand1];
let newP2 = [this.x1 + (this.x3 - this.x1) * rand2, this.y1 + (this.y3 - this.y1) * rand2];
let newP3 = [this.x3 + (this.x2 - this.x3) * rand3, this.y3 + (this.y2 - this.y3) * rand3];
return [
new Triangle(newP1[0], newP1[1], newP2[0], newP2[1], newP3[0], newP3[1], this.level + 1),
new Triangle(this.x1, this.y1, newP1[0], newP1[1], newP2[0], newP2[1], this.level + 1),
new Triangle(this.x2, this.y2, newP1[0], newP1[1], newP3[0], newP3[1], this.level + 1),
new Triangle(this.x3, this.y3, newP3[0], newP3[1], newP2[0], newP2[1], this.level + 1),
];
}
}

s.setup = function(){
s.createCanvas(400,400);
s.strokeWeight(.5);
s.noFill();
let tris = [new Triangle(200,0,400,400,0,400,0)];
// loop over all the triangles to do the division
for (let i = 0; i < tris.length; ++i) {
const t = tris[i];
// possibility based on level
if (Math.random() > 0.05 * (t.level + 1) && t.level < 5) tris.push(...t.divide());
}
//get rid of the divided ones
tris = tris.filter(t => !t.divided);
//draw
tris.forEach(t => s.triangle(t.x1, t.y1, t.x2, t.y2, t.x3, t.y3));
}
})
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more