2
votes

I have a Big Circle and several small circles around it as seen in picture

circle demo

First I'm drawing middle small circle like this:

cxSmallMiddle = cxBig + radiusBig + hDist + radiusSmall;
sySmallMiddle = radiusBig;

cxBig is center of Big circle. hDist is the distance I want every small circle to be from big circle.

So this way now middle small circle's middle point is parallel to big circle's.

Now I want to draw next small circle with hDist from big circle and vDist (vertical distance) from middle small circle.

So this way hDist and vDist will control the distance small circles are separated from big circle and gap between small circles accordingly.

how can I find cx and cy for other buttons?

This is a hand drawn finished version finished version

Edit: added a code suggested by @Gene

@Override
public void onDraw(Canvas canvas) {

    float radiusBig = 110f * singleDp;
    float cxBig = screenWidth / 2f;
    //float cyBig = screenHeight / 2f;
    float cyBig = radiusBig + strokeWidth + (20*singleDp);

    canvas.drawCircle(cxBig, cyBig, radiusBig, paint);

    float radiusSmall = 20 * singleDp;
    float vDist = 0 * singleDp;
    float hDist = 0 * singleDp;
    float acPoint = radiusBig;
    float bcPoint = radiusSmall + vDist;

    float theta = (float) Math.acos(bcPoint / acPoint);

    int i = 0;
    double x_i = acPoint * Math.cos(i * theta) + cxBig;
    double y_i = acPoint * Math.sin(i * theta) + cyBig;
    canvas.drawCircle((float) x_i, (float) y_i, radiusSmall, paint);

    i = 1;
    x_i = acPoint * Math.cos(i * theta) + cxBig;
    y_i = acPoint * Math.sin(i * theta) + cyBig;
    canvas.drawCircle((float) x_i, (float) y_i, radiusSmall, paint);

}

I experimented a lot with this code and this is what I got. When I draw i=0 is almost 45 degree distance from i=0. While experimenting, I discovered if I specify vDist = 80; then it looks okay. The bigger the vDist the closer it gets to i=0.

1
so the distance is the distance between the tangent lines of the respective circles? Is there a reason you wouldn't just want to do some polar logic, i.e. give a series of angles and the distance from the center of the big circle? Then every one of the little circles will be spaced evenly and will all be equidistant from the center of the big circle. I assume you want to plot a couple of smaller circles around the bigger one, maybe that's not right - Matt Messersmith
I'm going to plot 5 circles on left and right side of the big circle. Yes with tangent lines. I don't want to do angles because the distance can be changed, also the size of big and small circles can change and the gap between small circles can be changed. I also added a photo @MattMessersmith - Akaki Gabisonia

1 Answers

3
votes

This is high school trigonometry. There's a right triangle formed by the big circle center (A), the small circle center (C), and the point (B) on the horizontal radius directly below the small circle center.

The length of edge BC is vDist + 2 * radiusSmall. The length of AC is radiusBig

Let \theta be the angle BAC. Then

sin(\theta) = BC / AC = (vDist + 2 * radiusSmall) / radiusBig.

So you can determine \theta:

\theta = arcsin((vDist + radiusSmall) / radiusBig)

Once you have \theta, the locations of the circles wrt the origin are

x_i = radiusBig * cos(i * \theta)
y_i = radiusBig * sin(i * \theta)

For i = 0, +1, -1, +2, -2, ...

Edit

Okay here is a quick hack in Java Swing. Sorry in the original post I said arccos when I meant arcsin.

import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Circles extends JPanel {
   public static void main(String[] a) {
      JFrame f = new JFrame();
      f.setSize(800, 800);
      f.add(new Circles());
      f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      f.setVisible(true);
   }

   @Override
   public void paint(Graphics g) {
     int cx = 400, cy = 400, rBig = 200, rSmall = 40, hDist = 20, vDist = 10;
     drawCircle(g, cx, cy, rBig);  // Big circle.
     int rSmallCircleCenters = rBig + hDist + rSmall;
     double theta = Math.asin(((double) vDist + 2 * rSmall) / rSmallCircleCenters);
     int nPairs = 3;
     for (int i = 1 - nPairs; i < nPairs; ++i) {
       int dx = (int) (rSmallCircleCenters * Math.cos(i * theta));
       int dy = (int) (rSmallCircleCenters * Math.sin(i * theta));
       drawCircle(g, cx + dx, cy + dy, rSmall);
       drawCircle(g, cx - dx, cy - dy, rSmall);
     }
   }

   private void drawCircle(Graphics g, int cx, int cy, int r) {
     g.drawOval(cx - r, cy - r, 2 * r, 2 * r);
   }
}

Here's what it draws: