Page Loading

Triangle Grid

Processing.js

A grid made of triangles made in Processing. Click anywhere to make art! Each triangle iterates through three colors.

                        
Triangle[] triangles;
color[] colors = {color(255, 255, 184), color(122, 224, 184), color(51, 153, 102)}; //the ordered set of triangle colors (can be any length greater than 0)
float triBase; //length of each side of each triangle
float triHeight; //height of each triangle (corresponds to the width of each column of triangles)

void setup() { //sets up canvas, initializes global variables and triangle grid
  size(screen.width, screen.height);
  
  triBase = 50.0;
  triHeight = triBase/2.0 * sqrt(3);  
  int cols = int(ceil(width/triHeight)); //number of columns of triangles
  int rows = (int(ceil(height/triBase)) + int(ceil((height-(triBase/2.0)) / triBase)) + 1 ); //number of triangles per column
  triangles = new Triangle[rows * cols]; //number of triangles on the grid
  
  for(int c=0; c<cols; c++){ //sets up the triangle grid column by column
    for(int r=0; r<rows; r++){
      triangles[(c*rows)+r] = new Triangle((c*triHeight) + triHeight*((c+r)%2), r*(triBase/2.0), int(pow(-1, r+c)));  //alternates right-facing and left-facing triangles down each column
    }
  }
}

void draw() { //called each frame; displays each triangle in the grid
  background(#ffffff);
  for (int i=0; i<triangles.length; i++) {
    triangles[i].display();
  }
}

void mousePressed() { //called when mouse is pressed; calls updateColor to update the color of the pressed triangle
    for (int i=0; i<triangles.length; i++) {
      if(triangles[i].isInside(mouseX, mouseY)){
        triangles[i].updateColor();
        break;
      }
    }
}

//class representing each triangle in the grid
class Triangle {
  float x, y, x2, y2, x3, y3; //coordinates of the 3 vertices
  int dir; //-1 or 1, corresponding to left-facing and right-facing triangles, respectively
  int curColorIndex; //index of the current triangle color in colors array
  boolean isColored; //false when triangle is in default uncolored state, true otherwise
  
  Triangle(float x, float y, int dir) { //constructor to initialize instance variables; calculates the other vertex positions based on the passed in first vertex (x, y) and dir
    this.x = x;
    this.y = y;
    this.dir = dir;
    isColored = false;
    curColorIndex = colors.length;
    y2 = y + (triBase/2.0);
    y3 = y - (triBase/2.0);
    x2 = x3 = x + (triHeight*dir);  
  }
  
  void display() { //draws the triangle
    if(isColored){
      fill(colors[curColorIndex]);
      stroke(colors[curColorIndex]);
    } else{
      noFill();
      stroke(#f0f7ff);
    }
    triangle(x, y, x2, y2, x3, y3);
  }
  
  boolean isInside(int ix, int iy){ //returns true if point (ix, iy) lies inside the triangle, false otherwise
    float dx = (ix - x)/dir;
    if(dx < triHeight && dx >= 0){ //if point is in the same column as the triangle
      float dy = abs(iy - y);
      float yInside = abs(dx / sqrt(3));
      if(dy <= yInside){ //if point is in the same triangle
        return true;
      }
    }
    return false;
  }
  
  void updateColor(){ //Updates the current color index and isColored boolean, so the next frame is drawn with the correct color
    curColorIndex = (curColorIndex + 1) % (colors.length + 1); //curColorIndex cycles from 0 through colors.length, inclusive
    isColored = (curColorIndex < colors.length); //set isColored to false when curColorIndex is out of array bounds
  }
}