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.
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?
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
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: