Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

This article is a Private article. Only a writer and users who know the URL can access it.
Please change open range to public in publish setting if you want to share this article with other users.

More than 5 years have passed since last update.

カントール集合とシェルピンスキーのギャスケット

0
Last updated at Posted at 2020-12-09

#カントール集合とは
幾何学的には、線分を3等分し、得られた3つの線分の真ん中のものを取り除くという操作を、再帰的に繰り返すことで作られる集合である。ここで、取り除く線分は開区間である。すなわち、単位区間 I = [0, 1] から、1回目の操作では (1/3, 2/3) を取り除き、2回目の操作では (1/9, 2/9) と (7/9, 8/9) を取り除き……といった具合に操作を無限に繰り返し、残った部分集合がカントール集合である。
カントール.png
#カントール集合の図示
カントール集合をProcessingを用いて図示する。
もととなる線分を表示し、取り除く部分を白で重ねる方法を取った。
単位区間 I = [0,1] からn回目の操作で取り除く部分の座標は、

(\frac{3k+1}{3^n},\frac{3k+2}{3^n})  (k=0,1,2,...,n)

と表せる。

##取り除く部分の表示
取り除く部分は、下のプログラムで表示できる。
iでは操作の回数、jではi回目の操作ででてくる線分のうち左から何番目かを指定している。

:interbal3_1
size(1200,500);
strokeWeight(1.5); 
for (int i=0; i<10; i+=1){
  for (int j=0; j < (pow(3, i)-2)/2 ; j += 1) {
    line( 100 + 1000*(2*j+1)/pow(3,i), 30*i+100, 100 + 1000*(2*j+2)/pow(3,i), 30*i+100); 
  }
}

interval.png

6行目では、1,3番目の数値で先に示した一般項を指定している。
2,4番目の数値では見やすさのために、線分のy座標を30ピクセルずつ下方向にずらしている。(5行目30*i+100の部分)

4行目のjの範囲j < (pow(3, i)-2)/2の'-2'の部分は'-1'でも成り立つ。
これはjを整数として扱い、2で割っているためである。
例えばi=2のとき、

j<(3^2-2)/2=3.5\quad j<(3^2-1)/2=4

はどちらも、jは0から3までの整数値を取る。

参考_表示する部分の図示
size(1200, 500) ;
strokeWeight(1.5) ; 
for (int i=0; i < 10; i += 1) {
  for (int j=0; j < (pow(3, i)-1)/2+1 ; j += 1) {
  line( 100 + 1000*(2*j)/pow(3,i), 30*i+100, 100 + 1000*(2*j+1)/pow(3,i), 30*i+100); 
  }
}

##カントール集合を長方形で表示する
上のinterval3_1より、線分から長方形での表示に変えて見やすくする。

cantol_rect
void setup(){
  size(1200, 300) ;
  background(255);
  fill(0);
  rect(100,100,1000,50);
}

void draw(){
  stroke(255);  //線を白色で表示
  for (int i=0; i < 3; i += 1) {
    for (int j=0; j < (pow(3, i)-2)/2 ; j += 1) {
      fill(255);  //白く塗りつぶす
      rect( 100 + 1000*(2*j+1)/pow(3,i), 100, 1000*(2*j+2)/pow(3,i)-1000*(2*j+1)/pow(3,i), 50); 
    }
  }
}

1~6行目で背景の設定と、もととなる黒い長方形を表示する。
8~16行目で白く抜きたい部分を表示する。
13行目の3番目の数値1000*(2*j+2)/pow(3,i)-1000*(2*j+1)/pow(3,i)
interval3_1の(線分の右端のx座標)-(左端のx座標)とし、表示する長方形の幅としている。

以下が実行結果である。
初期状態 (i<1)
cantor1.png

1段階目 (i<2)
cantor2.png

2段階目 (i<3)
cantor3.png

3段階目 (i<4)
cantor4.png

4段階目 (i<5)
cantor5.png

#シェルピンスキーのギャスケット
シェルピンスキーのギャスケットとは、フラクタル図形の一種であり、自己相似的な無数の三角形からなる図形である。
正三角形を用意し、各辺の中点を結んだ三角形を取り除くという操作を、残った三角形に対して無限に繰り返すことで得られる。
triangle0001.png

このシェルピンスキーのギャスケットを、上で用いた「もとの図形から取り除く部分を白で表示する」方法を使ってProcessingを用いて表示したい。
正三角形は、円弧を等分して内接する多角形を描く方法をとる。この方法では、円の中心点と半径を指定すれば内接する正三角形を描画できる。

void drawTriangle(float x,float y,float r) {
  pushMatrix();
  translate(x, y);  // 中心となる座標
  rotate(radians(-90));

  // 円を均等に3分割する点を結び、三角形をつくる
  beginShape();
  for (int i = 0; i < 3; i++) {
    vertex(r*cos(radians(360*i/3)), r*sin(radians(360*i/3)));
  }
  endShape(CLOSE);
  popMatrix();
}

そのため、まず中心点を表示できるプログラムを考える。

##中心点を表示する
ここで表示したい円の中心点が正三角形の重心(・内心・外心)と一致することから、白く塗りつぶしたい三角形の重心の座標を表す。
triangle0003.png
三角形の内部だけで考えると複雑になるため、三角形を四角形に拡張して考える。図中で点線で示した三角形は、先に表示した三角形や三角形の外側(背景)になり結果としては見えないため、考慮しないこととする。
上図のように考えると、白く塗りつぶす三角形の重心の座標は、

(x\times\frac{1}{2^n}+x\times\frac{j}{2^n}\,,\,y\times\frac{i}{2^n}-y\times\frac{1}{2^n}\times\frac{2}{3})\\
\begin{align}
(j&=0,1,2,...,2^n-1)\\
(i&=0,1,2,...,2^n)
\end{align}

と表せる。よって、まず重心を表示するプログラムは下のようである。

sierpinski_point
float x = 500;           //底辺の長さ
float y = x*sqrt(3)/2;   //正三角形の高さ
float r = y*2/3;         //外接円の半径

void setup(){
  size(800,800);
  background(255);
  drawTriangle(400,450,r);   //もととなる三角形
}
void draw(){
  strokeWeight(10);
  points(2);                 //第何ステップの点を表示するか指定する

void points(int n){
  for (int k=1;k<=n;k+=1){
    for (int i=0 ;i<=pow(2,n);i+=1){
      if (i%2==1){
        for(int j=0;j<pow(2,n)-1;j+=1){
          point(150+x*(1/pow(2,k))+x*(1/pow(2,k))*j,450-r+y*(i/pow(2,k))-y*(1/pow(2,k))*2/3+y*(1/pow(2,k)));
        }
      }
    }
  }
}

void drawTriangle(float x,float y,float r) {
  pushMatrix();
  translate(x, y);  // 中心となる座標
  rotate(radians(-90));

  // 円を均等に3分割する点を結び、三角形をつくる
  beginShape();
  for (int i = 0; i < 3; i++) {
    vertex(r*cos(radians(360*i/3)), r*sin(radians(360*i/3)));
  }
  endShape(CLOSE);
  popMatrix();
}

実行結果は下のようである。
sierpinskiDot.png
(右側に想像していなかった点が表示されたが、三角形の外側の点であるため無視できると考えた。)
##シェルピンスキーのギャスケットの表示
円の半径は第nステップでは1/(2^n)倍される。
これらのことから、シェルピンスキーのギャスケットは下のようにして描画できる。

sierpinski_gasket
float x = 500;           //底辺の長さ
float y = x*sqrt(3)/2;   //正三角形の高さ
float r = y*2/3;         //外接円の半径
int a = 3;               //第3ステップ

void setup(){
  size(800,800);
  background(255);
  fill(0);
  drawTriangle(400,450,r);
}
void draw(){
  fill(255);
  noStroke();
  tri(a);
}
void tri(int n){
  for (int k=1;k<=n;k+=1){
    for (int i=0 ;i<=pow(2,n);i+=1){
      if (i%2==1){
        for(int j=0;j<pow(2,n)-1;j+=1){
          float xx = 150+x*(1/pow(2,k))+x*(1/pow(2,k))*j;
                       \\中心点のx座標
          float yy = 450-r+y*(i/pow(2,k))-y*(1/pow(2,k))*2/3+y*(1/pow(2,k));
                       \\中心点のy座標
          drawTriangle(xx,yy,-r/pow(2,k));       \\半径は2のk乗分の1 (下向きの三角形のため負の数にした
        }
      }
    }
  }
}

void drawTriangle(float x,float y,float r) {
  pushMatrix();
  translate(x, y);  // 中心となる座標
  rotate(radians(-90));

  // 円を均等に3分割する点を結び、三角形をつくる
  beginShape();
  for (int i = 0; i < 3; i++) {
    vertex(r*cos(radians(360*i/3)), r*sin(radians(360*i/3)));
  }
  endShape(CLOSE);
  popMatrix();
}

実行結果は以下の通りである。
第0ステップ(初期状態)
sierpinski0.png

第1ステップ
shelpin1.png

第2ステップ
shelpin2.png

第3ステップ
shelpin3.png

第4ステップ
shelpin4.png

変化の様子は下のようである。
1607182435.gif

#参考文献
巴山竜来 『数学から創るジェネラティブアート』p.146課題7.1

Wikipedia カントール集合
[https://bit.ly/3grBQve]

シェルピンスキーのギャスケット
[https://bit.ly/3m9Oj8d]

@reona396 『Processingで描ける図形』
https://qiita.com/reona396/items/5fa4babc8243c4ed4914

0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?