【问题标题】:Create a list of N random (x,y,z) points that are at least a distance r away from each other创建一个包含 N 个随机 (x,y,z) 点的列表,这些点彼此之间的距离至少为 r
【发布时间】:2019-07-10 19:45:38
【问题描述】:

我正在尝试使用 python 创建一个包含 N 个随机 (x,y,z) 点的列表,每个点与任何其他点的距离至少为 r。

我是编程的超级新手,到目前为止,我只能通过使用分别生成 x、y 和 z(然后放在一起)

import random 
def RandX(start, end, num): 
    res = [] 

    for j in range(num): 
        res.append(random.randint(start, end)) 

    return res 
num = N
start = 0
end = 100
print(RandX(start, end, num)) 

但我不知道如何控制或检查点 (x, y, z) 的位置,以使这些点彼此相距一定距离。

【问题讨论】:

标签: python


【解决方案1】:

要检查 (x,y,z) 和 (a,b,c) 两点之间的距离(存储为元组),您可以尝试:

def distance(p1,p2):
    d=0
    for i in range(3):
        d+=(p1[i]-p2[i])**2
    return d**(1/2)

一旦你随机生成xyz,你可以设置如下:

p1=x,y,z
p2=a,b,c

如果你的数字不是太大,虽然这样效率低,你可以生成随机数,直到它们满足距离条件。

【讨论】:

    【解决方案2】:

    这是我的解决方案:我们只需要一个距离函数和一个循环来生成随机点并检查我们已经生成的列表中的最小距离标准:

    def dist(new_point, points, r_threshold):
        for point in points:
            dist = np.sqrt(np.sum(np.square(new_point-point)))
            if dist < r_threshold:
                return False
        return True
    
    
    def RandX(N, r_threshold):
        points = []
        scope = np.arange(0,10,0.1)
        while len(points) < N:
            new_point = np.random.choice(scope, 3)
            if dist(new_point, points, r_threshold):
                points.append(new_point)
        return points
    

    例如:

    RandX(5, 4)
    [array([3.5, 2.6, 7.6]),
     array([9.9, 0.1, 7.2]),
     array([4. , 2.8, 0.3]),
     array([0.2, 7.4, 5.1]),
     array([7.4, 6.3, 5.2])]
    

    【讨论】:

      【解决方案3】:

      类似的东西。 (它可以被优化,但应该作为第一个版本为您服务)

      from collections import namedtuple
      import random
      import math
      
      Point = namedtuple('Point', ' x y z')
      
      MIN = 0
      MAX = 1000
      
      
      def fill_points_list(points, number_of_required_points, min_distance):
          def _get_distance(p1, p2):
              return math.sqrt(sum([(a - b) ** 2 for a, b in zip(p1, p2)]))
      
          while len(points) < number_of_required_points:
              temp = Point(random.randint(MIN, MAX), random.randint(MIN, MAX), random.randint(MIN, MAX))
              count = 0
              for p in points:
                  if _get_distance(temp, p) > min_distance:
                      count += 1
                  else:
                      break
              if len(points) == count:
                  points.append(temp)
      
      
      number_of_required_points = 9
      min_distance = 51
      points = []
      
      fill_points_list(points, number_of_required_points, min_distance)
      
      print(points)
      

      输出

      [Point(x=771, y=590, z=226), Point(x=385, y=835, z=900), Point(x=551, y=294, z=800), Point(x=824, y=306, z=333), Point(x=892, y=548, z=879), Point(x=520, y=660, z=384), Point(x=409, y=193, z=331), Point(x=411, y=706, z=300), Point(x=272, y=116, z=719)]

      【讨论】:

        【解决方案4】:

        您可以尝试随机生成一些点,然后根据距离标准过滤它们。 numpysklearn 软件包有助于提高流程效率。你可以想象这样的事情:

        import numpy as np
        from sklearn.metrics.pairwise import euclidean_distances
        
        r = 2
        
        # Generate 100 points (3-tuples) between 0 and 10
        points = np.random.randint(0,100,[1000,3])
        
        # Pairwise distances between points
        distances = euclidean_distances(points)
        
        # "Remove" distance to itself by setting to a distance of r+1 (to discard it later)
        distances += np.identity(len(distances)) * (r+1)
        
        # Retrieve the distance to the closest point
        min_dist = np.min(distances,axis=1)
        
        # Filter your set of points
        filtered_points = points[min_dist>r]
        

        这应该运行得很快。

        【讨论】:

          猜你喜欢
          • 2022-11-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-06-04
          • 2019-03-29
          • 2015-12-24
          相关资源
          最近更新 更多