嘿,我现在有一个代表Voxelgrid的numpy数组。我的函数获取坐标x,y,z,半径和一个值。我想将值添加到“坐标”中,它们是给定半径的球体表面的一部分。我尝试了方法,但是它们都很慢:
def spheric Surface (x, y, z, r, value):
phi = 0
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
第一种方法使用球面坐标,半径越大则eta + =必须越小..该方法非常慢。.
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
第二方法使用遮罩,但这也很慢。是否有更好的方法?是的,我的极角只能从2 / 3pi-pi ..
答案 0 :(得分:1)
通常,Python中的数据处理最好用以下形式表示: 迭代器...但是NumPy将所有事情都彻底搞砸了:最好的方法是 将算法表示为全数组运算的序列,以 尽量减少在缓慢的Python解释器中花费的时间,并 最大化在快速编译的NumPy例程中花费的时间。
- 由内而外地工作:即从最里面的循环开始,看是否可以向量化;然后,完成后,移出一个 并继续。
- (请保留该功能的原始版本(您确信该版本是正确的,以便可以在改进后的版本中测试它的正确性和速度)。
所以,让我们看看:
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
=>(大写字母表示向量)
voxelGrid = ceiling (
[ x + r * sin (ETA) * cos (PHI) ,
y + r * sin (ETA) * sin (PHI) ,
z + r * cos (ETA) ] * resolution )
eta = math.pi * 2 / 3
while eta <= math.pi:
<...>
eta += 1/10 * math.pi
=>
ETA = range ( pi*2/3, pi, pi*1/10 )
每个值都需要为phi
的每个值重复使用,因此numpy.repeat
的长度为PHI
。
phi = 0
while phi <= (2*math.pi):
<...>
phi += 1/10 * math.pi
=>
PHI = range ( 0.0, 2*pi, pi*1/10 )
需要为每个eta
的值重复,因此numpy.tile
的长度为ETA
。
最终会导致:
# numpy.linspace seems better for your task than arange
PHI = np.arange(0.0, 2*np.pi, np.pi*1/10)
ETA = np.arange(np.pi*2/3, np.pi, np.pi*1/10)
ETA, PHI = np.repeat(ETA, PHI.shape[0]), np.tile(PHI, ETA.shape[0])
XX = x + r * np.sin(ETA) * np.cos(PHI)
YY = y + r * np.sin(ETA) * np.sin(PHI)
ZZ = z + r * np.cos(ETA)
voxelGrid = np.vstack((XX,YY,ZZ))
voxelGrid = np.ceil(resolution * voxelGrid)
# plot it if you want
#import matplotlib.pyplot, mpl_toolkits.mplot3d
#fig=matplotlib.pyplot.figure()
#ax=fig.add_subplot(111,projection='3d')
#ax.scatter(*voxelGrid)
#fig.show()