中风是一个圆圈吗?

时间:2015-03-10 06:33:13

标签: c# silverlight windows-phone-8.1

是否可以检查用户在画布上绘制的笔划是否为圆形?

我有两个数组x[]y[],它们具有笔划的所有坐标。如何使用此信息检查笔划是否为圆形?

1 个答案:

答案 0 :(得分:1)

我想这取决于您对" circle"的定义。用户不太可能画一个实际的圆圈,尽管他们可能会接近。首先,您需要为" circle"。

定义规范

这是一个可行的方法:

  1. 绘制的形状是闭合曲线。即最后一点与初始点相对接近。
  2. 从每个点到" center"的距离,其中" center"被定义为所有点的平均值,相对接近所有点的平均距离。
  3. 请注意,该规范仍然相当含糊。我使用短语"相对接近"而不是精确的术语,因为我不知道你的标准是什么" circle"是。但我希望上述内容是一个很好的起点。


    修改

    正如评论中所指出的,上面的内容仍然允许一些相当草率的图纸作为一个圆圈,例如" D"形状提到。如果希望将图纸限制在合理的圆形范围内,但仍然允许公平地压扁图形"形状(例如更椭圆形,蛋形等),可以通过添加基于由三元组点构成的角度的启发式来改进上述内容。

    正确地做到这一点有点牵扯。您可以使用点积来轻松确定两个矢量之间的角度。但不幸的是,这种计算对于哪个向量是第一个"无动于衷。也就是说,如果您关心凹曲线与凸曲线,则点积不会区分。另一种方法是使用Math.Atan2()函数。例如,让我们看看前三个点之间的角度:

    // Note: normally one would make both vectors have the same start
    // point, i.e. using pointList[1], for the subtraction of the
    // Atan2 value to give the correct result. But here, what we really
    // want to know is how different in direction the second vector is
    // from the first, so calculating both line segment angles in the
    // same direction of drawing gives a more useful result.
    
    double vx1 = pointList[1].X - pointList[0].X, vy1 = pointList[1].Y - pointList[0].Y,
        vx2 = pointList[2].X - pointList[1].X, vy2 = pointList[2].Y - pointList[1].Y;
    double angleDifference = Math.Atan2(vx2, vy2) - Math.Atan2(vx1, vy1);
    

    (你当然会在一个循环中进行这些计算,以获得每个三重点的差异;以上仅用于说明目的)。

    假设用户沿逆时针方向画了一个圆圈,那么上面应该返回接近0的正角度差异。如果它们接近0,那么你会想要拒绝绘图,因为这表明用户正在绘制直线(例如" D"的垂直条)。但是如果某些差异与0相差太远,你也会想要拒绝绘图,因为这表明用户可能正在绘制尖角(例如&#34的左上角或左下角; D&# 34。)

    注意:较小的圆圈需要更锐利的角度。您可能希望根据圆的公称直径(即每个点距中心的距离的平均值)动态调整用于此的限制,对于较大的圆设置较小和最大角度差,对于较小的圆设置较大圆。

    注意:此处的角度值以弧度为单位。因此,在设置角度差的下限和上限时,您需要确保使用正确的单位进行比较。

    注意:用户当然可以顺时针方向画圆圈。如果你总结所有差异,你最终会得到正数或负数;该标志将告诉您是否应该将差异与期望的限制进行比较,或者将这些差异与这些限制的负数进行比较。要解决此问题,您可以执行以下任何操作:

    • 两次通过数据,首先查看您是否需要限制的正值或负值,然后再将实际值与限值进行比较。
    • 在第一次传递期间保存角度计算,然后将这些保存的值用于第二次传递。
    • 只需跟踪您的比较是否始终在正限制,负限制或两者之间(即两个标记,根据与正限制和负限制的比较将适当的一个设置为true)。在单次通过数据之后,您将知道是否应该使用正限制或负限制,然后只要在结尾处仅设置一个标记,圆就有效(假设没有角度超过绝对限制) ,当然)。