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);
}
}
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():
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 … running your code with the fixed indexes like 10 times () 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 , but I didn’t understood the question