マンデルブロー集合の描画プログラムについて

基本的にフラクタル大好き

なぜしばしばマンデルブロー集合の描画プログラムを書くのか?

フラクタルが好きなのだけど その中でもマンデルブロー集合については最初期のN88BASICの頃から記述に挑戦してきた。 そして結構時間のかかる処理なのでその時点の言語やPCの能力を見るのにも良いんじゃないかと思うようになった。 で、ベンチマークとしてある一定の条件を決めてその言語や環境で結果がどう変わるかを見て楽しんでいる。

ベンチマークとしてのマンデルブロー集合の描画

書き方を変えれば同じ結果が得られるプログラムも実行にかかる時間は当然変わるのだけどある程度条件を揃えることで ベンチマークとしての意味を持たせている。 出発点が古いBASICでのマンデルブロー集合描画から始まっているので下記のような感じでしばっている。

  • 基本的な計算方法はwikipedia に従う
  • 計算対象領域は実数部(通常x軸方向)が-2.5から1.2、虚数部(通常y軸方向)が-1.35から1.35とする
  • 発散確認の打ち切り回数は100回とする(実行速度が厳しければ下げる)
  • 描画領域は基本的には640x480の点の集まりとして扱う(古いBASICのエミュレータではその最大の解像度を利用する)
  • 描画領域をx,y方向でfor文などの繰り返しの2重ループでなぞるようにし計算のパラメータは媒介変数で渡す
  • 色は古いBASICに合わせて(黒,青,赤,マゼンタ,緑,水色,黄色,白)の8色とし黒はマンデル集合、他は発散回数の7の剰余で色を割り振る (見た目を合わせて比較しやすくするためもある)

以上のような感じで過去に行ったのがby Myself(別Blog)とか by Myself(別Blog)の別の検索

このブログ内でもいくつかの言語で扱うつもり

javascriptで記述したサンプル

->>ここ

上記のサンプルのjavascriptでcanvasに点を描画する命令がなかったので四角を書くstrokeRect(dx,dy,1,1)としたら やたらと画面がボケた感じになったのでcanvasのbitmapに色情報を直接代入するようにしてみた。実行も速い

->>ここ

(2019/02/07追記)

Arduinoを再開してシリアルモニタでも出せないか考えてみた

  • 基本的にキャラクタのみ、しかもエスケープシーケンスとか無いので改行のみ
  • 横のキャラクタ数はわりとあるけど縦は15行程度
  • もちろん色もつかない
  • 文字「0」〜「z」の75種を割り当てて表現する

この制約の中で考えるといつも表示しているベンチマークで用いているエリア全体を出すのはあきらめる。 むしろ640x480のVGA画面で8x8のキャラが80x30行ほど表示できたりするのでそれを基準に考える。 -2.5〜1.2で3.7の範囲を80で割ると⊿x=0.0462 -1.35〜1.35の範囲2.7を30で割って⊿y=0.09となるので これを表示文字数や行数に合わせたx,yの可変域と組み合わせて乗じて計算すれば形になりそう。

結果はこんなふう mandel

プログラムはcの気分でちょいちょいと書く

/*
 * Mandelbrot calculation
 * for charactor @20190207
 */

float dx = 0.0462;
float dy = 0.09;

void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
}

int calc_mandel(float re,float im){
  int i;
  float cr,ci,tmp;
  cr=re;
  ci=im;
  for(i=0;i<75;i++){
    tmp=cr*cr-ci*ci+re;
    ci=2*cr*ci+im;
    cr=tmp;
    if (cr*cr+ci*ci>4){
      return i+48;
    }
  }
  return 32;
}

void loop() {
  int x,y;

  for(y=-15;y<16;y++){
    for(x=-54;x<26;x++){
      Serial.write(calc_mandel(x*dx, y*dy));
    }
    Serial.println();
  }
    Serial.println();
    Serial.println();
    delay(1000);
}