I'm trying to improve my method of laying out the position of thousands of shapes with an equal footprint over a grid surface from a central point (it has a more organic look). The grid surface means that there's equal spacing between neighbours but I don't want to create a patch-work like pattern by picking a random x and y co-ordinate (or x and z in this case as I'm working in 3 dimensions). What I have now works but is incredibly slow when I start moving up from 2,000 objects. Is there a faster method? I'm avoiding the patch-work effect, like I said, as well as an even circular spread. The distribution right now is very city-like and perfect, but far too slow.
I've commented the function throughout so hopefully it explains everything thoroughly:
ArrayList buildingCoords; // stores the co-ordinates of occupied spaces
int w = 50 // Footprint dimensions. Width and depth.
PVector generateNewBuildingPosition(PVector coord) {
float sW = 30; // gap between shapes
// Starting at a coordinate of 0,0 if this is our 1st go
// (PVector coord initially feeds 0,0)
// or the last coordinate that was already taken
// (this loops with the last coordinate if it fails)
// we check one of the four spaces next to us with
// the roll of a dice (in a way...)
float randomX = random(0,15);
float randomZ = random(0,15);
if (randomX >= 10) {
randomX = w + sW;
} else if (randomX >= 5) {
randomX = (w + sW) * -1;
} else {
randomX = 0;
}
if (randomZ >= 10) {
randomZ = w + sW;
} else if (randomX >= 5) {
randomZ = (w + sW) * -1;
} else {
randomZ = 0;
}
// We've picked our direction.
// We have a PVector that acts as a marker for where we're
// placing. Adding or subtracting the movement of each
// attempt, one at a time, means the shapes spreads out
// more organically from the centre rather than trying
// to distribute each shape as a random patch.
PVector newDirection = new PVector(randomX, 0, randomZ);
coord.add(newDirection);
// Our marker moves to the new spot, we check if it exists.
// If it doesn't, we confirm it as this shape's anchor spot.
// If it does, we loop this function again, feeding it where our
// marker is.
if(buildingCoords.contains(coord)) {
generateNewBuildingPosition(coord);
} else {
// add this PVector to the arrayList
buildingCoords.add(coord);
}
// Return the coordinates that just succeeded.
return coord;
}