计算圆周点
Calculating points around circle
我有一个大圆圈和几个小圆圈,如图所示
首先我画中间的小圆圈是这样的:
cxSmallMiddle = cxBig + radiusBig + hDist + radiusSmall;
sySmallMiddle = radiusBig;
cxBig
是大圆的中心。 hDist
是我希望每个小圆与大圆的距离。
所以这样现在中间小圆的中点与大圆的中点平行。
现在我想画下一个小圆,大圆hDist
,中间小圆vDist
(垂直距离)
所以这样hDist
和vDist
会相应地控制小圆圈与大圆圈的距离和小圆圈之间的间隙。
如何找到其他按钮的 cx 和 cy?
这是手绘完成版
编辑:添加了@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
时,与 i=0
的距离几乎为 45 度。在试验时,我发现如果我指定 vDist = 80
;然后它看起来没问题。 vDist 越大,越接近 i=0
.
这是高中三角学。大圆心(A)、小圆心(C)、小圆心正下方水平半径上的点(B)构成直角三角形
边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, ...
编辑
好的,这里是 Java Swing 的快速破解。对不起,原文中 post 我说的是 arcsin 时说的是 arccos。
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);
}
}
这是它绘制的内容:
我有一个大圆圈和几个小圆圈,如图所示
首先我画中间的小圆圈是这样的:
cxSmallMiddle = cxBig + radiusBig + hDist + radiusSmall;
sySmallMiddle = radiusBig;
cxBig
是大圆的中心。 hDist
是我希望每个小圆与大圆的距离。
所以这样现在中间小圆的中点与大圆的中点平行。
现在我想画下一个小圆,大圆hDist
,中间小圆vDist
(垂直距离)
所以这样hDist
和vDist
会相应地控制小圆圈与大圆圈的距离和小圆圈之间的间隙。
如何找到其他按钮的 cx 和 cy?
这是手绘完成版
编辑:添加了@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
时,与 i=0
的距离几乎为 45 度。在试验时,我发现如果我指定 vDist = 80
;然后它看起来没问题。 vDist 越大,越接近 i=0
.
这是高中三角学。大圆心(A)、小圆心(C)、小圆心正下方水平半径上的点(B)构成直角三角形
边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, ...
编辑
好的,这里是 Java Swing 的快速破解。对不起,原文中 post 我说的是 arcsin 时说的是 arccos。
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);
}
}
这是它绘制的内容: