如何检查圆圈中的哪些点?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何检查圆圈中的哪些点?相关的知识,希望对你有一定的参考价值。

好的,所以说有一个网格,我已经存储为二维数组,即10×10。

int[][] grid = new int[10][10];

网格的原点位于左下方,就像普通的x y平面一样,网格中心有一个半径为5的圆(5,5),如下所示:

Terrible drawing

我想通过这个数组,基本上检查圆圈内的哪些点,但我不想遍历整个数组。默认情况下,角落上的每个点都不会出现在圆圈中,因此我希望忽略这些点,并且类似于靠近角落的点等。

只是圆圈中的点。我有一个更大的网格和循环不必要的东西,我已经知道不在圈内会浪费时间。有没有办法做到这一点?因为,鉴于我已经知道圆的半径和中心,应该有一个很好的简单方法来遍历圆中的那些点,并将它们从0更改为-1,例如。

否则,我会失去100 - 25π≈21.46%的时间。

更好的清晰度:我已经知道我可以用正方形限制圆圈,然后循环通过该正方形中的点并检查距离圆心(x ^ 2 + y ^ 2 <r ^ 2)的每个点距离,但是这是我想要避免的,因为每次检查不在圆圈中的位时,由于每次检查不在圆圈中的位,我知道它们不是事先在圆圈中。

答案

好的,经过长时间的讨论,这是解决方案。您扫描四分之一切片的一个轴,计算需要向外填充该四分之一的扩展,然后一次填充所有四个季度。

int n = 1000;

// you will need to think yourself about the odd number or elements
int r = n / 2;
int r2 = r * r;

在两种情况下将(0,0)放在矩阵的中心,优化的解决方案可能如下所示:

int[][] grid0 = new int[n][n];
for (int i = 0; i < r; i++) {
    double m = Math.sqrt(r2 - i * i);
    for (int j = 0; j < m; j++) {
        grid0[r + i][r + j] = 1;
        grid0[r + i][r - j] = 1;
        grid0[r - i][r + j] = 1;
        grid0[r - i][r - j] = 1;
    }
}

如其他地方所述,填充圆的扩展在O(n)中计算。

这是直截了当的验证:

int[][] grid1 = new int[n][n];
// you will need to think yourself about the even number
for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
        if ((i - r) * (i - r) + (j - r) * (j - r) < r2) {
            grid1[i][j] = 1;
        }
    }
}

两者都产生相同数量的填充点。

超过10000次执行的时间测量(在时间循环之外的阵列初始化):

优化的6.0s

详尽的15.6s

所以,我承认存在差异,这是一个令人惊讶的差异。虽然为了公平比较,后一个片段也应该使用圆的四分之一片。

可以使用某种内存复制例程来进一步加速优化的解决方案,将值从0填充到计算点而不是普通循环,但这超出了范围。

以上是关于如何检查圆圈中的哪些点?的主要内容,如果未能解决你的问题,请参考以下文章

检查纬度和经度是不是在一个圆圈内

如何有效地为列表列表中的多个补丁设置动画

我如何知道一个 Lat,Lng 点是不是包含在一个圆圈内?

在任何时间点获取 CABasicAnimation 中扩展圆圈的大小

地理位置 - 如何检查 2 个圆圈是不是重叠

如何优化C ++代码的以下片段 - 卷中的零交叉