用Python向球体表面添加值的最快方法?

时间:2018-09-07 14:52:36

标签: python numpy

我有一个表示我的voxelgrid的numpy数组。现在,我想为给定半径将值添加到球体表面。最快的方法是什么? 我的解决方案:

def spheric Surface (x, y, z, r, value):
        while phi <= (2*math.pi):
            eta = math.pi * 2 / 3
            while eta <= math.pi:
                xx = x + r * math.sin(eta) * math.cos(phi)
                yy = y + r * math.sin(eta) * math.sin(phi)
                zz = z + r * math.cos(eta)
                xx = int(xx*resoultion+0.5)
                yy = int(yy*resolution+0.5)
                zz = int(zz*resolution+0.5)
                voxelGrid[xx][yy][zz] += value

                eta += 1/10 * math.pi
            phi += 1/10 * math.pi

这是我的第一个想法:它不是很快也不很准确,因为随着r的增加,我需要更大的角度来进行计算..不仅是例如添加1 / 10pi,而是添加1 / 5pi,但这使得代码甚至更慢... 分辨率是我的voxelgrid的分辨率。因此,使用分辨率3,x = 2mm在数组中将变为xx = 6。 是的,我不想要球的整个表面,只是从2 / 3pi到pi ...

有没有更好,更快的方法?

我尝试过这样的口罩,但是速度更慢:

def sphericSurface(x, y, z, r, value):
    tol = 0.6

    grenz = math.pi * 2 / 3
    mask = (np.logical_and(np.logical_and((sx[:, None, None] - x) ** 2 + (sy[None, :, None] - y) ** 2 + (sz[None, None, :] - z) ** 2 <= (r + tol)**2,
                                          (sx[:, None, None] - x) ** 2 + (sy[None, :, None] - y) ** 2 + (sz[None, None, :] - z) ** 2 >= (r - tol)**2),
                           (sz[None, None, :] - z) <= (r*math.cos(grenz))))
    x, y, z = np.where(mask==True)
    z *= 2
    voxelGrid[x,y,z] += value

1 个答案:

答案 0 :(得分:0)

您可以通过生成遮罩来选择所有需要修改的元素。我不确定这与您已有的兼容性如何,但这就是方法。基本上,它将在速度方面解决while循环解决方案的问题。

import numpy as np
x = np.arange(0.0,5.0,0.1)
y = np.arange(0.0,5.0,0.1)
z = np.arange(0.0,5.0,0.1)
points = np.array(np.meshgrid(x,y,z)).T

def make_mask(points,a,b,c,r,tol=1e-2):
    """generates a boolean mask of positions within tol distance of the surface of the sphere
    (x-a)**2 + (y-b)**2 + (z-c)**2 = r**2"""
    mask = (points[...,0]-a)**2+(points[...,1]-b)**2+(points[...,2]-c)**2 < (r+tol)**2
    return mask

mask = make_mask(points,2.5,2.5,2.5,1.0,tol=0.2) 
# this will tell you all of the points in voxelgrid which need modification
voxelgrid[mask] #will return them all 

如果要向球体表面附近的每个点添加一个值,则可以

voxelgrid[mask]+=value

假设体素和点坐标在voxelgrid[i,j,k]是与点points[i,j,k]关联的容器的意义上是一致的。您将必须使用resolution参数来使{ {1}},因此这是正确的。

这是一个la脚的情节,表明它对我有用:

enter image description here

此绘图的代码为

x,y,z

您可以使用以下类似方法更清晰地计算出蒙版:

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(*points[mask].T)

ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
plt.show()
plt.savefig('works.png')

但是有点难读。可能更快?我对此不确定。 (有人可以称重吗?)