求一个点的 "movement direction"(角度)
Finding a "movement direction" (angle) of a point
我正在做一个非常酷的项目,我正在收集有关光标移动的数据,但我 运行 遇到了一个问题,我认为我需要一些帮助。我不断读取有关光标 x 和 y 位置的数据(以及其他相关数据),一旦光标在 y 维度上超过某个阈值,我需要计算移动方向(角度)。用我画的图来说明一下:
往往会发生的情况是,光标在直线上移动,但随后向移动的终点弯曲。我需要计算 theta,即蓝色矢量相对于正 x 轴的角度。我想出的想法是使用最后 2 个样本在很大程度上确定运动方向,否则如果我使用太多样本,我会扭曲实际角度。举个极端的例子,补一张图:
这里每个点代表一个样本。请注意,如果我同时使用两个点,我想要的实际角度将是错误的(同样,我需要找到光标最后移动的方向,也就是在线末端绘制的矢量)。我不希望这种情况出现太多,但想知道如果出现这种情况是否有办法解决。
最后,请注意这些运动可以发生在第一象限或第二象限,如果这会有所不同的话。
非常感谢任何帮助。我正在用 C++ 编写代码,但我想我可以翻译任何答案。谢谢
这应该可以帮助您入门 http://jsfiddle.net/0ao9oa7a/
- 获取所有记录点数
- 过滤掉靠近的点(我用了5个像素)
- 找出每对连续点的角度 (atan2)
- 找出每对连续角度之间的绝对差值
- 丢弃最大差值之前的所有角度
- 平均剩余的角度(平均所有点向量然后 atan2 回到一个角度)
代码
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;
}
}
据我所见,一个点的“运动方向”(角度)就是两个点的angular系数,一个点在向量的末尾,另一个点在向量的开头。
因为我们只能找到两个点的角度,所以我们可以画一条线,因为方向矢量是(B-A)
,其中A
和B
是点我已经告诉你了。
我们可以用直线的angular系数的公式来计算:
m = Tan θ = Δy / Δx
这很简单:
Tan θ = (yB – yA) / (xB – xA)
其中θ是“运动方向”(角度)和(x,y)是A点和B点的坐标.
说到象限,只要用三角圆就可以知道Tan θ的正弦值,所以看这张图:
当然,求出Tan θ的值后,还要用它求出arctan θ
,这就是你的最终答案。
我正在做一个非常酷的项目,我正在收集有关光标移动的数据,但我 运行 遇到了一个问题,我认为我需要一些帮助。我不断读取有关光标 x 和 y 位置的数据(以及其他相关数据),一旦光标在 y 维度上超过某个阈值,我需要计算移动方向(角度)。用我画的图来说明一下:
往往会发生的情况是,光标在直线上移动,但随后向移动的终点弯曲。我需要计算 theta,即蓝色矢量相对于正 x 轴的角度。我想出的想法是使用最后 2 个样本在很大程度上确定运动方向,否则如果我使用太多样本,我会扭曲实际角度。举个极端的例子,补一张图:
这里每个点代表一个样本。请注意,如果我同时使用两个点,我想要的实际角度将是错误的(同样,我需要找到光标最后移动的方向,也就是在线末端绘制的矢量)。我不希望这种情况出现太多,但想知道如果出现这种情况是否有办法解决。
最后,请注意这些运动可以发生在第一象限或第二象限,如果这会有所不同的话。
非常感谢任何帮助。我正在用 C++ 编写代码,但我想我可以翻译任何答案。谢谢
这应该可以帮助您入门 http://jsfiddle.net/0ao9oa7a/
- 获取所有记录点数
- 过滤掉靠近的点(我用了5个像素)
- 找出每对连续点的角度 (atan2)
- 找出每对连续角度之间的绝对差值
- 丢弃最大差值之前的所有角度
- 平均剩余的角度(平均所有点向量然后 atan2 回到一个角度)
代码
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;
}
}
据我所见,一个点的“运动方向”(角度)就是两个点的angular系数,一个点在向量的末尾,另一个点在向量的开头。
因为我们只能找到两个点的角度,所以我们可以画一条线,因为方向矢量是(B-A)
,其中A
和B
是点我已经告诉你了。
我们可以用直线的angular系数的公式来计算:
m = Tan θ = Δy / Δx
这很简单:
Tan θ = (yB – yA) / (xB – xA)
其中θ是“运动方向”(角度)和(x,y)是A点和B点的坐标.
说到象限,只要用三角圆就可以知道Tan θ的正弦值,所以看这张图:
当然,求出Tan θ的值后,还要用它求出arctan θ
,这就是你的最终答案。