Processingでクリスマス

普段データ操作とかユーザーインターフェースのプログラムばかり書いていると、たまには仕事とまったく関係ないプログラムを書きたくなりますよね。
そんな訳で今回はProcessingでちょっとクリスマスっぽい絵でも描いてみましょう。

# Processingとは
Processingは電子アートとビジュアルデザインのためのプログラミング言語であり、統合開発環境です。
こう書くと少し難しいものに思えるかもしれませんが、プログラムを書くことで絵を描けるくらいに考えてもらっても大丈夫だと思います。
記述したプログラムによる変化が視覚的にすぐにわかるので、データ操作をするようなプログラムよりも実行結果の違いがわかりやすいという特徴があります。

ProcessingはJavaで作られており、プログラムも基本はJavaで記述しますが、モードを追加することでPythonやJavaScriptなどでも記述できます。
自分の興味のあるプログラミング言語でProcessingにトライしてみましょう。

# インストールしてみよう
Processingのインストールは下記のページからZIPファイルをダウンロードし、解凍してからWindowsであればProcessing.exeを、MacであればProcessing.appをダブルクリックして実行するだけです。

https://processing.org/download/

Processingを起動すると、下記のようなIDEが表示されます。
<img width="678" alt="ide.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525968/8f272ad4-2ffc-9c77-a679-a4900295c12e.png">

さっそく何か描いてみましょう。
下記のプログラムをコピーしてIDEに貼り付けて実行してみてください。
実行は左上の三角が書かれているボタンです。

```java
size(300,250);
background(255);
stroke(0);

fill(255);
ellipse(150,160,100,100); // body
line(110,130,70,100); // left arm
line(190,130,230,100); // right arm
ellipse(150,100,60,60); // head
arc(150, 106, 30, 25, -TWO_PI, -PI); // mouth

fill(0);
rectMode(CENTER);
rect(150,65,34,20); // hat
line(125,75,175,75); // brim
ellipse(142,92,5,5); // left eye
ellipse(158,92,5,5); // right eye

noStroke();
fill(255,100,0); 
ellipse(150,102,7,7); // nose
```
<img width="201" alt="snowman.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525968/c4babb61-21b4-4a38-b006-e0397ae9939d.png">
こんなのが出てくれば成功です。
プログラムは単純に各パーツの丸を描いて塗り潰したり線を引いたりしているだけです。
各パーツの数値を変えることで絵が変化するので、色々ためしてみましょう。


# サンプルプログラム
今回はProcessingのプログラムの書き方については言及しません。
Processingの書き方やサンプルプログラムはWebで検索するとたくさん出てきます。
サンプルプログラムを写経したり、書き換えて動かしてみることで、プログラムの書き方はすぐに解ると思いますので、サンプルプログラムをたくさん動かしてみることをお勧めします。
ここではいくつかのサンプルプログラムをご紹介します。

## イルミネーション
クリスマスなのに部屋が殺風景だと感じたら、PCのディスプレイをクリスマスイルミネーションにしてしまいましょう。
サンプルプログラムの描画領域や円のサイズを調整してディスプレイを華やかにしてみてください。
やっていることは乱数で座標、丸の大きさ、色、透過度を変化させて描画しているだけです。
setup()は最初に１回だけ実行され、draw()は定期的に繰り返し実行されます。

```java
void setup() {
  size(700,400);
  background(0);
  smooth();
}

void draw() {
  float r = random(255);
  float g = random(255);
  float b = random(255);
  float a = random(255);
  float x = random(width);
  float y = random(height);
  float diameter = random(20);
  
  noStroke();
  fill(r,g,b,a);
  ellipse(x,y,diameter,diameter);
}
```

<img width="701" alt="illumination.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525968/4dbf6d80-a5c1-9810-6776-58c617f967a4.png">


## フラクタル図形で木を書く
フラクタル図形とは、「図形の部分と全体が自己相似（再帰）になっているもの」です。
フラクタル図形にはいろいろな種類がありますが、ここではクリスマスツリーにちなんで木のようなものを描いてみましょう。

```java
int angle = 110;

void setup() {
  background(255);
  size(600, 600, P2D);
  
  tree(300, 600, 0.0, radians(0), radians(angle), 200, 10);
  tree(300, 600, 0.0, radians(angle), radians(0), 200, 10);
}

void tree(float posX, float posY, float angle, float forkRight, float forkLeft, float length, int counter) {
  if (counter == 0) {
    return;
  }

  float nextX = posX + length * sin(angle);
  float nextY = posY - length * cos(angle);

  line(posX, posY, nextX, nextY);
  
  tree(nextX, nextY, angle + forkRight, forkRight, forkLeft, length*0.6, counter - 1);
  tree(nextX, nextY, angle - forkLeft,  forkRight, forkLeft, length*0.6, counter - 1);
}
```
<img width="580" alt="tree2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525968/6616c86d-d745-e85a-d4df-d0f68d810283.png">

再帰処理に慣れていないと読みにくいかもしれませんが、同じ形のものを縮小して一定回数繰り返し描画しています。
angleの値を変化させると、木の形が変化するので試してみましょう。
下記は size=80 にした時の描画結果になります。

<img width="596" alt="tree_radian80.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525968/f99c39e5-e99d-8787-43af-ead9ade5f497.png">

## フラクタル図形で雪の結晶を書く
フラクタル図形の一種にコッホ曲線というのがあります。
線分を3等分し、分割した2点を頂点とする正三角形の作図を無限に繰り返すことによって下記の様な図形が作成できます。
<img width="368" alt="kochCurve.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525968/b7f77cf2-8547-9bfc-b155-22c136916844.png">

このコッホ曲線を正三角形に配置すると、雪の結晶のような図形が出現します。
この図形はコッホ雪片と呼ばれます。

<img width="379" alt="snowFrake.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525968/0ce1628d-29e1-742d-2a05-bb68406b7520.png">

以下のサンプルは、コッホ雪片を段階的に作成するプログラムです。
実際に動かしてみてコッホ雪片がどのように作られるのかを見てみましょう。

```java
int depth = -1;

void setup(){
  background(255);
  size(400, 400);
  frameRate(1);
}

void draw() {
  background(255);
  depth++;
  if (depth > 5) {
    depth = 0;
  }

  int border = (int) (width * 0.8);
  int triangleHeight = (int) (border * Math.sin(Math.toRadians(60.0)));
  
  Point p1 = new Point(width / 2, 10);
  Point p2 = new Point(width / 2 - border / 2, 10 + triangleHeight);
  Point p3 = new Point(width / 2 + border / 2, 10 + triangleHeight);

  drawKochCurve(depth, p1, p2);
  drawKochCurve(depth, p2, p3);
  drawKochCurve(depth, p3, p1);
}

void drawKochCurve(int count, Point p1, Point p2) {
  stroke(0);

  if (count == 0) {
    line(p1.x, p1.y, p2.x, p2.y);
  } else {
    int deltaX = p2.x - p1.x;
    int deltaY = p2.y - p1.y;
    
    double cosConst = Math.cos(Math.toRadians(30.0));
    int zx = (int)((p1.x + p2.x)/2 + cosConst * (p1.y - p2.y)/3.0);
    int zy = (int)((p1.y + p2.y)/2 + cosConst * (p2.x - p1.x)/3.0);
    
    Point x = new Point(p1.x + deltaX / 3, p1.y + deltaY / 3);
    Point y = new Point(p1.x + deltaX * 2 / 3, p1.y + deltaY * 2 / 3);
    Point z = new Point(zx, zy);

    drawKochCurve(count - 1, p1, x);
    drawKochCurve(count - 1, x, z);
    drawKochCurve(count - 1, z, y);
    drawKochCurve(count - 1, y, p2);
  }
}

class Point {
  int x;
  int y;
 
  Point(int x, int y){
    this.x = x;
    this.y = y;
  } 
}
```

# The Nature of Code
ここまでいかがでしたでしょうか。
Processingというものに少しでも興味を持ってもらえたら幸いです。
最後に「The Nature of Code」について紹介させてください。
「The Nature of Code」は物理や数学の法則・公式といった自然界のルールをProcessingを使って記述する方法について書かれた書籍です。
今回紹介したフラクタル図形についても詳しく書かれているので、興味のあるかたはご一読ください。

https://www.amazon.co.jp/Nature-Code-Processingではじめる自然現象のシミュレーション-ダニエル・シフマン/dp/4862462456

英語版であれば、下記のサイトから無料で閲覧することができます。

https://natureofcode.com

それでは皆様、良いクリスマスをお迎えください。