寻找"运动方向" (角度)一点

时间:2015-07-31 18:14:26

标签: c++ algorithm matlab math angle

我正在开展一个非常酷的项目,我正在收集有关光标移动的数据,但我遇到了一个问题,我认为我可以使用一些帮助。我不断阅读有关光标x和y位置的数据(以及其他相关数据),一旦光标超过y维度的某个阈值,我需要计算运动方向(角度)。让我用我画的图来说明:

enter image description here

趋势发生的是光标以略微的直线移动,但随后向运动的末端弯曲。我需要计算θ,即蓝色矢量相对于正x轴的角度。我想出的想法是使用最后2个样本来很大程度上确定移动方向是什么,否则如果我使用太多样本,我会扭曲实际角度。为了给出一个极端的案例,让我跟进另一张图片:

enter image description here

这里每个点代表一个样本。请注意,如果我使用BOTH点,我想要的真实角度将是错误的(同样,我需要找到光标最后移动的方向,这是在行尾绘制的矢量)。我不希望这个案子出现太多,但想知道是否有办法解决它,如果它。

最后,请注意,这些动作可以在第一或第二象限中发生,如果这会产生影响。

我非常感谢这里的任何帮助。我用C ++编写代码,但我想我可以翻译任何答案。感谢。

2 个答案:

答案 0 :(得分:3)

This should get you started http://jsfiddle.net/0ao9oa7a/

  • Get all of the recorded points
  • Filter out points that are close together (I use 5 pixels)
  • Find the angles of each consecutive pair of points (atan2)
  • Find the absolute differences between each consecutive pair of angles
    • Throw away all of the angles before the max difference
  • Average the remaining angles (average all point vectors then atan2 back into an angle)

Code

function process(points) {
    if(points.length === 0) { 
        txt = "Not enough points\n" + txt;
        return null; 
    }
    // compress points, removing those that are too close together
    var newPoints = [];
    newPoints.push(points[0]);
    for(var i = 1; i < points.length; i++) {
        if(Math.sqrt(Math.pow(points[i].x - newPoints[newPoints.length - 1].x, 2) + Math.pow(points[i].y - newPoints[newPoints.length - 1].y, 2)) > 5) {
            newPoints.push(points[i]);
        }
    }
    points = newPoints;
    if(points.length < 2) { 
        txt = "Not enough points\n" + txt;
        return null; 
    }
    // get all of the angles
    var angles = [];
    for(var i=0; i < points.length - 1; i++) {
        var rad = Math.atan2(points[i + 1].y - points[i].y, points[i + 1].x - points[i].x);
        angles[i] = rad;
        txt += "x: " + (points[i].x|0) + " y: " + (points[i].y|0) + " x: " + (points[i+1].x|0) + " y: " + (points[i+1].y|0) + " [" + ((rad * 180 / Math.PI)|0) + "]" + "\n";
    }
    txt += "\n";
    // get all of the diffs between angles
    // save the index of the max diff
    var absDiffs = [];
    var maxDiff = -1;
    var maxDiffAngleIndex = -1;
    for(var i=0; i < points.length - 1; i++) {
        var delta = Math.abs(angles[i] - angles[i + 1]);
        if(delta >= maxDiff) {
            maxDiff = delta;
            maxDiffAngleIndex = i + 1;
        }
    }
    if(maxDiffAngleIndex == -1) {
        txt = "Angle: " + angles[0] + " : " + (angles[0] * 180 / Math.PI) + "\n" + txt;
        return angles[0];
    } else if(maxDiffAngleIndex == angles.length - 1) {
        txt = "Angle: " + angles[angle.length - 1] + " : " + (angles[angles.length - 1] * 180 / Math.PI) + "\n" + txt;
        return angles[angles.length - 1];
    } else {
        // find the average angle from the index to the end
        var sumX = 0;
        var sumY = 0;
        for(var i = maxDiffAngleIndex; i < angles.length; i++) {
            sumX += Math.cos(angles[i]);
            sumY += Math.sin(angles[i]);
        }
        var avgX = sumX / (angles.length - maxDiffAngleIndex);
        var avgY = sumY / (angles.length - maxDiffAngleIndex);
        //
        var avgAngle = Math.atan2(avgY, avgX);
        txt = "Angle: " + avgAngle + " : " + (avgAngle * 180 / Math.PI) + "\n" + txt;
        return avgAngle;
    }
}

答案 1 :(得分:0)

As I can see, the “movement direction” (angle) of a point would be the angular coefficient of two dots, one dot at the end of the vector and the other one at the begnning.

Cause we can only find the angle with two dots, so we can make a line, since the direction vector would be (B-A), where A and B are the points I already told you about.

We can calcule this using the formula of the angular coefficient of a line:

m = Tan θ = Δy / Δx

And that is simply:

Tan θ = (yB – yA) / (xB – xA)

Where θ is the “movement direction” (angle) and (x,y) are the coordinates of the points A and B.

Talking about the quadrant, you will only need to use the trigonometric circle to know the sinal of the value of Tan θ, so take a look at this image:

enter image description here

And of course, after you find the value of Tan θ, you will need to use it to find the arctan θ, and that will be your final answer.