C# 笔划是圆吗?
是否可以检查用户在画布上绘制的笔划是否为圆形C# 笔划是圆吗?,c#,silverlight,windows-phone-8.1,C#,Silverlight,Windows Phone 8.1,是否可以检查用户在画布上绘制的笔划是否为圆形 我有两个数组x[]和y[],它们具有笔划的所有坐标。如何使用此信息检查笔划是否为圆形?我想这取决于您对“圆”的定义。用户不太可能画出一个实际的圆圈,尽管他们可能很接近。因此,首先,您需要定义“圆”的规范 下面是一个可能有效的方法: 绘制的形状是一条闭合曲线。也就是说,终点与起点相对较近 从每个点到“中心”的距离(其中“中心”定义为所有点的平均值)相对接近所有点的平均距离 请注意,该规范仍然相当模糊。我用“相对接近”这个短语来代替精确的术语,因为我真的
我有两个数组
x[]
和y[]
,它们具有笔划的所有坐标。如何使用此信息检查笔划是否为圆形?我想这取决于您对“圆”的定义。用户不太可能画出一个实际的圆圈,尽管他们可能很接近。因此,首先,您需要定义“圆”的规范
下面是一个可能有效的方法:
编辑: 如注释中所述,上面的说明仍然允许一些相当粗糙的图形限定为圆形,如所提到的“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太远,您也会希望拒绝该图形,因为这表明用户可能正在绘制锐角(例如“D”的左上角或左下角)
注意:较小的圆需要更锐利的角度。您可能希望根据圆的标称直径(即每个点到中心距离的平均值)动态调整用于此操作的限制,对于较大的圆,将最小和最大角度差设置为较小,对于较小的圆,将其设置为较大
注意:此处的角度值以弧度为单位。因此,在设置角度差的下限和上限时,需要确保使用正确的单位进行比较
注意:用户当然可以按顺时针方向画一个圆。如果你把所有的差异加起来,你会得到一个正数或负数;这个标志会告诉你是应该将你的差异与你想要的极限进行比较,还是与那些极限的负值进行比较。要解决此问题,您可以执行以下任一操作:
- 对数据进行两次遍历,第一次是为了找出限制值的正值还是负值,第二次是为了将实际值与限制值进行比较
- 在第一个过程中保存角度计算,然后在第二个过程中使用这些保存的值
- 只需跟踪您的比较是否始终在正限值、负限值或两者之间(即两个标志,根据正限值和负限值的比较,将相应的标志设置为
)。单次通过数据后,您将知道应该使用正极限还是负极限,然后只要在末尾只设置一个标志,圆就有效(当然,假设没有角度超过绝对极限)true