Curve di Bézier
Per evitare di indicare tutti i segmenti o i punti di una curva è possibile utilizzare algoritmi che permettono di indicare solo il punto iniziale, quello finale e uno o più punti di controllo.
Il calcolo dei punti della curva avviene in tre passaggi:
- calcolo dei punti intermedi dei 2 tragitti (grigi) fra inizio e punto di controllo e fra questo e la fine
- generazione di un ulteriore tragitto (verde) in movimento
- calcolo dei punti intermedi (rossi) sul nuovo tragitto in movimento
// width=360 height=230
let p0, p1, p2; // p1 == punto di controllo
let t01, t12; // tracciati
let tb; // punti Bézier
let bpoints = [];
let t = 0;
let radio;
let radioValue;
function setup() {
createCanvas(360, 230);
p0 = createVector(70, 160);
p1 = createVector(150, 30);
// p2 = createVector(290, 160);
p2 = createVector(300, 160);
radio = createRadioButtons( 6, function() {
radioValue = int(radio.value());
t = 0;
bpoints = [];
}); // implementare uso parametro
// radio.changed(radioChanged);
textSize(14);
}
function draw() {
t += 0.005;
if (t > 1.2) {
t = 0;
bpoints = [];
}
let tt = min(t, 1);
t01 = p5.Vector.lerp(p0, p1, tt);
t12 = p5.Vector.lerp(p1, p2, tt);
tb = p5.Vector.lerp(t01, t12, tt);
bpoints.push(tb);
// background(255);
clear();
// linee grigie
if (radioValue > 0) {
stroke(224);
strokeWeight(4);
line(p0.x, p0.y, p1.x, p1.y);
line(p1.x, p1.y, p2.x, p2.y);
}
// linea verde
if (radioValue > 2 && t <= 1) {
stroke(0, 255, 0);
strokeWeight(2);
line(t01.x, t01.y, t12.x, t12.y);
}
// punti verdi
if (radioValue > 1) {
stroke(255);
strokeWeight(1);
fill(0, 255, 0);
circle(t01.x, t01.y, 7);
circle(t12.x, t12.y, 7);
}
// punti di riferimento
stroke(0);
strokeWeight(1);
fill(255);
circle(p0.x, p0.y, 6);
circle(p1.x, p1.y, 6);
circle(p2.x, p2.y, 6);
noStroke();
fill(128);
textAlign(RIGHT, CENTER);
text("inizio", p0.x-12, p0.y);
textAlign(CENTER, BOTTOM);
text("punto di controllo", p1.x, p1.y-10);
textAlign(LEFT, CENTER);
text("fine", p2.x+12, p2.y);
// curva
if (radioValue == 0 || radioValue > 4) {
noStroke();
fill(255, 0, 0);
for (let i = 0; i < bpoints.length; ++i) {
let bp = bpoints[i];
circle(bp.x, bp.y, 4);
}
}
// punto nero
if (radioValue > 3 && t <= 1) {
if (radioValue == 4) {
fill(255,0,0);
} else {
fill(0);
}
circle(tb.x, tb.y, 6);
}
}
function createRadioButtons( quanti, callback ) {
var radio = createRadio();
/* radio.option('0');
radio.option('1');
radio.option('2');
radio.option('3');
radio.option('4');
radio.option('5'); */
for (var i=0; i<quanti; ++i) {
radio.option(str(i));
}
radio.selected('0');
radioValue = 0;
radio.class('radio-buttons');
// radio.style('width', '360px');
// radio.style('display', 'flex');
// radio.style('justify-content', 'center');
/* let labels = radio.elt.getElementsByTagName("LABEL");
for (let i = 0; i < labels.length; ++i) {
labels[i].style.display = "none";
} */
// radio.position(0, height - 20);
radio.changed(callback);
return radio;
}
/* function radioChanged() {
radioValue = int(radio.value());
t = 0;
bpoints = [];
} */