Python SciPy中带有QHull的凸壳体积

Python SciPy中带有QHull的凸壳体积,python,scipy,convex-hull,qhull,Python,Scipy,Convex Hull,Qhull,我正试图用这个函数得到一组点的凸包的体积 根据,我应该通过“FA”选项来获得总表面积和体积 这是我得到的。。我做错了什么 > pts [(494.0, 95.0, 0.0), (494.0, 95.0, 1.0) ... (494.0, 100.0, 4.0), (494.0, 100.0, 5.0)] > hull = spatial.ConvexHull(pts, qhull_options="FA") > dir(hull) ['__class

我正试图用这个函数得到一组点的凸包的体积

根据,我应该通过
“FA”
选项来获得总表面积和体积

这是我得到的。。我做错了什么

> pts
     [(494.0, 95.0, 0.0), (494.0, 95.0, 1.0) ... (494.0, 100.0, 4.0), (494.0, 100.0, 5.0)]


> hull = spatial.ConvexHull(pts, qhull_options="FA")

> dir(hull)

     ['__class__', '__del__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_qhull', '_update', 'add_points', 'close', 'coplanar', 'equations', 'max_bound', 'min_bound', 'ndim', 'neighbors', 'npoints', 'nsimplex', 'points', 'simplices']

 > dir(hull._qhull)
     ['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']

似乎没有任何明显的方法可以直接获得您想要的结果,不管您传入了什么参数。如果您使用的不是
凸包
,而是(它还提供了大部分凸包相关信息),那么您自己计算应该不会太困难


编辑根据注释,以下是获取凸面外壳体积的更快方法:

def convex_hull_volume(pts):
    ch = ConvexHull(pts)
    dt = Delaunay(pts[ch.vertices])
    tets = dt.points[dt.simplices]
    return np.sum(tetrahedron_volume(tets[:, 0], tets[:, 1],
                                     tets[:, 2], tets[:, 3]))

def convex_hull_volume_bis(pts):
    ch = ConvexHull(pts)

    simplices = np.column_stack((np.repeat(ch.vertices[0], ch.nsimplex),
                                 ch.simplices))
    tets = ch.points[simplices]
    return np.sum(tetrahedron_volume(tets[:, 0], tets[:, 1],
                                     tets[:, 2], tets[:, 3]))
对于一些虚构的数据,第二种方法的速度似乎快了2倍左右,数值精度似乎非常好(15位小数!!!),尽管必须有更多的病理病例:

pts = np.random.rand(1000, 3)

In [26]: convex_hull_volume(pts)
Out[26]: 0.93522518081853867

In [27]: convex_hull_volume_bis(pts)
Out[27]: 0.93522518081853845

In [28]: %timeit convex_hull_volume(pts)
1000 loops, best of 3: 2.08 ms per loop

In [29]: %timeit convex_hull_volume_bis(pts)
1000 loops, best of 3: 1.08 ms per loop

尽管这个问题已经庆祝了它的第二个生日,但我想指出的是,现在,scipy包装器会自动报告Qhull计算的体积(和面积)。

尝试用一个真实的问题更新你的问题(而不是“我得到了什么”)。。尽管您提供了正确的选项,但我花了一段时间才发现没有任何地方可以找到总面积和体积。我的猜测是,SciPy没有包装特定的选项标志。困难的方法是实现它:有一件事会有帮助,那就是完整的
pts
。这样我们就可以自己尝试了。它没有在ScipyQhull包装器中实现。如果需要的话,可以很容易地添加。这很好。为了节省计算时间,我一直在从qhull中寻找卷信息,但我认为在Python中完成的速度不会比您的版本快。那么,为了确认,Delaunay对凸面外壳进行了细分,对吗?还有,这个
einsum
是一个很好的小东西。。。我不知道。:)Delaunay的速度非常慢,所以我使用ConvexHull,得到了极限点(船体上的点),然后只在这些点上运行Delaunay。在我的数据上,这种方式快了1-2个数量级。这确实很聪明。。。它可能没有进一步的改进,但您可能希望尝试完全跳过对
Delaunay
的调用,通过选择外壳上的一个点,然后计算包含该点的所有四面体的体积以及每个凸包的简单面上的点,来构建凸包的三角剖分(即
convxhull
对象的
.simplices
属性).它会产生更长的四面体,所以它在数值上可能不太稳定。但它必须更快。我也试过了,但结果差异太大。也许我做错了。数值不稳定不能解释体积值的两个数量级差异,因为它已经是凸包了,对吗?我可能会再看看这个。看看最新的编辑,对于随机数据,我得到了2倍的速度和精度,精确到15位小数位…注意,你至少需要scipy版本0.17.0才能工作。
pts = np.random.rand(1000, 3)

In [26]: convex_hull_volume(pts)
Out[26]: 0.93522518081853867

In [27]: convex_hull_volume_bis(pts)
Out[27]: 0.93522518081853845

In [28]: %timeit convex_hull_volume(pts)
1000 loops, best of 3: 2.08 ms per loop

In [29]: %timeit convex_hull_volume_bis(pts)
1000 loops, best of 3: 1.08 ms per loop