Whether multiple points make up for a circle? [clo

2020-07-10 06:37发布

If I have e.g. 20 points, how can i check to see if those points make up for a circle? It doesnt have to be a perfect circle.

For example if I store the coordinates of my mouse every 200ms (as the user moves the mouse), I want to see if the user makes a circle gesture. And I cant expect the user to make a perfect circle.

3条回答
放荡不羁爱自由
2楼-- · 2020-07-10 07:14

Update: with the suggestion from @LastCoder to drop consecutive points too close to the previous one (I set the threshold at the distance of 10; perhaps it can be increased) and the tolerance level set to 0.25 (i.e. discrepancy of 25% from the average distance to the centre point is acceptable), the app I made recognizes my "circles" in more than half cases, and is not deceived by squares anymore. So might be not a bad idea, after all.


I would find the centroid for the given set of points, and check if the distance from the centroid to each point is more or less the same (assuming that you expect an approximation of full circle, not just an arc).

It works for me in practice for the problem of detecting a circle gesture done with mouse; see an example in C# (VS2010, the main form only, the rest of app is automatic boilerplate; ignore the errors at ideone) and a screenshot for it here:

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

查看更多
在下西门庆
3楼-- · 2020-07-10 07:15

I'd do the following;

  • Compute a best fit circle through the points
  • Calculate a residual for each point (the join distance from the centre to the point minus the best fit circle radius)
  • Accept the result if a large enough percentage of the residuals were below a certain value defined as a small percentage of the best fit radius. These parameters would be user definable acceptance criteria.
查看更多
太酷不给撩
4楼-- · 2020-07-10 07:25

Here's a simple method, with a working implementation I threw together.

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

  • Loop through the points
  • Find a second point with the maximum distance from the first
  • Record the distance
  • Once you have all of the max distances average them and calculate the error tolerance
  • Check all your recorded distances against your error tolerance

This works great for user input like from a mouse or touch sensor. This algorithm is O(n^2) and uses the delta max distance as opposed to finding the center of mass and checking radii distances.

It "seems" to be more efficient than the best-fit-circle method which has to calculate on every combination of 3 points.

This hack~algo takes advantage of the fact that the maximum distance between two points on a circle is the diameter of the circle.

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;
}
查看更多
登录 后发表回答