Drawing multiple objects with calculations related to the previous object

I need help figuring out how to figure out something.

So I have hardcoded two circles and an external and internal tangent line. Here is the code:

PVector c1, c2; //center of circles
PVector t1, t2; //tangent points of external tangent
PVector t3, t4; //tangent points of internal tangent 

int r1, r2; //radii
float etheta, itheta //angles to calculate tangent points
float c1c2; //length of the vector between the two centers

void setup() {
  size(500, 500);

  //definition of circles and radii
  c1 = new PVector(150, 150);
  c2 = new PVector (300, 300);
  r1 = 70;
  r2 = 55;
}

void draw() {
  //draw the circles
  ellipse(c1.x, c1.y, 2*r1, 2*r1);
  ellipse(c2.x, c2.y, 2*r2, 2*r2);

  float c1c2= PVector.dist(c1, c2);

  //calculate the angle for the external tangent
  etheta = atan2(c2.y-c1.y, c2.x-c1.x)+acos((r1-r2)/c1c2)+PI; 

  //calculate the angle for the internal tangent points
  itheta =atan2(c2.y-c1.y, c2.x-c1.x)+asin((r1+r2)/c1c2)-(PI/2);

//calculate the two external tangent points
  t1 = new PVector(c1.x+(r1*cos(etheta)), c1.y+(r1*sin(etheta)));
  t2 = new PVector(c2.x+(r2*cos(etheta)), c2.y+(r2*sin(etheta)));

//calculate the internal tangent points
  t3 = new PVector(c1.x+(r1*cos(itheta)), c1.y+(r1*sin(itheta)));
  t4 = new PVector(c2.x+(r2*cos(itheta+PI)), c2.y+(r2*sin(itheta+PI))); 

  //draw the lines
  line(t1.x, t1.y, t2.x, t2.y);
  line(t3.x, t3.y, t4.x, t4.y);
}

This gives me two circles with two tangent lines. Now, I want a third circle. I can code a third one in manually that I call “c3” and recalculate the tangent points between c3 and c2 and then I can end up with this image:

My question is if I want to automate it so that I can draw 20 circles or a random number of circles each with tangent lines to the previous circle how do I need to go about doing this? I can stumble through figuring it out, I just need to be pointed in the right direction. Like do I need to use ArrayLists or 2D Arrays? Something else? Or is this even easier than I realize?

No arrays needed unless you want the full list available at the end. Just reuse your variables:

choose c0 = (x0, y0)
draw c0
for( int i=1; i<20; i++ ) {
  calculate c1 = (x1, y1) from c0
  draw c1 and tangent lines
  c0 = c1;    // throws away c0 (Java "forgets" about it)
}

If you want to make sure that your circles are not on top of each other, then you might want to keep a list of the previous circles and loop to choose a new one until it doesn’t overlap any of the previous. Depends on your artistic goal.

Even if you kept the past ones in a list, you would still have a variable (c0) pointing to the most recent circle and use it to compute the next one.

2 Likes

Great! This was what I needed—it was more simple than I thought. Here it is with 10:

And if I wanted to have a list in the end of circles, so that perhaps I might draw the lines not only to the previous circle but let’s say the 2nd one or whichever or my choosing, would I make a PVector array?

And how would I make sure one circle isn’t on top of another? I would assume it has to do with calculating the distance between two centers and making sure that is more than the sum of the radii but I don’t really know how to have it rechoose numbers if those conditions aren’t satisfied?

1 Like

For past circles, you would want both the center and the radius, so you could either have two lists or you could make a class that contains all the circle information you want to save:

class Circle {
  float x, y, r;
  Circle( float x_, float y_, float r_ ) {
    x = x_;  y = y_;  r = r_;
  }
}

and keep of list of them. Then generate your new circles as you said, comparing their distance vs the sum of their radii:

boolean overlapped;
do {
  overlapped = false;
  generate new circle
  for each old circle in your list:
    if distance between old circle and new circle < sum of radii:
      overlapped = true
} while( overlapped is true );
add new circle to list
1 Like

Slowly working my way through actually understanding this. Am going to attach what I just found as a resource for other people who are looking to write something with objects that do not overlap:

YouTube by Daniel Shiffman here: 9.8: Random Circles with No Overlap - p5.js Tutorial - YouTube

Example code in Processing here: website-archive/Tutorials/Processing/sketch_9_5_uniform_random_sampling at dbd1dfe415fd0a6e1f2bbeb8675e39c42d32ee71 · CodingTrain/website-archive · GitHub