Poisson-disc Sampling

Hi there,

I’ve been working from one of Daniel Shiffman’s coding challenges and have been trying to implement it from P5.js to Processing.

Im almost there but I always get an Array Index Out Of Bounds error (line 68).

The code is not pretty and Im sure I’ve made some rookie errors.

I’d appreciate if someone could glance over this for me and steer me in the right direction.

cheers

float   r = 15;                 
int     k = 30;                 //limit of samples
PVector [] grid;
float   cellSize = r / sqrt(2); 
int     cols;
int     rows;
ArrayList <PVector> active;     //active list
ArrayList <PVector> ordered;


void setup() {
  size (400,400);
  background(0);


//STEP 0 - setup grid
  cols    = floor(width/cellSize);
  rows    = int(height/cellSize);
  grid    = new PVector[cols * rows];
  
  active  = new ArrayList<PVector>();
  ordered = new ArrayList<PVector>();
  for (int i = 0; i < cols * rows; i ++) {
    grid[i] = null;
  }

//STEP 1 - pick a random point to start
  float x = random(width);              //  choose random x on canvas...
  float y = random(height);             // choose random y on canvas...
  int i = floor(x / cellSize);          // grid "x" position
  int j = floor(y / cellSize);          // grid "y" position
  PVector pos = new PVector(x,y);       // make position vector
  grid[i + j * cols] = pos;             // insert into grid
  active.add(pos);
}


void draw () {
  background(0);

  //STEP 2
  if(active.size() > 0) {                  // as long as active is not empty
    int     randIndex = floor(random(active.size()));
    PVector pos       = active.get(randIndex);
    boolean found     = false;

    for(int n = 0; n < k; n ++) {          // generate up to k sample points

      PVector sample = PVector.random2D(); // use a random vector
      float magnitude = random(r,2*r);
      sample.setMag(magnitude);
      sample.add(pos);

      int colX = floor(sample.x/cellSize); // x position in grid
      int colY = floor(sample.y/cellSize); // y position in grid

      if (colX >= 1 &&
          colY >= 1 &&
          colX <= cols -1 &&
          colY <= rows -1 &&
          grid[colX + colY * cols] == null) {

            boolean ok = true;
            for(int i = -1; i <= 1; i ++) {
              for(int j = -1; j <= 1; j ++) {
                int index = (colX + i) + (colY + j)  * cols;
                //println(index);
                PVector neighbor = grid[index];
                if (neighbor != null) {  //is valid
                    float d = PVector.dist(sample,neighbor);
                    if (d < r) {
                      ok = false;
                  }
              }
          }
      }
      if(ok) {
        found = true;
        grid[colX + colY * cols] = sample;
        active.add(sample);
        ordered.add(sample);
        break;
      }
    }
    }
    if(!found) {
      active.remove(randIndex);
    }
  }




  for(int i = 0; i < grid.length; i ++) {
    if(grid[i] != null){
      stroke (255);
      strokeWeight(4);
      point(grid[i].x,grid[i].y);
    }
  }

  for(int i = 0; i < active.size(); i ++) {  
      stroke (255,0,255);
      strokeWeight(4);
      point(active.get(i).x,active.get(i).y);  
  }
}
1 Like

just to get it running ( without reading or understanding it )

            if ( index > grid.length-1 ) index =  grid.length-1;

@kllThanks for your reply.
This didn’t help unfortunately. I do have an if statement with some conditions that should help avoid the error.

It does run, but eventually I always get the out of bounds exception. I can’t figure out why though.

Hi there TimoL,

The reason for the ArrayIndexOutOfBoundsException error is because you’re asking for data that’s not there. Add the following line of code at the bottom of void setup():

println(i + " * " + j + " * " + cols + " = " + grid.length);

Combining this with the error feedback, do you understand what’s causing the issue?

1 Like

Yep, just control your indexes :stuck_out_tongue:

Spoiler
                if (index < grid.length){
Final Spoiler
              PVector neighbor = grid[index];
            if (neighbor != null) {  //is valid
                float d = PVector.dist(sample,neighbor);
                if (d < r) {
                  ok = false;
                }

Appreciate the help fellas. :slight_smile:

But I’m still getting the error.
I understand why its happening; my grid array only goes up to a certain size and and what’s happening is a number above that is being called.

But from what I can see the if statement (line 57) should guard against that. I feel like the answer is staring me in the face.

I’ll continue to stare back until it hits me or one of you kind souls can help.
Cheers!

You use the if statements as measurement, but have you taken in account that you subsequently increasing these numbers again in the nested for-loops that follow?

for(int i = -1; i <= 1; i ++) {
   for(int j = -1; j <= 1; j ++) {
      int index = (colX + i) + (colY + j)  * cols;

I ran your sketch several times, and each time the error pops up when (colY + j) equals 37 (because j = 1 at that point).

Sorry, I don’t know then what is happening :exploding_head: … running your code with the fixed indexes like 10 times (:crazy_face:) I didn’t get any error …

This code doesn't give me any error
int     k = 30;                 //limit of samples
PVector [] grid;
float   cellSize = r / sqrt(2); 
int     cols;
int     rows;
ArrayList <PVector> active;     //active list
ArrayList <PVector> ordered;


void setup() {
  size (400,400);
  background(0);


//STEP 0 - setup grid
  cols    = floor(width/cellSize);
  rows    = int(height/cellSize);
  grid    = new PVector[cols * rows];
  
  active  = new ArrayList<PVector>();
  ordered = new ArrayList<PVector>();
  for (int i = 0; i < cols * rows; i ++) {
    grid[i] = null;
  }

//STEP 1 - pick a random point to start
  float x = random(width);              //  choose random x on canvas...
  float y = random(height);             // choose random y on canvas...
  int i = floor(x / cellSize);          // grid "x" position
  int j = floor(y / cellSize);          // grid "y" position
  PVector pos = new PVector(x,y);       // make position vector
  grid[i + j * cols] = pos;             // insert into grid
  active.add(pos);
}


void draw () {
  background(0);

  //STEP 2
  if(active.size() > 0) {                  // as long as active is not empty
    int     randIndex = floor(random(active.size()));
    PVector pos       = active.get(randIndex);
    boolean found     = false;

    for(int n = 0; n < k; n ++) {          // generate up to k sample points

      PVector sample = PVector.random2D(); // use a random vector
      float magnitude = random(r,2*r);
      sample.setMag(magnitude);
      sample.add(pos);

      int colX = floor(sample.x/cellSize); // x position in grid
      int colY = floor(sample.y/cellSize); // y position in grid

      if (colX >= 1 &&
          colY >= 1 &&
          colX <= cols -1 &&
          colY <= rows -1 &&
          grid[colX + colY * cols] == null) {

            boolean ok = true;
            for(int i = -1; i <= 1; i ++) {
              for(int j = -1; j <= 1; j ++) {
                int index = (colX + i) + (colY + j)  * cols;
                //println(index);
                if (index < grid.length){
                PVector neighbor = grid[index];
                if (neighbor != null) {  //is valid
                    float d = PVector.dist(sample,neighbor);
                    if (d < r) {
                      ok = false;
                  }
              }}
          }
      }
      if(ok) {
        found = true;
        grid[colX + colY * cols] = sample;
        active.add(sample);
        ordered.add(sample);
        break;
      }
    }
    }
    if(!found) {
      active.remove(randIndex);
    }
  }




  for(int i = 0; i < grid.length; i ++) {
    if(grid[i] != null){
      stroke (255);
      strokeWeight(4);
      point(grid[i].x,grid[i].y);
    }
  }

  for(int i = 0; i < active.size(); i ++) {  
      stroke (255,0,255);
      strokeWeight(4);
      point(active.get(i).x,active.get(i).y);  
  }
}

Other thing is that you want to care about your indexes carefully and don’t want to use the if condition, then… okay you have to figure out other elegant way :stuck_out_tongue:, but I didn’t understood the question :sweat_smile:

Regards :wave:

1 Like

Thanks for all the help guys. I’ve cleaned up my code and after comparing it to yours can see where I went wrong.

cheers :slight_smile:

1 Like