簡體   English   中英

如何在凸包中獲得均勻分布的點?

[英]How to get uniformly distributed points in convex hull?

給定一組點,

points = np.random.randn(...) # n 3d points

我想通過 3d 點的列表(形狀為nx3 np.array )均勻地填充由凸包定義的體積,它們位於其中。

我可以得到凸包

hull = scipy.spatial.ConvexHull(points)

獲得均勻填充該船體體積的點列表的最快方法是什么?

1) 找到船體的 delaunay 單純形

2)根據它們的面積隨機采樣單純形

3) 對於每個單純形,使用dirichelet分布找到采樣點的dirichelet分布

4) 將分布與單純形相乘以找到最終點。

from scipy.spatial import ConvexHull, Delaunay
import numpy as np
from numpy.linalg import det
from scipy.stats import dirichlet


def dist_in_hull(points, n):
    dims = points.shape[-1]
    hull = points[ConvexHull(points).vertices]
    deln = points[Delaunay(hull).simplices]

    vols = np.abs(det(deln[:, :dims, :] - deln[:, dims:, :])) / np.math.factorial(dims)    
    sample = np.random.choice(len(vols), size = n, p = vols / vols.sum())

    return np.einsum('ijk, ij -> ik', deln[sample], dirichlet.rvs([1]*(dims + 1), size = n))

編輯:功能化並擴展到更高維度(警告: ConvexHull僅適用於 9D)

在邊界框中均勻地繪制點並拒絕那些不在船體內部的點。 (由於外殼是凸的,這可以在線性時間 O(F) 內完成,無需預處理,預處理后的對數時間 O(log F),將面投影到平面並考慮平面細分)。

如果它對某人有幫助,這里是實現 Yves 答案的代碼:

  1. 在凸包的邊界框中均勻地繪制點。
  2. 拒絕落在船體外的點。
import numpy as np
import matplotlib.pyplot as plt
from scipy.spatial import ConvexHull
from matplotlib.patches import Rectangle
from matplotlib.path import Path

#Initial positions
pos = np.random.uniform(-30, 10, (20, 2))

#Convex hull of initial positions
hull = ConvexHull( pos )

#Bounding box
bbox = [hull.min_bound, hull.max_bound]

#Hull path
hull_path = Path( hull.points[hull.vertices] )

#Draw n random points inside the convex hull
n = 10**3
rand_points = np.empty((n, 2))
for i in range(n):
    #Draw a random point in the bounding box of the convex hull
    rand_points[i] = np.array([np.random.uniform(bbox[0][0], bbox[1][0]), np.random.uniform(bbox[0][1], bbox[1][1])])

    #We check if the random point is inside the convex hull, otherwise we draw it again            
    while hull_path.contains_point(rand_points[i]) == False:
        rand_points[i] = np.array([np.random.uniform(bbox[0][0], bbox[1][0]), np.random.uniform(bbox[0][1], bbox[1][1])])

#Plot
plt.scatter(pos[:, 0],pos[:, 1], marker='o',  c='blue', alpha = 1, label ='Initial points')
for simplex in hull.simplices:
        plt.plot(hull.points[simplex, 0], hull.points[simplex, 1], '-k')
plt.gca().add_patch(Rectangle((bbox[0][0], bbox[0][1]), bbox[1][0] - bbox[0][0], bbox[1][1] - bbox[0][1],facecolor = 'None', edgecolor = 'cyan'))
plt.scatter(rand_points[:, 0],rand_points[:, 1], marker='o',  c='red', alpha = 0.31, label ='Random points inside hull')
plt.legend()
plt.savefig("fig.png", dpi = 300)

在此處輸入圖片說明

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM