泊松盘采样
Poisson Disk Sampling

原始链接: https://stripeacross.com/posts/poisson-disk-sampling/

Bridson 算法(2007)是一种广泛应用且高效的泊松盘采样生成方法,用于在保持点间最小距离的同时随机分布点(如模拟中的树木)。与效率低下的简单拒绝采样不同,Bridson 算法利用基于网格的空间划分,以常数时间执行碰撞检测。 该算法通过维护一个活跃点列表,并尝试在其周围的环形区域内放置新采样点来运作。作者强调了两个关键优化: 1. **父级优化:** 通过跟踪每个点的“父级”,算法可以排除会导致碰撞的特定角度范围,从而显著提高生成速度。 2. **径向分布:** 通过调整半径采样分布的指数($c$),可以控制点的密度。通过经验调整该值,可以在高堆积密度和自然的随机性之间取得平衡。 除了基础分布外,动态半径采样还可以实现图像点彩等效果。虽然 Bridson 算法因其简洁性仍是行业标准,但更新的方法(如 Scott A. Mitchell 在 2022 年提出的算法)通过完全消除拒绝采样,在“最大化”和“均匀性”方面表现更优,但代价是增加了实现复杂度。

抱歉。
相关文章

原文

In 2024, a team of nine mathematicians released a monstrous, nearly 1,000 page proof of the geometric Langlands conjecture. It is a crowning achievement in pure mathematics, and I have accepted that I will never understand even the statements that they proved, much less the proof itself.

On the total opposite end of the spectrum, in 2007, Robert Bridson published a one page paper that has nearly 1,000 citations and takes less than 10 minutes to fully understand. It presents a simple solution to a problem that commonly arises in computer graphics and simulations: placing things randomly, but not too close together.

Say you’re trying to procedurally generate a forest and need a way to place the trees. The problem with plain random sampling is obvious:

Some of the trees would be on top of each other! What we need is the ability to set a minimum distance between any two trees. A distribution of trees that obeys this rule is called a Poisson disk distribution. We can try a naive rejection sampling approach where we throw random darts and reject any point that falls within that minimum distance of any other point, but without a more clever data structure, it takes linear time to check collisions for each sample and the rejection rate quickly approaches one. Bridson’s algorithm gives us an efficient way to do this.

Bridson’s Algorithm

Suppose the desired minimum distance between points is rr and we are working in a dd-dimensional space. Bridson’s algorithm goes as follows:

  1. Partition the space into a grid of side length rd\frac{r}{\sqrt{d}}
  2. Initialize a list active to have one random point chosen uniformly from the space.
  3. While active is non-empty:
    1. Select an element pp from active uniformly at random.
    2. Uniformly sample the annulus centered at pp of inner radius rr and outer radius 2r2r at most kk times. If a valid Poisson disk sample is found, using the grid for efficient collision detection, add it to active and pick a new pp. If no valid point is found within kk attempts, remove pp from active. Bridson recommends setting k=30k = 30

The easiest way to uniformly sample the annulus is to generate a random unit vector vRd\vec{v} \in \mathbb{R}^d

Improvements

There are two simple improvements to Bridson’s algorithm that I have found drastically reduce the number of iterations required to generate the same number of points. The first works in two dimensions, but the second works in higher dimensions as well.

Let’s start with the two dimensional improvement. Consider when the algorithm places a point pp and then samples its annulus to get a new point qq. We call pp the parent of qq. There is valuable information stored in the relation between these points. When we inevitably sample the annulus centered at qq, there is an entire range of angles that we need not consider because the points within them would be too close to pp. This range is represented by the dotted lines in the following figure.

While the visual intuition is easy to grasp, translating it into a formula is a tedious trigonometry exercise. I’ll spare you the details and claim without proof that the cone formed by the dotted lines is centered at angle α\alpha and its width is 2β2\beta where

α=atan2(pyqy,pxqx),β=min(arccospq2+3r24rpq,arccospq2r).\begin{align*} \alpha &= \operatorname{atan2}(p_y - q_y, p_x - q_x), \\ \beta &= \min\left(\arccos\frac{|p-q|^2+3r^2}{4r \cdot |p-q|}, \arccos\frac{|p-q|}{2r}\right). \end{align*}
联系我们 contact @ memedata.com