# How to give circles(ellipses) certain distance, apart from each other? giving random position every time I press key

**URL:** https://discourse.processing.org/t/how-to-give-circles-ellipses-certain-distance-apart-from-each-other-giving-random-position-every-time-i-press-key/26646
**Category:** Coding Questions
**Created:** [December 31, 2020, 1:43pm UTC](https://discourse.processing.org/t/how-to-give-circles-ellipses-certain-distance-apart-from-each-other-giving-random-position-every-time-i-press-key/26646 "2020-12-31T13:43:33Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![yewon](https://avatars.discourse-cdn.com/v4/letter/y/9de0a6/32.png) [@yewon](https://discourse.processing.org/u/yewon)
#### Post date: [December 31, 2020, 1:43pm UTC](https://discourse.processing.org/t/how-to-give-circles-ellipses-certain-distance-apart-from-each-other-giving-random-position-every-time-i-press-key/26646/1 "2020-12-31T13:43:33Z")

</div>

Hi.  
what I want to do is,  
Every time I press key, I want to reposition my object inside screen, but each of my object should be apart from each other by certain distance. for example at least the distance should be larger than 50.

this is some code that I tried, but I think I have problems with while loop.

I made class Attractor, attractors[] which need to be repositioned when keypressed.

I hope my question is understandable.

```auto
Mover movers[] = new Mover[1000];
Attractor attractors[]=new Attractor[5];

void setup() {
  size(300, 400, P3D);
  for (int i=0; i<attractors.length; i++) {
    attractors[i] = new Attractor(random(0.1, 2), random(0, width), random(0, height), random(-100, 100));
  }
}

void draw() {
  background(255);
  for (int i=0; i<attractors.length; i++) {
    attractors[i].display();
  }
  
}

void keyPressed() {
for (int i=0; i<attractors.length; i++) {
    for (int j=0; j<attractors.length; j++) {
     PVector f = PVector.sub(attractors[i].loc,attractors[j].loc);
    float distance = f.mag();
      if (i!=j) {
        while (true) {
          attractors[j].loc.x = random(0, width);
          attractors[j].loc.y = random(0, height);
          attractors[j].loc.z = 0;
          if (distance>=50) {
            break;
          }    
        }

        println(distance);
      }
    }
  
  }
}

```

---

<div class="post-metadata">

### Author: ![yewon](https://avatars.discourse-cdn.com/v4/letter/y/9de0a6/32.png) [@yewon](https://discourse.processing.org/u/yewon)
#### Post date: [December 31, 2020, 1:45pm UTC](https://discourse.processing.org/t/how-to-give-circles-ellipses-certain-distance-apart-from-each-other-giving-random-position-every-time-i-press-key/26646/2 "2020-12-31T13:45:27Z")

</div>

```auto

```

```auto
class Attractor {
  PVector loc;
  float mass;
  float G;
  Attractor(float m, float x, float y,float z) {
    loc = new PVector(x, y, z);
    mass = m;
    G=0.4;
  }
  PVector attract(Mover m){
  PVector force = PVector.sub(loc,m.loc);
  float distance = force.mag();
  distance = constrain(distance,5.0,25.0);
  force.normalize();
  float strength = (G*mass*m.mass)/(distance*distance);
  force.mult(strength);
  return force;
  }
void display(){
  pushMatrix();
  translate(loc.x,loc.y,loc.z);
  sphere(5);
  popMatrix();
  }
  
}

```

this is class Attractor

---

<div class="post-metadata">

### Author: ![CodeMasterX](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/codemasterx/32/2942_2.png) [@CodeMasterX](https://discourse.processing.org/u/CodeMasterX)
#### Post date: [December 31, 2020, 3:08pm UTC](https://discourse.processing.org/t/how-to-give-circles-ellipses-certain-distance-apart-from-each-other-giving-random-position-every-time-i-press-key/26646/3 "2020-12-31T15:08:10Z")

</div>

If you want to create a system with maximum number of circes in a space while being evenly spaced you should create an algorithm that creates circles like this  
 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/e/e1655bb9c881c992207f079be8671cf32def8daa.png)  
black is random, pick 1 pit of 2 dark red (then the other), draw red ones, then orange and finally yellow. Continue this infinetly and voila

---

<div class="post-metadata">

### Author: ![micycle](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/micycle/32/201_2.png) [@micycle](https://discourse.processing.org/u/micycle)
#### Post date: [December 31, 2020, 3:43pm UTC](https://discourse.processing.org/t/how-to-give-circles-ellipses-certain-distance-apart-from-each-other-giving-random-position-every-time-i-press-key/26646/4 "2020-12-31T15:43:35Z")

</div>

Poisson-Disc Sampling is a go-to technique for this problem.

> Poisson-disc sampling produces points that are tightly-packed, but no closer to each other than a specified minimum distance, resulting in a more natural pattern.

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/5/53c18203e26d514e5665df0720f7f582f24a7ee2.png)

```auto
import java.util.Vector;
import java.util.LinkedList;

PoissonDistribution points = new PoissonDistribution();

int minimumDistance = 50;

void setup() {
  size(800, 800);
  fill(200, 40, 80);
  points.generate(0, 0, width, height, minimumDistance, 15);
}

void draw() {
  background(255);
  for (PVector coord : points.getPoints()) {
    ellipse(coord.x, coord.y, minimumDistance - 10, minimumDistance - 10);
  }
}

void keyPressed() {
  points.generate(0, 0, width, height, minimumDistance, 15);
}

class PoissonDistribution
{
  /** From "Fast Poisson Disk Sampling in Arbitrary Dimensions"
   * by Robert Bridson
   * http://www.cs.ubc.ca/~rbridson/docs/bridson-siggraph07-poissondisk.pdf
   **/

  PoissonDistribution()
  {
    _points = new Vector<PVector>();
  }

  Vector<PVector> getPoints() { 
    return _points;
  }

  Vector<PVector> generate(float xmin, float ymin, float xmax, float ymax, float minDist, int rejectionLimit)
  {
    _xmin = xmin; 
    _xmax = xmax; 
    _ymin = ymin; 
    _ymax = ymax;
    _cellSize = minDist / sqrt(2);
    _gridWidth = ceil((xmax-xmin) / _cellSize);
    _gridHeight = ceil((ymax-ymin) / _cellSize);
    int s = _gridWidth * _gridHeight;
    _grid = new ArrayList<Vector<PVector>>();
    for (int i=0; i<s; i++)
      _grid.add(new Vector<PVector>());

    _points.clear();
    LinkedList<PVector> processList = new LinkedList<PVector>();

    PVector p = new PVector(random(_xmin, _xmax), random(_ymin, _ymax));
    processList.add(p);
    _points.add(p);
    addToGrid(p);

    while (processList.size() > 0)
    {
      int i = floor(random(processList.size()));
      p = processList.get(i);
      processList.remove(i);
      for (i=0; i<rejectionLimit; i++)
      {
        PVector n = createRandomPointAround(p, minDist, minDist*2);
        if (insideBoundaries(n) && testGrid(n, minDist)) {
          processList.add(n);
          _points.add(n);
          addToGrid(n);
        }
      }
    }

    return _points;
  }

  private boolean insideBoundaries(PVector p)
  {
    return (p.x >= _xmin && p.x < _xmax && p.y >= _ymin && p.y < _ymax);
  }

  private PVector createRandomPointAround(PVector p, float minDist, float maxDist)
  {
    float a = random(2*PI);
    float r = random(minDist, maxDist);
    return new PVector(p.x + r * cos(a), p.y + r * sin(a));
  }

  // return true if there are no points inside the circle of minDist radius around p
  private boolean testGrid(PVector p, float minDist)
  {
    int minX = floor(max(0, (p.x - minDist - _xmin) / _cellSize));
    int maxX = ceil(min(_gridWidth - 1, (p.x + minDist - _xmin) / _cellSize));
    int minY = floor(max(0, (p.y - minDist - _ymin) / _cellSize));
    int maxY = ceil(min(_gridHeight - 1, (p.y + minDist - _ymin) / _cellSize));

    for (int y=minY; y<=maxY; y++) {
      for (int x=minX; x<=maxX; x++) {
        Vector<PVector> cell = _grid.get(y * _gridWidth + x);
        for (PVector t : cell)
          if (dist(p.x, p.y, t.x, t.y) <= minDist)
            return false;
      }
    }

    return true;
  }

  private void addToGrid(PVector p)
  {
    _grid.get(index(p.x, p.y)).add(p);
  }

  protected int index(float x, float y)
  {
    int gx = floor((x - _xmin) / _cellSize);
    int gy = floor((y - _ymin) / _cellSize);
    return gy * _gridWidth + gx;
  }

  private ArrayList<Vector<PVector>> _grid;
  private float _cellSize;
  private int _gridWidth, _gridHeight;
  private float _xmin, _xmax, _ymin, _ymax;
  private Vector<PVector> _points;
}

```

---

<div class="post-metadata">

### Author: ![paulgoux](https://avatars.discourse-cdn.com/v4/letter/p/b9bd4f/32.png) [@paulgoux](https://discourse.processing.org/u/paulgoux)
#### Post date: [January 1, 2021, 1:24am UTC](https://discourse.processing.org/t/how-to-give-circles-ellipses-certain-distance-apart-from-each-other-giving-random-position-every-time-i-press-key/26646/5 "2021-01-01T01:24:09Z")

</div>

Is efficiency an issue here, just wandering, otherwise the last post has you covered.

---

<div class="post-metadata">

### Author: ![yewon](https://avatars.discourse-cdn.com/v4/letter/y/9de0a6/32.png) [@yewon](https://discourse.processing.org/u/yewon)
#### Post date: [January 1, 2021, 3:56am UTC](https://discourse.processing.org/t/how-to-give-circles-ellipses-certain-distance-apart-from-each-other-giving-random-position-every-time-i-press-key/26646/6 "2021-01-01T03:56:48Z")

</div>

oh I think i made my question unclear. I mean, the spacing doesn’t have to be even. it can be random but the spacing should be no less than for example 50.(I choose the minimum value). thank you for your reply though.

---

<div class="post-metadata">

### Author: ![yewon](https://avatars.discourse-cdn.com/v4/letter/y/9de0a6/32.png) [@yewon](https://discourse.processing.org/u/yewon)
#### Post date: [January 1, 2021, 3:57am UTC](https://discourse.processing.org/t/how-to-give-circles-ellipses-certain-distance-apart-from-each-other-giving-random-position-every-time-i-press-key/26646/7 "2021-01-01T03:57:35Z")

</div>

not really. I was just playing around with attractor and got stuck in this problem.

---

<div class="post-metadata">

### Author: ![yewon](https://avatars.discourse-cdn.com/v4/letter/y/9de0a6/32.png) [@yewon](https://discourse.processing.org/u/yewon)
#### Post date: [January 1, 2021, 4:05am UTC](https://discourse.processing.org/t/how-to-give-circles-ellipses-certain-distance-apart-from-each-other-giving-random-position-every-time-i-press-key/26646/8 "2021-01-01T04:05:15Z")

</div>

thank you for the solution. this technique is new to me. I got something new to study.  
but does this technique give dynamic changes in position???

---

<div class="post-metadata">

### Author: ![yewon](https://avatars.discourse-cdn.com/v4/letter/y/9de0a6/32.png) [@yewon](https://discourse.processing.org/u/yewon)
#### Post date: [January 1, 2021, 4:14am UTC](https://discourse.processing.org/t/how-to-give-circles-ellipses-certain-distance-apart-from-each-other-giving-random-position-every-time-i-press-key/26646/9 "2021-01-01T04:14:35Z")

</div>

![ezgif.com-gif-maker](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/0/009c4ade4e25e7d3a6dab08793c4f8459eb544e1.gif)

this is something I have done. this is close to what i want, but the spacing needs to be at least [some value that i choose] for example 50. other than that spacing can be big or small. doesn’t have to be even. right now minimum value of spacing is not set.

```auto
Mover movers[] = new Mover[1000];
Attractor attractors[]=new Attractor[5];

void setup() {
  size(800, 400, P3D);
  for (int i=0; i<attractors.length; i++) {
    attractors[i] = new Attractor(random(0.1, 2), random(0, width), random(0, height), random(-100, 100));
  }
}

void draw() {
  background(255);
  for (int i=0; i<attractors.length; i++) {
    attractors[i].display();
    attractors[i].update();
   
  }
}

void keyPressed(){
  for(int i=0;i<attractors.length;i++){
attractors[i].targetloc = new PVector(random(0,width),random(0,height),random(-100,0));
 
  }
}

```

```auto
class Attractor {
  PVector prevloc;
  PVector targetloc;
  float mass;
  float G;
  Attractor(float m, float x, float y,float z) {
    prevloc = new PVector(x, y, z);
    targetloc = new PVector(width/2,height/2,0);
    mass = m;
    G=0.4;
  }
  PVector attract(Mover m){
  PVector force = PVector.sub(prevloc,m.loc);
  float distance = force.mag();
  distance = constrain(distance,5.0,25.0);
  force.normalize();
  float strength = (G*mass*m.mass)/(distance*distance);
  force.mult(strength);
  return force;
  }
  
  void update(){
 prevloc.lerp(targetloc,0.1);
  }
void display(){
  pushMatrix();
  noStroke();
  fill(255,223,0);
  translate(prevloc.x,prevloc.y,prevloc.z);
  sphere(5);
  popMatrix();
  }

}

```

---

<div class="post-metadata">

### Author: ![micycle](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/micycle/32/201_2.png) [@micycle](https://discourse.processing.org/u/micycle)
#### Post date: [January 1, 2021, 12:02pm UTC](https://discourse.processing.org/t/how-to-give-circles-ellipses-certain-distance-apart-from-each-other-giving-random-position-every-time-i-press-key/26646/10 "2021-01-01T12:02:50Z")

</div>

You can get dynamic changes in position by _lerping_ between two sets of points.

The start and end states meet the distance-apart condition, but as the circles are moving there will be overlap between them – it sounds like you don’t want this.

Circles applying a repulsion force to each other as they travel from their start to end destination may be a solution. In this case, the `toxiclibs` library may be worth a look.

 ![circles](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/8/8fe0e357c243548f010377132da5c4d2cf9427ad.gif)

```auto
import java.util.Vector;
import java.util.LinkedList;

PoissonDistribution points = new PoissonDistribution();
Vector<PVector> pointsA;
Vector<PVector> pointsB;

int minimumDistance = 100;
PVector[] animate;

void setup() {
  size(800, 800);
  colorMode(HSB, 1);
  noStroke();

  pointsA = points.generate(0, 0, width, height, minimumDistance, 15);
  pointsB = points.generate(0, 0, width, height, minimumDistance, 15);
  animate = new PVector[(min(pointsA.size(), pointsB.size()))];
}

void draw() {
  background(0, 0, 1);

  float lerp = 1 - abs(millis()*0.0004 % (2) - 1); // 0...1 triangle wave

  float smoothLerp = easeInOutQuint(lerp);

  for (int i = 0; i < animate.length; i++) {
    animate[i] = PVector.lerp(pointsA.get(i), pointsB.get(i), smoothLerp);
    fill(i/(float) animate.length, 0.8, 1, 0.75);
    ellipse(animate[i].x, animate[i].y, minimumDistance - 10, minimumDistance - 10);
  }
}

void keyPressed() {
  pointsA = points.generate(0, 0, width, height, minimumDistance, 15);
  pointsB = points.generate(0, 0, width, height, minimumDistance, 15);
  animate = new PVector[(min(pointsA.size(), pointsB.size()))];
}

static float easeInOutQuint(float x) {
  return x < 0.5 ? 16 * x * x * x * x * x : 1 - pow(-2 * x + 2, 5) / 2;
}

class PoissonDistribution
{
  /** From "Fast Poisson Disk Sampling in Arbitrary Dimensions"
   * by Robert Bridson
   * http://www.cs.ubc.ca/~rbridson/docs/bridson-siggraph07-poissondisk.pdf
   **/

  PoissonDistribution()
  {
    _points = new Vector<PVector>();
  }

  Vector<PVector> getPoints() { 
    return _points;
  }

  Vector<PVector> generate(float xmin, float ymin, float xmax, float ymax, float minDist, int rejectionLimit)
  {
    _xmin = xmin; 
    _xmax = xmax; 
    _ymin = ymin; 
    _ymax = ymax;
    _cellSize = minDist / sqrt(2);
    _gridWidth = ceil((xmax-xmin) / _cellSize);
    _gridHeight = ceil((ymax-ymin) / _cellSize);
    int s = _gridWidth * _gridHeight;
    _grid = new ArrayList<Vector<PVector>>();
    for (int i=0; i<s; i++)
      _grid.add(new Vector<PVector>());

    _points.clear();
    LinkedList<PVector> processList = new LinkedList<PVector>();

    PVector p = new PVector(random(_xmin, _xmax), random(_ymin, _ymax));
    processList.add(p);
    _points.add(p);
    addToGrid(p);

    while (processList.size() > 0)
    {
      int i = floor(random(processList.size()));
      p = processList.get(i);
      processList.remove(i);
      for (i=0; i<rejectionLimit; i++)
      {
        PVector n = createRandomPointAround(p, minDist, minDist*2);
        if (insideBoundaries(n, minDist/2) && testGrid(n, minDist)) {
          processList.add(n);
          _points.add(n);
          addToGrid(n);
        }
      }
    }

    return new Vector<PVector>(_points);
  }

  private boolean insideBoundaries(PVector p, float border)
  {

    // return (p.x >= _xmin && p.x < _xmax && p.y >= _ymin && p.y < _ymax); // keep center points in bounds of sketch
    return (p.x >= _xmin+border && p.x < _xmax-border && p.y >= _ymin+border && p.y < _ymax-border); // keep cicles in bounds of sketch
  }

  private PVector createRandomPointAround(PVector p, float minDist, float maxDist)
  {
    float a = random(2*PI);
    float r = random(minDist, maxDist);
    return new PVector(p.x + r * cos(a), p.y + r * sin(a));
  }

  // return true if there are no points inside the circle of minDist radius around p
  private boolean testGrid(PVector p, float minDist)
  {
    int minX = floor(max(0, (p.x - minDist - _xmin) / _cellSize));
    int maxX = ceil(min(_gridWidth - 1, (p.x + minDist - _xmin) / _cellSize));
    int minY = floor(max(0, (p.y - minDist - _ymin) / _cellSize));
    int maxY = ceil(min(_gridHeight - 1, (p.y + minDist - _ymin) / _cellSize));

    for (int y=minY; y<=maxY; y++) {
      for (int x=minX; x<=maxX; x++) {
        Vector<PVector> cell = _grid.get(y * _gridWidth + x);
        for (PVector t : cell)
          if (dist(p.x, p.y, t.x, t.y) <= minDist)
            return false;
      }
    }

    return true;
  }

  private void addToGrid(PVector p)
  {
    _grid.get(index(p.x, p.y)).add(p);
  }

  protected int index(float x, float y)
  {
    int gx = floor((x - _xmin) / _cellSize);
    int gy = floor((y - _ymin) / _cellSize);
    return gy * _gridWidth + gx;
  }

  private ArrayList<Vector<PVector>> _grid;
  private float _cellSize;
  private int _gridWidth, _gridHeight;
  private float _xmin, _xmax, _ymin, _ymax;
  private Vector<PVector> _points;
}

```

---

<div class="post-metadata">

### Author: ![yewon](https://avatars.discourse-cdn.com/v4/letter/y/9de0a6/32.png) [@yewon](https://discourse.processing.org/u/yewon)
#### Post date: [January 1, 2021, 2:01pm UTC](https://discourse.processing.org/t/how-to-give-circles-ellipses-certain-distance-apart-from-each-other-giving-random-position-every-time-i-press-key/26646/11 "2021-01-01T14:01:53Z")

</div>

it looks wonderful. when I was considering 3d i dont want overlap. But if it’s going to be 2d, I think it looks great. Thank you so much!! I love how it looks.
