Loops and repeating a pattern

Viewed 58

I'm completing a pattern for my Processing class this is my code so far

      color[] lemonspears =
      {
       #f9f8ae, //#0 highlight lemon
       #fffc24, //#1 mid lemon
       #d6c000, //#2 dark lemon
       #242000, //#3 detailing
       #e7b416, //#4 highlight pear 
       #a8da2b, //#5 mid pear
       #667a2a, //#6 dark pear
        #f2e6ba, //#7 light beige
        #8acdff, //#8 light blue
       #0551ff, //#9 dark blue

       };

       color palette[] = lemonspears;
       PShape Circle, Triangle;
       PShape Oval, Pear, Olives, Leaves;
       PShape Twig, Dots, Stem, Lines;

       PShape[] Fruit = new PShape[1];
       PShape[] Details = new PShape[1];

       void setup()
       {
       size(800, 800);
       background(palette[7]);
       }


       void draw() {
       scale(.3,.3);
       pushMatrix();
       //BACKGROUND
       //outer circles

       fill(palette[8]);
       stroke(palette[9]);
       strokeWeight(5);
       circle( 30, 40, 200);
       circle( 760, 40, 200);
       circle( 30, 760, 200);
       circle( 760, 760, 200);

       //mid triangles
       fill(palette[9]);
        stroke(palette[8]);
         triangle( 350, 0, 405, 80, 460, 0);
        stroke(palette[8]);
      triangle( 350, 800, 405, 720, 460, 800);

        //mid circle
          ellipseMode(CENTER);
        stroke(palette[1]);
        fill(palette[4]);
        circle( 405, 400, 200);

       // right dots
        strokeWeight(3);
       stroke(palette[1]);
        fill(palette[4]);
        circle(630, 330, 11);
        circle(720, 400, 11);
        circle(630, 470, 11);

        // left dots
        circle(170, 330, 11);
       circle(80, 400, 11);
       circle(170, 470, 11);
     popMatrix();
     }

I want this image as is to act as a tile running across and throughout the screen, I'm wondering what the best way to do this is using loops. I've tried translate() but that doesn't work for obvious reasons. Thanks!

2 Answers

You can save your tile as a PImage (https://processing.org/reference/PImage.html) and then just use a loop to tessellate it by considering your tile as a square.

The following solution should produce the output you are looking for.

color[] palette =
  {
  #f9f8ae, //#0 highlight lemon
  #fffc24, //#1 mid lemon
  #d6c000, //#2 dark lemon
  #242000, //#3 detailing
  #e7b416, //#4 highlight pear 
  #a8da2b, //#5 mid pear
  #667a2a, //#6 dark pear
  #f2e6ba, //#7 light beige
  #8acdff, //#8 light blue
  #0551ff, //#9 dark blue

};

boolean drawTile = true;

void setup() {
  size(800, 800);
  background(palette[7]);
}

void tessellateTile(float scale){
  // Save the sketch as a PImage
  PImage tile = get(0, 0, width, height);
  
  // Calculate height and width of scaled tile
  int tileWidth = (int)(width*scale);
  int tileHeight = (int)(height*scale);
  
  // Resize tile
  tile.resize(tileWidth, tileHeight);
  
  // Redraw the tile at every position
  for(int i = 0; i <= width; i+= tileWidth){
    for(int j =0; j <= height; j+= tileHeight){
      image(tile, i, j);
    }
  }  
}

void draw() {
  // Tile should be drawn and tessellated once
  if(drawTile){
      //BACKGROUND
      //outer circles
      fill(palette[8]);
      stroke(palette[9]);
      strokeWeight(5);
      circle( 30, 40, 200);
      circle( 760, 40, 200);
      circle( 30, 760, 200);
      circle( 760, 760, 200);
    
      //mid triangles
      fill(palette[9]);
      stroke(palette[8]);
      triangle( 350, 0, 405, 80, 460, 0);
      stroke(palette[8]);
      triangle( 350, 800, 405, 720, 460, 800);
    
      //mid circle
      ellipseMode(CENTER);
      stroke(palette[1]);
      fill(palette[4]);
      circle( 405, 400, 200);
    
      // right dots
      strokeWeight(3);
      stroke(palette[1]);
      fill(palette[4]);
      circle(630, 330, 11);
      circle(720, 400, 11);
      circle(630, 470, 11);
    
      // left dots
      circle(170, 330, 11);
      circle(80, 400, 11);
      circle(170, 470, 11);
      
      // Comment this line out to just work on your single tile.
      tessellateTile(0.3);
      
      drawTile = false;
  }
}

You're on the right track using pushMatrix()/popMatrix() to isolate coordinate spaces to translate the group of shapes individually. If you do that in a for loop, incrementing x,y positions accordingly you should be able to render repeat the pattern:

color[] lemonspears =
  {
  #f9f8ae, //#0 highlight lemon
  #fffc24, //#1 mid lemon
  #d6c000, //#2 dark lemon
  #242000, //#3 detailing
  #e7b416, //#4 highlight pear 
  #a8da2b, //#5 mid pear
  #667a2a, //#6 dark pear
  #f2e6ba, //#7 light beige
  #8acdff, //#8 light blue
  #0551ff, //#9 dark blue

};

color palette[] = lemonspears;

void setup()
{
  size(800, 800);
  
}

void draw() {
  background(palette[7]);
  scale(.3, .3);
  for(int i = 0 ; i < 3; i++){
    for(int j = 0 ; j < 3; j++){
      pushMatrix();
      translate(150 + i * mouseX,150 + j * mouseX);
      //BACKGROUND
      //outer circles
    
      fill(palette[8]);
      stroke(palette[9]);
      strokeWeight(5);
      circle( 30, 40, 200);
      circle( 760, 40, 200);
      circle( 30, 760, 200);
      circle( 760, 760, 200);
    
      //mid triangles
      fill(palette[9]);
      stroke(palette[8]);
      triangle( 350, 0, 405, 80, 460, 0);
      stroke(palette[8]);
      triangle( 350, 800, 405, 720, 460, 800);
    
      //mid circle
      ellipseMode(CENTER);
      stroke(palette[1]);
      fill(palette[4]);
      circle( 405, 400, 200);
    
      // right dots
      strokeWeight(3);
      stroke(palette[1]);
      fill(palette[4]);
      circle(630, 330, 11);
      circle(720, 400, 11);
      circle(630, 470, 11);
    
      // left dots
      circle(170, 330, 11);
      circle(80, 400, 11);
      circle(170, 470, 11);
      popMatrix();
    }
  }
}

(Notice I've removed unused variables)

Mady Daby's method will work too (+1) With that approach I would also like to point out that you could use draw a quad with a texture() applied and textureWrap(REPEAT) which would be faster and remove the need to the nested for loop (and multiple image() calls):

color[] lemonspears =
  {
  #f9f8ae, //#0 highlight lemon
  #fffc24, //#1 mid lemon
  #d6c000, //#2 dark lemon
  #242000, //#3 detailing
  #e7b416, //#4 highlight pear 
  #a8da2b, //#5 mid pear
  #667a2a, //#6 dark pear
  #f2e6ba, //#7 light beige
  #8acdff, //#8 light blue
  #0551ff, //#9 dark blue

};

color palette[] = lemonspears;

PImage snapshot;

void setup()
{
  // use the OpenGL renderer to use textures
  size(800, 800, P2D);
  background(palette[7]);
  
  scale(.3, .3);
  pushMatrix();
  //BACKGROUND
  //outer circles

  fill(palette[8]);
  stroke(palette[9]);
  strokeWeight(5);
  circle( 30, 40, 200);
  circle( 760, 40, 200);
  circle( 30, 760, 200);
  circle( 760, 760, 200);

  //mid triangles
  fill(palette[9]);
  stroke(palette[8]);
  triangle( 350, 0, 405, 80, 460, 0);
  stroke(palette[8]);
  triangle( 350, 800, 405, 720, 460, 800);

  //mid circle
  ellipseMode(CENTER);
  stroke(palette[1]);
  fill(palette[4]);
  circle( 405, 400, 200);

  // right dots
  strokeWeight(3);
  stroke(palette[1]);
  fill(palette[4]);
  circle(630, 330, 11);
  circle(720, 400, 11);
  circle(630, 470, 11);

  // left dots
  circle(170, 330, 11);
  circle(80, 400, 11);
  circle(170, 470, 11);
  popMatrix();
  
  // cache the drawn data as a bitmap 
  snapshot = get(0, 0, 220, 220);
  // set texture coordinates to normal (between 0.0 and 1.0) instead of pixel coordinates
  textureMode(NORMAL);
  // this will repeat the texture for you depending on the U, V coordinates passed in vertex(x, y, u, v)
  textureWrap(REPEAT);
}


void draw() {
  // map mouse position to tile repetitions
  int repeats = (int)map(mouseX, 0, width, 3, 21);
  // start a quad shape
  beginShape();
  // apply the texture
  texture(snapshot);
  // pass x, y, U, V coordinates
  // top left corner
  vertex(0, 0         , 0, 0);
  // top right corner
  vertex(width, 0     , repeats, 0);
  // bottom right cornder
  vertex(width, height, repeats, repeats);
  // bottom left corner
  vertex(0, height, 0 , repeats);
  endShape();
  // optional usage text
  fill(0);
  text("move mouse on X axis", 10, 15);
}

Hopefully the comment help illustrate the idea.

I've noticed you had PShape variables declared at the top, but not used.

You could use that too. For example you could use createShape() to create a GROUP of all the circles and triangles (of course re-use createShape() for each primitive (e.g. createShape(ELLIPSE, x, y, w, h), createShape(TRIANGLE, x1, y1, x2, y2, x3, y3), etc.) and lastly you'd simply call shape() for render the group in a for loop to render the tiles:

color[] lemonspears =
  {
  #f9f8ae, //#0 highlight lemon
  #fffc24, //#1 mid lemon
  #d6c000, //#2 dark lemon
  #242000, //#3 detailing
  #e7b416, //#4 highlight pear 
  #a8da2b, //#5 mid pear
  #667a2a, //#6 dark pear
  #f2e6ba, //#7 light beige
  #8acdff, //#8 light blue
  #0551ff, //#9 dark blue

};

color palette[] = lemonspears;
// container for mulitple circles and triangles;
PShape pattern;

void setup()
{
  size(800, 800);
  
  pattern = createShape(GROUP);
  // outer circles
  pattern.addChild(circle(30, 40, 200, 5, palette[9], palette[8]));
  pattern.addChild(circle(760, 40, 200, 5, palette[9], palette[8]));
  pattern.addChild(circle(30, 760, 200, 5, palette[9], palette[8]));
  pattern.addChild(circle(760, 760, 200, 5, palette[9], palette[8]));
  
  //mid triangles
  pattern.addChild(triangle(350, 0, 405, 80, 460, 0, 5, palette[9], palette[8]));
  pattern.addChild(triangle(350, 800, 405, 720, 460, 800, 5, palette[9], palette[8]));
  
  //mid circle
  pattern.addChild(circle(405, 400, 200, 5, palette[4], palette[1]));
  
  // right dots
  pattern.addChild(circle(630, 330, 11, 3, palette[4], palette[1]));
  pattern.addChild(circle(720, 400, 11, 3, palette[4], palette[1]));
  pattern.addChild(circle(630, 470, 11, 3, palette[4], palette[1]));
  
  // left dots
  pattern.addChild(circle(170, 330, 11, 3, palette[4], palette[1]));
  pattern.addChild(circle(80, 400, 11, 3, palette[4], palette[1]));
  pattern.addChild(circle(170, 470, 11, 3, palette[4], palette[1]));
}


void draw() {
  background(palette[7]);
  scale(.3, .3);
  // for each row / column
  for(int i = 0 ; i < 3; i++){
    for(int j = 0 ; j < 3; j++){
      // offset the tile (for the sake of this demo based on mouseX
      pushMatrix();
      translate(150 + i * mouseX,150 + j * mouseX);
      // render the tile
      shape(pattern);
      popMatrix();
    }
  }
}
// utility function to create a circle and set it's styles
PShape circle(float x, float y, float size, float strokeSize, color stroke, color fill){
  PShape shape = createShape(ELLIPSE, x, y, size, size);
  shape.setStrokeWeight(strokeSize);
  shape.setStroke(stroke);
  shape.setFill(fill);
  return shape;
}
// utility function to create a triangle and set it's styles
PShape triangle(float x1, float y1, 
                float x2, float y2,
                float x3, float y3, 
                float strokeSize, color stroke, color fill){
  PShape shape = createShape(TRIANGLE, x1, y1, x2, y2, x3, y3);
  shape.setStrokeWeight(strokeSize);
  shape.setStroke(stroke);
  shape.setFill(fill);
  return shape;
}
Related