Найти все целочисленные координаты в заданном радиусе

даны в двухмерной системе координат, как я могу найти все точки с целочисленными координатами в радиусе от заданной точки? Я хочу, чтобы точки были координатами 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 добавляется или нет. Другими словами, мне не нужна точность с плавающей запятой.

4 ответов


самое простое решение: возьмите квадрат и отфильтруйте его:

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));
}

один из способов-внешний цикл на x от-R до +R и внутренний цикл на y в соответствии со значениями y круга при этом значении x (от-sqrt(r^2 - x^2) до sqrt (r^2 - x^2), Если центр находится в 0,0), если центр находится в X, Y - просто добавьте X или Y ко всем диапазонам цикла так же, как вы сделали в своем примере


вы можете внести небольшие изменения в алгоритм окружности средней точки, чтобы получить заполненный круг.

сначала сгенерируйте координаты:

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);
    }
}

это экономит некоторые рабочие точки посещения, которые не будут в круге, но за счет небольшой предварительной обработки. Это определенно не поможет для меньших кругов, а для больших, ну, я честно не знаю. Вы должны проверить это.


следующий код просто анализирует границу вдоль четверти круга, чтобы определить внутреннюю область. Ему не нужно вычислять расстояние ни для внешних точек, ни для внутренних точек. (редактировать: но, наконец, все точки заполненного круга добавляются)

в некоторых мини-Java-бенчмарках для малого радиуса ( 50. Для некоторого гораздо большего радиуса (>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));
    }
}