ここでは、書籍「フラクタル: 混沌と秩序のあいだに生まれる美しい図形 アルケミスト双書」のp.4,5に掲載されていたコッホ曲線やコッホ雪片について、自分でも作ってみました。

コッホ曲線

まず、コッホ雪片を作るための基礎となる、コッホ曲線について解説します。

コッホ曲線

コッホ曲線の描き方

このコッホ曲線の描き方を説明します。なお、書籍「フラクタル: 混沌と秩序のあいだに生まれる美しい図形 アルケミスト双書」のp.4にある解説そのままです。

  1. 1本の線分を引く。
  2. 次に真ん中の3分の1を正三角形から底辺を除いた”テント”にして、長さの等しい4本の線分にする。
  3. 同じ操作を4本の線分すべてで再度行う。

これを繰り返すことでコッホ曲線を描くことができます。

プログラムコード

コッホ曲線を描くためのプログラムコードを載せておきます。上記の解説では「線分を引いて、真ん中の3分の1を削除してテントに置き換える」となっていますが、実際のプログラムで「一度描いて、一部削除」は余計な処理になりますので、今回のプログラムでは「再帰的な呼び出し処理の最後にコッホ曲線を描く」ようにしています。

float h_min = 10.0; // 枝の長さの最小値

void setup(){
  size(500,500);
  background(255,255,255);
  
  // コッホ曲線
  PVector start = new PVector(0.0, height*2.0/3.0);
  PVector end = new PVector(width, height*2.0/3.0);
  drawKoch(start, end);
}

// コッホ曲線を描くための関数
void drawKoch(PVector start, PVector end){
  // startとendで結ばれる線分を3分割する点
  PVector sub_vec = end.copy().sub(start.copy());
  PVector sep_point1 = PVector.add(start.copy(), sub_vec.copy().mult(1.0/3.0));
  PVector sep_point2 = PVector.add(start.copy(), sub_vec.copy().mult(2.0/3.0));
  PVector koch_point = PVector.add(sep_point1.copy(), sub_vec.copy().mult(1.0/3.0).rotate(radians(-60)));

  // コッホ曲線を再帰的に描画する
  if(sub_vec.mag() > h_min){
    drawKoch(start, sep_point1);
    drawKoch(sep_point1, koch_point);
    drawKoch(koch_point, sep_point2);
    drawKoch(sep_point2, end);
  } else {
    line(start.x, start.y, sep_point1.x, sep_point1.y);
    line(sep_point1.x, sep_point1.y, koch_point.x, koch_point.y);
    line(koch_point.x, koch_point.y, sep_point2.x, sep_point2.y);
    line(sep_point2.x, sep_point2.y, end.x, end.y);
  }
} 

コッホ雪片

コッホ雪片は正三角形を描き、3辺それぞれをコッホ曲線で置き換えることで描くことができます。

コッホ雪片

プログラムコード

コッホ雪片を描くためのプログラムコードを載せておきます。コッホ曲線ではline関数を用いて描きましたが、コッホ雪片では図形の塗りつぶしのことも考えて、テントの部分をtriangle関数を用いて描いています。

float h_min = 10.0; // 枝の長さの最小値

void setup(){
  size(500,500);
  background(255,255,255);

  translate(width/2, height/2);
  rotate(radians(30));
  // コッホ雪片を描く
  stroke(100,100,100);
  fill(100,100,100);
  drawSnowFlake(width/3.0);
}

// コッホ雪片を作る関数
void drawSnowFlake(float radius){
  // 最初の段階の三角形の頂点
  PVector[] vertices = new PVector[3];
  vertices[0] = PVector.fromAngle(radians(-90)).mult(radius);
  vertices[1] = PVector.fromAngle(radians(30)).mult(radius);
  vertices[2] = PVector.fromAngle(radians(150)).mult(radius);

  triangle(
    vertices[0].x, vertices[0].y,
    vertices[1].x, vertices[1].y,
    vertices[2].x, vertices[2].y
  );
  drawKoch(vertices[0], vertices[1]);
  drawKoch(vertices[1], vertices[2]);
  drawKoch(vertices[2], vertices[0]);
}

// コッホ雪片を作るためのコッホ曲線
void drawKoch(PVector start, PVector end){
  // startとendで結ばれる線分を3分割する点
  PVector sub_vec = end.copy().sub(start.copy());
  PVector sep_point1 = PVector.add(start.copy(), sub_vec.copy().mult(1.0/3.0));
  PVector sep_point2 = PVector.add(start.copy(), sub_vec.copy().mult(2.0/3.0));
  PVector koch_point = PVector.add(sep_point1.copy(), sub_vec.copy().mult(1.0/3.0).rotate(radians(-60)));

  // sep_point1とsep_point2, koch_pointを頂点とする三角形を描く
  triangle(
    sep_point1.x, sep_point1.y,
    koch_point.x, koch_point.y,
    sep_point2.x, sep_point2.y
  );

  // コッホ曲線を再帰的に描画する
  if(sub_vec.mag() > h_min){
    drawKoch(start, sep_point1);
    drawKoch(sep_point1, koch_point);
    drawKoch(koch_point, sep_point2);
    drawKoch(sep_point2, end);
  }
}  
  

コッホ雪片を用いた図形

書籍「フラクタル: 混沌と秩序のあいだに生まれる美しい図形 アルケミスト双書」のp.5にある、コッホ雪片を用いた図形を再現してみました。

コッホ雪片を用いた図形

コメントを残す