Алгоритм поиска окружности с максимальным числом точек (алгоритм углового заметания)

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

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

Вот мои наработки - https://github.com/sltrs1/angular_sweep

Я реализовал наивный алгоритм, который дал мне верный ответ.

Далее я попытался реализовать алгоритм углового заметания (angular sweep), описанный вот здесь https://www.geeksforgeeks.org/angular-sweep-maximum-points-can-enclosed-circle-given-radius/ с некоторыми модификациями.

Модификации следующие: исходный алгоритм исполняется только для заданного набора точек, то есть, ищет подходящий круг с центром в одной из точек заданного множества. Я сделал так, что он исполняется для каждой из всех возможных точек плоскости. То есть, центр круга не обязательно должен быть одной из точек набора.

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

Наивный алгоритм

    for(i = 0; i < MAX_POINTS_X; i++) {
        for (j = 0; j < MAX_POINTS_Y; j++) {
            z1 = (double)i + ((double)j)*I;
            for (k = 0; k < num_points; k++) {
                dist = cabs(z1 - points[k]);
                if (dist <= radius) {
                    naive_solution[i][j]++;
                    if ( naive_solution[i][j] > naive_solution_max ) {
                        naive_solution_max = naive_solution[i][j];
                        max_i = i;
                        max_j = j;
                    }
                }
            }
        }
    }

При данных из репозитория и радиусе 10 дает результат 86 точек и круг с центром (44,47).

Угловой алгоритм

    for (i = 0; i < num_points; i++) {
        z1 = (x+y*I);
        if ( cabs(z1 - points[i]) > 0.001 &&
             dis[x][y][i] < 2*radius ) {
            b = acos( dis[x][y][i]/(2*radius) );
            a = carg( z1 - points[i] );
            alpha = a-b;
            beta = a+b;
            angles[angles_count].first = alpha;
            angles[angles_count].second = 1;
            angles_count++;
            angles[angles_count].first = beta;
            angles[angles_count].second = 0;
            angles_count++;
        }
    }

    for ( i = 0; j < angles_count - 1; i++ ) {
        for (j = (int)angles_count - 1; j > i; j--) {
            if ( !comparePairs(angles[j-1], angles[j]) ) {
                swapPairs( &angles[j-1], &angles[j] );
            }
        }
    }

    count = 1;
    res = 1;
    for (j = 0; j < angles_count; j++) {

        if (angles[j].second)
            count++;
        else
            count--;

        if (count > res)
            res = count;
    }

Дает при тех же данных 88 и (42,56).

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

Буду очень признателен, если кто-то поможет разобраться.


Ответы (0 шт):