如何创建菱形区域的等间距网格

How to create an equally spaced grid of a diamond shaped area

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

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]

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相同:

我的方法是用一个环状物覆盖您的钻石,然后去除它外面的点。

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

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 掩蔽方法在您的钻石内部进行过滤。这意味着我首先创建一个 true/false 数组,其中我想保留的点为真,否则为假,然后将其应用于这些点。

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]])

它从左下角开始向右(x方向)0.04,然后向上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)