16

我正在寻找一种简单的程序化方式来检测用户是否绘制了圆形。我在 C 中工作,但很高兴使用伪代码工作。一些谷歌搜索带来了一些(希望)过于复杂的方法。

我将鼠标坐标跟踪为浮点数,并创建了一个向量数组来跟踪鼠标随时间的移动。本质上,我希望检测何时绘制了一个圆圈,然后忽略与该圆圈无关的所有运动数据。

我对如何实现这一点有一个基本的想法:

使用轮询功能跟踪所有运动。每次轮询函数时,都会存储当前鼠标位置。在这里,我们遍历历史位置数据并进行粗略的“定位”以比较两个位置。如果新位置距离旧位置足够近,我们会删除旧位置之前的所有历史数据。

虽然这在理论上可行,但在实践中却是一团糟。有没有人有什么建议?如果建议的方法可以检测它是顺时针还是逆时针绘制,则加分。

4

5 回答 5

6

基于您的跟踪/轮询功能,它将浮点对推送到堆栈上。这必须在固定的时间间隔内完成。

  1. 对列表中的两个相等条目进行基于阈值的搜索。现在您的堆栈中有两个索引;第一个和第二个相等的条目。将此视为一条线。
  2. 获取指数的绝对差异。然后除以二,得到这个点的坐标。(线的中心。)
  3. 你有两点:因此你可以通过两点之间的距离除以二来得到圆的半径。
  4. 将第 2 步的数量除以 2,现在你得到了四分之一。

    如果第 1 步的直线是垂直的并且直线的第一个点在顶部:如果第一个四分之一在中心点的左侧,则逆时针绘制圆。如果第一季度在中心点的右侧,则圆是顺时针绘制的。如果线的第一个点在底部,则反转(即 ccw => cw 和 cw => ccw)

    如果第 1 步的线是水平的并且列表的第一个点在左侧: 如果第一个四分之一在中心点上方,则逆时针绘制圆。如果第一季度低于中心点,则圆是顺时针绘制的。如果线的第一个点在右侧,则反转。

  5. 检查它是否是一个圆:遍历所有坐标对并计算到中心点的距离。从计算的距离和到中心点的实际距离调整允许距离的阈值。

在第 2 步和第 4 步中,如果时间间隔非常低(快速轮询),您可以通过取多个索引的平均值来进一步调整此算法。例如:数组中有 30 对,然后您在 0、1 和 28、29 处平均对以获得最高点。对所有其他点执行相同操作。

我希望这很容易。

于 2010-03-06T18:37:12.817 回答
5

恕我直言,您绝对走在正确的轨道上。基本上,您需要将每个鼠标点与前一个鼠标点进行比较并计算它们之间的角度(如在第一个点位于原点的单位圆上所设想的那样)。为此,您可以使用以下公式:

double angle = atan2(y2 - y1, x2 - x1) * 180 / PI;

if (angle < 0)
    angle += 360;

你最终得到的是,对于顺时针移动,角度将在正方向循环,而对于逆时针移动,角度将在负方向循环。您可以使用以下逻辑确定当前角度是大于还是小于前一个角度:

if (angle2 > 270 && angle1 < 90)
{
    angle1 += 360
}
else if (angle1 > 270 && angle2 < 90)
{
    angle2 += 360
}

bool isPositive = (angle2-angle1 > 0);

如果你得到一定数量的向量,它们的角度都在增加(isPositive 是真的,比如说 10 次),你可以假设正在绘制一个顺时针圆;如果趋势为负(isPositive 为假 10 次),则为逆时针圆圈。:)

于 2011-09-01T19:50:11.407 回答
1

这是一个算法来查看一个点数组是否适合一个圆:

  1. 计算点的质心(所有 x 和 y 坐标的平均值)

  2. 计算所有点到质心的距离

  3. 找到最大和最小距离

  4. 如果最大值 - 最小值 < 公差,则检测到圆形截面

NB 这也将检测圆的一部分,因此您需要确定足够的角度被扫过以使其成为一个完整的圆。

去做这个:

  1. 如上计算质心
  2. 计算质心和每个点之间的角度(使用 atan2 函数)
  3. 将角度映射到段(我发现 12 个 30 度段对我有用;只需将角度除以 30 并向下舍入为整数 - 假设您在这里以度为单位工作)
  4. 如果所有线段至少包含 1 个点,则它是一个圆(即映射的线段数组包含 0 到 11 之间的所有值)

  5. 奖励:增加角度是逆时针的;顺时针递减

于 2019-11-09T20:11:07.240 回答
0

没有尝试过,但是在阅读您的问题时想到了这个想法,所以不妨与您分享:

我假设必须在合理的时间内绘制圆,给定鼠标的稳定“采样率”,这将留下已知大小的二维向量(点)数组。将它们全部相加并除以 2D 向量的计数,以获得数组中“中心”点的估计值。然后从这个中心点到数组中的点形成向量并进行点积(通过向量长度进行归一化),确保点积的符号对于一系列点保持相同意味着这些点都以相同的方式移动方向,正号表示逆时针运动,负号则相反。如果累积角度超过 2 PI,则绘制圆周运动。

祝你好运。

于 2010-03-06T19:29:17.060 回答
0

1 - 选择任意 3 个点

2 - 如果这些点是共线的 +/- 'some buffer' 那么它不是一个圆。

3 - 使用维基百科上描述的方法找到三角形的外接圆来找到候选圆的中点和半径

可以通过绘制三个垂直平分线中的任何两个来构造三角形的外心。对于三个不共线的点,这两条线不能平行,外心就是它们相交的点。平分线上的任何一点与它平分的两个点的距离相等,由此得出,两个平分线上的这个点与所有三个三角形顶点的距离相等。外接半径是从它到三个顶点中的任何一个的距离。

4 - 检查到剩余点的距离。如果这些点在“候选圆半径”+/-“一些缓冲余量”之内,那么它就是一个圆。

5 - 要确定方向,只需从中点计算第一点和第二点之间的角度。负角是正确的。留下一个正角。(可以根据您使用的坐标系反转)

于 2019-09-17T19:53:36.740 回答