2

我是一个新手,正在尝试使用 Numpy 在 python 2.7.2 中进行一些操作,但它没有按预期工作,所以想检查一下我是否误解了一些基本的东西。

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

    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[:,:]

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

4

2 回答 2

1

如果我很好地理解了您的问题,那么m您就有了形成n三角形的点,并且trivertidx是一个形状数组,其(n, 3)值在 range 内[0, m),其中是构成第 -th 三角形trivertidx[j]的 3 个点的列表。j

trinormals然后是一个形状数组,(n,)其中包含分配给每个三角形的值,并且您希望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])

即使 position 中的元素在2左侧出现了两次,但会发生相同值的两个副本1相加,然后将增加的值复制两次到相同的位置。

要矢量化这个总和,您需要一个形状数组,如果 vertex是 triangle 的一部分,则(n, m)position 处的值[j, k]是,如果不是。您可以像这样构建该数组:TruekjFalse

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)
于 2013-01-02T13:39:11.557 回答
1

Numpy 有一个功能bincount,在这种情况下非常有用。当 的元素唯一时,下面的两行是相同的index,但当index具有重复值时是不同的:

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

我相信你想要第二个的行为,但你的代码有点复杂,因为 A、index 和 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)

希望有帮助。

于 2013-01-02T18:29:57.873 回答