有效的债券清单到三角测量转换? (蟒蛇)

时间:2015-08-25 23:22:30

标签: python arrays triangulation

我需要将'bond'(点索引对)数组转换为'triangles'数组(点索引的三元组,表示三角剖分)。 我的方法对于大的(N~100000 +)点来说太慢了,因为对于~1,000,000点的网格我需要多次这样做。

我得到一个数组'BL',其中每一行包含两个有连接点的索引。我的方法是创建一个数组'NL',其中第i行包含第i个点的邻居的索引。然后对于NL的每一行(比如第i行),我创建一个布尔数组,告诉我哪些BL行包含索引,其中两个点都是第i个粒子的邻居。如果BL的第k行满足NL的第i行的这个条件,那么我在点[i,BL [k,0],BL [k,1]]之间有一个三角形。

我确信这个过程可以更有效率。有什么建议? 我的功能'BL2TRI'如下:

4

要使用此功能,这是一个简短的工作示例:

def BL2TRI(BL,nn):
    '''Convert bond list (#bonds x 2) to Triangulation array (#tris x 3)

    Parameters
    ----------
    BL : array of dimension #bonds x 2
        Each row is a bond and contains indices of connected points
    nn : int
        max number of nearest neighbors expected in NL and KL

    Returns
    ----------
    TRI : array of dimension #tris x 3
        Each row contains indices of the 3 points lying at the vertices of the tri.
    '''
    print('BL2TRI: computing NL...')
    NL, KL = BL2NLandKL(BL,nn)
    print('BL2TRI: assembling TRI...')
    ind = 0 #index to keep track of where we are in TRI
    # make TRItmp longer than necessary (to fill it in without appending)
    TRItmp = np.zeros((10*len(NL),3),dtype='int')
    # add 1 to all BL values and to all NL values for which KL!=0 to avoid finding that zero is a neighbor of every particle with fewer than nn neighbors
    BLp = BL + np.ones(np.shape(BL))
    NLp = copy.deepcopy(NL)
    NLp[KL!=0] +=1

    for kk in range(len(NLp)):
        idx = np.logical_and( ismember(BLp[:,0], NLp[kk,:]), ismember(BLp[:,1], NLp[kk,:]) )
        TRIS = BL[idx,:]
        TRItmp[ind:ind+len(TRIS),:]  = np.hstack(( TRIS, kk*np.ones((len(TRIS),1)) ))
        ind = ind+len(TRIS)

    #trim off the extra zeros at the end
    TRI = TRItmp[0:ind,:]
    return TRI

请注意,结果有重复的行并且没有排序,但这些是我在此省略的简单步骤。

1 个答案:

答案 0 :(得分:1)

根据我的时间安排,这是一种更快的方法,并且根据我所做的一些快速测试,这种方法可以更好地扩展。它也有点清洁:

def BL2TRI(BL):
    d = {}
    tri = np.zeros((len(BL),3), dtype=np.int)
    c = 0
    for i in BL:
        if(i[0] > i[1]):
            t = i[0]
            i[0] = i[1]
            i[1] = t
        if(i[0] in d):
            d[i[0]].append(i[1])
        else:
            d[i[0]] = [i[1]]
    for key in d:
        for n in d[key]:
            for n2 in d[key]:
                if (n>n2) or n not in d:
                    continue
                if (n2 in d[n]):
                    tri[c,:] = [key,n,n2]
                    c += 1
    return tri[0:c]

在这里,我使用字典,这意味着即使有大量节点,我们也可以从各种哈希表中获益。我还通过确保(a,b) a<b所有节点来减少要检查的节点数。

值得注意的是,总的来说,对于涉及大型阵列的许多问题,其中缺少numpy(和相关的库 - scitools等),我发现它通常更容易(并且通常稍微更清洁,取决于你有多喜欢一些更加模糊的numpy语法)将grunt工作卸载到C - 通过ctypes(https://docs.python.org/2/library/ctypes.html)等库。这很容易上手,所以如果你对你编码的内容很灵活,你需要做额外的计算,那么值得一看。