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:

  1. calcolo dei punti intermedi dei 2 tragitti (grigi) fra inizio e punto di controllo e fra questo e la fine
  2. generazione di un ulteriore tragitto (verde) in movimento
  3. 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 = [];
} */