Расчет очков по кругу - PullRequest
0 голосов
/ 05 октября 2018

У меня есть Большой Круг и несколько маленьких кругов вокруг него, как показано на рисунке

circle demo

Сначала я рисую средний маленький круг, как это:

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

cxBig - центр Большого круга.hDist - это расстояние, которое я хочу, чтобы каждый маленький круг находился от большого круга.

Таким образом, теперь средняя точка среднего малого круга параллельна точке большого круга.

Теперь я хочу нарисовать следующуюмаленький круг с hDist от большого круга и vDist (вертикальное расстояние) от среднего маленького круга.

Таким образом, hDist и vDist будут контролировать расстояние, маленькие круги отделяются от большого круга исоответственно промежуток между маленькими кружочками.

как мне найти cx и cy для других кнопок?

Это готовая версия, нарисованная от руки finished version

Редактировать: добавил код, предложенный @ 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=0, расстояние составляет почти 45 градусов от i=0.Во время эксперимента я обнаружил, если я укажу vDist = 80;тогда это выглядит хорошо.Чем больше vDist, тем ближе он становится к i=0.

1 Ответ

0 голосов
/ 06 октября 2018

Это тригонометрия средней школы.Прямой треугольник, образованный центром большого круга (A), центром малого круга (C) и точкой (B) на горизонтальном радиусе непосредственно под центром малого круга.

image

Длина ребра BC равна vDist + 2 * radiusSmall.Длина AC равна radiusBig

Пусть \ theta будет углом BAC.Тогда

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

Таким образом, вы можете определить \ theta:

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

После того, как у вас есть \ theta, местоположения окружностей относительно источника будут

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

Для i = 0, +1, -1, +2, -2, ...

Edit

Хорошо, вот быстрый взлом в Java Swing.Извините, в оригинальном посте я сказал arccos, когда имел в виду 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);
   }
}

Вот что он рисует:

image

...