Creative Coding

ジェネラティブアート試行錯誤04・三角形な三〇六輪はrotate関数で割と簡単

五輪マーク風な三〇六輪をまたまた検討です。3から14まで加算すると102になりますが、これが3つで306になります。3つなので正三角形風に作ってみます。正三角形の各辺から外に向かって五輪風に円を描くように。

下の図のように、1個目の五輪風マークは正三角形の底辺から外へ(黄色丸の部分)、2個目は左辺から外へ(灰色丸の部分)、3個目は右辺から外へ(緑丸の部分)描いていきます。

ちなみに図形を90度刻みでずらすのは問題ないのですが、斜めにずらすには三角関数が必要なようで色々調べてました。正三角形のそれぞれの辺に沿って丸をずらしながら描くにはどうしたらよいかと。

が、角度がつくとは言え、丸を描く方向に向かって隣に配置するのはどの辺に対しても同じなので、座標ごとずらす方法はないのかと思ったら、Processingにありました。rotate関数です。

描き方

  • 上図の左上の赤点が(x,y)=(0,0)の原点。黄色点の位置を求めて描いていきます。このときはrotateなし。X軸、Y軸ともに正の方向に向かうので、X軸サイン、Y軸サインともにプラス。
  • 次に灰色点の位置を求めて描いていきます。正三角形はすべての角が60度ですが、もともとのX軸(黄色線)の傾きと灰色X軸の傾きの差分は120度になるので、この分rotateします(rotate(radians(120));)。またrotateする前に、灰色点を座標の原点としています(translate)。X軸サインはマイナス、Y軸サインはプラス。
  • 最後に緑色点の位置を求めて、rotateします。もともとのX軸の傾きと緑色X軸の傾きの差分は60度になるので、rotate(radians(60));とします。ここでも緑色点を座標の原点としています。X軸サインはマイナス、Y軸サインはマイナス。
  • なお、座標系を動かすので、それぞれ動かす前に座標系を初期化します(resetMatrix)。
  • 灰色点、緑色点の求め方ですが、それぞれが直近する黄色の丸の位置から斜め上に60度ずれたあたりにしています(30度、60度の直角三角形の場合の辺の長さ=1:2:√3なので、それ風に求めました)。これでいいのかどうかはなんともですが。
  • 丸を描くのはdrawという関数を作成して行っていますが、X軸サイン、Y軸サインとして、プラスであれば1、マイナスであれば-1を引数として渡しています(xSgn、ySgn)。
  • draw関数には引数として書き出しのX、Yの値も渡していますが、直前にtranslateしているためX、Yともにゼロなので渡さなくてもよいのですが、前の試行錯誤03で作ったdrawを元にしており、ここは引数として残しました。
  • 丸の色は以前からやっているのに沿って、色相、彩度を設定し、明度のみ変化させています。
// 初期値
// 輪の個数:底辺個数=itr1
int itr1 = 14;
int itr2 = 3;
// 輪の直径、線の太さ、X軸方向の増分、Y軸方向の増分
float wd = 40;
float linewgt = 3;
float spx = 48;
float spy = 20;
// 色の初期値(HBSのH色相3種類、S彩度3種類)
// 1個目:黄系、2個目:グレー系、3個目:緑系
float strokeH1 = 60.0; 
float strokeH2 = 0.0;
float strokeH3 = 90.0;
float strokeS1= 100.0;
float strokeS2 = 0.0;
float strokeS3 = 40.0;
// 明度初期値
float maxB = 100.0;


//
// 描画ウィンドウサイズ決定(ざっくり個数の2倍としておく)
//
void settings() {
int szx = 2 * (int(spx) * itr1);
int szy =szx;
size(szx, szy);
}

//
// メイン処理
//
void setup() {
  float xStart1, yStart1, xStart2, yStart2;  // 書き出し位置
  
  colorMode(HSB,360,100,100);                // カラーモード設定
  strokeWeight(linewgt);                     // 線の太さ
  background(0,0,100);                       // 背景色(白)
  smooth();                                  // アンチエイリアス
  noFill();                                  // 塗りつぶしなし
  
  // 1個目:三角形の底辺から下向きに描く
  // 書き出し位置決定
  xStart1 = width/2 - spx * itr1 / 2;
  yStart1 = height/3*2;
  translate(xStart1,yStart1);                // 書き出し位置を座標(0,0)にする
  draw(0,0,1,1,strokeH1,strokeS1);
  
  // 2個目:三角形の左辺から左斜め上向きに描く  
  // 書き出し位置決定 
  xStart2 = xStart1 - spx + spx/2;
  yStart2 = yStart1 - sqrt(3) * spx/2;
  resetMatrix();                             // 座標系の初期化
  translate(xStart2, yStart2);
  rotate(radians(120));
  draw(0,0,-1,1,strokeH2,strokeS2);
  
  // 3個目:三角形の右辺から右斜め上向きに描く
  // 書き出し位置決定  
  xStart2 = xStart1 + spx*(itr1-1) + spx/2;
  yStart2 = yStart1 - sqrt(3) * spx/2;  
  resetMatrix();                             // 座標系の初期化
  translate(xStart2, yStart2);
  rotate(radians(60));
  draw(0,0,-1,-1,strokeH3,strokeS3);

  save("306rin.png");
}


//
// 輪を五輪風に描く
//
void draw(float xPos, float yPos, float xSgn, float ySgn, float varH, float varS) {
  int itrRW = 0;
  int itrCircle;
  float scale;
  float xStart = xPos;                         // X方向の開始位置を設定

// 輪の個数がMAX値〜MIN値まで
  for (int itrMax = itr1; itrMax >= itr2; itrMax--) {      
    itrRW++;                                   // 行カウンタ加算
    itrCircle = 0;                             // 輪カウンタ初期化 
    
    while (itrCircle < itrMax) {               // 輪カウンタが各行の輪の個数まで以下を行う
      itrCircle++;                             // 輪カウンタ加算
      scale = maxB - float(itrRW + itrCircle); // 明度を行数と輪カウンタより計算する
      stroke(varH,varS,scale);                 // 描画色を決定
      ellipse(xPos, yPos, wd, wd);             // 楕円を描く
      xPos = xPos +spx * xSgn;                 // 次の輪のx位置を決める
    }
    xPos = xStart + (spx * itrRW) / 2 * xSgn;  // 次の行のx位置を決める
    yPos = yPos + spy * ySgn;                  // 次の行のy位置を決める
  }
}

雑感

図形の形が盾みたいに見えるので、アンチウィルスソフトのマークみたいになってしまったのが残念でした。収まりのよい三色というのも調和的でよくないです。

※以下が描画ウィンドウサイズ指定込みの描画した画像(最初の画像はトリミングしています)。余白が多すぎますね。

(追記)
色相と彩度をランダムにしてみたら、それの方が全然いい感じでしたよ。
コードの下から8行目を以下のように変えました。
修正前:stroke(varH,varS,scale);
修正後:stroke(random(360),random(100),scale);