Попробуйте этот документ .Он имеет хороший, интуитивно понятный алгоритм, который делает то, что вам нужно.
В нашей модели мы приняли другую модель: мы считаем, что каждый центр связан со всеми своими соседями отталкивающей строкой.
В начале моделирования центры распределяются случайным образом, а также сильные стороны струн.Мы выбираем случайным образом переместить один центр;затем мы вычисляем результирующую силу, вызванную всеми соседями данного центра, и вычисляем смещение, которое пропорционально и ориентировано в смысле результирующей силы.
После определенного числа итераций (которое зависит отчисло центров и степень начальной случайности) система становится стабильной.
Если из рисунков не ясно, этот подход генерирует равномерно распределенные точки.Вместо этого вы можете использовать силу, которая равна нулю внутри ваших границ (например, между 2 и 3) и ненулевой в противном случае (отталкивающая, если точки слишком близки, привлекательная, если слишком далеко).
Реализация на Python (извините, я не знаю ruby).Просто импортируйте это и вызовитеiform (), чтобы получить список точек.
import numpy as np
from numpy.linalg import norm
import pylab as pl
# find the nearest neighbors (brute force)
def neighbors(x, X, n=10):
dX = X - x
d = dX[:,0]**2 + dX[:,1]**2
idx = np.argsort(d)
return X[idx[1:11]]
# repulsion force, normalized to 1 when d == rmin
def repulsion(neib, x, d, rmin):
if d == 0:
return np.array([1,-1])
return 2*(x - neib)*rmin/(d*(d + rmin))
def attraction(neib, x, d, rmax):
return rmax*(neib - x)/(d**2)
def uniform(n=25, rmin=0.1, rmax=0.15):
# Generate randomly distributed points
X = np.random.random_sample( (n, 2) )
# Constants
# step is how much each point is allowed to move
# set to a lower value when you have more points
step = 1./50.
# maxk is the maximum number of iterations
# if step is too low, then maxk will need to increase
maxk = 100
k = 0
# Force applied to the points
F = np.zeros(X.shape)
# Repeat for maxk iterations or until all forces are zero
maxf = 1.
while maxf > 0 and k < maxk:
maxf = 0
for i in xrange(n):
# Force calculation for the i-th point
x = X[i]
f = np.zeros(x.shape)
# Interact with at most 10 neighbors
Neib = neighbors(x, X, 10)
# dmin is the distance to the nearest neighbor
dmin = norm(Neib[0] - x)
for neib in Neib:
d = norm(neib - x)
if d < rmin:
# feel repulsion from points that are too near
f += repulsion(neib, x, d, rmin)
elif dmin > rmax:
# feel attraction if there are no neighbors closer than rmax
f += attraction(neib, x, d, rmax)
# save all forces and the maximum force to normalize later
F[i] = f
if norm(f) <> 0:
maxf = max(maxf, norm(f))
# update all positions using the forces
if maxf > 0:
X += (F/maxf)*step
k += 1
if k == maxk:
print "warning: iteration limit reached"
return X