p5.jsの関数まとめ part.14 bezierVertex()

この記事は Qiita p5js アドベントカレンダ19日目の記事です。

## これはなに
p5.jsが用意している関数について理解を深める記事です。
今回はVertexのbezierVertex()について。

## bezierVertex()
ベジェ曲線を描くための関数です。
さて、ベジェ曲線がわからないので調べてみました。
[こちらの記事](https://ferret-plus.com/1953)によると、
> ベジェ曲線とは、フランスの自動車メーカー「シトロエン社」のド・カステリョ氏と「ルノー社」のピエール・ベジェ氏が設計した、曲線を描く数式のことを指します。

おおなるほど。
ドローイングを行えるソフトなどで曲線を書く際はこのベジェ曲線で表現されるみたいです。

このベジェ曲線に従って、曲線を描画できる...という関数なのですね。

### リファレンスより
> Bezier曲線の頂点座標を指定する。bezierVertex()を呼び出すたびに、ベジェ曲線の2つの制御点と1つのアンカーポイントの位置が定義され、線や図形に新しいセグメントが追加されます。WebGL モードでは、bezierVertex() は 2D および 3D モードで使用することができます。2Dモードでは6つのパラメータを、3Dモードでは9つのパラメータ（z座標を含む）を想定しています。(DeepL翻訳)

`ベジェ曲線の2つの制御点`で曲がる方向などを指定し、アンカーポイントまでの線を描きます。
この時始点となる座標は`vertex()`で制御するみたいですね。

### Type
```typescript
bezierVertex(x2: number, y2: number, x3: number, y3: number, x4: number, y4: number): p5;
```
引数

- x2 制御点①のx座標
- y2 制御点①のy座標
- x3 制御点②のx座標
- y3 制御点③のy座標
- x4 アンカーポイントのx座標
- y4 アンカーポイントのy座標

WebGLモードの場合はこれにプラスして`z2, z3, z4`を渡せるようになります。

### 試してみる
ではリファレンスのコードを参考に、下記のようなコードを書いてみます。

```javascript
function setup() {
  createCanvas(600, 600);	
  background(0);
}

function draw() {
  fill('white')
  beginShape();
  vertex(300, 200);
  bezierVertex(500, 0, 500, 400, 300, 400);
  endShape();
}
```
![スクリーンショット 2021-12-19 1.24.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358229/5b61475a-d876-79d8-d197-e173aefc88a1.png)

`D`のような曲線が現れました。
ただ正直これだと何が起きているかさっぱりなので、`point()`で`bezierVertex()`の制御点を描画してみることにします。

```javascript
  fill('white')
  beginShape();
  vertex(300, 200);
  bezierVertex(500, 0, 500, 400, 300, 400);
  endShape();
  
  push()
  stroke('red')
  strokeWeight(15); 
  point(500, 0)
  point(500, 400)
  pop()
```
![スクリーンショット 2021-12-19 1.19.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358229/7dd271bf-841d-544b-ea46-d2aa9443d677.png)
２箇所に赤い丸が現れました。
ついでに各座標もあとづけで書いておきました。
こうしてみると、二つの制御点を考慮しつつ、アンカーポイントに到達するような曲線を描いていることが分かります。

また最初のカーブは二つ目の制御点が考慮されています。
試しに二つめの制御点のx座標を350にしてみると、制御点①からのカーブがきつくなります。

```javascript
  fill('white')
  beginShape();
  vertex(300, 200);
  bezierVertex(500, 0, 350, 400, 300, 400);
  endShape();
  
  push()
  stroke('red')
  strokeWeight(15); 
  point(500, 0)
  point(350, 400)
  pop()
```
![スクリーンショット 2021-12-19 1.34.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358229/6664b12e-a07d-d3e8-1795-cdb385c799ca.png)


このような方法で表現できる曲線が**ベジェ曲線**なのですね！

#### 二つのbezierVertex()を組み合わせる
ということができるんですね〜
こちらもリファレンスを参考に試してみたいと思います。
今回はpointも増えるので座標を変数化しています。

```javascript
function setup() {
  createCanvas(600, 600);	
  background(0);
}

let bezierY1 = 0
let bezierX1 = 500
let bezierY2 = 400
let bezierX2 = 350

let bezier2Y1 = 100
let bezier2X1 = 550
let bezier2Y2 = 400
let bezier2X2 = 500

function draw() {  
  fill('white')
  beginShape();
  vertex(300, 200);
  bezierVertex(bezierX1, bezierY1, bezierX2, bezierY2, 300, 400);
  bezierVertex(bezier2X1, bezier2Y1, bezier2X2, bezier2Y2, 300, 400);
  endShape();
  
  push()
  stroke('red')
  strokeWeight(15); 
  point(bezierX1, bezierY1)
  point(bezierX2, bezierY2)
  
  stroke('blue')
  point(bezier2X1, bezier2Y1)
  point(bezier2X2, bezier2Y2)
  pop()
}
```
![スクリーンショット 2021-12-19 1.55.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358229/f1e48a04-8dbc-37a1-66f6-d718445cb2df.png)


すると大変いびつなハートのような形になりました。
`bezierVertex()`は前回のアンカーポイントを始点とする特性があり、二つめのbezierVertex()の始点は`(300, 400)`となります。
始点から始点と同じアンカーポイントに着く曲線が追加されたためこのような図形になっています。

![スクリーンショット 2021-12-19 1.50.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358229/288cf966-c970-ecaa-7537-e3df70c1b9c3.png)


この始点の特性は知っていないと「あれ？」ってなりそうですね。

このあと１時間半ほどbezierVertex()で面白い動きが作れないか試していたのですが、大したものはできませんでした。。
修行が足りないですね。


## 参考
[p5.js reference | bezierVertex()](https://p5js.org/reference/#/p5/bezierVertex)