ternary diagram
click to add points, space to reset, arrows for color
let points = [];
let pt;
let cfactor = 1;
let cf2 = 1;
function setup() {
createCanvas(720, 720);
background(200, 200, 200);
noStroke();
pt = [];
points = [];
for (let i = 0; i < 3; i++) {
pt[i] = createVector(
(width / 2.5) * cos((TWO_PI / 3) * i - PI / 2),
(width / 2.5) * sin((TWO_PI / 3) * i - PI / 2)
);
}
triangle(
pt[0].x + width / 2,
pt[0].y + width / 2,
pt[1].x + width / 2,
pt[1].y + width / 2,
pt[2].x + width / 2,
pt[2].y + width / 2
);
}
function draw() {
t = frameCount / 1000;
cfactor = cf2 * (1 + 0.5 * sin(t));
translate(width / 2, height / 2);
for (let i = 0; i < 3; i++) {
points.push(
new entity(
random(-width / 2, width / 2),
random(-width / 2, width / 2),
2
)
);
}
for (let i = 0; i < points.length; i++) {
if (points[i].in) {
points[i].display();
points[i].move();
} else {
points.splice(i, 1);
}
}
}
function mousePressed() {
mp = createVector(mouseX - width / 2, mouseY - height / 2);
if (checkPoint(mp)) {
points.push(new entity(mp.x, mp.y, 2));
}
}
class entity {
constructor(x, y, r) {
this.x = x;
this.y = y;
this.r = random(1, 10);
this.u =
((pt[1].y - pt[0].y) * (this.x - pt[0].x) -
(pt[2].x - pt[0].x) * (this.y - pt[0].y)) /
((pt[2].y - pt[0].y) * (pt[1].x - pt[0].x) -
(pt[2].x - pt[0].x) * (pt[1].y - pt[0].y));
this.v =
((pt[0].y - pt[1].y) * (this.x - pt[0].x) -
(pt[0].x - pt[1].x) * (this.y - pt[0].y)) /
((pt[2].y - pt[0].y) * (pt[1].x - pt[0].x) -
(pt[2].x - pt[0].x) * (pt[1].y - pt[0].y));
this.upv = this.u + this.v;
this.vx = random(-0.2, 0.2);
this.vy = random(-0.2, 0.2);
this.in = true;
}
move() {
if (this.u >= 0 && this.v >= 0 && this.upv <= 1) {
this.x += this.vx;
this.y += this.vy;
this.u =
((pt[1].y - pt[0].y) * (this.x - pt[0].x) -
(pt[2].x - pt[0].x) * (this.y - pt[0].y)) /
((pt[2].y - pt[0].y) * (pt[1].x - pt[0].x) -
(pt[2].x - pt[0].x) * (pt[1].y - pt[0].y));
this.v =
((pt[0].y - pt[1].y) * (this.x - pt[0].x) -
(pt[0].x - pt[1].x) * (this.y - pt[0].y)) /
((pt[2].y - pt[0].y) * (pt[1].x - pt[0].x) -
(pt[2].x - pt[0].x) * (pt[1].y - pt[0].y));
this.upv = this.u + this.v;
} else {
this.in = false;
}
}
display() {
if (this.u >= 0 && this.v >= 0 && this.upv <= 1) {
fill(
cfactor * this.u * 225 + random(5),
cfactor * this.v * 200 + random(5),
cfactor * this.upv * 255 + random(5)
);
circle(this.x, this.y, this.r);
} else {
fill(230 + this.u * 20, 220 + this.v * 20, 210 + this.upv * 20);
circle(this.x, this.y, 2);
}
}
}
function checkPoint(mp) {
let u =
((pt[1].y - pt[0].y) * (mp.x - pt[0].x) -
(pt[2].x - pt[0].x) * (mp.y - pt[0].y)) /
((pt[2].y - pt[0].y) * (pt[1].x - pt[0].x) -
(pt[2].x - pt[0].x) * (pt[1].y - pt[0].y));
let v =
((pt[0].y - pt[1].y) * (mp.x - pt[0].x) -
(pt[0].x - pt[1].x) * (mp.y - pt[0].y)) /
((pt[2].y - pt[0].y) * (pt[1].x - pt[0].x) -
(pt[2].x - pt[0].x) * (pt[1].y - pt[0].y));
return u >= 0 && v >= 0 && u + v <= 1;
}
function keyPressed() {
if (keyCode === 32) {
setup();
draw();
} else if (keyCode === 38) {
cf2 = cf2 * 1.1;
} else if (keyCode === 40) {
cf2 = cf2 * 0.9;
}
}