正弦波を使ってオリジナルパワポ背景生成器を作った

## はじめに
オリジナルパワポ背景、欲しいですよね。
それどころか、もしそれぞれのページに固有の背景パターンを作れたら、どうでしょう。

もしセクションごとに背景パターンが異なると、「違う話を始めたな」と **視覚的に** 分かります。（もちろんちゃんとそれが分かるようにお話するべきであるのは間違いないですが、、、）

今回は、テキストからパワポ背景に変換するサイトを作りました。

これには[見てて面白いの王、見てて面白いキング](https://qiita.com/uts1_6/items/11e348ead4bae71571b8)であるところの　（正弦波による） **合成波** を描画しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/c374190f-e72b-c8f7-4df1-6f120b0cc77f.png)


:::note
動作サイト: https://konbraphat51.github.io/SinDrawer/
レポジトリ: https://github.com/konbraphat51/SinDrawer
:::

## 仕組み
発想はいたって単純
```plantuml
start
:テキストを入力;
:テキストを数値に変換;
:その数値を乱数シードに;
:その乱数からsin関数のパラメーターを生成;
:複数のsin関数を合成して描画;
stop
```
これだけです。

## 実装
弊ライブラリ `HotSoupScript`を使っています。

:::note
こちらの記事もオススメです
[初心者向けゲームプログラミングJavaScriptライブラリを作り、講座をした](https://qiita.com/konbraphat51/items/b138683db352afd77714)
:::

### テキストを数値に変換
ぶっちゃけ単射でも全射でもあるほど一意性に対する需要はないので、`char`コードを足し算しているだけです
```javascript
function TextToSeed(text) {
	let seed = 0
	for (let i = 0; i < text.length; i++) {
		seed += text.charCodeAt(i)
	}

	return seed
}
```

### 乱数シードに
高級乱数には詳しくありませんが、標準的な乱数には「シード値」があって、そのシード値を設定すると決まった順番の乱数が排出されます。

`JavaScript`の標準乱数であるところの`Math.random()`は初期シードを設定できません。 ([参考](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Math/random))
なので、シード値を設定できる自前の乱数関数を作る必要があります。

簡単な実装として **XorShift** アルゴリズムがあります。
特に暗号性に対する需要がないので、こちらを選択。

コードをコピペするのは申し訳ないので、参照元の記事をﾍﾟﾀﾘ
[JavaScriptで再現性のある乱数を生成する + 指定した範囲の乱数を生成する](https://sbfl.net/blog/2017/06/01/javascript-reproducible-random/)

これで **入力テキストに対して一意の乱数列** が得られます。

### sin関数のパラメーターを生成
$sin$関数の一般形は、 $x$を変数として
$d\sin{(ax + b)}$
ですね。振幅、角速度、位相。

まずはそれを実装。
```javascript
class Sin {
	constructor(amplitude, angularVelocity, phase) {
		this.amplitude = amplitude
		this.angularVelocity = angularVelocity
		this.phase = phase
	}

	Calc(x) {
		return this.amplitude * Math.sin(this.angularVelocity * x + this.phase)
	}
}
```

先ほどの乱数生成器`Random`クラスを使って、パラメーターを割り当てます。
```javascript
function MakeSinsRandomly(
	amount,
	amplitudeWidth = 2.5,
	amplitudeMin = 0.1,
	angularVelocityWidth = 0.2,
	angularVelocityMin = 0.05,
	phaseShiftMax = 2 * Math.PI,
) {
	const sins = []
	const random = new Random(textSeed)
	for (let cnt = 0; cnt < amount; cnt++) {
		sins.push(
			new Sin(
				random.nextFloat() * amplitudeWidth + amplitudeMin,
				random.nextFloat() * angularVelocityWidth + angularVelocityMin,
				random.nextFloat() * phaseShiftMax,
			),
		)
	}

	return sins
}
```

### 複数のsin関数を合成して描画
合成はただの足し算
```javascript
function Func(x, sins) {
	let value = 0
	for (let cnt = 0; cnt < sins.length; cnt++) {
		value += sins[cnt].Calc(x)
	}

	return value
}
```

描画は弊ライブラリ`HotSoupScript`の腕の見せ所、これだけ
```javascript
function _DrawCurve(curve, lineWidth = 3) {
	for (let i = 0; i < curve.length - 1; i++) {
		DrawLine(
			curve[i][0],
			curve[i][1],
			curve[i + 1][0],
			curve[i + 1][1],
			lineWidth,
		)
	}
}
```
要するに隣り合う2点に直線を引くのを繰り替えしていますが、それぞれの直線が短いので、遠目に見ると綺麗な曲線に見えるってやつですね。

## 結果
[あんみつの王　あんみつキング](https://qiita.com/uts1_6/items/11e348ead4bae71571b8)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/b2f8d164-848c-f358-fc56-d62d81faa119.png)


[忸怩の王、忸怩キング](https://qiita.com/uts1_6/items/11e348ead4bae71571b8)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/5de01d66-35b6-e28a-d0fa-7b984f525914.png)

[ちょ待てよの王、ちょ待てよキング](https://qiita.com/uts1_6/items/11e348ead4bae71571b8)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/71a9f341-a385-343a-bba3-2ab1a0e9f5b2.png)


### バリエーションあるよ(笑)
右上埋め
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/3f8530f4-4242-866f-d13d-0ade0d3c5218.png)


右埋め
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/b703c98e-5b0e-b672-2513-566b6599bc4b.png)

上埋めず
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/4415a766-0419-605c-6416-7a29444bfbc8.png)

上埋め
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/fa857ee3-f924-e641-5a23-0608ebf3144c.png)

:::note
この記事にいいね、[レポジトリ](https://github.com/konbraphat51/SinDrawer)にスターつけてくださると泣いて喜びます！！！！！！！！！！！！！！１
:::