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

问题描述 投票:0回答:1

好的,所以说有一个网格,我已经存储为二维数组,即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)的每个点距离,但是这是我想要避免的,因为每次检查不在圆圈中的位时,由于每次检查不在圆圈中的位,我知道它们不是事先在圆圈中。

java arrays geometry
1个回答
1
投票

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

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填充到计算点而不是普通循环,但这超出了范围。

© www.soinside.com 2019 - 2024. All rights reserved.