見出し画像

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()。皆さんのご家庭でもぜひご活用ください!


この記事が面白かったらサポートしていただけませんか? ぜんざい好きな私に、ぜんざいをお腹いっぱい食べさせてほしい。あなたのことを想いながら食べるから、ぜんざいサポートお願いね 💕