C# 我有一个点列表,想确定它们是否形成一个圆

C# 我有一个点列表,想确定它们是否形成一个圆,c#,list,math,vector,gestures,C#,List,Math,Vector,Gestures,我使用的是C#,我有一个向量点列表,我想尝试近似它们看起来像一个圆 你有什么想法可以实现这一点,或者其他人有什么想法吗?1)从列表中选择任意三个点,找到相应圆圈的中心 我们可以这样做,使用三角形-外接圆构造方法,找到所有三条边(两条边足够)的中间点,它们的交点是圆的中心。大概是这样的: public PointF findCenter(PointF a, PointF b, PointF c) { float k1 = (a.Y - b.Y) / (a.X - b.X) //Two-po

我使用的是C#,我有一个向量点列表,我想尝试近似它们看起来像一个圆

你有什么想法可以实现这一点,或者其他人有什么想法吗?

1)从列表中选择任意三个点,找到相应圆圈的中心

我们可以这样做,使用三角形-外接圆构造方法,找到所有三条边(两条边足够)的中间点,它们的交点是圆的中心。大概是这样的:

public PointF findCenter(PointF a, PointF b, PointF c)
{
    float k1 = (a.Y - b.Y) / (a.X - b.X) //Two-point slope equation
    float k2 = (a.Y - c.Y) / (a.X - c.X) //Same for the (A,C) pair
    PointF midAB = new PointF((a.X + b.X) / 2, (a.Y + b.Y) / 2) //Midpoint formula
    PointF midAC = new PointF((a.X + c.X) / 2, (a.Y + c.Y) / 2) //Same for the (A,C) pair
    k1 = -1*k1; //If two lines are perpendicular, then the product of their slopes is -1.
    k2 = -1*k2; //Same for the other slope
    float n1 = midAB.Y - k1*midAB.X; //Determining the n element
    float n2 = midAC.Y - k2*midAC.Y; //Same for (A,C) pair
    //Solve y1=y2 for y1=k1*x1 + n1 and y2=k2*x2 + n2
    float x = (n2-n1) / (k1-k2);
    float y = k1*x + n1;
    return new PointF(x,y);
}
2) 检查其他点与该中心的距离是否相等,如果是,则有一个圆,如果不是,则没有


另外,我还没有测试代码,所以请准备调试。询问您是否还需要什么

从您的积分集中取任意三分。 如果点是共线的,则点集并不都位于圆上。 找出三角形的中心线。直径由以下公式给出:
d=(a*b*c)/2*面积
。圆心是三条边的垂直平分线的交点

现在,对于点集中的每个剩余点,如果距离中心的距离不等于半径,则点不在圆上。通过比较半径的平方与给定点与中心之间距离的平方,可以加快计算速度

另一种可能性:

  • 找到质心 ()的 要点
  • 确定每一点与目标位置之间的距离(半径) 质心
  • 计算分布并确定各点 在可接受的公差范围内(例如标准偏差<±0.05×平均半径或类似值)
  • 如果不知道更多关于点的来源,就很难提出最佳解决方案

    这些可能有用:而且。这些方法将为您提供通过点的最佳拟合圆,但您仍然需要确定数据点是否足够接近您的目的

    更新:基于“手势”标记,有人已经实现了它:

    基于“手势”标记,我想你不仅想知道这些点离最小圆有多近(搜索“最小圆问题”),还必须关注它们的顺序和分布:

  • 我从最小圆的距离开始。如果他们太远,你就完了,这不是一个圆
  • 如果它们足够接近配置的阈值,则计算圆心、第一个点和每个其他点定义的向量之间的角度(下图)
  • 检查每个角度是否大于上一个角度
  • 检查相邻任意两个角度之间的差值是否不超过某个配置的阈值
  • 检查最后一个点是否与第一个点足够接近
  • 最终,您可能会想到其他一些检查,因此请简化扩展

  • 只有当您的点形成一个完美的圆时,才能拾取任意三个点。如果您正在寻找一个近似值,例如,在最终用户用手指在触摸屏上画圆的情况下,您可能会得到一个完全错误的中心。正如@dasblinkenlight指出的,我的答案是数学方法。考虑到计算代数是离散的,如果复制粘贴整个代码而不进行修改,则这不适用。您应该添加一个允许+/-2px(或其他值)坐标振荡的错误函数。您通过以下方式计算错误:
    (Math.Abs(targetPoint.X-returnedPoint.X)+Math.Abs(targetPoint.Y-returnedPoint.Y))<2
    我知道我的回答没有回答您的问题。但也许你在寻找一个圆,它可以为你提供一个关于这些点离形成一个圆有多近的统计估计。然后,您可以为一个点集设置边界(以标准偏差为单位),以符合形成cirlce的条件。为什么您会假定这些点是按特定顺序提供的?还请记住,如果可以从等效角度生成任何几何图形,则不能开始分析角度。首先要分析的是圆的定义特征(即,距中心相同距离的所有点);角度只能在稍后阶段进入图片,以确定它是一个完整的圆还是圆的一部分。为了检查最后一个点是否与第一个点足够接近,我建议该点的角度总和>340度或类似。假设这是一个手势,你只想要一个最小的完整圆,可能不在乎你是否超过它(例如1.5圈)@如果点的来源是触摸时的手势,那么点的顺序很重要screen@ColinYoung请看一下我的回答(澄清2)。点的顺序(如果有)非常重要。我问瓦茨拉夫希尔他为什么认为有订单。如果存在订单(您正在手动绘制圆),则必须考虑这一事实;如果有一堆随机点,你就不能考虑这个问题,因为这会导致错误的结果。OP没有提到这个问题,这就是为什么我认为VaclavSir不应该考虑这个问题(或者他应该提到他的方法不能用于随机点)。我假设有一个顺序,因为这个问题被标记为“手势”。我可能错了。如果你真正想做的是识别一个手势,那么这个链接可能会有帮助:如果没有代码,这是一个糟糕的问题。只是强调一下(正如我在VaclavSir回答中的评论)你不能盲目地使用“手势方法”,而只能在非常特定的条件下(即实际发生的手势)。从OP的问题来看,不清楚数据点的来源(包括标记“手势”;但这可能只是吸引足够近的回答者的一种方式),而且这种方法不能用于随机点。@varocarbas是的,它会