【问题标题】:Find all integer coordinates in a given radius查找给定半径内的所有整数坐标
【发布时间】:2013-01-11 19:32:27
【问题描述】:

给定一个二维坐标系,如何从给定点的半径内找到所有具有整数坐标的点?我想要这些点作为 x 坐标和 y 坐标值。

在给定点周围的正方形中查找点很容易,可以这样完成:

for(int x = -radius + point.x; x < radius + point.x; ++x)
for(int y = -radius + point.y; y < radius + point.y; ++y)
{
    points.insert(point(x, y));
}

但是我怎样才能找到围绕给定点的圆圈中的点?该算法与性能有关,但与准确性无关。因此,如果一个点接近于半径而不是添加 1 并不重要。换句话说,我不需要浮点精度。

【问题讨论】:

  • 感谢您指出这一点。英语不是我的第一语言。我更新了问题文本和标题。

标签: performance algorithm geometry coordinates


【解决方案1】:

最简单的解决方案:取一个正方形并过滤它:

Point point(100, 100);
for(int x = -radius; x <= radius; ++x)
for(int y = -radius; y <= radius; ++y)
if(x*x + y*y <= radius* radius)   {
    points.insert(Point(x + point.x, y + point.y));
}

【讨论】:

  • 此外,此方法在 4 个外部点中的每一个处创建一个辐条:i.imgur.com/wirxfJP.jpg
  • @PsychoDad:与问题中的含义相同。此外,这些尖峰是正确的行为。
  • 请注意,如果point.xpoint.y 不是整数,则代码需要进行一些调整。
【解决方案2】:

一种方法是在 x 上从 -R 到 +R 的外循环和在 y 上的内循环,根据该 x 值处的圆的 y 值(从 -sqrt(r^2 - x^2) 到 sqrt (r^2 - x^2) 如果中心在 0,0),如果中心在 X,Y - 只需按照与示例中相同的方式将 X 或 Y 添加到所有循环范围

【讨论】:

    【解决方案3】:

    您可以对中点圆算法进行小修改以获得实心圆。

    首先生成坐标:

    data = new int[radius];
    int f = 1 - radius, ddF_x = 1;
    int ddF_y = -2 * radius;
    int x = 0, y = radius;
    while (x < y)
    {
        if (f >= 0)
        {
            y--;
            ddF_y += 2; f += ddF_y;
        }
        x++;
        ddF_x += 2; f += ddF_x;
        data[radius - y] = x; data[radius - x] = y;
    }
    

    然后访问所有内部点:

    int x0 = center.X;
    int y0 = center.Y - Radius;
    int y1 = center.Y + Radius - 1;
    
    for (int y = 0; y < data.Length; y++)
    {
        for (int x = -data[y]; x < data[y]; x++)
        {
            doSomething(x + x0, y + y0);
            doSomething(x + x0, y1 - y);
        }
    }
    

    这节省了一些不会在圈内的工作访问点,但会牺牲一点预处理。对于较小的圈子,它肯定无济于事,而对于较大的圈子,老实说,我不知道。您必须对其进行基准测试。

    【讨论】:

      【解决方案4】:

      下面的代码只是沿着四分之一圆解析边界以确定内部区域。它不需要计算外点的距离,也不需要计算内点的距离。 (编辑:但最后,实心圆的所有点都被添加)

      在一些 mini-Java-benchmarks 中,对于小半径( 50,它实现了大约 4 倍的加速。对于一些更大的半径(> 200),加速再次降低,因为对于任何方法,都需要支配时间用于创建和添加 >100k 点 - 无论它们是如何确定的。

      // add the full length vertical center line once
      for (int y = -radius + point.y; y <= radius + point.y; ++y)
          points.insert(Point(point.x, y));
      
      int sqRadius = radius * radius;
      
      // add the shorter vertical lines to the left and to the right
      int h = radius;
      for (int dx = 1; dx <= radius; ++dx) {
          // decrease h
          while (dx*dx + h*h > sqRadius && h > 0)
              h--;
      
          for (int y = -h + point.y; y <= h + point.y; ++y) {
              points.insert(Point(point.x + dx, y));
              points.insert(Point(point.x - dx, y));
          }
      }
      

      【讨论】:

      • 填充 - 但它不能确定到内部点的距离,类似于 harold 的中点算法。
      • 那我一定会试试的。
      • 先加上全长垂直中心线有什么原因吗?为什么不把它合并到后面的循环中呢?
      猜你喜欢
      • 2012-05-04
      • 1970-01-01
      • 2013-09-01
      • 2019-12-18
      • 2013-09-12
      • 2015-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多