代码之家  ›  专栏  ›  技术社区  ›  David S

如何将角点列表转化为晶格

  •  0
  • David S  · 技术社区  · 1 年前

    我使用的是Python中的一个命令,该命令分析我拥有的一个文件,该文件包含一个2D矩形晶格,并且只返回一个角的列表。

    如果我的晶格由N个正方形组成,则该命令返回一个形状为(N,4)的数组,其中每行具有每个正方形四个角的节点索引。

    例如,如果我的晶格有两个正方形,并且节点被逐行标记,那么函数返回的数组将包含两行[1,2,4,5]和[2,3,5,6]。

    有没有一种有效的方法可以将这个角四元组列表再次转换为完整的晶格?也许在某些包中甚至有一些我不知道的内置功能。

    对于我的例子,我想要数组[[1,2,3],[4,5,6]]作为结果。

    这是我的(效率很低,可能不是100%的函数)尝试,它获取(N,4)数组的“顶点”,并返回数组“网格”和“面网格”,前者包含我上面描述的形式的节点,后者包含晶格“面”,即与原始(N,四)数组中相同的数据,但在晶格形式中正确排列。

    它的工作原理是找到一个角,外推连接到所述角的两条边,最后求解晶格的其余部分,因为每个晶格的“面”仅由三个角唯一定义,因此很容易找到第四个角。起始角处的晶格“面”有三个角,因此很容易添加第四个角,完成后,其侧面的晶格“面的”也是如此。

    在数学上,我认为这是一个不错的解决方案,但在计算上,它非常慢。在我的电脑上,使用3070晶格大约需要20秒。此外,我也尝试过一些更大的案例,我不确定它是卡住了,还是没有给它足够的时间完成。如果有人能找到一个更聪明,或者至少更快的解决方案,我将不胜感激。

    def makemesh(vertices):
        corners = np.unique(vertices)[np.unique(vertices,return_counts=True)[1] == 1]
        edges = np.unique(vertices)[np.unique(vertices,return_counts=True)[1] == 2]
        x,y = len(np.unique(vertices)), (len(corners)+len(edges)+4)/2
    
        L,W = round((y-(y**2-4*x)**0.5)/2),round((y+(y**2-4*x)**0.5)/2)
    
        mesh = np.zeros((W,L),dtype=int)
    
        mesh[0][0] = corners[0]
    
        where = [corners[0] in j for j in vertices]
        neighbours = [i for i in vertices[where][0] if i in edges]
        for n in neighbours:
            breaker = False
            border = [corners[0],n]
            while not breaker:
                nextwhere = [border[-1] in j and not any([i in j for i in border[:-1]]) for j in vertices]
                nextneighbours = [i for i in vertices[nextwhere][0] if i in edges]
                newpt = [i for i in nextneighbours if i not in border]
                for i in vertices[nextwhere][0]:
                    if i in corners:
                        border.append(i)
                        breaker = True
                if not breaker:
                    border.append(newpt[0])
            if len(border) == L:
                mesh[0] = border
            else:
                mesh[:,0] = border
    
        for i in range(W-1):
            for j in range(L-1):
                localvertex = np.array([mesh[i,j],mesh[i,j+1],mesh[i+1,j],mesh[i+1,j+1]])
                where = [mesh[i,j] in n and mesh[i,j+1] in n and mesh[i+1,j] in n for n in vertices]
                mesh[i+1,j+1] = [i for i in vertices[where][0] if i not in localvertex][0]
       
        facemesh = np.zeros(np.shape(mesh),dtype=int)[:-1,:-1]
        for i in range(np.shape(mesh)[0]-1):
            for j in range(np.shape(mesh)[1]-1):
                for k,v in enumerate(vertices):
                    if mesh[i,j] in v and mesh[i+1,j] in v and mesh[i,j+1] in v and mesh[i+1,j+1] in v:
                        facemesh[i,j] = k
                        break
       
        return mesh,facemesh
    
    0 回复  |  直到 1 年前