所以我在 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 的圆。