沿圆排列圆而不重叠
Arrange Circles along Circle without Overlap
我想将一组圆圈沿另一个圆圈放置,以使“子”圆圈彼此不重叠。我知道所有圆的半径,还有目标圆的位置。
目标圆总是足够大以适合所有圆。
看这张图:
:
interface Circle {
radius: number;
x: number;
y: number;
}
const childRadii = [1, 3, 2, 5, 1, 2];
const largeCircle = { radius: 10, x: 0, y: 0 };
const arrangedCircles = positionCirclesOnCircle(largeCircle, childRadii);
function positionCirclesOnCircle(
largeCircle: Circle,
radii: number[]
): Circle[] {
const arrangedCircles: Circle[] = [];
//for each of our radii find the correct x and y position along largeCircle
for (let index = 0; index < radii.length; index++) {
//find the x and y pos for this circle
//push to arrangedCircles
}
return arrangedCircles;
}
我不确定我应该用什么样的方程或数学来找到每个子圆圈的 x 和 y 位置。
我在数学论坛上看到 that there's an equation for something that looks similar,但我对如何将其翻译成打字稿一无所知。
设R
为大圆的半径,r[i]
为小圆的半径i = 0..n
。
让我们把第一个圆的圆心放在点
c[0] = (R, 0)
.
Т然后后续圆心的坐标:
c[i] = (R * cos(f[i]), R * sin(f[i]))
在哪里
f[i] = f[i-1] + 2 * arcsin((r[i] + r[i-1]) / (2 * R))
f[0] = 0
用 Python 和 matplotlib 测试这个给出了下图。
关于试穿:
- 如果两个相邻的圆的半径之和大于大圆的直径,则无法放置。
f[i] > 2 * Pi
的值表示不能再添加不重叠的圆
这是另一种方法。我试图避免使用“计算昂贵”的函数arcsin
、sin
和cos
,只用昂贵的函数sqrt
代替它们,你可以试试根据您的需要调整以下代码。
import math
import numpy as np
def initial_child_cetner(large_circle, argument):
cos_arg = math.cos(math.pi * argument / 180)
sin_arg = math.sin(math.pi * argument / 180)
rotation = np.array([[ cos_arg, -sin_arg],
[ sin_arg, cos_arg]])
initial_center = large_circle['radius'] * np.array([1., 0.])
return rotation.dot(initial_center)
def cos_sin_angle(large_radius, chord):
cos_angle = 1 - ( chord )**2 / (2*large_radius**2)
sin_angle = math.sqrt(1 - cos_angle**2)
return cos_angle, sin_angle
def next_child_center(large_circle_center, current_child_center, large_radius, chord):
cos_a, sin_a = cos_sin_angle(large_radius, chord)
rotation = np.array([[ cos_a, sin_a],
[-sin_a, cos_a]])
child_center_next = large_circle_center + rotation.dot(current_child_center - large_circle_center)
return child_center_next
def chain_of_child_circles(large_circle, child_radii, argument):
n = len(child_radii)
child_centers = np.empty((n, 2), dtype = float)
child_centers[0, :] = initial_child_cetner(large_circle, argument)
large_center = np.array([large_circle['x'], large_circle['y']])
for i in range(n-1):
chord = child_radii[i] + child_radii[i+1]
child_centers[i+1, :] = next_child_center(large_center,
child_centers[i, :],
large_circle['radius'],
chord)
return child_centers
childRadii = [1, 3, 2, 5, 1, 2]
largeCircle = { 'radius': 10, 'x': 0, 'y': 0 }
childCircleCenters = chain_of_child_circles(largeCircle, childRadii, -90)
fig, axs = plt.subplots()
axs.plot(childCircleCenters[:,0], childCircleCenters[:,1], 'bo')
axs.plot(childCircleCenters[:,0], childCircleCenters[:,1])
axs.set_aspect('equal')
plt.grid()
plt.show()
我想将一组圆圈沿另一个圆圈放置,以使“子”圆圈彼此不重叠。我知道所有圆的半径,还有目标圆的位置。
目标圆总是足够大以适合所有圆。
看这张图:
interface Circle {
radius: number;
x: number;
y: number;
}
const childRadii = [1, 3, 2, 5, 1, 2];
const largeCircle = { radius: 10, x: 0, y: 0 };
const arrangedCircles = positionCirclesOnCircle(largeCircle, childRadii);
function positionCirclesOnCircle(
largeCircle: Circle,
radii: number[]
): Circle[] {
const arrangedCircles: Circle[] = [];
//for each of our radii find the correct x and y position along largeCircle
for (let index = 0; index < radii.length; index++) {
//find the x and y pos for this circle
//push to arrangedCircles
}
return arrangedCircles;
}
我不确定我应该用什么样的方程或数学来找到每个子圆圈的 x 和 y 位置。
我在数学论坛上看到 that there's an equation for something that looks similar,但我对如何将其翻译成打字稿一无所知。
设R
为大圆的半径,r[i]
为小圆的半径i = 0..n
。
让我们把第一个圆的圆心放在点
c[0] = (R, 0)
.
Т然后后续圆心的坐标:
c[i] = (R * cos(f[i]), R * sin(f[i]))
在哪里
f[i] = f[i-1] + 2 * arcsin((r[i] + r[i-1]) / (2 * R))
f[0] = 0
用 Python 和 matplotlib 测试这个给出了下图。
关于试穿:
- 如果两个相邻的圆的半径之和大于大圆的直径,则无法放置。
f[i] > 2 * Pi
的值表示不能再添加不重叠的圆
这是另一种方法。我试图避免使用“计算昂贵”的函数arcsin
、sin
和cos
,只用昂贵的函数sqrt
代替它们,你可以试试根据您的需要调整以下代码。
import math
import numpy as np
def initial_child_cetner(large_circle, argument):
cos_arg = math.cos(math.pi * argument / 180)
sin_arg = math.sin(math.pi * argument / 180)
rotation = np.array([[ cos_arg, -sin_arg],
[ sin_arg, cos_arg]])
initial_center = large_circle['radius'] * np.array([1., 0.])
return rotation.dot(initial_center)
def cos_sin_angle(large_radius, chord):
cos_angle = 1 - ( chord )**2 / (2*large_radius**2)
sin_angle = math.sqrt(1 - cos_angle**2)
return cos_angle, sin_angle
def next_child_center(large_circle_center, current_child_center, large_radius, chord):
cos_a, sin_a = cos_sin_angle(large_radius, chord)
rotation = np.array([[ cos_a, sin_a],
[-sin_a, cos_a]])
child_center_next = large_circle_center + rotation.dot(current_child_center - large_circle_center)
return child_center_next
def chain_of_child_circles(large_circle, child_radii, argument):
n = len(child_radii)
child_centers = np.empty((n, 2), dtype = float)
child_centers[0, :] = initial_child_cetner(large_circle, argument)
large_center = np.array([large_circle['x'], large_circle['y']])
for i in range(n-1):
chord = child_radii[i] + child_radii[i+1]
child_centers[i+1, :] = next_child_center(large_center,
child_centers[i, :],
large_circle['radius'],
chord)
return child_centers
childRadii = [1, 3, 2, 5, 1, 2]
largeCircle = { 'radius': 10, 'x': 0, 'y': 0 }
childCircleCenters = chain_of_child_circles(largeCircle, childRadii, -90)
fig, axs = plt.subplots()
axs.plot(childCircleCenters[:,0], childCircleCenters[:,1], 'bo')
axs.plot(childCircleCenters[:,0], childCircleCenters[:,1])
axs.set_aspect('equal')
plt.grid()
plt.show()