Detecting edges in an array of coloured circles

Hi,

I’m instantiating a grid of Circles and then using noise to fill each Circle with a perlin noise value based on an increment, if the brightness value of a circle exceeds an amount it will be filled green, if not it will be red. This works, however, I would like to have the edge of the ‘green zone’ to be blue. I thought this would be a simple case whereby you loop through the circle array and compare it with the circle immediately to its left, if it’s a different colour it becomes blue:

however I am not getting this result.

Here is the code:

float xn,yn,zn;
long n;
float threshold = 50;
int gridSize = 10;
int numCircles = Math.round(500/gridSize * 500/gridSize);
Circle[] circles = new Circle[numCircles];

void setup()
{
  for (int i = 0; i < numCircles; i++)
  {
  circles[i] = new Circle(0,0,gridSize,gridSize,color(255,255,255));
  }
n = (long)random(10000);
size(500,500);
background(255,255,255);
frameRate(25);
}

void draw()
{
clear();
Perlin();
}

void Perlin()
{
xn=noise(n);
yn=noise(n);
for (int colls = 1; colls  < 500 ;colls+=gridSize){
     yn+=0.02;
     zn+=0.02/100;
     xn=0;
     for (int rows = 1; rows < 500; rows+=gridSize){
        xn+=0.02;
        float rs = noise(xn,yn,zn)*15;
        circles[colls].colour = color(100*rs/10,100*rs/10,100*rs/10);
        circles[colls].xPos = colls;
        circles[colls].yPos = rows;

        
        if(brightness(circles[colls].colour) < 50){
        circles[colls].colour = color(0,255,0);

        }
         else{
        circles[colls].colour = color(255,0,0);

        }
     
         if(circles[colls].colour != circles[colls-1].colour){
                 circles[colls].colour = color(0,0,255);

         }
         circles[colls].Display();
         }
       }
}

 public class Circle {
  int xPos,yPos,dim,dim2; // location // dimension
  color colour; // color
 
   Circle(int xPos, int yPos,int dim,int dim2,color colour) {
    this.xPos = xPos;
    this.yPos = yPos;
    this.dim = dim;
    this.dim2 =dim2;
    this.colour = colour;
  }
   void Display(){
    fill(colour);
    ellipse(xPos,yPos,dim,dim2);
   // println(colour);


}
}
2 Likes

generally speaking you’ll want to have an array arrayList that keeps a track of the neighbours a circle has, neighbours will be top left, top, top right, right,bottom right, bottom, and bottom left.

The check only needs to done once, then each cell can again check which neighbours have different colors, if the total is more than 0 then change the color. Again this check only needs to happen once unless color is updated.

2 Likes

Hi Paul,

Thanks for the advice. Is there an example of this I can check out?

Best,

1 Like

yes and no

yes I can show you

this is currently one of my projects, and is supposed to be something to help me learn to code, so its kind of a mess.

click on grid then terrain, then contour

1 Like

I can’t see ‘terrain’ and it also this seems a bit high level for this task.

1 Like

Everything relevant is found in the Grid_space class, and the Grid class.

  void get_neighbours(){
    ArrayList<Grid_space> n = new ArrayList<Grid_space>();
    ArrayList<Grid_space> n2 = new ArrayList<Grid_space>();
    int cell = id;
    if(image){Grid_space b = gimg.imsquares.get(cell);}
    else { Grid_space b = g.squares.get(cell);}
    
    Grid_space topl,top,topr,right,btmr,btm,btml,left;
    
    if(image){
       topl = index2(int(xpos) - 1, int(ypos) - 1,gimg);
       top = index2(int(xpos) , int(ypos) - 1,gimg);
       topr = index2(int(xpos) + 1, int(ypos) - 1,gimg);
       right = index2(int(xpos) + 1, int(ypos),gimg);
       btmr = index2(int(xpos) + 1, int(ypos) + 1,gimg);
       btm = index2(int(xpos) , int(ypos) + 1,gimg);
       btml = index2(int(xpos) - 1, int(ypos) + 1,gimg);
       left = index2(int(xpos) - 1, int(ypos) ,gimg);
    }else{
       topl = index2(int(xpos) - 1, int(ypos) - 1,g);
       top = index2(int(xpos) , int(ypos) - 1,g);
       topr = index2(int(xpos) + 1, int(ypos) - 1,g);
       right = index2(int(xpos) + 1, int(ypos),g);
       btmr = index2(int(xpos) + 1, int(ypos) + 1,g);
       btm = index2(int(xpos) , int(ypos) + 1,g);
       btml = index2(int(xpos) - 1, int(ypos) + 1,g);
       left = index2(int(xpos) - 1, int(ypos) ,g);
    }
    if(topl!=null){
      n.add(topl);
      Neighbours_a[0] = topl;
      kernel1d[0] = topl;
    }
    if(top!=null){
      n.add(top);
      n2.add(top);
      Neighbours_a[1] = top;
      Neighbours_b[0] = top;
      kernel1d[1] = top;
    }
    if(topr!=null){
      n.add(topr);
      Neighbours_a[2] = topr;
      kernel1d[2] = topr;
    }
    if(right!=null){
      n.add(right);
      n2.add(right);
      Neighbours_a[3] = right;
      Neighbours_b[1] = right;
      kernel1d[3] = right;
    }
    if(btmr!=null){
      n.add(btmr);
      Neighbours_a[4] = btmr;
      kernel1d[5] = btmr;
    }
    if(btm!=null){
      n.add(btm);
      n2.add(btm);
      Neighbours_a[5] = btm;
      Neighbours_b[2] = btm;
      kernel1d[6] = btm;
    }
    if(btml!=null){
      n.add(btml);
      Neighbours_a[6] = btml;
      kernel1d[7] = btml;
    }
    if(left!=null){
      n.add(left);
      n2.add(left);
      Neighbours_a[7] = left;
      Neighbours_b[3] = left;
      kernel1d[7] = left;
    }
    Neighbours = n;
    Neighbours2 = n2;
    neighboured = true;
  };
  
};

Grid_space index2(int xpos,int ypos,Grid a){
  Grid_space b = null;
  if(a.imtoggle){
    if(xpos<0||xpos>a.img.width-1||ypos<0||ypos>a.img.height-1){
     
    return null;
  }else{
     b = a.imsquares.get(xpos + (ypos * int(a.img.width)));
    
    }}
    else{
      if(xpos<0||xpos>a.cols-1||ypos<0||ypos>a.rows-1){
     
    return null;
  }else{
     b = a.squares.get(xpos + (ypos * int(a.cols)));
    
    }}
  return b;
};


this is the code to check neighbours, please note there are some things that can be stripped from this ie, you do not have to check.

if(image)

Also note the various arrays I’m using to store the neighbours, I think theres one which just stores {top right bottom left}, Also noticing some errors

1 Like

terrain is set to false by default or it will render a 3d map, I dont think pde can handle listing all the tabs, it is there just not visible.

Select the last tab you can find and then press ctrl + PgDn.

also this is why I said yes and no.

You can ignore any class that sound gui related, its just Grid_space and Grid. Although if you use my code it will have dependencies.

in the grid class there is the following code

void draw_2d(){
        if(terrain3d&&toggle){
          pushMatrix();
          translate(W/2, H/2);
          
          if(mousePressed){
             //XX += pmouseX - mouseX;
             //YY += pmouseY - mouseY;
          }
          rotateX(PI/3+radians(xrot+YY));
          translate(-W/2, -W/2);
          translate(w/2, h/2);
          rotateZ(radians(zrot+XX));
          translate(-w/2, -h/2);
          translate(w/2, 0);
          rotateY(radians(yrot));
          translate(-w/2, 0);
          translate(-hdistance-400, -distance-400,-vdistance);
          keys();
        }
        
        if(toggle){
          logic();
          
          fill(255);
          text("hello",100,100);
          text(rows,100,120);
          rowcount = 0;
          colcount = 0;
          if(terrain2d&&!plain){
            float yoffr = flyingy;
            float yoffg = 0;
            float yoffb = 0;//small float offset for smooth changes in value
            
            for (int yy = 0; yy < rows; yy++) {
              
              float xoffr = flyingx;
              float xoffg = 0;
              float xoffb = 0;
              
              for (int xx = 0; xx< cols; xx++) {
                if(perlcolor){
                //perlx[xx][yy] = map(noise(xoffr, yoffr), 0, 1, -255, 255);
                perlx[xx][yy] = noise(xoffr, yoffr);
                //perly[xx][yy] = map(noise(xoffg, yoffg), 0, 1, -255, 255);//output of map(last numbers) controlled for height of mountains.
                //perlz[xx][yy] = map(noise(xoffb, yoffb), 0, 1, -255, 255);
                //terrain[xx][yy] = map(noise(xoffr, yoffr), 0, 1, -255, 255);
                }
                terrain[xx][yy] = map(noise(xoffr, yoffr), 0, 1, -255, 255);
                perlx[xx][yy] = noise(xoffr, yoffr);
                if(perlheight){
                //perlr[xx][yy] = map(noise(xoffr, yoffr), 0, 1, -255, 255);
                perlx[xx][yy] = noise(xoffr, yoffr);
                //perlg[xx][yy] = map(noise(xoffg, yoffg), 0, 1, 0, 255);//output of map(last numbers) controlled for height of mountains.
                //perlb[xx][yy] = map(noise(xoffb, yoffb), 0, 1, 0, 255);
                
                }
                xoffr += 0.05 + zoom;
                xoffg += 0.3;
                xoffb += 0.5;//change offsets to control smoothness.
              }
              yoffr +=0.05 + zoom;
              yoffg +=0.3;
              yoffb +=0.5;
            }}
          
    for (int yy = 0; yy < rows-1; yy++) {
      if(terrain3d)beginShape(TRIANGLE_STRIP);
      for (int xx = 0; xx< cols; xx++) {
        
        int pos = xx + yy * cols;
        strokeWeight(0);
        //Grid_space posre = squares.get(0 + i * rows);
        //Grid_space posce = squares.get(j + 0 * rows);
        Grid_space a = squares.get(pos);
        //if(mousePressed){
        //  deltay = a.shape.y - mouseY;
        //  deltax = a.shape.x - mouseX;
        //a.shape.x = mouseX - deltax;
        //a.shape.y = mouseY - deltay;
        //}
        //if(!shape){
        
        float num = perlx[xx][yy];
        float R = terrain[xx][yy];
        float floor2 = groundlevel2;
        float mountain = mountainlevel;
        float sea = sealevel;
        float grass = grasslevel;
        if(a.shape!=null){a.shape.draw();}
        if((terrain2d||terrain3d)&&!plain){
        fill(a.col);
        if(R<sea){
                  
            a.col2 = color(0,0,255);
            a.col = color(0,0,255,255-abs(R)*1.2);
            C = color(0,0,255,255-abs(R)*1.2);
          }
          if(R>floor2){
            a.col2 = color(255,255,0);
            a.col = color(255,255,0,255-abs(R)*1.2);
            C = color(255,255,0,255-abs(R)*1.2);
          }
          if(R>grass){
            a.col2 = color(0,255,0);
            a.col = color(0,255,0,255-abs(R)*1.2);
            C = color(0,255,0,255-abs(R)*1.2);
          }
          if(R>mountain){
            a.col2 = color(255,255,255);
            a.col = color(255,255,255,255-abs(R)*1.2);
            C = color(255,255,255,255-abs(R)*1.2);
          }
        //if(posre.col == temp_rows.get(i).col){
        //  rowcount ++;
        //}
        //if(posce.col == temp_cols.get(j).col){
        //  colcount ++;
        //}
      }fill(a.col);
          if(rowcount == rows) rowrepeat = true;
          else rowrepeat = false;
          if(colcount == cols) colrepeat = true;
          else colrepeat = false;
          
        if(forward||backward){
        if(acceleration!=0)a.ax = acceleration;a.ay = acceleration;
        if(a.collide) fill(0);
        if(a.pos()&&hover) fill(0,255,0);
        if(!fill) noFill();
        stroke(a.col);
        strokeWeight(bordersize);
        if(!border) noStroke();
        
        if(forward&&!pause&&!backward) a.forward = true;a.pause = false;a.backward = false;a.update();
        if(backward&&!pause&&!forward) a.forward = false;a.pause = false;a.backward = true;a.update();
        
        a.attractors();
        
        if(mouse)a.mouse();
        }
        if(!terrain3d){
        if(!circle&&!dot&&!shape&&!plain){
        //if(num>=0.80)fill(0);
        
        noStroke(); if(plain)stroke(0);rect(a.x,a.y,a.w,a.h);
        //a.get_neighbours();
        strokeWeight(0);
        fill(255);
        
          for(int k=0;k<a.Neighbours_b.length;k++){
          
          Grid_space neighbour = a.Neighbours_b[k];
          
          if(neighbour!=null&&neighbour.col2!=a.col2){
            a.Walls_b.set(k,false);
          }
          else{
            a.Walls_b.set(k,true);
          }
          noStroke();
          stroke(0);
          strokeWeight(1);
          if(!a.Walls_b.get(k)&&contour){
            if(k==0){
              line(a.x,a.y,a.x+a.w,a.y);
            }else if(k==1){
              line(a.x+a.w,a.y,a.x+a.w,a.y+a.h);
            }else if(k==2){
              line(a.x+a.w,a.y+a.h,a.x,a.y+a.h);
            }else if(k==3){
              line(a.x,a.y+a.h,a.x,a.y);
              strokeWeight(1);
              
          }}}}else{
        if(circle){
        ellipseMode(CORNER);ellipse(a.x,a.y,a.w,a.h);
         }
        else if(dot){
                strokeWeight(2);
                point(a.x,a.y);
                strokeWeight(1);
          }
        else{
        //text(deltax,a.x,a.y);
        }}}
        else if(terrain3d){
          float mult = 1;
          fill(a.col);
          stroke(a.col);
          if(!border)noStroke();
          if(!fill)noFill();
          if(floored){
            
          float a1 = terrain[xx][yy];
          float a2 = terrain[xx][yy];
          float a3 = terrain[xx][yy];
          float a4 = terrain[xx][yy];
          
           if(a1<sealevel){
             a1 = sealevel;
           }else{
             if(a1<groundlevel2){
               a1 = groundlevel2;
             }else{
               if(a1<grasslevel){
               a1 = grasslevel;
             }else{
             a1 = a3;
           }}}
           if(a2<sealevel){
             a2 = sealevel;
           }else{
             if(a2<groundlevel2){
               a2 = groundlevel2;
             }else{
               if(a2<grasslevel){
               a2 = grasslevel;
             }else{
             a2 = a4;
           }}}
           
           vertex(xx*a.w*mult, yy*a.h*mult, terrain[xx][yy]);
           vertex(xx*a.w*mult, (yy+1)*a.h*mult, terrain[xx][yy+1]);
        
          }else if(R<-100){
          vertex(xx*a.w*mult, (yy)*a.h*mult, terrain[xx][yy]);
          vertex(xx*a.w*mult, (yy+1)*a.h*mult, terrain[xx][yy+1]);
        }}}
        if(terrain3d)endShape(CLOSE);
      }}
    if(terrain3d){
    popMatrix();
    }
    if(toggle)gridbox.draw();keys();
    if(toggle)sliderMenu.draw();
          
  };``` 

the specific bit of code that draws the lines


for(int k=0;k<a.Neighbours_b.length;k++){

      Grid_space neighbour = a.Neighbours_b[k];
      
      if(neighbour!=null&&neighbour.col2!=a.col2){
        a.Walls_b.set(k,false);
      }
      else{
        a.Walls_b.set(k,true);
      }
      noStroke();
      stroke(0);
      strokeWeight(1);
      if(!a.Walls_b.get(k)&&contour){
        if(k==0){
          line(a.x,a.y,a.x+a.w,a.y);
        }else if(k==1){
          line(a.x+a.w,a.y,a.x+a.w,a.y+a.h);
        }else if(k==2){
          line(a.x+a.w,a.y+a.h,a.x,a.y+a.h);
        }else if(k==3){
          line(a.x,a.y+a.h,a.x,a.y);
          strokeWeight(1);
          
      }}}}

not sure why the code is escaping the code block.
1 Like

please un-comment

//a.get_neighbours();
1 Like

Hi Paul,

I’ve added an edge detect method from the info you provided although I keep getting an array outofbounds error

float xn,yn,zn;
long n;
float threshold = 50;
int gridSize = 10;
int numCircles = Math.round(500/gridSize * 500/gridSize);
Circle[] circles = new Circle[numCircles];

void setup()
{
  for (int i = 0; i < numCircles; i++)
  {
  circles[i] = new Circle(0,0,gridSize,gridSize,color(255,255,255));
  }
n = (long)random(10000);
size(500,500);
background(255,255,255);
frameRate(25);
}

void draw()
{
clear();
Perlin();
}

void Perlin()
{
xn=noise(n);
yn=noise(n);
for (int colls = 1; colls  < 500 ;colls+=gridSize){
     yn+=0.02;
     zn+=0.02/100;
     xn=0;
     for (int rows = 1; rows < 500; rows+=gridSize){
        xn+=0.02;
        float rs = noise(xn,yn,zn)*15;
        circles[colls].colour = color(100*rs/10,100*rs/10,100*rs/10);
        circles[colls].xPos = colls;
        circles[colls].yPos = rows;

       
        if(brightness(circles[colls].colour) < 50){
          

        }
         else{
        circles[colls].colour = color(255,0,0);

        }
     
                 neighbouringCells(rows, colls, colls);

         circles[colls].Display();
         }
       }
       
}



    int neighbouringCells(int x, int y, int cellToCheck){
    
    color c = circles[cellToCheck].colour;
    
   int l = (x-1) + y * width/50;
   color lc = circles[l].colour;
   int tl = (x-1) + (y - 1) * width/50;
   color tlc = circles[tl].colour;
    int t = (x) + (y - 1) * width/50;
   color tc = circles[t].colour;
    int tr = (x + 1) + (y - 1) * width/50;
   color trc = circles[tr].colour;;
    int r = (x+1) + (y) * width/50;
   color rc = circles[r].colour;
   int br = (x+1) + (y+1) * width/50;
   color brc = circles[br].colour;
    int b = (x) + (y+1) * width/50;
   color bc = circles[b].colour;
    int bl = (x-1) + (y+1) * width/50;
   color blc = circles[bl].colour;;
   
   
   if(lc!=c||tlc!=c||tc!=c||trc!=c||rc!=c||brc!=c||bc!=c||blc!=c){
   
   return 1;
   }
   else {
   return 0;
   }
   
 
1 Like

if you don’t mind do you have the rest of the code?

1 Like
 public class Circle {
  int xPos,yPos,dim,dim2; // location // dimension
  color colour; // color
 
   Circle(int xPos, int yPos,int dim,int dim2,color colour) {
    this.xPos = xPos;
    this.yPos = yPos;
    this.dim = dim;
    this.dim2 =dim2;
    this.colour = colour;
  }
   void Display(){
    fill(colour);
    ellipse(xPos,yPos,dim,dim2);
   // println(colour);


}
}
3 Likes

it might be the edge cases. You are starting at 1 which is fine for eliminating the first rows and the first column however you are also going all the way to 500 for both the rows and the columns. Unless there are 501 rows and columns this will also cause problems, because a circle at row 500 column 500 does not have a neighbour at column 501 or at row 501.

1 Like

Hello @Smuel,

Before handling your edge detection issue, I think you should refactor your code.

As of now I don’t think you are using your circles array the way you intend to.

Based on your code, only the elements 1, 11, 21, 31… and so on are actually used. Because of this you can’t perform an edge detection because you are loosing previsous information that you would need.

I tried to do as little change as possible to your code so you can understand how it works:

void Perlin()
{
  xn=noise(n);
  yn=noise(n);
  for (int colls = 0; colls  < 50; colls++) {
    yn+=0.02;
    zn+=0.02/100;
    xn=0;
    for (int rows = 0; rows < 50; rows++) {
      xn+=0.02;
      float rs = noise(xn, yn, zn)*15;
      
      int idx = rows * 50 + colls;
      if (idx >= 2500) {
        println(colls, rows, idx);
      }
      circles[idx].colour = color(100*rs/10, 100*rs/10, 100*rs/10);
      circles[idx].xPos = colls * gridSize;
      circles[idx].yPos = rows * gridSize;


      if (brightness(circles[idx].colour) < 50) {
        circles[idx].colour = color(0, 255, 0);
      } else {
        circles[idx].colour = color(255, 0, 0);
      }
      
      circles[idx].Display();
    }
  }
}

The idea behind the code is that instead of increasing colls and rows by the size of your grid, I simply make them move by one to fit the position in the grid (i.g. the circle on the 3rd column and 10th row).

Also note that I start at 0 since arrays are indexed starting at 0.

Then I’m creating an index to transform the 2D position into a 1D position in my array. It works the same way as the Pixels[] array of Processing.

Finnally, I scale everything by your grid size factor to store the real position of the circle on the screen.

2 Likes

I’ve tidied up the code, it now doesn’t produce an array out of bounds error, however you’ll need to add the color change functionality again.

float xn,yn,zn;
long n;
float threshold = 50;
int gridSize = 10;
int numCircles = floor(500/gridSize * 500/gridSize);
Circle[] circles = new Circle[numCircles];

void setup()
{
  for (int y = 0; y < 50; y++){
    for (int x = 0; x < 50; x++){
      
      int pos = x + y * 50;
      circles[pos] = new Circle(pos,0+gridSize*x,0+gridSize*y);
      
  }}
n = (long)random(10000);
size(500,500);
background(255,255,255);
frameRate(25);
}

void draw()
{
clear();
Perlin();
}

void Perlin(){
  
xn=noise(n);
yn=noise(n);
for (int rows = 1; rows  < 49;rows++){
     yn+=0.02;
     zn+=0.02/100;
     xn=0;
     for (int cols = 1; cols < 49 ; cols++){
        xn+=0.02;
        float rs = noise(xn,yn,zn)*15;
        int pos = cols + rows * 50;
        
        if(brightness(circles[pos].colour) < 50){}
         else circles[pos].colour = color(255,0,0);
                 
                 //neighbouringCells(rows, colls, rows + colls * 50);
                 neighbouringCells(cols, rows, pos);

         circles[pos].Display();
         }
       }
       
}



    int neighbouringCells(int x, int y, int cellToCheck){
    
    color c = circles[cellToCheck].colour;
    
   int l = (x-1) + y * 50;
   color lc = circles[l].colour;
   int tl = (x-1) + (y - 1) * 50;
   color tlc = circles[tl].colour;
    int t = (x) + (y - 1) * 50;
   color tc = circles[t].colour;
    int tr = (x + 1) + (y - 1) * 50;
   color trc = circles[tr].colour;;
    int r = (x+1) + (y) * 50;
   color rc = circles[r].colour;
   int br = (x+1) + (y+1) * 50;
   color brc = circles[br].colour;
    int b = (x) + (y+1) * 50;
   color bc = circles[b].colour;
    int bl = (x-1) + (y+1) * 50;
   color blc = circles[bl].colour;;
   
   if(lc!=c||tlc!=c||tc!=c||trc!=c||rc!=c||brc!=c||bc!=c||blc!=c){
   
   return 1;
   }
   else {
   return 0;
   }
   
};
   

public class Circle {
  int xPos,yPos,dim,dim2,id,x,y; // location // dimension
  color colour = color(255,255,255); // color
  
 
   Circle(int xPos, int yPos,int dim,int dim2,color colour) {
    this.xPos = xPos;
    this.yPos = yPos;
    this.dim = dim;
    this.dim2 =dim2;
    this.colour = colour;
  }
  
  Circle(int id,int xPos, int yPos) {
    this.id = id;
    this.x = xPos;
    this.y = yPos;
    this.dim = gridSize;
    this.dim2 = gridSize;
    this.colour = colour;
  }
   void Display(){
    fill(colour);
    ellipse(x+dim/2,y+dim/2,dim,dim2);
   // println(colour);


}
}

//---------------------------------------------------------------------------------------

Changes made;

Circles array is initialised in a double loop, which provides xpos, ypos, x,y, and an id;

You dont need to have the id, although I like to have it so you can easily find a circle in the future.

When using double loops to create a grid, use the equation x + y * cols to identify position in grid. Also always remember convention dictates the first loop is for the rows/ or y, and the second loop is for cols or x. This will make sense if you run through a grid.

1 Like

Hello @paulgoux,

You need to perform the neighbour check after your 2 for loop. Otherwise, you are checking the neighbour with a mix of new values and old values.

You should first do the loop the assign the green red value and then perform the same loop again the check for neighbour color.

It would also allow you to update all your circles without avoiding the edges.

1 Like

Almost but not quite,

float xn,yn,zn;
long n;
float threshold = 50;
int gridSize = 10;
int numCircles = floor(500/gridSize * 500/gridSize);
Circle[] circles = new Circle[numCircles];

void setup()
{
  for (int y = 0; y < 50; y++){
    for (int x = 0; x < 50; x++){
      
      int pos = x + y * 50;
      circles[pos] = new Circle(pos,0+gridSize*x,0+gridSize*y);
      
  }}
n = (long)random(10000);
size(500,500);
background(255,255,255);
frameRate(25);
}

void draw()
{
clear();
Perlin();
}

void Perlin(){
  
xn=noise(n);
yn=noise(n);

for (int rows = 1; rows  < 49;rows++){
  
     yn+=0.02;
     zn+=0.02/100;
     xn=0;
     for (int cols = 1; cols < 49 ; cols++){
        xn+=0.02;
        float rs = noise(xn,yn,zn)*15;
        int pos = cols + rows * 50;
        
        circles[pos].colour = color(100*rs/10, 100*rs/10, 100*rs/10);
        
        if(brightness(circles[pos].colour) < 50)circles[pos].colour = color(0, 255, 0);
        else circles[pos].colour = color(255,0,0);
        
        circles[pos].c = circles[pos].colour;
         
        if(neighbouringCells(cols, rows, pos)==1) {}
        //circles[pos].c = color(255,0,0);
        else circles[pos].c = color(255,255,255);
         
        circles[pos].Display();
      }
    }
       
};

int neighbouringCells(int x, int y, int cellToCheck){
    
   color c = circles[cellToCheck].colour;
    
   int l = (x-1) + y * 50;
   color lc = circles[l].colour;
   int tl = (x-1) + (y - 1) * 50;
   color tlc = circles[tl].colour;
   int t = (x) + (y - 1) * 50;
   color tc = circles[t].colour;
   int tr = (x + 1) + (y - 1) * 50;
   color trc = circles[tr].colour;;
   int r = (x+1) + (y) * 50;
   color rc = circles[r].colour;
   int br = (x+1) + (y+1) * 50;
   color brc = circles[br].colour;
   int b = (x) + (y+1) * 50;
   color bc = circles[b].colour;
   int bl = (x-1) + (y+1) * 50;
   color blc = circles[bl].colour;;
   
   if(lc!=c||tlc!=c||tc!=c||trc!=c||rc!=c||brc!=c||bc!=c||blc!=c){
   
   return 1;
   }
   else {
   return 0;
   }
   
};

public class Circle {
  int xPos,yPos,dim,dim2,id,x,y; // location // dimension
  color colour = color(255,255,255),c; // color
  
 
   Circle(int xPos, int yPos,int dim,int dim2,color colour) {
    this.xPos = xPos;
    this.yPos = yPos;
    this.dim = dim;
    this.dim2 =dim2;
    this.colour = colour;
  }
  
  Circle(int id,int xPos, int yPos) {
    this.id = id;
    this.x = xPos;
    this.y = yPos;
    this.dim = gridSize;
    this.dim2 = gridSize;
    this.colour = colour;
  }
   void Display(){
    fill(c);
    ellipse(x+dim/2,y+dim/2,dim,dim2);
   // println(colour);


}
}

1 Like

completed

float xn,yn,zn;
long n;
float threshold = 50;
int gridSize = 10;
int numCircles = floor(500/gridSize * 500/gridSize);
Circle[] circles = new Circle[numCircles];

void setup()
{
  for (int y = 0; y < 50; y++){
    for (int x = 0; x < 50; x++){
      
      int pos = x + y * 50;
      circles[pos] = new Circle(pos,0+gridSize*x,0+gridSize*y);
      
  }}
n = (long)random(10000);
size(500,500);
background(255,255,255);
frameRate(25);
}

void draw()
{
clear();
Perlin();
}

void Perlin(){
  
xn=noise(n);
yn=noise(n);

for (int rows = 1; rows  < 49;rows++){
  
     yn+=0.02;
     zn+=0.02/100;
     xn=0;
     for (int cols = 1; cols < 49 ; cols++){
        xn+=0.02;
        float rs = noise(xn,yn,zn)*15;
        int pos = cols + rows * 50;
        
        circles[pos].colour = color(100*rs/10, 100*rs/10, 100*rs/10);
        
        if(brightness(circles[pos].colour) < 50){
          circles[pos].c = color(0, 255, 0);
          circles[pos].colour = color(0, 255, 0);
        }
        else{ circles[pos].c = color(255,0,0);
              circles[pos].colour = color(255,0,0);
        }
        
        //circles[pos].c = circles[pos].colour;
         
        if(neighbouringCells(cols, rows, pos)==1) circles[pos].c = color(0,0,255);
        //else if(neighbouringCells(cols, rows, pos)==0) circles[pos].c = circles[pos].colour;;
         
        circles[pos].Display();
      }
    }
       
};

int neighbouringCells(int x, int y, int cellToCheck){
    
   color c = circles[cellToCheck].colour;
    
   int l = (x-1) + y * 50;
   color lc = circles[l].colour;
   int tl = (x-1) + (y - 1) * 50;
   color tlc = circles[tl].colour;
   int t = (x) + (y - 1) * 50;
   color tc = circles[t].colour;
   int tr = (x + 1) + (y - 1) * 50;
   color trc = circles[tr].colour;;
   int r = (x+1) + (y) * 50;
   color rc = circles[r].colour;
   int br = (x+1) + (y+1) * 50;
   color brc = circles[br].colour;
   int b = (x) + (y+1) * 50;
   color bc = circles[b].colour;
   int bl = (x-1) + (y+1) * 50;
   color blc = circles[bl].colour;;
   
   if(lc!=c||tlc!=c||tc!=c||trc!=c||rc!=c||brc!=c||bc!=c||blc!=c)return 1;
   else return 0;
   
};

public class Circle {
  int xPos,yPos,dim,dim2,id,x,y; // location // dimension
  color colour = color(255,255,255),c; // color
  
 
   Circle(int xPos, int yPos,int dim,int dim2,color colour) {
    this.xPos = xPos;
    this.yPos = yPos;
    this.dim = dim;
    this.dim2 =dim2;
    this.colour = colour;
  }
  
  Circle(int id,int xPos, int yPos) {
    this.id = id;
    this.x = xPos;
    this.y = yPos;
    this.dim = gridSize;
    this.dim2 = gridSize;
    this.colour = colour;
  }
   void Display(){
    fill(c);
    ellipse(x+dim/2,y+dim/2,dim,dim2);
   // println(colour);


}
}

Thank you very much for your help Paul and Jb4x, much appreciated.

Best,

1 Like