繁体   English   中英

在边界内的表面上分布点

[英]Distributing points over a surface within boundries

我对将预定义数量的点分布在4个侧面(如正方形)上的方式(算法)感兴趣。

主要问题是每个点必须彼此之间具有最小和最大距离(两个预定义值之间的随机性)。 基本上,任何两个点的距离都不应比我们说的2更近,而不能比3更远。

我的代码将以红宝石实现(点是位置,表面是地图),但是任何想法或摘要都绝对受欢迎,因为我的所有想法都包含相当多的蛮力。

试试这篇论文 它有一个不错的,直观的算法,可以满足您的需求。

在我们的建模中,我们采用了另一种模型:我们认为每个中心都通过排斥字符串与其所有邻居相关。

在模拟开始时,中心以及弦的强度是随机分布的。 我们随机选择移动一个中心。 然后我们计算由给定中心的所有邻居引起的合力,并计算在合力意义上成比例和定向的位移。

经过一定数量的迭代(取决于中心的数量和初始随机性的程度)后,系统变得稳定。

如果从图中不清楚,则此方法会生成均匀分布的点。 您可以改为使用在边界内为零(例如,介于2和3之间)的力,否则为非零(如果点太近则排斥,如果点太远则有吸引力)。

这是我的Python实现(对不起,我不知道ruby)。 只需导入它,然后调用uniform()即可获取点列表。

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

我认为您的蛮力想法之一就是随机地反复生成点,并检查约束是否满足。

另一种方法是采用一种满足约束条件的配置,并反复干扰其中的一小部分,这是随机选择的,例如移动单个点,以移动到随机选择的附近配置。 如果您经常进行此操作,则应转到几乎与起点无关的随机配置。 可以在http://en.wikipedia.org/wiki/Metropolis%E2%80%93Hastings_algorithmhttp://en.wikipedia.org/wiki/Gibbs_sampling下进行辩护。

我可能会尝试随机执行,然后删除掉与其他点接近的点。 您可以比较距离的平方,以节省一些数学时间。

或创建带有边框的单元格并在每个单元格中放置一个点。 随机性较小,这取决于这是否是“仅用于外观的事物”。 但这可能很快。

我做出了让步,最终使用了Poisson Disk Sampling方法。

结果非常接近我的需求,尤其是尝试次数较少(这也大大降低了成本)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM