计算MySQL中风向的平均值

stU*_*Urb 5 mysql trigonometry degrees atan2 radians

我在新行上每隔10秒就有一张带风向的表格(以及其他天气值).方向存储为度数:0 - 360.


目的

这个平均值是什么意思?数据库每隔10秒存储一行信息.对于性能问题,我想将5天之前的数据汇总到每小时一(平均)线.

随着温度很容易实现:avg(temp)可以解决问题,因为温度不会在很多不同的值之间跳跃.

随着盛行风,获得这种"平均"要困难得多.


以度为单位计算平均风向并不像使用聚合函数avg()那样简单,因为它是一个圆,例如:

dir1 = 10; dir2 = 350;
avg() = (10+350)/2 = 180;
Run Code Online (Sandbox Code Playgroud)

哪个不准确; 它应该是:0或360.

因此,在我的脑海中,我的大学三角学课程认为,如果我将其转换为Radians,并计算x和y分量,我将能够重新计算平均方向.

在PHP中,$ w ['w']是存储在数据库中的方向.

while($w = $stmt->fetch()){
    $x += cos(deg2rad($w['w']));
    $y += sin(deg2rad($w['w']));     
}

$angle = atan2($y, $x);
$angle = 360 + round(rad2deg($angle));
Run Code Online (Sandbox Code Playgroud)

这个公式是否正确?

如果这个公式是正确的; 理想情况下,我想获得MySQL的完整功能.我是这样做的; 但我发现很多()的......

(360 + degrees(atan2(sum(sin(radians(W))), sum(cos(radians(W))))))) AS angle
Run Code Online (Sandbox Code Playgroud)

JJJ*_*JJJ 2

如果我们在圆上画出方向,我们会看到在这种情况下您所追求的“平均值”落在圆的较短部分(绿色部分)的一半上。较长线段的中点位于另一线段中点的对面。

\n\n

圆圈图

\n\n

简单的(A+B)/2计算即可给出较长或较短线段的中点。如果它是较长的线段,则可以通过S1 = (S2+180) % 360其中S2是较长的线段(并且%模运算符)找到较短的线段。

\n\n

现在剩下要做的就是确定何时获得较长的段以及何时获得较短的段,即每当 时ABS(B-A) > 180

\n\n

将所有这些放在一起,计算结果为:

\n\n
( (A+B)/2 + IF( ABS(B-A) > 180, 180, 0 ) ) % 360\n
Run Code Online (Sandbox Code Playgroud)\n\n

这很可能比三角函数快得多。

\n\n

正如评论中提到的,如果两个方向彼此完全相反(例如 0\xc2\xb0 和 180\xc2\xb0),则“平均值”可能位于圆的任一侧(90\xc2\xb0 或270\xc2\xb0)。您只需决定选择哪一个即可。在这种情况下,上面的公式将选择 90\xc2\xb0。如果您想要 270\xc2\xb0,请将比较从 更改>>=

\n