2013-01-02 31 views
2

我是一个新手,并试图在Python 2.7.2与Numpy的东西没有按预期工作,所以想检查是否有什么基本的东西,我是误解。使用索引的Numpy循环

我正在计算三角形(trinormals)的值,​​然后使用三角形索引(trivertexidx)数组更新三角形(vertnormals)的每个点的值。作为一个循环,我计算:

for itri in range(ntriangles) : 
     vertnormals[(trivertidx[itri,0]),:] += trinormals[itri,:] 
     vertnormals[(trivertidx[itri,1]),:] += trinormals[itri,:] 
     vertnormals[(trivertidx[itri,2]),:] += trinormals[itri,:] 

由于这是我认为它可以修改成一个有点慢:

vertnormals[(trivertidx[:,0]),:] += trinormals[:,:] 
    vertnormals[(trivertidx[:,1]),:] += trinormals[:,:] 
    vertnormals[(trivertidx[:,2]),:] += trinormals[:,:] 

然而,这并没有给相同的结果。是否有另一种更简单的方法来编写循环?任何指针赞赏。请注意这里的意图是为vertiant中的每个条目获取单个值,然后对结果进行归一化。

回答

1

numpy的具有功能bincount,可以是在像场景非常有帮助这个。这两条线波纹管是当index的元素是唯一当index已经重复值相同,但不同的:

A[index] += W 
A += np.bincount(index, W, minlenght=len(A)) 

我相信你想第二的行为,但你的代码是多一点因为A,索引和W不是1d。你可以试试这样的,

import numpy as np 
N = len(vertnormals) 
for j in range(vertnormals.shape[-1]): 
    vertnormals[:, j] += np.bincount(trivertidx[:, 0], trinormals[:, j], minlength=N) 
    vertnormals[:, j] += np.bincount(trivertidx[:, 1], trinormals[:, j], minlength=N) 
    vertnormals[:, j] += np.bincount(trivertidx[:, 2], trinormals[:, j], minlength=N) 

希望有帮助。

+0

抱歉没有发现这个答案(不知道如何回到它)。很好的解决方案,并完美运作 – user1942439

1

如果我理解你的问题很好,你必须从中已经形成n三角形m点,trivertidx是形状(n, 3)控股值的范围[0, m),其中trivertidx[j]是3分的组成名单数组j第三个三角形。

trinormals然后是形状(n,)保持分配给每个trinagle一个值的数组,并且希望vertnormals是形状(m,)保持的阵列,对于每个点,分配给每个三角的值的总和这一点是顶点。

如果以上是正确的,下面的例子应该说明为什么你的第二个代码无法正常工作:

>>> a = np.arange(5) 
>>> a 
array([0, 1, 2, 3, 4]) 
>>> a[[1,2,0,2]] += 1 
>>> a 
array([1, 2, 3, 3, 4]) 

即使在2位置的元素在左侧两次出现时,会发生什么情况是相同值的两个副本已添加1,然后将增加的值复制两次到同一位置。

向量化该求和,其中在[j, k]位置的值是True如果顶点k是三角形jFalse如果不是的一部分就需要形状(n, m)的阵列。你可以建立一个数组是这样的:

trivert = np.zeros((n, m), dtype='bool') 
trivert[np.arange(n).reshape(n, 1), trivertidx] = 1 

一旦你有了这个数组,你可以让你的每个顶点款项

vertnormals = np.sum(trivert * trinormals.reshape(-1, 1), axis=0) 
+0

因为我没有发现答案,所以迟到了。非常好的解释发生了什么,并导致第二个代码集的问题。解决方案虽然有两个问题。首先,布尔型数组似乎对于一大组三角形和法线来说有一个极限(数组太大)。第二个问题是广播上最后一步从未匹配,因为它试图广播(m,n)v(3m,1) – user1942439