Problem with intersection algorithm

This code is supposed to draw 20 circles that are not intersecting, but it doesn’t.
Where is the error in this?

var circles=[];

function setup() {
  createCanvas(600, 400);
  background(0);
  
  for(var i=0; i<20; i++) {
    
    var circle = {
      x: random(width),
      y: random(height),
      r: 36 
    }
    
    var overlapping=false;
    
    for(var j = 0; j < circles.length; j++) {
      
      var other = circles[j];
      var d = dist(circle.x, circle.y, other.x, other.y);
      
      if(d < circle.r + other.r) {
        overlapping = true;
        
      }
      
      if(!overlapping) {
        circles.push(circle);
      
      }
      
      
      
    }
    
    
    
    
    
  }
  
  for(i=0; i<circles.length; i++) {
    ellipse(circles[i].x, circles[i].y, circles[i].r);
  }
  
}






function draw() {
  
}
1 Like

What did you use to code this? This code doesn’t seem to work on processing 3 because “function”
And “var” don’t exist.

I’m on p5.js web editor

fixed the not drawing part

although I cant seem to fix the intersection check.

var circles=[];

function setup() {
  createCanvas(1200, 600);
  background(0);
  
  for(var i=0; i<20; i++) {
    
    var circle = {
      x: random(width),
      y: random(height),
      r: 36 
    }
    
    
    if(circles.length>0){
    for(var j = 0; j < circles.length; j++) {
      
      var other = circles[j];
      var d = dist(circle.x, circle.y, other.x, other.y);
      var overlapping = false;
      if(d < (circle.r/2 + other.r/2)&&other!==circle) {
        overlapping = true;
      }
      var k = circles.includes(circle);
      if(!overlapping&&!k) {
				
        circles.push( circle);
      }}}
		else{
			circles.push( circle);
		}}
}

function draw() {
	background(51);
	fill(255);
	text(circles.length,10,10);
  for(i=0; i<circles.length; i++) {
		stroke(255);
		fill(255);
    ellipse(circles[i].x, circles[i].y, circles[i].r);
  }
}

The way you’re doing it now adds the circle so long as there is at least one circle which it doesn’t intersect. What you actually want is to only add it if there are no circles it intersects.

In order to accomplish that, you need to declare your overlapping boolean before your for loop, and your conditional push of the circle after the for loop.

Like so:

var circles=[];

function setup() {
  createCanvas(1200, 600);
  background(0);
  
  for(var i=0; i<20; i++) {
    
    var circle = {
      x: random(width),
      y: random(height),
      r: 36 
    }
    
    
    if(circles.length>0){
       var overlapping = false;
    for(var j = 0; j < circles.length; j++) {
      
      var other = circles[j];
      var d = dist(circle.x, circle.y, other.x, other.y);
     
      if(d < (circle.r/2 + other.r/2)&&other!==circle) {
        overlapping = true;
      }
      var k = circles.includes(circle);
     }
    
        if(!overlapping&&!k) {			
            circles.push( circle);
        } 
    } 
    else {
       circles.push( circle);
    }
   }
}

function draw() {
	background(51);
	fill(255);
	text(circles.length,10,10);
  for(i=0; i<circles.length; i++) {
		stroke(255);
		fill(255);
    ellipse(circles[i].x, circles[i].y, circles[i].r);
  }
}


4 Likes

Nice! I would say this solves almost everything, the only thing it doesn’t solve is the fact that it doesn’t always produce an array of circles size 20, if the overlap check fails, the for loop continues to iterate up, and therefore you end up with a circles array of size 20 - failed checks.

1 Like

Added i-- to cause the loop to track back if the intersection check fails.

Please not that you will be limited by the amount of space you have on your canvas. So if your circles radius is 36 you have to limit the total number of circles to something that can fit in the canvas otherwise your for loop will eventually get stuck, as there is no possible space to place the next circle.

var circles=[];
var radius = 36;
var total = 200;
function Circle(x,y,r){
	this.x = x
	this.y = y;
	this.r = r;

	this.draw = function(){

		stroke(255);
		noFill();
		ellipse(this.x,this.y,this.r);
	}
}

function setup() {
  createCanvas(1200, 600);
  background(0);

  for(var i=0; i<total; i++) {

    // var circle = {
      var x =  random(width);
      var y = random(height);
      var r = radius;
    // }
		var a = new Circle(x,y,r);
    
    if(circles.length>0){
			var overlapping = false;
    for(var j = 0; j < circles.length; j++) {

      var other = circles[j];
      var d = dist(a.x, a.y, other.x, other.y);

      if(d < radius) {
        overlapping = true;
      }
      }
      if(!overlapping) {

        circles.push( a);
      }
			else{
				i--;
			}
    }
		else{
			circles.push( a);
		}}
}

function draw() {
	background(51);
	fill(255);
	text(circles.length,10,10);
  for(i=0; i<circles.length; i++) {
		stroke(255);
		fill(255);
    ellipse(circles[i].x, circles[i].y, circles[i].r);
  }
}

3 Likes