多个点是否构成一个圆圈?

时间:2012-01-30 12:25:03

标签: algorithm geometry point gesture-recognition

如果我有例如20分,我该怎么检查这些点是否能弥补一个圆圈?它不一定是一个完美的圆圈。

例如,如果我每隔200ms存储鼠标的坐标(当用户移动鼠标时),我想看看用户是否做了圆形手势。我不能指望用户做一个完美的圈子。

3 个答案:

答案 0 :(得分:9)

我执行以下操作;

  • 计算best fit circle through the points
  • 计算每个点的残差(从中心到点的连接距离减去最佳拟合圆半径)
  • 如果足够大的残差百分比低于定义为最佳拟合半径的一小部分的特定值,则接受结果。这些参数是用户可定义的验收标准。

答案 1 :(得分:3)

更新:根据@LastCoder的建议,将连续点丢弃得太接近前一个(我将阈值设置为10;也许可以增加),公差等级设置为0.25(即差异为25)从平均距离到中心点的百分比是可以接受的),我做的应用程序在超过一半的情况下识别我的“圆圈”,并且不再被正方形欺骗。毕竟,这可能不是一个坏主意。


我会找到给定点集的centroid,并检查从质心到每个点的距离是否大致相同(假设您期望得到一个完整圆的近似值,而不仅仅是弧)。

在实践中,它对于检测用鼠标完成的圆形手势的问题是有用的;请参阅an example in C#(仅限主要表单VS2010,应用程序的其余部分是自动样板;忽略ideone处的错误)及其屏幕截图:

Certainly I am bad at drawing circles with laptop's touch-stick

答案 2 :(得分:2)

这是一个简单的方法,我将工作实现放在一起。

http://jsfiddle.net/kBsdW/29/

  • 循环点
  • 找到与第一个
  • 的最大距离的第二个点
  • 记录距离
  • 一旦您将所有最大距离平均并计算误差容差
  • 根据容错检查所有记录的距离

这非常适合用户输入,例如鼠标或触摸传感器。该算法为O(n ^ 2)并使用delta最大距离,而不是查找质心和检查半径距离。

“似乎”似乎比最佳拟合圆方法更有效,它必须计算3个点的每个组合。

这个hack~algo充分利用了这样一个事实:圆上两点之间的最大距离就是圆的直径。

function isCircle(points, error) {
    if(points.length <= 2) return true;
    var weights = [];
    var maxDistance = 0;
    var sumDistance = 0;
    var avgDistance = 0;
    var errorConstraint = 0;
    for(var i=0; i<points.length; i++) {
        var distance = 0;
        for(var j=0; j<points.length; j++) {
            var d = getDistance(points[i], points[j]);
            if(d > distance) {
                distance = d;
            }
        }
        if(distance > 0) {
            if(distance > maxDistance) maxDistance = distance;
            sumDistance += distance;
            weights.push(distance);
        }
    }
    avgDistance = sumDistance / weights.length;
    errorConstraint = error * avgDistance;
    for(var i=0; i<weights.length; i++) {
        if(Math.abs(avgDistance - weights[i]) > errorConstraint) {
            return false;
        }
    }
    return true;
}