均匀生成圆和三角形内的随机点的方法
主要参考 均匀的生成圆和三角形内的随机点,先分别把方法列出来。
均匀生成圆内随机点:
#include <random>
#include <cmath>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
double radius = 1.0, x_center = 0.0, y_center = 0.0;
mt19937 rng{random_device{}()};
uniform_real_distribution<double> uni{0, 1};
double d = radius * sqrt(uni(rng));
double theta = uni(rng) * (2 * M_PI);
cout << d * cos(theta) + x_center << ", ";
cout << d * sin(theta) + y_center << endl;
#undef M_PI
均匀生成三角形内随机点:
import numpy as np
import matplotlib.pyplot as plt
import random
def GeneratePointInTriangle(point_num, pointA, pointB, pointC):
for i in range(0, point_num):
u = random.uniform(0.0, 1.0)
v = random.uniform(0.0, 1.0)
if u+v>1.0: #以(0.5,0.5)为中心进行映射
u=1-u
v=1-v
pointP = u*pointC + v*pointB + (1.0-u-v)*pointA;
plt.plot(pointP[0], pointP[1], '.', color="black")
pointA = np.array([0,10])
pointB = np.array([33,15])
pointC = np.array([-50,20])
plt.figure()
plt.plot([pointA[0],pointB[0]], [pointA[1],pointB[1]])
plt.plot([pointA[0],pointC[0]], [pointA[1],pointC[1]])
plt.plot([pointB[0],pointC[0]], [pointB[1],pointC[1]])
GeneratePointInTriangle(4000, pointA, pointB, pointC)
plt.show()
如果去掉“以(0.5,0.5)为中心进行映射”的操作,则是在平行四边形内生成点。
说明
在圆内随机生成点的方法,和文中方法相同,证明参考 一种解法的证明。
在三角形内随机生成点的方法,我在看了文中解法5和解法6后,发现解法6只适用于底边平行于坐标轴,且底边邻角不是钝角的情况,当然可以让不满足条件的三角形旋转以满足条件,但太复杂了。
重新考虑解法5:
对于三角形ABC和一点P,可以有如下的向量表示:
AP = uAC + vAB
p点在三角形内部的充分必要条件是:1 >= u >= 0, 1 >= v >= 0, u+v <= 1。
先生成[0,1]的随机数u,然后生成[0, 1-u]内的随机数v,u、v生成后,就可以得到p点的坐标:P = uC + vB + (1-u-v)A
这种方法生成的点不是均匀的,是因为u、v的生成不是独立的,如果能让u、v是独立生成的,结果就均匀了。
看一下这个图:
u作为横轴,v作为纵轴,都取[0,1]之间的随机值,满足u+v<1的是左下的三角形,右上的三角形内的点,通过一定的变换一一映射到左下三角形中就可以了。可以通过轴对称映射,也可以通过(0.5,0.5)中心对称映射,后者计算比较简单。
所以就得到了最后的算法,该方法可以支持任意三角形。