有没有办法使用 numpy 生成索引列表

Is there a way to generate a list of indices using numpy

例如,我可以使用 numpy 生成索引的重复模式吗?

0, 1, 2, 3, 4, 5, 0, 6, 7, 8, 9, 10, 0, 11, 12, 13, 14, 15

0,1,2,1,2,3,4,5,6,5,6,7

我可以使用 numpy 中的方法生成范围内的这些列表吗?

目前我正在使用 python 中的列表来执行此操作,但我很好奇是否可以使用 numpy 来加快速度。

我不确定除了 numpy.arange 之外还有什么方法可以研究。

为了进一步说明,我正在以各种模式在 opengl 中生成三角形索引。

所以对于圆圈中的三角形,我有一些这样的代码。

    for fan_set in range(0, len(self.vertices) / vertex_length, triangle_count):
        for i in range(fan_set + 1, fan_set + 8):
            self.indices.append(fan_set)
            self.indices.append(i)
            self.indices.append(i + 1)

我不确定我是否完全理解你的意思,但以下是我用来为 3D 点生成唯一索引的方法;

def indexate(points):
    """
    Convert a numpy array of points into a list of indices and an array of
    unique points.

    Arguments:
        points: A numpy array of shape (N, 3).

    Returns:
        An array of indices and an (M, 3) array of unique points.
    """
    pd = {}
    indices = [pd.setdefault(tuple(p), len(pd)) for p in points]
    pt = sorted([(v, k) for k, v in pd.items()], key=lambda x: x[0])
    unique = np.array([i[1] for i in pt])
    return np.array(indices, np.uint16), unique

您可以在 github 上找到 this code in my stltools 包。

它是这样工作的;

In [1]: import numpy as np

In [2]: points = np.array([[1,0,0], [0,0,1], [1,0,0], [0,1,0]])

In [3]: pd = {}

In [4]: indices = [pd.setdefault(tuple(p), len(pd)) for p in points]

In [5]: indices
Out[5]: [0, 1, 0, 2]

In [6]: pt = sorted([(v, k) for k, v in pd.items()], key=lambda x: x[0])

In [7]: pt
Out[7]: [(0, (1, 0, 0)), (1, (0, 0, 1)), (2, (0, 1, 0))]

In [8]: unique = np.array([i[1] for i in pt])

In [9]: unique
Out[9]: 
array([[1, 0, 0],
       [0, 0, 1],
       [0, 1, 0]])

关键点(如果你会原谅双关语的话)是使用点的元组(因为元组是不可变的,因此是可散列的)作为字典中的键 setdefault 方法,而 dict 的长度就是值。实际上,该值是第一次看到此 确切 点。

我不是 100% 确定这就是你想要的,我认为你可以使用一对 range 值并增加 n 3 倍(每组之间的差距)来实现这一点,然后使用 numpy.concatenate 连接最终数组,如下所示:

import numpy as np

def gen_list(n):
    return np.concatenate([np.array(range(i, i+3) + range(i+1, i+4)) + i*3 
                           for i in xrange(n)])

用法:

gen_list(2)
Out[16]: array([0, 1, 2, 1, 2, 3, 4, 5, 6, 5, 6, 7])

gen_list(3)
Out[17]: 
array([ 0,  1,  2,  1,  2,  3,  4,  5,  6,  5,  6,  7,  8,  9, 10,  9, 10,
       11])

list(gen_list(2))
Out[18]: [0, 1, 2, 1, 2, 3, 4, 5, 6, 5, 6, 7]

在我的示例中,我只使用 n 作为您要生成的组数,您可以更改它以满足您的三角形要求。

您的第一个示例可以通过 numpy 方法生成为:

In [860]: np.concatenate((np.zeros((3,1),int),np.arange(1,16).reshape(3,5)),axis=1).ravel()
Out[860]: 
array([ 0,  1,  2,  3,  4,  5,  0,  6,  7,  8,  9, 10,  0, 11, 12, 13, 14,
       15])

那是因为我看到了这个 2d 重复模式

array([[ 0,  1,  2,  3,  4,  5],
       [ 0,  6,  7,  8,  9, 10],
       [ 0, 11, 12, 13, 14, 15]])

第二个模式可以由这个二维数组的ravel生成(通过广播2个数组生成):

In [863]: np.array([0,1,4,5])[:,None]+np.arange(3)
Out[863]: 
array([[0, 1, 2],
       [1, 2, 3],
       [4, 5, 6],
       [5, 6, 7]])

我可以生成第一个模式,但在第二个模式上有变化(0 的初始列破坏了模式)

I=np.array([0,5,10])[:,None]+np.arange(0,6)
I[:,0]=0

我认为你的双循环可以表示为列表推导式

In [872]: np.array([ [k,i,i+1] for k in range(0,1,1) for i in range(k+1,k+8)]).ravel()
Out[872]: array([0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 6, 0, 6, 7, 0, 7, 8])

或者没有解开:

array([[0, 1, 2],
       [0, 2, 3],
       [0, 3, 4],
       [0, 4, 5],
       [0, 5, 6],
       [0, 6, 7],
       [0, 7, 8]])

虽然我不知道是什么参数产生了你的例子。