ここでは、正三角形と正方形によるタイリング(2通りあるうちの1つで「正三角形と正方形①」とします)を再現してみました。なお、今回のタイリングを作成するにあたって、書籍「アートで魅せる数学の世界」の「2種類以上の正多角形によるタイリング」(p.94)を参考にしました。

正三角形と正方形①

タイリング〈正三角形と正方形①〉は以下のような図形になります。

正三角形と正方形①

以下で、このタイリング〈正三角形と正方形①〉の描き方について解説していきます。

正三角形と正方形①の描き方

対称性について

まず、このタイリング〈正三角形と正方形①〉の対称性について考えます。

正三角形と正方形①の対称性

上図のように、タイリングのパターンをじっくり見ていくと、上図の赤丸の周りの180°回転に対して図形は回転対称になっていることが分かります。そして縦横の赤色の線に対して図形は鏡映対称であり、赤色の点線の軸に対して図形はすべり鏡映対称であることがわかります。また、黒色の点を格子としてみると、近接する4つの黒色の点同士が菱形を形作っていることから、黒色の点は菱形格子になっていることが分かります。これらをまとめると、タイリング〈正三角形と正方形①〉は、壁紙群CMMの対称性を持つことが分かります。

アイソヘドラルタイリングの観点でみると、IH17(CMM)IH26(CMM)IH54(CMM)のいずれにも分類することができますが、今回は基本図形が一番細かくなるIH54(CMM)で再現しました。

基本図形の準備

タイリング〈正三角形と正方形①〉に現れる正三角形や正方形の一辺の長さを\(1\)とすると、タイリング〈正三角形と正方形①〉の基本図形は、斜辺の長さが\(1\)となる30°、60°、90°の直角三角形と、一辺の長さが\(1/2\)となる正方形を組み合わせたものになります(下図参照)。

正三角形と正方形①の基本図形

菱形格子の準備

また、菱形格子は、上図の基本図形で示したように、正方形の下部2つの頂点と直角三角形の斜辺の中点が近接する菱形格子点となるように準備します。

壁紙群CMMの対称性に合わせて並べる

ここまで準備ができたら、あとは壁紙群CMMの対称性に合わせて基本図形を並べていくことでタイリング〈正三角形と正方形①〉を作成することができます。

ソースコード

今回再現したタイリング〈正三角形と正方形①〉のプログラムのソースコードを示しておきます。

PVector[][] lattice; // 格子点ベクトル
PShape tile; // タイル
PVector[] base = new PVector[2]; // 格子を張るベクトル
int col_num = 16; // 描画するタイルの列の数
float scalar; // タイルの辺の長さ

void setup(){
  
  size(1000, 1000, P2D);
  noFill();
  noLoop();
  scalar = width * 1.0 / ( col_num / 2.0 ); // 描画ウィンドウと行の数からタイルの大きさを決定
  makeRhombusVector(); // 菱形格子を張るベクトルの生成
  makeLattice(); // 格子点ベクトルを生成
  makeTileCMM(); // タイルを生成
  drawTiling(); // タイリングを描画
}

// 菱形格子を張るベクトルを生成する関数
void makeRhombusVector(){
  base[0] = new PVector(0.5, 0.0);
  base[1] = new PVector(0.25, (2.0+sqrt(3.0))/4.0);
}

// 菱形格子を生成する関数
void makeLattice(){
  int row_num = ceil(col_num / base[1].y); // 行の数
  lattice = new PVector[col_num+1][row_num];
  PVector v;
  for (int i = 0; i < col_num+1; i++){
    for (int j = 0; j < row_num; j++){
      if( j%2 == 0 ){
        v = new PVector(base[0].x * i * scalar, 0.0 ); 
        v.add( new PVector(0.0, base[1].y * j * scalar));
      } else {
        v = new PVector(base[0].x * i * scalar + base[1].x * scalar, 0.0 ); 
        v.add( new PVector(0.0, base[1].y * j * scalar));
      }
      lattice[i][j] = v;
    }
  }
}

// 四角形を生成する関数(基本図形)
PShape makeRectangle(){
  
  PVector[] v = new PVector[4]; // 四角形の頂点

  v[0] = new PVector(0.0,0.0);
  v[1] = base[0].copy().mult(scalar);
  v[2] = PVector.fromAngle( -radians(60.0) ).mult( scalar / 2.0 );
  v[2].add( new PVector( base[1].x, - base[1].y).mult(scalar) );
  v[3] = PVector.fromAngle( radians(120.0) ).mult( scalar / 2.0 );
  v[3].add( new PVector( base[1].x, - base[1].y).mult(scalar) );

  PVector v_middle = new PVector( 1.0 ,-1.0).mult(scalar / 2.0);
  
  PShape trapezium = createShape(GROUP);

  // 正方形を描く
  fill(255,0,0);
  noStroke();
  PShape rect = createShape();
  rect.beginShape(); 
  rect.vertex(v[0].x, v[0].y);
  rect.vertex(v[1].x, v[1].y);
  rect.vertex(v_middle.x, v_middle.y);
  rect.vertex(v[3].x, v[3].y);
  rect.endShape(CLOSE);
  trapezium.addChild(rect);

  // 30,60,90二等辺三角形を描く
  fill(0,0,255);
  PShape tri = createShape();
  tri.beginShape(); 
  tri.vertex(v_middle.x, v_middle.y);
  tri.vertex(v[2].x, v[2].y);
  tri.vertex(v[3].x, v[3].y);
  tri.endShape(CLOSE);
  trapezium.addChild(tri);

  // 正方形の一部の輪郭を描く
  stroke(0,0,0);
  PShape rect_line = createShape();
  rect_line.beginShape(); 
  rect_line.vertex(v[0].x, v[0].y);
  rect_line.vertex(v[3].x, v[3].y);
  rect_line.vertex(v[0].x, v[0].y);
  rect_line.endShape(CLOSE);
  trapezium.addChild(rect_line);
  
    // 三角形の一部の輪郭を描く
  stroke(0,0,0);
  PShape tri_line = createShape();
  tri_line.beginShape(); 
  tri_line.vertex(v[2].x, v[2].y);
  tri_line.vertex(v[3].x, v[3].y);
  tri_line.vertex(v_middle.x, v_middle.y);
  tri_line.endShape();
  trapezium.addChild(tri_line);
  
  return trapezium;
}

// タイルを生成する関数
void makeTileCMM(){
  tile = createShape(GROUP); // PShapeのグループを作る
  for(int i=0; i<2; i++){
    for(int j=0; j<2; j++){
      PShape rectangle = makeRectangle(); // 四角形の生成
      rectangle.scale(pow(-1,j),pow(-1,i)); // 四角形の反転
      tile.addChild(rectangle); // グループに追加
    }
  }
}

// 格子形状に合わせたタイリングを描画する関数
void drawTiling(){
//  background(255);
  for (int i=0; i<lattice.length; i++){
    for (int j=0; j<lattice[0].length; j++){
      if( (j%4 == 0 && i%2 == 0 ) || (j%4 == 2 && i%2 == 1 ) ){
        tile.resetMatrix();
        tile.translate(lattice[i][j].x, lattice[i][j].y); // タイルの位置を指定
        shape(tile); // タイルを描画
      } 
    }
  }
}

参考

参考までに、アイソヘドラルタイリングIH17(CMM)IH26(CMM)とみなしたときの基本図形を示しておきます。

IH17(CMM)とした場合の基本図形
IH26(CMM)とした場合の基本図形