【问题标题】:How to create an equally spaced grid of a diamond shaped area如何创建菱形区域的等距网格
【发布时间】:2021-11-19 03:34:45
【问题描述】:

我正在尝试在一个类似于不规则菱形或菱形的区域内构建一个等距的点网格。该菱形的边框由以下列表给出:

xlim = list(np.linspace(0,1/4*(np.sqrt(3)+1), num=56)) + list(np.linspace(1/4*(np.sqrt(3)+1),np.sqrt(3)/2, num=20)) + \
list(np.linspace(np.sqrt(3)/2, 1/4*(np.sqrt(3)+1), num=20)) + list(np.linspace( 1/4*(np.sqrt(3)+1),0, num=56))

ylim = list(np.linspace(0, np.sqrt(3)/4, num=56)) + list(np.linspace(np.sqrt(3)/4,0, num=20)) +\
list(np.linspace(0, -np.sqrt(3)/4,num=20)) + list(np.linspace(-np.sqrt(3)/4,0, num=56))

然后我创建了border 列表,其中包含一个带有周长坐标的元组:

border = []

for i in range(len(xlim)):
    border.append((xlim[i],ylim[i]))

您可以通过绘制xlimylim 数组来检查我们得到下面的多边形形状 .

我正在尝试在这个多边形内创建一个等间距的网格并包括边界,这就是我到目前为止所做的:


width = np.linspace(0,np.sqrt(3)/2,20)
kgrid = []

for i in range(0,len(width)):
    for j in range(0,len(width)):
        
        x = width[i]
        y = width[j]
        
        if (x,y) in border:
            
            continue
            
        else:
            kgrid.append([x,y])

Kgrid 将是我的结果列表,其中包含等距点的 x 和 y 坐标的元组,但是,我得到了长度和宽度 sqrt(3)/2 的整个正方形,而不是菱形内的网格仅限。

我不完全确定我做错了什么,所以任何朝着正确方向的指导或提示都会对我有所帮助。

编辑:

测试 Mozway 网格的连续交叉点或点之间的距离。

已将点保存在列表中:

for x, y in zip(X, Y):
    xs = np.linspace(*x,n1)
    ys = np.linspace(*y,n1)
    
    kx.append(xs)
    ky.append(ys)
        
    ax.plot(xs, ys, c='k', ls='', marker='.')
    plt.gca().set_aspect('equal')

这里的kx和ky,我可以把这两个展平得到网格的坐标:

kx = np.array(kx).flatten()
ky = np.array(ky).flatten()

当我测试 (kx,ky) 对(即 kx[0],ky[0] 和 kx1, ky1)之间的距离时,当循环在迭代中接近 (kx) 的长度时, 连续点 (kx,ky) 之间的距离减小。见这里:

dist = []

for i in range(len(kx)-1):
    
    dist.append(np.sqrt((kx[i]-kx[i+1])**2 + (ky[i]-ky[i+1])**2))

检查 ``dist``` 的输出,我发现对于几次迭代,我得到了大致相同的距离,但在循环的整个生命周期中,情况并非如此。

例如检查输出。

...0.049274092704200266,
 0.049274092704200266,
 0.04927409270420008,
 0.04927409270420032,
 0.049274092704200266,
 0.04927409270420008,
 0.04927409270420021,
 0.04927409270420008,
 2.045339229827365,
 0.04868407742479125,
 0.04868407742479123,
 0.04868407742479123,
 0.04868407742479125,
 0.04868407742479125,
 0.048684077424791194,
 0.04868407742479126,
 0.04868407742479124,
 0.04868407742479124,
 0.048684077424791215,
 0.0486840774247913,
 0.048684077424791104,
 0.048684077424791306,
 0.04868407742479132,
 0.0486840774247913,
 0.048684077424791104,
....

编辑 2:

Mozway 的参考图片。下图所示为网格面积的一半。等间距的点是蓝色的,但我应该能够控制网格内有多少点,从而控制点的稀疏程度。

[![下图][2]][2]

【问题讨论】:

    标签: python arrays numpy for-loop continue


    【解决方案1】:

    我的方法是在你的钻石上套一条带子,然后去掉它外面的点。

    首先我把你的点放在一个数组中并计算中心

    import numpy as np
    import matplotlib.pyplot as plt
    import functools
    
    arr = np.array([[ 0.       ,  0.       ],
                    [ 0.6830127, -0.4330127],
                    [ 0.8660254,  0.       ],
                    [ 0.6830127,  0.4330127],
                    [ 0.       ,  0.       ]
                   ])
    
    center = np.mean(arr, axis=0)
    

    现在我创建一个覆盖菱形的网格。

    x = np.arange(min(arr[:,0]), max(arr[:,0])+0.04, 0.04)
    y = np.arange(min(arr[:,1]), max(arr[:,1])+0.04, 0.04)
    a,b = np.meshgrid(x,y)
    points = np.stack([a.reshape(-1),b.reshape(-1)]).T
    

    最后,我使用典型的 numpy 掩蔽方法在您的钻石内部进行过滤。这意味着我首先创建一个真/假数组,在我想要保留的点为真,否则为假,然后将其应用于点。

    def normal(a,b):
        v = b-a
        n = np.array([v[1], -v[0]])
        #normal needs to point out
        if (center-a)@n > 0:
             n *= -1
        return n
    
    mask = functools.reduce(np.logical_and, [((points-a)@normal(a, b)) < 0 for a,b in zip(arr[:-1], arr[1:])])
    plt.plot(arr[:,0],arr[:,1])
    plt.gca().set_aspect('equal')
    plt.scatter(points[mask][:,0], points[mask][:,1])
    

    显然你的积分是points[mask]

    计算点之间的差异以检查距离是否恒定

    好吧,只需将点移动 1,然后像这样减去:

    points[mask][1:]-points[mask][:-1]
    

    你会得到

    array([[ 0.04,  0.  ],
           [-0.12,  0.04],
           [ 0.04,  0.  ],
           [ 0.04,  0.  ],
           [ 0.04,  0.  ],
           [-0.16,  0.04],
           [ 0.04,  0.  ],
           [ 0.04,  0.  ],
           [ 0.04,  0.  ],
           [ 0.04,  0.  ],
           [ 0.04,  0.  ],
           [-0.28,  0.04],
           [ 0.04,  0.  ],
           [ 0.04,  0.  ],
           [ 0.04,  0.  ],
           [ 0.04,  0.  ],
           [ 0.04,  0.  ],
           [ 0.04,  0.  ],
           [ 0.04,  0.  ],
           [-0.32,  0.04],
    ...
           [-0.12,  0.04],
           [ 0.04,  0.  ],
           [ 0.04,  0.  ],
           [ 0.  ,  0.04]])
    

    从左下角开始向右走 0.04(x 方向),然后向上走 0.04(y 方向)和 0.12(0.04 的 3 步)向左(负 x 方向)等等.

    这是顺便说一句。这并不奇怪,因为我在这一行中选择了这种方式:

    x = np.arange(min(arr[:,0]), max(arr[:,0])+0.04, 0.04)
    

    我发布了差异,因为这似乎更容易理解。但是你可以得到实际的距离

    np.linalg.norm(points[mask][1:]-points[mask][:-1], axis=1)
    

    【讨论】:

    • 使用此算法,似乎两个连续点之间的距离可能不一样。我如何检查它们是否存在?
    • @Madlad 哦,有趣的是,它看起来确实不是。原因是matplotlib 没有选择相等的纵横比。我将对其进行编辑并发布具有相同纵横比的图片。
    • 哇哦!是的,我忘记了 matplotlib 的纵横比。感谢您注意到这一点!并感谢您的回答,我也在实施它:D
    • @Madlad 我在上面加了一些东西。看看吧。
    • @Madlad 我很高兴能帮上忙。
    【解决方案2】:

    IIUC 你想得到一个连接对边的线网格。

    为此,您可以保持四个边的坐标分开并使用循环连接均匀间隔的点:

    n1 = 10 # number of blue -> green linew
    n2 = 20 # number of orange -> red lines
    
    faces = [ # blue
             (np.linspace(0,1/4*(np.sqrt(3)+1), num=n1), np.linspace(0, np.sqrt(3)/4, num=n1)),
              # orange
             (np.linspace(1/4*(np.sqrt(3)+1),np.sqrt(3)/2, num=n2), np.linspace(np.sqrt(3)/4,0, num=n2)),
              # green
             (np.linspace(np.sqrt(3)/2, 1/4*(np.sqrt(3)+1), num=n1), np.linspace(0, -np.sqrt(3)/4,num=n1)),
              # red
             (np.linspace( 1/4*(np.sqrt(3)+1),0, num=n2), np.linspace(-np.sqrt(3)/4,0, num=n2)),
            ]
    
    ax = plt.subplot()
    for face in faces:
        ax.plot(face[0], face[1])
    
    for i in range(2):
        x1 = faces[i][0]
        x2 = faces[i+2][0][::-1]
        y1 = faces[i][1]
        y2 = faces[i+2][1][::-1]
        
        X = list(zip(x1, x2))
        Y = list(zip(y1, y2))
        
        for x, y in zip(X, Y):
            ax.plot(x, y, c='k', ls=':')
    

    与点相同:

    n1 = 10
    n2 = 20
    
    faces = [(np.linspace(0,1/4*(np.sqrt(3)+1), num=n1), np.linspace(0, np.sqrt(3)/4, num=n1)),
             (np.linspace(1/4*(np.sqrt(3)+1),np.sqrt(3)/2, num=n2), np.linspace(np.sqrt(3)/4,0, num=n2)),
             (np.linspace(np.sqrt(3)/2, 1/4*(np.sqrt(3)+1), num=n1), np.linspace(0, -np.sqrt(3)/4,num=n1)),
             (np.linspace( 1/4*(np.sqrt(3)+1),0, num=n2), np.linspace(-np.sqrt(3)/4,0, num=n2)),
            ]
    
    ax = plt.subplot()
    for face in faces:
        ax.plot(face[0], face[1])
    
    i = 0
        
    x1 = faces[i][0]
    x2 = faces[i+2][0][::-1]
    y1 = faces[i][1]
    y2 = faces[i+2][1][::-1]
        
    X = list(zip(x1, x2))
    Y = list(zip(y1, y2))
    
    for x, y in zip(X, Y):
        xs = np.linspace(*x, num=20)
        ys = np.linspace(*y, num=20)
        ax.plot(xs, ys, c='k', ls='', marker='.')
    

    n1 = 20n2 = 20 相同:

    【讨论】:

    • 在列表中,索引为 0 的面和索引为 2 的面是相反的,1 和 3 相同,所以我只循环两次,一次为 0/2,一次为 1/3
    • linspace 为您解决问题
    • 注意。我在这里为两个维度使用了两个不同的间距,但当然你可以对两个维度使用相同的间距
    • 谢谢 Mozway 我刚刚检查了一个很好的旧距离公式检查,这些点实际上是等距的。只是想确定一下!非常感谢您的帮助。
    • 好的,感谢您的澄清,那么@user2640045 的答案不符合您的需求吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-25
    • 1970-01-01
    • 2016-04-29
    • 2018-01-09
    • 2019-05-16
    • 1970-01-01
    相关资源
    最近更新 更多