星形を描く

 プログラムで正多角形やその応用として星形を描く手法を紹介します。複素数平面上の“1のn乗根”を利用します。

概要

 複素数平面上で“1のn乗根”は中心原点、半径1の円に内接する正n角形の頂点に対応します。したがって、それらの点を結べば簡単に正n角形が描けます。特にn=5のときは頂点を結ぶ順序を工夫すれば星形が描けますし、2つの正五角形を用意すれば少し丸みを帯びた星形なども描くことができるわけです。

ソースコード

正多角形の頂点の確保

private static final int X = 0;
private static final int Y = 1;

public int[][] getPolygonPoints(int n, int o[], float r) {
// 中心 o 、半径 r の正n角形の頂点を返します
  int[][] p = new int[n][2];
  // 1のn乗根に座標を対応させます。なお角度はラジアン単位です
  for (int c=0; c < n; c++) {
    // 1番目の頂点を上側に置くため "90.0 +" を追加しています
    p[c][X] = o[X] + (int)(r * (float)Math.cos((90.0 + 360.0 / n * c) / 180.0 * Math.PI) + 0.5f);
    // コンピュータ座標系はY軸が逆さであるためマイナスにします
    p[c][Y] = o[Y] - (int)(r * (float)Math.sin((90.0 + 360.0 / n * c) / 180.0 * Math.PI) + 0.5f);
  }
  return p;
}

星形の描画

標準的な星形を描く

public void drawStar1(Graphics g, int[] o, float r) {
  // まず正五角形の頂点を確保します
  int[][] p = getPolygonPoints(5, o, r);
  // ついで1番目の頂点から1個飛びずつで点同士を結びます
  for (int c=0; c < 5; c++) {
    g.drawLine(p[(c * 2) % 5][X], p[(c * 2) % 5][Y], p[(c * 2 + 2) % 5][X], p[(c * 2 + 2) % 5][Y]);
  }
}

少し丸みを帯びた星形を描く

// 星形に適度な丸みを帯びさせる適当な数を決めておきます
private static final float R = 0.5f;

public void drawStar2(Graphics g, int[] o, float r) {
  // まず正五角形の頂点を確保します
  int[][] p1 = getPolygonPoints(5, o, r);
  int[][] p2 = getPolygonPoints(5, o, r * R);
  for (int c=0; c < 5; c++) {
    // 原点に対称な位置に移します
    p2[c][X] = o[X] - (p2[c][X] - o[X]);
    p2[c][Y] = o[Y] - (p2[c][Y] - o[Y]);
  }
  for (int c=0; c < 5; c++) {
    // ついで順に頂点を結びます
    g.drawLine(p1[c][X], p1[c][Y], p2[(c + 3) % 5][X], p2[(c + 3) % 5][Y]);
    g.drawLine(p2[(c + 3) % 5][X], p2[(c + 3) % 5][Y], p1[(c + 1) % 5][X], p1[(c + 1) % 5][Y]);
  }
}

複素数平面の活用

 上記のように複素数平面はたいへん有用です。極座標から直交座標に変換するのも簡単ですから、点の回転などでも活用できます。グラフィックスの分野においてはベクトルや複素数などの数学の知識が役に立つのでした。

著作・制作/永施 誠
e-mail; webmaster@stardustcrown.com