问题
Given a set of points,
points = np.random.randn(...) # n 3d points
I would like to uniformly fill the volume defined by the convex hull in which they lie by a list (np.array of shape nx3
) of 3d points.
I can get the convex hull by
hull = scipy.spatial.ConvexHull(points)
What would be the fastest way to get a list of points that uniformly fills this hull's volume?
回答1:
1) Find delaunay simplices of the hull
2) randomly sample the simplices based on their area
3) for each simplex, find uniform distribution of sampled points using dirichelet
distribution
4) multiply the distributions with the simplices to find final points.
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))
EDIT: functionalized and extended to higher dimensions (Warning: ConvexHull
only works up to 9D)
回答2:
Draw points uniformly in the bounding box and reject those that aren't inside the hull. (As the hull is convex, this can be done in linear time O(F) without preprocessing, and logarithmic time O(log F) after preprocessing, projecting the faces to a plane and considering a planar subdivision).
来源:https://stackoverflow.com/questions/59073952/how-to-get-uniformly-distributed-points-in-convex-hull