Ele*_*opa 5 python random numpy triangular
我想生成x和y具有均匀分布,并通过限制[xmin,xmax]和[ymin,ymax]
点 (x,y) 应该在三角形内。
我该如何解决这样的问题?
Mar*_*son 11
这是一些在平面上的任意三角形上均匀生成点的代码。
import random
def point_on_triangle(pt1, pt2, pt3):
"""
Random point on the triangle with vertices pt1, pt2 and pt3.
"""
x, y = sorted([random.random(), random.random()])
s, t, u = x, y - x, 1 - y
return (s * pt1[0] + t * pt2[0] + u * pt3[0],
s * pt1[1] + t * pt2[1] + u * pt3[1])
Run Code Online (Sandbox Code Playgroud)
这个想法是计算三个顶点的加权平均值,权重通过将单位间隔随机[0, 1]分成三部分(在所有这些中断上均匀)给出。这里x和y表示我们打破单元间隔的地方,和s,t和u是下列其断裂片的长度。然后我们使用s,t和u作为三角形中点的重心坐标。
这是上面的一个变体,它避免了排序的需要,而是使用了绝对值调用:
def point_on_triangle2(pt1, pt2, pt3):
"""
Random point on the triangle with vertices pt1, pt2 and pt3.
"""
x, y = random.random(), random.random()
q = abs(x - y)
s, t, u = q, 0.5 * (x + y - q), 1 - 0.5 * (q + x + y)
return (
s * pt1[0] + t * pt2[0] + u * pt3[0],
s * pt1[1] + t * pt2[1] + u * pt3[1],
)
Run Code Online (Sandbox Code Playgroud)
这是在三角形中生成 10000 个点的示例用法:
pt1 = (1, 1)
pt2 = (2, 4)
pt3 = (5, 2)
points = [point_on_triangle(pt1, pt2, pt3) for _ in range(10000)]
Run Code Online (Sandbox Code Playgroud)
以及从上面获得的图,证明了均匀性。该图是由以下代码生成的:
import matplotlib.pyplot as plt
x, y = zip(*points)
plt.scatter(x, y, s=0.1)
plt.show()
Run Code Online (Sandbox Code Playgroud)
这是图片:
由于您用“numpy”标签标记了问题,这里有一个 NumPy 版本,可以一次生成多个样本。请注意,它使用@Python 3.5 中引入并在 NumPy >= 1.10 中支持的矩阵乘法运算符。您需要将其替换为np.dot对较旧 Python 或 NumPy 版本的调用。
import numpy as np
def points_on_triangle(v, n):
"""
Give n random points uniformly on a triangle.
The vertices of the triangle are given by the shape
(2, 3) array *v*: one vertex per row.
"""
x = np.sort(np.random.rand(2, n), axis=0)
return np.column_stack([x[0], x[1]-x[0], 1.0-x[1]]) @ v
# Example usage
v = np.array([(1, 1), (2, 4), (5, 2)])
points = points_on_triangle(v, 10000)
Run Code Online (Sandbox Code Playgroud)
好的,我想是时候添加另一个版本了。有已知的算法在三角形中均匀采样,详见论文,第 4.2 章。
蟒蛇代码:
import math
import random
import matplotlib.pyplot as plt
def trisample(A, B, C):
"""
Given three vertices A, B, C,
sample point uniformly in the triangle
"""
r1 = random.random()
r2 = random.random()
s1 = math.sqrt(r1)
x = A[0] * (1.0 - s1) + B[0] * (1.0 - r2) * s1 + C[0] * r2 * s1
y = A[1] * (1.0 - s1) + B[1] * (1.0 - r2) * s1 + C[1] * r2 * s1
return (x, y)
random.seed(312345)
A = (1, 1)
B = (2, 4)
C = (5, 2)
points = [trisample(A, B, C) for _ in range(10000)]
xx, yy = zip(*points)
plt.scatter(xx, yy, s=0.2)
plt.show()
Run Code Online (Sandbox Code Playgroud)
结果看起来像
三角形上均匀吗?
import numpy as np
N = 10 # number of points to create in one go
rvs = np.random.random((N, 2)) # uniform on the unit square
# Now use the fact that the unit square is tiled by the two triangles
# 0 <= y <= x <= 1 and 0 <= x < y <= 1
# which are mapped onto each other (except for the diagonal which has
# probability 0) by swapping x and y.
# We use this map to send all points of the square to the same of the
# two triangles. Because the map preserves areas this will yield
# uniformly distributed points.
rvs = np.where(rvs[:, 0, None]>rvs[:, 1, None], rvs, rvs[:, ::-1])
Finally, transform the coordinates
xmin, ymin, xmax, ymax = -0.1, 1.1, 2.0, 3.3
rvs = np.array((ymin, xmin)) + rvs*(ymax-ymin, xmax-xmin)
Run Code Online (Sandbox Code Playgroud)
统一边距?最简单的解决方案是将质量均匀集中在 (ymin, xmin) - (ymax, xmax) 线上
rvs = np.random.random((N,))
rvs = np.c_[ymin + (ymax-ymin)*rvs, xmin + (xmax-xmin)*rvs]
Run Code Online (Sandbox Code Playgroud)
但这不太有趣,不是吗?
| 归档时间: |
|
| 查看次数: |
4924 次 |
| 最近记录: |