🤖

3次ベジェ曲線_2点特殊バージョン

に公開


黄色の点を二つ決め、
中間の二つの制御点を自動計算することで、
4つの点を指定しなければいけないところを二つに限定している。

自由度が下がる代わりに使いやすくなる。


let z0, z1, z2, z3; // 制御点

function setup() {
  createCanvas(600, 400); // キャンバスを作成
  background(240); // 背景色を設定

  // 制御点の座標を定義
  z0 = createVector(50, 200);   // 始点
  z3 = createVector(550, 200);  // 終点
  z1 = createVector((z0.x + z3.x) /2 , z0.y);   // 1つ目の制御点
  z2 = createVector((z0.x + z3.x) /2, z3.y);  // 2つ目の制御点
  
}

function draw() {

  z1.x = (z0.x + z3.x) /2;
  z1.y = z0.y;
  z2.x = (z0.x + z3.x) /2;
  z2.y = z3.y;
  background(240); // 毎回背景をクリアして再描画

  // 制御点を描画(視覚化のため)
  fill(0);
  noStroke();
  ellipse(z0.x, z0.y, 8, 8); // 始点
  ellipse(z1.x, z1.y, 8, 8); // 制御点1
  ellipse(z2.x, z2.y, 8, 8); // 制御点2
  ellipse(z3.x, z3.y, 8, 8); // 終点

  // 制御点間の補助線を描画(曲線の形状を理解しやすくするため)
  stroke(150, 150, 150);
  line(z0.x, z0.y, z1.x, z1.y);
  line(z1.x, z1.y, z2.x, z2.y);
  line(z2.x, z2.y, z3.x, z3.y);

  // ベジェ曲線を計算し、描画
  stroke(255, 0, 0); // 曲線の色を赤に
  strokeWeight(2); // 曲線の太さ

  noFill(); // 塗りつぶしなし

  beginShape(); // 曲線を描画するための点の集合を開始
  for (let t = 0; t <= 1; t += 0.005) { // tを0から1まで少しずつ増やす
    // ベジェ曲線の式に基づいて点の座標を計算
    let x = pow(1 - t, 3) * z0.x + 3 * pow(1 - t, 2) * t * z1.x + 3 * (1 - t) * pow(t, 2) * z2.x + pow(t, 3) * z3.x;
    let y = pow(1 - t, 3) * z0.y + 3 * pow(1 - t, 2) * t * z1.y + 3 * (1 - t) * pow(t, 2) * z2.y + pow(t, 3) * z3.y;

    vertex(x, y); // 計算した点を曲線のパスに追加
  }
  endShape(); // 曲線の描画を終了

  // p5.jsのbezier()関数を使った場合(比較用、コメントアウト解除で表示)
  /*
  stroke(0, 0, 255); // 青色
  strokeWeight(1);
  noFill();
  bezier(z0.x, z0.y, z1.x, z1.y, z2.x, z2.y, z3.x, z3.y);
  */
}

// マウスドラッグで制御点を移動させる機能(オプション)
// これを実装することで、インタラクティブに曲線の形状を変更できます
function mouseDragged() {
  // マウスの位置に最も近い制御点を探す
  let minDist = Infinity;
  let closestPoint = null;

  let points = [z0, z1, z2, z3];
  for (let i = 0; i < points.length; i++) {
    let d = dist(mouseX, mouseY, points[i].x, points[i].y);
    if (d < minDist) {
      minDist = d;
      closestPoint = points[i];
    }
  }

  // 検出した制御点をマウスの位置に移動
  if (minDist < 50) { // 制御点の近くをクリックした場合のみ移動
    closestPoint.x = mouseX;
    closestPoint.y = mouseY;
  }
}```

Discussion