将指定距离的随机点绘制成

时间:2017-07-17 13:46:13

标签: numpy matplotlib

我试图想出一个在单位圆圈内绘制n个点的函数,但是我需要将它们充分展开。

即。看起来像这样的东西:

enter image description here

是否可以使用两个参数n(点数)和min_d(相距最小距离)编写一个函数,使得这些点为:

a)等距

b)没有成对距离超过给定的min_d

从均匀分布中采样的问题在于,可能发生两点几乎在彼此之上,我不想发生这种情况。我需要这种输入来表示节点集群的网络图。

编辑:我在这里找到了答案:Generator of evenly spaced points in a circle in python,但b)仍然没有找到我。

1 个答案:

答案 0 :(得分:3)

在提供此答案时,问题是随机数字。因此,该答案给出了绘制随机数的解决方案。它忽略了之后对该问题所做的任何编辑。

开可以简单地绘制随机点,并且每个点检查是否满足最小距离的条件。如果不是,则可以丢弃该点。这可以在列表填充足够的点或满足某些中断条件之前完成。

import numpy as np
import matplotlib.pyplot as plt

class Points():
    def __init__(self,n=10, r=1, center=(0,0), mindist=0.2, maxtrials=1000 ) :
        self.success = False
        self.n = n
        self.r = r
        self.center=np.array(center)
        self.d = mindist
        self.points = np.ones((self.n,2))*10*r+self.center
        self.c = 0
        self.trials = 0
        self.maxtrials = maxtrials
        self.tx = "rad: {}, center: {}, min. dist: {} ".format(self.r, center, self.d)
        self.fill()

    def dist(self, p, x):
        if len(p.shape) >1:
            return np.sqrt(np.sum((p-x)**2, axis=1))
        else:
            return np.sqrt(np.sum((p-x)**2))

    def newpoint(self):
        x = (np.random.rand(2)-0.5)*2
        x = x*self.r-self.center
        if self.dist(self.center, x) < self.r:
            self.trials += 1
            if np.all(self.dist(self.points, x) > self.d):
                self.points[self.c,:] = x
                self.c += 1

    def fill(self):
        while self.trials < self.maxtrials and self.c < self.n:
            self.newpoint()
        self.points = self.points[self.dist(self.points,self.center) < self.r,:]
        if len(self.points) == self.n:
            self.success = True
        self.tx +="\n{} of {} found ({} trials)".format(len(self.points),self.n,self.trials)

    def __repr__(self):
        return self.tx


center =(0,0)
radius = 1 

p  = Points(n=40,r=radius, center=center)

fig, ax = plt.subplots()
x,y = p.points[:,0], p.points[:,1]

plt.scatter(x,y)
ax.add_patch(plt.Circle(center, radius, fill=False))

ax.set_title(p)
ax.relim()
ax.autoscale_view()
ax.set_aspect("equal")
plt.show()

enter image description here

如果要修复点数,您可以尝试运行找到这个点数来减少距离,直到找到所需的点数。

在下面的例子中,我们正在寻找60个点并以最小距离0.6开始,我们逐步减少0.05,直到找到解决方案。请注意,这不一定是最佳解决方案,因为每个步骤中只有maxtrials次重试。增加maxtrials当然会使我们更接近最优,但需要更多的运行时间。

center =(0,0)
radius = 1 
mindist = 0.6
step = 0.05
success = False
while not success:
    mindist -= step
    p = Points(n=60,r=radius, center=center, mindist=mindist)
    print p
    if p.success:
        break

fig, ax = plt.subplots()
x,y = p.points[:,0], p.points[:,1]

plt.scatter(x,y)
ax.add_patch(plt.Circle(center, radius, fill=False))

ax.set_title(p)
ax.relim()
ax.autoscale_view()
ax.set_aspect("equal")
plt.show()

此处找到的解决方案最小距离为0.15。

enter image description here