> show canvas only <


/* built with Studio Sketchpad: 
 *   https://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   https://studio.sketchpad.cc/sp/pad/view/ro.5F8RfJgRkRm/rev.935
 * 
 * authors: 
 *   Lionel Ringenbach
 *   Sami
 *   

 * license (unless otherwise specified): 
 *   creative commons attribution-share alike 3.0 license.
 *   https://creativecommons.org/licenses/by-sa/3.0/ 
 */ 



// Written by Lionel Ringenbach

// params
int n = 8;
float slowFactor = 2;
float div = 360 * slowFactor;
float inc = TWO_PI / div;
float alpha = 50;

// globals
float[] dots;
float centerX;
float centerY;
float circleWidth;

// colors
color black = color(0);
color gray = color(220);
color white = color(255);
color cyan = color(0, 174, 239);
color magenta = color(236, 0, 140);
color yellow = color(255, 242, 0);

void setup() {
  smooth();
  size(800, 800);
  stroke(white);
  strokeWeight(0.5);
  noStroke();

  dots = new float[n];  
  centerX = width / 2;
  centerY = height / 2;
  circleWidth = width - 100;

  for (int i = 0; i < n; ++i) {
    dots[i] = i * TWO_PI / n;
  }
}

void draw() {
  background(white, 255);

  for (int i = 0; i < n; i++) {
    int r = (i + 3) % 3;

    if (r == 0)
      fill(cyan, alpha);
    else if (r == 1)
      fill(yellow, alpha);
    else if (r == 2)
      fill(magenta, alpha);

    for (int j = 0; j < n; ++j) {
      if (i != j) {
        PVector p1 = pointOnCircle(centerX, centerY, dots[i], circleWidth / 2);
        PVector p2 = pointOnCircle(centerX, centerY, dots[j], circleWidth / 2);
        triangle(p1.x, p1.y, centerX, centerY, p2.x, p2.y);
      }
    }
  }

  for (int i = 0; i < n; ++i) { 
      int r = (i + 2) % 2;
      dots[i] += inc * (r + 1);
  }

  shifter(8, 0, 0, width / 2, height / 2);
  mirror();
}

PVector pointOnCircle(float x, float y, float t, float r) {
  PVector pos = new PVector();
  pos.x = r * cos(t) + x;
  pos.y = r * sin(t) + y;
  return pos;
}

///////////////
// Utilities //
///////////////

int getPixelIndex(int x, int y) {
  return x + y * width;
}

void shiftPixels(int xA, int yA, int xB, int yB) {
  int idxA = getPixelIndex(xA, yA);
  int idxB = getPixelIndex(xB, yB);
  int temp = pixels[idxA];
  pixels[idxA] = pixels[idxB];
  pixels[idxB] = temp;
}

/////////////
// Filters //
/////////////

void shifter(int nVert, int startX, int startY, int areaWidth, int areaHeight) {
  int endX = startX + areaWidth - 1;
  int endY = startY + areaHeight - 1;
  int hVert = areaHeight / nVert;
  int offset = areaWidth % 2;

  loadPixels();
  for (int y = startY; y < endY; ++y) {
    for (int x = startX; x < areaWidth / 2; ++x) {
      if (x <= width && y <= height) {
          int relY = y - startY;
          int d = y / hVert;
          if (d % 2 == 0) {
            int newX = endX - x - offset;         
            shiftPixels(x, y, newX, y);
          }
      }
    }
  }
  updatePixels();
}

void mirror() {
  PImage img = get(0, 0, width / 2, height / 2);

  pushMatrix();

  translate(width, 0);
  scale(-1, 1);
  image(img, 0, 0);

  translate(0, height);
  scale(1, -1);
  image(img, 0, 0);

  translate(width, 0);
  scale(-1 ,1);
  image(img, 0, 0);

  popMatrix();
}