Итак, я поиграл в Python (просто потому, что мне проще всего прототипировать решение) и придумал следующее:
from collections import namedtuple
from math import sqrt
from statistics import mean
Point = namedtuple('Point', ['x', 'y'])
def length_between_points(a: Point, b: Point):
squared = (pow(a.x - b.x, 2) + pow(a.y - b.y, 2))
return sqrt(squared)
def normalize(raw):
return [float(i)/max(raw) for i in raw]
def is_roughly_circle(x, y, confidence=0.1):
center = Point(x=mean(x), y=mean(y))
points = [Point(x[i], y[i]) for i in range(len(x))]
lengths_from_center = [length_between_points(p, center) for p in points]
normalized = normalize(lengths_from_center)
is_circle = all([length > 1 - confidence for length in normalized])
return is_circle
x = [1, 2, 3, 4, 5]
y = [1, 2, 3, 4, 5]
print(is_roughly_circle(x, y)) # False
x = [0, 1, 0, -1]
y = [1, 0, -1, 0]
print(is_roughly_circle(x, y)) # True
x = [0, 1.1, 0, -1]
y = [1, 0, -1, 0]
print(is_roughly_circle(x, y)) # True
x = [0, 1.2, 0, -1]
y = [1, 0, -1, 0]
print(is_roughly_circle(x, y)) # False
x = [0, 1.2, 0, -1]
y = [1, 0, -1, 0]
print(is_roughly_circle(x, y, confidence=0.2)) # True
Предположения:
- Лучше рассчитать центр всех точек, а не только первые 3. Он не самый оптимальный, но обрабатывает случай, если первая точка ввода находится в геометрическом центре.
- Овалы и эллипсы не являются "примерно кругом"
- Как можно установить «грубый» круг с помощью параметра достоверности [0,1)
Алгоритм:
- Рассчитать среднее значение всех точек (в центре)
- Рассчитать расстояние от центра для всех точек
- Нормализация расстояний до диапазона [0,1]
- Все значения в нормализованном векторе больше 0,9?
- Если это так, набор точек представляет собой круг с уверенностью 0,1.