Python 离散凸壳

Python 离散凸壳,python,discrete-mathematics,convex-hull,convex,Python,Discrete Mathematics,Convex Hull,Convex,在python中,给定nxn网格中的m个随机点,如何计算(大致)凸壳,其中壳只能使用离散网格上的点而不是连续点创建 像scipy.spatial这样的模块只提供连续的凸包,其中连接顶点的线是纯代数的,但是我想要一个边界离散的近似凸包 您仍然可以使用qhull+一些后期处理: import numpy as np from scipy.spatial import ConvexHull # https://stackoverflow.com/a/47705495/7207392 def conn

在python中,给定nxn网格中的m个随机点,如何计算(大致)凸壳,其中壳只能使用离散网格上的点而不是连续点创建


像scipy.spatial这样的模块只提供连续的凸包,其中连接顶点的线是纯代数的,但是我想要一个边界离散的近似凸包

您仍然可以使用qhull+一些后期处理:

import numpy as np
from scipy.spatial import ConvexHull

# https://stackoverflow.com/a/47705495/7207392
def connect2(ends):
    d0, d1 = np.diff(ends, axis=0)[0]
    if np.abs(d0) > np.abs(d1): 
        return np.c_[np.arange(ends[0, 0], ends[1,0] + np.sign(d0), np.sign(d0), dtype=np.int32),
                     np.full(np.abs(d0)+1, ends[0, 1]) if d1==0 else
                     np.arange(ends[0, 1] * np.abs(d0) + np.abs(d0)//2,
                               ends[0, 1] * np.abs(d0) + np.abs(d0)//2 + (np.abs(d0)+1) * d1, d1, dtype=np.int32) // np.abs(d0)]
    else:
        return np.c_[np.full(np.abs(d1)+1, ends[0, 0]) if d0==0 else
np.arange(ends[0, 0] * np.abs(d1) + np.abs(d1)//2,
                               ends[0, 0] * np.abs(d1) + np.abs(d1)//2 + (np.abs(d1)+1) * d0, d0, dtype=np.int32) // np.abs(d1),
                     np.arange(ends[0, 1], ends[1,1] + np.sign(d1), np.sign(d1), dtype=np.int32)]

def dch(points):
    ch = ConvexHull(points)
    n = len(ch.vertices)
    return np.concatenate([connect2(points[ch.vertices[[i, (i+1)%n]]])[:-1] for i in range(n)], axis=0)

points = np.argwhere(np.random.random((24, 24)) < 0.03)
import pylab
pylab.plot(*dch(points).T, 'bo')
pylab.plot(*points.T, 'rd')
pylab.show()
将numpy导入为np
从scipy.spatial导入convxhull
# https://stackoverflow.com/a/47705495/7207392
def接头2(末端):
d0,d1=np.差异(端部,轴=0)[0]
如果np.abs(d0)>np.abs(d1):
返回np.c_uu[np.arange(ends[0,0],ends[1,0]+np.sign(d0),np.sign(d0),dtype=np.int32),
如果d1==0,则为np.full(np.abs(d0)+1,结束[0,1])
np.arange(结束[0,1]*np.abs(d0)+np.abs(d0)//2,
结束[0,1]*np.abs(d0)+np.abs(d0)//2+(np.abs(d0)+1)*d1,d1,dtype=np.int32)//np.abs(d0)]
其他:
如果d0==0,则返回np.c_uuu[np.full(np.abs(d1)+1,结束[0,0])
np.arange(结束[0,0]*np.abs(d1)+np.abs(d1)//2,
结束[0,0]*np.abs(d1)+np.abs(d1)//2+(np.abs(d1)+1)*d0,d0,dtype=np.int32)//np.abs(d1),
np.arange(ends[0,1],ends[1,1]+np.sign(d1),np.sign(d1),dtype=np.int32)]
def dch(点数):
ch=凸出(点)
n=透镜(通道顶点)
返回np.连接([connect2(点[ch.vertices[[i,(i+1)%n]])[:-1]表示范围(n)]内的i,轴=0)
点=np.argwhere(np.random.random((24,24))<0.03)
进口派拉布
pylab.plot(*dch(points.T,'bo'))
pylab.plot(*points.T,'rd'))
pylab.show()

计算普通凸面外壳,并用数字线段连接外壳顶点(例如DDA算法)