要统一采样三角形ABC,我可以使用以下公式:
P =(1 - sqrt(r1))* A +(sqrt(r1)*(1 - r2))* B +(r2 * sqrt(r1))* C
其中r1和r2是0到1之间的随机数。你采取的样本越多越好。但是,如果我希望获得更好的分布,同时保持低样本数量呢?
例如,如果我有一个正方形,我可以隐式地将其划分为N x N网格,并在较小的网格正方形内生成随机样本。像这样:
float u = (x + rnd(seed)) / width;
float v = (y + rnd(seed)) / height;
重点是我强制采样以较低的样本分辨率覆盖整个网格。
如何用三角形实现这一目标?我能想到的唯一方法是使用类似Triangle的库将其明确细分为多个三角形。但有没有办法像广场一样隐式地做这个,而不必实际划分三角形?
答案 0 :(得分:2)
好的,我有一些想法,并相信使用准随机数可以改善"均匀性"在没有细分为较小三角形的情况下,三角形中的点覆盖范围。使用Sobol序列的Quasirandom sampling可以提供更好的覆盖范围,如Wiki文章所示。
这是使用标准RNG的三角形中的200个点(无论它在Python中是什么)
这是从Sobol 2D序列中采集200点的图片
对我来说看起来好多了。用于播放的Python代码
import os
import math
import random
import numpy as np
import matplotlib.pyplot as plt
import sobol_seq
def trisample(A, B, C, r1, r2):
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)
if __name__ == "__main__":
N = 200
A = (0.0, 0.0)
B = (1.0, 0.0)
C = (0.5, 1.0)
seed = 1
xx = list()
yy = list()
random.seed(312345)
for k in range(0, N):
pts, seed = sobol_seq.i4_sobol(2, seed)
r1 = pts[0]
r2 = pts[1]
# uncomment if you want standard rng
#r1 = random.random()
#r2 = random.random()
pt = trisample(A, B, C, r1, r2)
xx.append(pt[0])
yy.append(pt[1])
plt.scatter(xx, yy)
plt.show()
sys.exit(0)
答案 1 :(得分:0)
我建议使用泊松磁盘采样(short academic paper link, pretty visualization link,wiki link,code link)在三角形的边界框内生成配置,然后裁剪到由三角形限定的区域。
我建议从简短的学术论文开始。这里的工作原理很容易理解。这个想法的很多变种在那里漂浮,所以要掌握它并找到适合你的那个。