我有一个表示我的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
答案 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脚的情节,表明它对我有用:
此绘图的代码为
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')
但是有点难读。可能更快?我对此不确定。 (有人可以称重吗?)