There are particles in a box, the black circle representing the spawn point and the red circle representing the particles.

How could I spawn them so they don't spawn outside the box, and so that they are at an exact distance away from the spawn point and particles can slightly overlap.

Here is an example of what I'm trying to do:

enter image description here


1 Answer 1


You can pick a random location an exact distance away from the spawn point, first pick a random angle, find the x & y components of that angle, scale out by the desired distance & add the results to the spawn point to get the new coord:

double spawnDistance = 10;
Point.Double spawnPoint = new Point.Double(15, 17);
Random rng = new Random();
double value = rng.nextDouble();
double dx = Math.cos(value*Math.PI*2) * spawnDistance;
double dy = Math.sin(value*Math.PI*2) * spawnDistance;
Point.Double randomSpawn = new Point.Double(spawnPoint.x+dx, spawnPoint.y+dy);

To make sure the newest spawn point doesn't clip the boundary, test that its center is at least as far away from the boundary edges as the size of its radius:

boolean clippedByBoundary = (randomSpawn.x - radius < minBoundary.x ||
                             randomSpawn.y - radius < minBoundary.y ||
                             randomSpawn.x + radius > maxBoundary.x ||
                             randomSpawn.y + radius > maxBoundary.y);   
// check clippedByBoundary & do whatever

To prevent the newest spawn point from overlapping other spawn points by too much, you'll need to check that it isn't too close to any other point generated thus far:

boolean isTooClose = false;
for(Point.Double pt : spawnPointList){
   if(pt.distance(randomSpawn) < maxOverlap){
     isTooClose = true;
// check isTooClose & whatever you need based on the result

Note: the code above could be sped up a bit by checking squared distances instead of actual distances. Also, my solution has a bias for picking locations closer to the center of the spawn area. Uniform disk picking requires a couple more square root calculations:

double dx = Math.cos(value*Math.PI*2) * Math.sqrt(spawnDistance);
double dy = Math.sin(value*Math.PI*2) * Math.sqrt(spawnDistance);

Alternatively, you could also create a random 2D vector & normalize/scale it as needed (as suggested in comments by @Bálint).

For the convenience of answering, I put the test results in variables; you'll probably want to just use the tests directly in line or possibly as method calls depending on your situation. Since testing for edge clipping is cheaper, I would do that before checking for edge overlaps. If you need to generate many points, looping to check for overlap might prove to be a bit of a bottleneck - if that's the case, you might want to use a Poisson distribution placement scheme instead.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .