首页 > 解决方案 > 在具有一定距离的外圆内生成随机点

问题描述

我目前真的被我的一些代码困住了,我似乎找不到问题。这是我想要做的:我有一个大的外圈,我想在其中显示较小的点。这些点应随机分布但不应重叠,因此它们之间应具有最小距离。

我尝试的是首先随机生成一个点,检查它是否在外圈中,如果是,则将其附加到点位置的最终列表中。然后创建另一个点,检查是否在圆圈中,然后应该检查该点是否与最终列表中的其他点有最小距离。

但是,我的代码似乎存在一些问题,因为每当我将所需的距离设置为高于 1 时,它都不会运行。我已经更改了多项内容,但无法使其正常工作。

有谁知道问题可能是什么?

这是我一直在尝试的:

import random
import numpy as np
import math

#Variables
radiusOC = 57
size_obj = 7
required_dist = 5
no_stimuli = 3


def CreatePos(radiusOC, size_obj, required_dist, no_stimuli):
    final_list = []
    def GenRandPos(radiusOC,size_obj):
        """
        Takes the radius of the outer circle and generates random dots within this radius. Then checks if the the dots are located 
        within the outer circle.
        """
        while True:
            xPos = random.randint(-radiusOC,radiusOC)
            yPos = random.randint(-radiusOC,radiusOC)
        
            # check if in Circle 
            on_circle = (xPos- 0)**2 + (yPos-0)**2
            if (radiusOC-size_obj)**2 >= on_circle:
                print("Still in circle",on_circle, xPos, yPos )
                position = [xPos, yPos]
                break
            else:
                print("Not in circle",on_circle, xPos, yPos )
                continue
                
        return position


    def CheckSurrounding(position, final_list, required_dist): 
        """
        Takes dot positions that are in the visual field, the list of positions, and the distances dots are required to have from each other. 
        It is checked if there are dots close by or not.  
        """
        X1 = position[0]
        Y1 = position[1]
        dist_list = []
        for elem in final_list:
            for i in elem: 
                X2 = elem[0]
                Y2 = elem[1]
                dist = math.sqrt((X1-X2)**2 + (Y1-Y2)**2)
                dist_list.append(dist)
                
        if all(dist_list) >= required_dist: 
            return position
            
        else:
            return None

    # append the first dot to the list
    position = GenRandPos(radiusOC, size_obj)
    final_list.append(position)

    # now append the rest of the dots if they have a certain distance to each other
    while len(final_list) < no_stimuli: 
        position = GenRandPos(radiusOC, size_obj)

        if CheckSurrounding(position, final_list, required_dist)  != None: 
            position = CheckSurrounding(position, final_list, required_dist)
            final_list.append(position)

        else: 
            continue
    
    return final_list


´´´

标签: pythonmathrandom

解决方案


在行

if all(dist_list) >= required_dist:

all(dist_list)将是TrueFalse,在数值上等于 1 或 0。如果required_dist大于 1,则永远不会满足不等式。我认为你打算这样做

if all(dist_list >= required_dist):

但这不起作用,因为您无法将列表dist_list与数字进行比较required_dist。要修复它,请转换dist_list为 numpy 数组:

if np.all(np.array(dist_list) >= required_dist):

顺便说一句,您选择的随机点将始终具有整数坐标,因为您正在使用random.randint(),我不确定这是否是故意的。

使用 numpy 数组可以提高整个代码的效率。例如:

import numpy as np

def CreatePos(radiusOC, size_obj, required_dist, no_stimuli):
    final_list = []

    def GenRandPos(radiusOC, size_obj):
        """
        Takes the radius of the outer circle and generates 
        random dots within this radius. Then checks if the dots are 
        located within the outer circle.
        """

        while True:
            position = (2 * np.random.random(2) - 1) * radiusOC
            # check if in Circle
            if (radiusOC - size_obj)**2 >= (position**2).sum():
                return position

    def CheckSurrounding(position, final_list, required_dist):
        """
        Takes dot positions that are in the visual field, 
        the list of positions, and the distances dots are 
        required to have from each other. 
        It is checked if there are dots close by or not.  
        """

        final_arr = np.array(final_list)
        dist = ((np.array(final_list) - position)**2).sum(axis=1)
        if np.all(np.array(dist) >= required_dist**2):
            return position

    # append the first dot to the list
    position = GenRandPos(radiusOC, size_obj)
    final_list.append(position)

    # now append the rest of the dots if they have a certain distance to each other
    while len(final_list) < no_stimuli:
        position = GenRandPos(radiusOC, size_obj)
        if CheckSurrounding(position, final_list, required_dist) is not None:
            final_list.append(position)

    return final_list

请注意,这将返回一个点列表,其坐标由浮点数给出,而不是整数。

示例用法:

#Variables
radiusOC = 57
size_obj = 7
required_dist = 3
no_stimuli = 400

final_list  = np.array(CreatePos(radiusOC, size_obj, required_dist, no_stimuli))

绘制结果点:

import matplotlib.pyplot as plt
fig = plt.figure(figsize=(7,7))
ax = fig.add_subplot(111)
ax.set_aspect("equal")
plt.scatter(f[:, 0], f[:, 1])
plt.show()

这给出了:

圆圈中的点

我会在最后一个while循环中添加一个条件,这样如果在经过一定次数的尝试后找不到新点,它就会中断。否则,它可能会无限期地运行。


推荐阅读