下面是一些在平面中的任意三角形上均匀生成点的代码。
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])
这个想法是计算三个顶点的加权平均值,权重由单位间隔的随机中断给出[0, 1]
分成三部分(在所有此类中断上统一)。这里x
and y
表示我们打破单位间隔的地方,并且s
, t
and u
是断裂后碎片的长度。然后我们使用s
, t
and u
as the 重心坐标 https://en.wikipedia.org/wiki/Barycentric_coordinate_system#Barycentric_coordinates_on_triangles三角形中的点。
这是上面的一个变体,它避免了排序的需要,而是使用绝对值调用:
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],
)
以下是在三角形中生成 10000 个点的示例用法:
pt1 = (1, 1)
pt2 = (2, 4)
pt3 = (5, 2)
points = [point_on_triangle(pt1, pt2, pt3) for _ in range(10000)]
从上面获得的图显示了均匀性。该图是由以下代码生成的:
import matplotlib.pyplot as plt
x, y = zip(*points)
plt.scatter(x, y, s=0.1)
plt.show()
这是图片:
由于您使用“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)