map() を活用して作品作りを楽に:Processing Tips
このノートでは、Processing Tips の小ネタ、
・ある範囲の値が欲しいとき計算を楽にしてくれる map()
・map() で指定した範囲ってはみ出すことないの?
の2本立てをお送りします。
map() で書けば簡単!コードもわかりやすい!
ある範囲のランダム値、たとえば 0 から 360 のランダム値とかが欲しいときってありますよね?
そんなとき、ランダム値なら
val = random(360);
ノイズ値なら
val = noise(x) * 360;
で出来ますね。
これが 100 から 200 までだと。
val = random(100, 200);
val = 100 + noise(x) * 100;
noise() の方はちょっと分かりづらくなってきましたね。
さらに、100 から 200 の間の sin() カーブを書きたい場合、sin() は -1 から 1 の値を取るので、
val = 150 + sin(r) * 50;
ですね。
んー… なんかちょっと面倒くさくないですか?
直感的じゃないし、こんな計算式をコードのあちこちに入れていくのはバグの元になりそうです。
そんな誰もが抱くお悩みに応えてくれるのがこちらの map() !
map(変換元の値, 変換元の From, 変換元の To, 変換後の From, 変換後の To)
と書くだけで、面倒な計算をやってくれるんです。
先程の 100 から 200 までのノイズ値なら
val = 100 + noise(x) * 100; // こう書くのは面倒…
val = map(noise(x), 0, 1, 100, 200); // あら簡単!
sin() の例なら
val = 150 + sin(r) * 50; // これどういうこと?
val = map(sin(r), -1, 1, 100, 200); // まあ直感的!
という具合です。
Processing で制作をしていると、微妙な値の違いで出来上がりの結果が全然違ってきたりするので、「0.0001 から 0.032 の間の値が欲しい!」なんていう場面があったりします。
map() を使い始めてからは、こういう計算部分のコーディングで時間を取られることも無くなり、思ったように動かずに悩むことが少なくなって、制作がかなり楽になりました。
map() の詳細はリファレンスを参照ください。
とっても重宝している map() ですが、実は私、こんな勘違いをしていました…
ああ、勘違い:map() の計算結果は指定した範囲を超えることはない?
はい、白状します! 私は
val = map(x, 0, 1, 100, 200);
とした場合、x の値が 1 を超えても val の値は 200 を超えることはないと勝手に思い込んでいました。
map() で変換後の値は常に範囲内に収まるものと思っていたんです。
そんな私の考えは大間違い。
上の式では、x が 2 の場合 val は 300 に、x が -1 の場合は val は 0 になります。
私はこれがこうなると思ってたんですよね~。
map() に過度な期待をし、甘えすぎた私…
でもこれはこれで使いみちがありそうな気がしませんか?
map() ではこういうことはできないんでしょうか?
常に範囲内に収めるには?
map() だけでは出来ませんが、こうやればできますね。
val = min(
200,
max(
100,
map(x, 0, 1, 100, 200)
)
);
max() で 100以上を保証、min() で 200以下を保証というわけです!
サインカーブでやってみるとこんな感じになります。
// map() sample 03
for (int i = 0; i < 360; ++i) {
float r = radians(i);
float normalMap = map(sin(r), -0.5, 0.5, 100, 200);
float limitMap = min(
200,
max(
100,
map(sin(r), -0.5, 0.5, 100, 200)
)
);
fill(150, 80, 100, 10);
pushMatrix();
translate(i, normalMap);
ellipse(0, 0, 6, 6);
popMatrix();
fill(30, 80, 100, 100);
pushMatrix();
translate(i, limitMap);
ellipse(0, 0, 3, 3);
popMatrix();
}
normalMap が単純に map() で計算した値、limitMap が 100 から 200 までに範囲を限定したものです。
追記
min()、max() を使わなくても、constrain() を使えば簡単でした…
応用していけばなかなか面白い効果が出せそうです。
こんな感じで使える map()。皆さんのご家庭でもぜひご活用ください!
この記事が面白かったらサポートしていただけませんか? ぜんざい好きな私に、ぜんざいをお腹いっぱい食べさせてほしい。あなたのことを想いながら食べるから、ぜんざいサポートお願いね 💕