Algorithm 如何创建随机的非重叠坐标?

Algorithm 如何创建随机的非重叠坐标?,algorithm,rust,geometry,coordinates,Algorithm,Rust,Geometry,Coordinates,我正在尝试创建一个函数,该函数将生成长度为n的vec,在一些边界(.b,b)之间具有类型为f64的随机x和y坐标。具有该坐标的每个点之间必须有最小距离d。我试图使用thread\u rng()函数,但我被卡住了。我应该使用特定的分布或添加一些过滤器或条件来实现这一点吗 extern crate rand; // 0.5.5 use rand::prelude::*; use rand::distributions::Standard; pub fn apply_random_pos(n: u

我正在尝试创建一个函数,该函数将生成长度为
n
vec
,在一些边界
(.b,b)
之间具有类型为
f64
的随机
x
y
坐标。具有该坐标的每个点之间必须有最小距离
d
。我试图使用
thread\u rng()
函数,但我被卡住了。我应该使用特定的分布或添加一些过滤器或条件来实现这一点吗

extern crate rand; // 0.5.5

use rand::prelude::*;
use rand::distributions::Standard;

pub fn apply_random_pos(n: usize, min_distance: f64) -> Vec<(f64, f64)> {
    let mut rng = thread_rng();
    let mut x: f64;
    let mut y: f64;

    let mut positions: Vec<(f64, f64)> = Vec::with_capacity(n);

    positions = thread_rng()
        .sample_iter(&Standard)
        .take(n)
        .collect::<Vec<(f64, f64)>>();

    positions
}
extern板条箱兰德;//0.5.5
使用兰德::前奏::*;
使用rand::distributions::Standard;
发布fn应用随机位置(n:usize,最小距离:f64)->Vec{
设mut rng=thread_rng();
设mut x:f64;
让mut y:f64;
让mut位置:Vec=Vec::具有_容量(n);
位置=螺纹
.样品(标准)
.take(n)
收集::();
位置
}

您可以使用简单算法:当生成的点不正常时,尝试使用另一个算法:

extern crate rand;
use rand::prelude::*;

pub fn apply_random_pos(n: usize, min_distance: f64, boundary: f64) -> Vec<(f64, f64)> {
    fn distance(p1: (f64, f64), p2: (f64, f64)) -> f64 {
        ((p1.0 - p2.0).powf(2.) + (p1.1 - p2.1).powf(2.)).sqrt()
    }

    let mut rng = thread_rng();
    let mut positions = Vec::with_capacity(n);

    while positions.len() < n {
        let p1 = (
            rng.gen_range(boundary, -boundary),
            rng.gen_range(boundary, -boundary),
        );
        if positions.iter().all(|&p2| distance(p1, p2) > min_distance) {
            positions.push(p1);
        }
    }
    positions
}
extern板条箱兰德;
使用兰德::前奏::*;
发布fn应用随机位置(n:usize,最小距离:f64,边界:f64)->Vec{
fn距离(p1:(f64,f64),p2:(f64,f64))->f64{
((p1.0-p2.0).powf(2.)+(p1.1-p2.1).powf(2.).sqrt()
}
设mut rng=thread_rng();
设mut positions=Vec::具有_容量(n);
while positions.len()最小距离){
位置。推动(p1);
}
}
位置
}

请注意,此算法根本不适用于大量点。这甚至是最糟糕的算法。

我使用了一些附加的算法,它似乎可以按照我的要求工作。唯一的小问题是,我没有想到一种方法来输出一个更具体的范围,其中也包含负片

pub fn apply_random_pos(n: usize, min_distance: f64) -> Vec<(f64, f64)> {
    fn distance(p1: (f64, f64), p2: (f64, f64)) -> f64 {
        ((p1.0 - p2.0).powf(2.) + (p1.1 - p2.1).powf(2.)).sqrt()
    }
    let mut rng = thread_rng();
    let mut positions = Vec::with_capacity(n);

    while positions.len() < n {
        let mut p1 = rng.gen::<(f64, f64)>();
        let mut p2 = rng.gen::<(f64, f64)>();
        // Multiply with 10 because we need numbers bigger than 1
        p1 = (p1.0 * 10.0, p1.1 * 10.0);
        p2 = (p2.0 * 10.0, p2.1 * 10.0);

        if positions.iter().all(|&p2| distance(p1, p2) > min_distance) {
            positions.push(p1);
            positions.push(p2);
        }
    }
    positions
}
pub fn应用随机位置(n:usize,最小距离:f64)->Vec{
fn距离(p1:(f64,f64),p2:(f64,f64))->f64{
((p1.0-p2.0).powf(2.)+(p1.1-p2.1).powf(2.).sqrt()
}
设mut rng=thread_rng();
设mut positions=Vec::具有_容量(n);
while positions.len()最小距离){
位置。推动(p1);
位置。推(p2);
}
}
位置
}

大量点的算法草图(但分布与网格相关):

在您的区域上构建方形网格。选择单元格
Size=3*mindsist
。所以你有
(宽*高)/(9*明德主义者^2)
点站点

添加新点时,选择“随机自由场地”并将点放置在网格结中,然后在范围
-Mindist..Mindist
中的两个方向上随机更改其位置。单元大小3保证没有点靠得太近

生成示例:左图占据了一半的站点,右图占据了所有站点


为了获得更好的“随机外观”,你可以缩小单元格大小——例如,
2*MinDist
,但在这种情况下,你必须检查相邻的站点——但只有四个而不是所有站点。

嗯,这看起来更像是一个问题,而不是一个问题。你的代码样本中有一堆未使用的东西,你所有的类型标注都是无用的。在惯用的Rust中,您应该仅在需要时添加它们。事实上,您的整个函数可以用一行代码来编写:
thread\u rng().sample\u iter(&Standard).take(n).collect()
。您确定不需要
x,y
的某种域吗?'随机
f64
”是一个巨大的域。@orlp我想我可以将
x
y
绑定在两个值之间,比如说
-10.0,10.0
。试着检查所有方法都是二次的,并且在一百万点上变得不可靠。也许你必须考虑KD树在未来它是一个很好的近似,但我必须修改它,因为它以无穷大结束。loop@Moreorem
gen
将生成一个介于0和1之间的数字。您的距离应在此范围内。您可能必须在函数中添加检查,以查看请求是否可行(例如,最小距离为0.9的10个点是不可能的)。True。检查确实是必要的。我在@orlp的建议后决定绑定这些值。没有必要使用负值,因为之后我会将它们转移到画布上,但这会有所帮助。然而,我找不到一个
rng
函数,在这里我可以指定输出的类型(
(f64,f64)
)和范围(
-b,b
),这是一个非常有趣的方法!我会尽快实施