見出し画像

いろいろな円を描く by Processing

僕がProcessingでクンフーを積んでいくうちに培ったいろんな円の表現方法を紹介します。

まずは基本の円から始めましょう

ellipse(centerX, centerY, width, height);
circle(enterX, centerY, diameter);

Processing 3.5で追加されたcircle()。直径だけを渡せばいいという便利仕様なのでどんどん使っていきましょう。

次に円を三角関数を使って表します。

  beginShape();
  for(float a = 0; a < TAU; a += TAU / 90){
    float x = centerX + radius * cos(a);
    float y = centerY + radius * sin(a);
    vertex(x, y);
  }
  endShape(CLOSE);

TAU / 36は360 / 36 = 10で10度ずつ描画することになります。増分を減らせばもっと滑らかな円になります。

基本はこのくらいにしてもっと楽しい円を作ってみましょう。

円の中を点で埋める

円内にランダムなたくさんの点を打ってくれるように作ってみましょう。
先ほどやった三角関数を使う方程式の角度の部分を0~PIのランダムに、直径も0~指定した直径の値をランダムに返してくれるようにしましょう。

void myCircle(float centerX, float centerY, float diameter) {
  float radius = diameter/2;
  int count = 10000;  //点の数
  for (int i = 0; i < count; i ++) {
    float angle = random(TWO_PI);
    float r = random(1);
    float x = centerX + r * radius * cos(angle);
    float y = centerY + r * radius * sin(angle);
    point(x, y);
  }
}

このコードなら円の中に均等に沢山の点を打ってくれるはずです!

おっと、満遍なく配置されてないですね。予想とは違いますがこれはこれで美しいのでOKです。

この円を観察すると半径が小さい大きいに関係なく点を打っています。
それが中心部が渋滞している原因ですね。

半径が小さいときには点の数を減らしたい…

こんな時は無理関数です!
√を使うための関数sqrt()があるのでコードにこれを組み込みましょう。

void myCircle(float centerX, float centerY, float diameter) {
  float radius = diameter/2;
  int count = 10000;
  for (int i = 0; i < count; i ++) {
    float angle = random(TWO_PI);
    float r = sqrt(random(1));
    float x = centerX + r * radius * cos(angle);
    float y = centerY + r * radius * sin(angle);
    point(x, y);
  }
}

美しい…。
なんでこうなるのかわからなくても大丈夫です。なるもんはなるの精神でいきましょう。

真ん中に集まるパターン、均等に配置するパターン、となると残りも試したくなりますね。
円の外側ほど多く点が配置されるようにしてみましょう。

これもrの値のみをいじることにします。
ランダム関数の中にランダム関数を入れるつまりrandom(random())とすると小さい値が選ばれやすくなります。
そして0.0~1.0を返すので、1から引いてあげれば逆になる、つまり大きい値が選ばれやすくなります。
以上を踏まえた結果コードはこうなります。

void myCircle(float centerX, float centerY, float diameter) {
  float radius = diameter/2;
  int count = 10000;
  for (int i = 0; i < count; i ++) {
    float angle = random(TWO_PI);
    float r = 1-(random(random(random(1))));
    float x = centerX + r * radius * cos(angle);
    float y = centerY + r * radius * sin(angle);
    point(x, y);
  }
}

うん、いい感じになりましたね

少しパワープレー感もありますが、rの中をmap(), sq(), pow()などを使ってランダムな値に変化を加えると色々な表現が楽しめそうですね。blendMode()で光らせたり、グラデージョンを加えたりしても楽しそうです。

グラデーションを加えて立体感のある円を作る

lerpColor()の3つ目の引数には2つの値の間を0.0~1.0の比率で指定します。

void myCircle(float centerX, float centerY, float diameter) {
  int count = 100;          //ループ回数
  color c1 = color(0);      //外側の色
  color c2 = color(255);    //内側の色
  noStroke();
  
  for (int i = 0; i < count; i ++) {
    color c = lerpColor(c1, c2, float(i)/float(count));
    //半径が徐々に小さくなるようにマッピング
    float d = map(i, 0, count-1, diameter, 0);
    fill(c);
    circle(centerX, centerY, d);
  }
}

さらにここからアレンジを加えましょう。

円が小さくなる位置を中心にではなく右上にします。
それと円の最小値を0ではなく直径 × 0.2の大きさにします

void myCircle(float centerX, float centerY, float diameter) {
  int count = 100;         //ループ回数
  color c1 = color(0);     //外側の色
  color c2 = color(255);   //内側の色
  noStroke();
  for (int i = 0; i < count; i ++) {
    color c = lerpColor(c1, c2, float(i)/float(count));
    //半径が徐々に小さくなるようにマッピング
    float d = map(i, 0, count-1, diameter, diameter*0.2);
    float shift = map(i, 0, count-1, 0, diameter/5);
    fill(c);
    circle(centerX + shift, centerY - shift, d);
  }
}

メタリックな球のような円が完成です。

透明度もグデーションにしてくれるのでぼんやりした表現も作ることができます。

arc()で円を分割する

whileループを使って0から2πまでをarc()で指定してあげましょう。
前回の値を代入して保持しておくことでarc()を敷き詰めることができます。

void myCircle(float x, float y, float d) {
  float angle = 0;      //現在の値
  float lastAngle = 0;  //ひとつ前の値
  noStroke();
  pushMatrix();
  translate(x, y);
  //ランダムに角度を変える
  rotate(random(PI));
  while (angle < TAU) {
    fill(random(255), random(255), random(255));
    arc(0, 0, d, d, lastAngle, angle, PIE);
    lastAngle = angle;         //現在の値を代入
    angle += random(PI*0.2);   //値が小さいほど細かく分割
  }
  fill(random(255), random(255), random(255));
  //残りを描画(最後の値から2πまで)
  arc(0, 0, d, d, lastAngle, TAU, PIE);
  popMatrix();
}

円グラフのような感じになりました。
これだけですとまだ面白さが足りないので、少し手を加えてみましょう。

void myCircle(float x, float y, float d) {
  float angle = 0;      //現在の値
  float lastAngle = 0;  //ひとつ前の値
  noStroke();
  pushMatrix();
  translate(x, y);
  //ランダムに角度を変える
  rotate(random(PI));
  while (angle < TAU) {
    fill(random(255), random(255), random(255));
    arc(0, 0, d, d, lastAngle, angle, PIE);
    lastAngle = angle;
    angle += random(PI*0.01);
  }
  fill(random(255), random(255), random(255));
  //残りを描画(最後の値から2πまで)
  arc(0, 0, d, d, lastAngle, TAU, PIE);
  popMatrix();
  //0.9倍の円を重ねる
  circle(x, y, d * 0.9);
}


ノーマルな円を重ねることで特別な輪郭線で描画したようにできました。

はい、終わり!

まとめ

今回いろんな円を作りましたがこれだけで作品になるというよりは作品の中の円に一味加えたいときに役立てていただければ幸いです。

応援してくださる方はご購入もお願いします。

ありがとうございました。

Happy coding!

ここから先は

0字

¥ 100

期間限定 PayPay支払いすると抽選でお得に!

応援してくださる方!いつでもサポート受け付けてます!