sketch_200205b

sketch_200205b.pde

int[] nPointsList;
float[] freqList;
float[] radiusList;
color[] palette;

final int BUFF_SIZE = 65536;
MyPoint[] prev;
MyPoint[] curr;
int cursor;

boolean saveFlag = false;

void setup() {
  size(1000, 1000);
  
  int max_depth = (int)random(2, 5);
  
  nPointsList = new int[max_depth];
  freqList = new float[max_depth];
  radiusList = new float[max_depth];
  
  for (int k = 0; k < max_depth; k++) {
    nPointsList[k] = (int)random(2, 5);
    freqList[k] = (int)random(1, 4) * (random(1) > 0.5 ? 1 : -1);
    radiusList[k] = random(5.0, 100.0);
  }
  
  palette = selectPalette();
  
  // 前の時点と現在の時点における各座標を保存しておくバッファを初期化
  prev = null;
  curr = new MyPoint[BUFF_SIZE];
  cursor = 0;
  
  strokeWeight(2.0);
  background(0);
  
  saveFlag = false;
}

void draw() {
  translate(width / 2.0, height / 2.0);
  
  float t = (frameCount - 1) / 60.0;
  float x = 200.0 * cos(t);
  float y = 200.0 * sin(t);
  
  // 一周したら止める
  if (t >= TWO_PI) {
    saveFlag = true;
    noLoop();
  }
  
  // 現在の時点におけるペンの座標を計算する
  drawLines(x, y, t, 0);
  
  // 2フレーム目以降なら,前の時点と現在の時点の対応する点を結ぶ
  if (prev != null) {
    for (int k = 0; k < curr.length; k++) {
      if (curr[k] == null) {
        break;
      }
      if (curr[k].depth == 0) {
        continue;
      }
      stroke(palette[curr[k].depth % palette.length]);
      line(prev[k].x, prev[k].y, curr[k].x, curr[k].y);
    }
  }
  
  // 現在の時点のバッファを前の時点のバッファにコピーし,
  // 現在の時点のバッファを初期化
  prev = curr.clone();
  curr = new MyPoint[BUFF_SIZE];
  cursor = 0;
  
  if (saveFlag) {
    saveFrame(String.format("frames/%s", timestamp("Project", ".png")));
  }
}

void drawLines(float cx, float cy, float t, int depth) {
  
  MyPoint p = new MyPoint(cx, cy, depth);
  curr[cursor++] = p;
  
  if (depth == nPointsList.length) {
    return;
  }
  
  int npoints = nPointsList[depth];
  float f = freqList[depth];
  float r = radiusList[depth];
  
  for (int k = 0; k < npoints; k++) {
    float dx = r * cos(t * f + TWO_PI / npoints * k);
    float dy = r * sin(t * f + TWO_PI / npoints * k);
    drawLines(cx + dx, cy + dy, t, depth + 1);
  }
}

color[] selectPalette() {
  color[][] palettes = new color[][] {
    {color(0xED, 0x24, 0x53, 0x80), color(0xF5, 0xBC, 0x48, 0x80),  color(0x58, 0xD6, 0xA8, 0x80), color(0x52, 0x3E, 0xFF, 0x80)},
    {color(0xDA, 0x25, 0x50, 0x80), color(0x34, 0x1F, 0x47, 0x80), color(0x96, 0x96, 0xD5, 0x80)},
    {color(0x69, 0xE8, 0x7E, 0x80), color(0x66, 0x2E, 0x8B, 0x80), color(0xEC, 0x44, 0x39, 0x80)},
    {color(0x53, 0x36, 0x33, 0x80), color(0xC5, 0x4F, 0x1F, 0x80), color(0xE7, 0xB8, 0x72, 0x80), color(0x75, 0x82, 0x5A, 0x80)},
    {color(0x00, 0xA3, 0xEB, 0x80), color(0xFF, 0x60, 0x40, 0x80)},
    {color(0xFF, 0xF8, 0xB8, 0x80), color(0x01, 0xB3, 0xED, 0x80), color(0xB3, 0x4E, 0x7E, 0x80)},
  };
  return palettes[(int)random(palettes.length)];
}

static final String timestamp(final String name, final String ext) {
  return name + "-" + year() + nf(month(), 2) + nf(day(), 2) +
    "-" + nf(hour(), 2) + nf(minute(), 2) + nf(second(), 2) + ext;
}

class MyPoint {
  
  public float x;
  public float y;
  public int depth;
  
  public MyPoint(float x, float y, int depth) {
    this.x = x;
    this.y = y;
    this.depth = depth;
  }
}

/*
  nPointsList = new int[] {3, 2, 4};
  freqList = new float[] {4.0, 1.0, 5.0};
  radiusList = new float[] {50.0, 20.0, 5.0};
  
  palette = new color[] {
    color(0xED, 0x24, 0x53),
    color(0xF5, 0xBC, 0x48), 
    color(0x58, 0xD6, 0xA8),
    color(0x52, 0x3E, 0xFF)
  };
*/