首先,如果有人能给我一个适当的术语“带有移位孔的环”,我将不胜感激,请看下我在下面图片中的形状。
回到主要问题:我想在橙色区域中选择一个随机点,不需要均匀分布。对于通常环的情况,我会选择随机点(r:R)范围和随机角度,然后将它们转换为x,y并完成。但对于这种不寻常的形状......是否有一个“简单”的公式,或者我应该通过做某种形状的多边形近似来接近它?
我对一般方法感兴趣,但会欣赏python,javascript或您选择的任何编码语言的示例。
答案 0 :(得分:3)
你真的需要精确抽样吗?因为接受/拒绝它应该工作得很好。我假设大橙色圆圈位于(0,0)
import math
import random
def sample_2_circles(xr, yr, r, R):
"""
R - big radius
r, xr, yr - small radius and its position
"""
x = xr
y = yr
cnd = True
while cnd:
# sample uniformly in whole orange circle
phi = 2.0 * math.pi * random.random()
rad = R * math.sqrt(random.random())
x = rad * math.cos(phi)
y = rad * math.sin(phi)
# check condition - if True we continue in the loop with sampling
cnd = ( (x-xr)**2 + (y-yr)**2 < r*r )
return (x,y)
答案 1 :(得分:3)
这是一种简单的方法,可以在没有重新采样的情况下提供均匀分布。
为简单起见,假设外边界圆的中心(半径r_outer
)位于(0, 0)
,内圆边界的中心(半径r_inner
)位于{{ 1}}。
为外部磁盘写(x_inner, y_inner)
,为偏心内孔给出的平面子集D
,为中心写H1
半径为H2
的磁盘,以r_inner
为中心。
现在假设我们忽略了内圈不是中心的事实,而不是从(0, 0)
采样,我们从D-H1
采样(这很容易统一)。然后我们犯了两个错误:
D-H2
,即使这些样本不在结果中。A = H1 - H2
,即使我们应该但事情就是这样:区域B = H2 - H1
和A
是一致的:在平面中给出任何点B
,(x, y)
在(x, y)
当且仅当H2
位于(x_inner - x, y_inner - y)
时,H1
位于(x, y)
当{且仅当A
位于(x_inner - x, y_inner - y)
时{} {1}}!地图B
表示点(x, y) -> (x_inner - x, y_inner - y)
周围的旋转180度。所以有一个简单的诀窍:从(0.5*x_inner, 0.5*y_inner)
生成,如果我们在D - H2
中得到一些内容,请旋转以获得相应的H1 - H2
点。
这是代码。注意使用均匀分布的平方根来选择半径:这是一个标准技巧。例如,请参阅this article。
H2 - H1
一个示例图,由以下内容生成:
import math
import random
def sample(r_outer, r_inner, x_inner, y_inner):
"""
Sample uniformly from (x, y) satisfiying:
x**2 + y**2 <= r_outer**2
(x-x_inner)**2 + (y-y_inner)**2 > r_inner**2
Assumes that the inner circle lies inside the outer circle;
i.e., that hypot(x_inner, y_inner) <= r_outer - r_inner.
"""
# Sample from a normal annulus with radii r_inner and r_outer.
rad = math.sqrt(random.uniform(r_inner**2, r_outer**2))
angle = random.uniform(-math.pi, math.pi)
x, y = rad*math.cos(angle),rad*math.sin(angle)
# If we're inside the forbidden hole, reflect.
if math.hypot(x - x_inner, y - y_inner) < r_inner:
x, y = x_inner - x, y_inner - y
return x, y
答案 2 :(得分:2)
由于您没有显示自己的方程式,算法或代码,只是中心对齐圆的算法大纲,我也只是在这里给出一个算法的大纲,用于更一般的情况。 / p>
较小的圆是相似变换下的较大圆的图像。即在较大的圆中有一个固定点和一个比率(R / r,大于1),这样你可以在较小的圆上取任意点,检查从固定点到该点的矢量,并乘以该矢量通过比率,那么当从固定点开始时该矢量的结束是较大圆上的点。这种转变是一对一的。
因此,您可以在较小的圆上选择一个随机点(在0和2-pi之间选择随机的角度)并选择1之间的随机比率和圆之间的比例比R / r。然后使用具有相同固定点的相似变换,但使用随机比率来获得较小圆上的刚选择点的图像点。这是您所需区域的随机点。
这种方法相当简单。事实上,最难的数学部分是找到相似变换的固定点。但考虑到两个圆圈的中心和半径,这很容易。提示:转换将较小圆的中心带到较大圆的中心。
询问您是否需要更多细节。我的算法不会产生均匀的分布:在圆圈最接近的地方,点数会更加紧密,而在圆圈相距最远的地方,点数会更紧密。
以下是一些未经测试的Python 3.6.2代码。我会测试它并在可能的时候显示它的图形。
import math
import random
def rand_pt_between_circles(x_inner,
y_inner,
r_inner,
x_outer,
y_outer,
r_outer):
"""Return a random floating-point 2D point located between the
inner and the outer circles given by their center coordinates and
radii. No error checking is done on the parameters."""
# Find the fixed point of the similarity transformation from the
# inner circle to the outer circle.
x_fixed = x_inner - (x_outer - x_inner) / (r_outer - r_inner) * r_inner
y_fixed = y_inner - (y_outer - y_inner) / (r_outer - r_inner) * r_inner
# Find a a random transformation ratio between 1 and r_outer / r_inner
# and a random point on the inner circle
ratio = 1 + (r_outer - r_inner) * random.random()
theta = 2 * math.pi * random.random()
x_start = x_inner + r_inner * math.cos(theta)
y_start = y_inner + r_inner * math.sin(theta)
# Apply the similarity transformation to the random point.
x_result = x_fixed + (x_start - x_fixed) * ratio
y_result = y_fixed + (y_start - y_fixed) * ratio
return x_result, y_result
答案 3 :(得分:1)
Severin Pappadeux描述的接受/拒绝方法可能是最简单的。
对于直接逼近,您也可以在极坐标中工作,孔的中心为极点。
外部圆的极坐标方程(Θ, σ)
(抱歉,没有rho)将是
(σ cosΘ - xc)² + (σ sinΘ - yc)² = σ² - 2(cosΘ xc + sinΘ yc)σ + xc² + yc² = R²
这是σ
中的二次方程,您可以根据Θ
轻松解决。然后,您可以在0, 2π
绘制一个角度,在r
和σ
之间绘制半径。
这不会给你一个统一的分布,因为σ
的范围是Θ
的函数,并且由于极性偏差。这可以通过计算合适的传递函数来解决,但这有点技术性,可能不易分析。