Skip to content

Commit 10438db

Browse files
authored
Ignore small wind direction changes with insignificant speed magnitude (#164)
* Ignore small wind direction changes if insignificant speed * lceanup
1 parent 3ec0cdc commit 10438db

File tree

4 files changed

+131
-60
lines changed

4 files changed

+131
-60
lines changed

src/features/rap/Row.tsx

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import styled from "@emotion/styled";
2+
import { WindsAloftAltitude, WindsAloftHour } from "../../models/WindsAloft";
3+
import Altitude from "./cells/Altitude";
4+
import Temperature from "./cells/Temperature";
5+
import WindDirection from "./cells/WindDirection";
6+
import WindSpeed from "./cells/WindSpeed";
7+
import { css } from "@emotion/react";
8+
import { vectorDifferenceMagnitude } from "../../helpers/vector";
9+
10+
const DELTA_WINDSPEED_VECTOR_THRESHOLD_KPH = 10;
11+
12+
const TableRow = styled.tr<{ opaque: boolean }>`
13+
${({ opaque }) =>
14+
opaque &&
15+
css`
16+
opacity: 0.5;
17+
`}
18+
`;
19+
20+
interface RowProps {
21+
datum: WindsAloftAltitude;
22+
index: number;
23+
displayedRapData: WindsAloftAltitude[];
24+
surfaceLevel: number;
25+
windsAloftHour: WindsAloftHour;
26+
}
27+
28+
export default function Row({
29+
datum,
30+
index,
31+
displayedRapData,
32+
surfaceLevel,
33+
windsAloftHour,
34+
}: RowProps) {
35+
function negativeAltitude(datum: WindsAloftAltitude): boolean {
36+
return !!(datum.altitudeInM - surfaceLevel < 0);
37+
}
38+
39+
const shearEligible =
40+
displayedRapData[index - 1] &&
41+
vectorDifferenceMagnitude(
42+
datum.windSpeedInKph,
43+
datum.windDirectionInDeg,
44+
displayedRapData[index - 1]?.windSpeedInKph,
45+
displayedRapData[index - 1]?.windDirectionInDeg,
46+
) > DELTA_WINDSPEED_VECTOR_THRESHOLD_KPH;
47+
48+
return (
49+
<TableRow key={index} opaque={negativeAltitude(datum)}>
50+
<td>
51+
<Altitude
52+
heightInMeters={datum.altitudeInM}
53+
surfaceLevelInMeters={surfaceLevel}
54+
pressure={datum.pressure}
55+
/>
56+
</td>
57+
<td>
58+
<Temperature
59+
temperature={datum.temperatureInC}
60+
dewpoint={datum.dewpointInC}
61+
lapseRate={
62+
displayedRapData[index - 1]
63+
? -(
64+
(datum.temperatureInC -
65+
displayedRapData[index - 1].temperatureInC) /
66+
(datum.altitudeInM - displayedRapData[index - 1].altitudeInM)
67+
)
68+
: undefined
69+
}
70+
pressure={datum.pressure}
71+
hour={new Date(windsAloftHour.date)}
72+
/>
73+
</td>
74+
<td>
75+
<WindDirection
76+
curr={datum.windDirectionInDeg}
77+
prev={displayedRapData[index - 1]?.windDirectionInDeg}
78+
shearEligible={shearEligible}
79+
/>
80+
</td>
81+
<td>
82+
<WindSpeed
83+
curr={datum.windSpeedInKph}
84+
prev={displayedRapData[index - 1]?.windSpeedInKph}
85+
/>
86+
</td>
87+
</TableRow>
88+
);
89+
}

src/features/rap/Table.tsx

Lines changed: 9 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
1-
import { css } from "@emotion/react";
21
import styled from "@emotion/styled";
32
import { useAppDispatch, useAppSelector } from "../../hooks";
4-
import Altitude from "./cells/Altitude";
5-
import Temperature from "./cells/Temperature";
6-
import WindDirection from "./cells/WindDirection";
7-
import WindSpeed from "./cells/WindSpeed";
83
import { headerText } from "./CinCape";
94
import { WindsAloftAltitude, WindsAloftHour } from "../../models/WindsAloft";
105
import {
@@ -22,6 +17,7 @@ import { toggleAltitude } from "../user/userSlice";
2217
import { toggleAltitudeType } from "../../helpers/locale";
2318
import { notEmpty } from "../../helpers/array";
2419
import Tooltip from "../../shared/Tooltip";
20+
import Row from "./Row";
2521

2622
const TableEl = styled.table`
2723
width: 100%;
@@ -35,14 +31,6 @@ const TableEl = styled.table`
3531
}
3632
`;
3733

38-
const Row = styled.tr<{ opaque: boolean }>`
39-
${({ opaque }) =>
40-
opaque &&
41-
css`
42-
opacity: 0.5;
43-
`}
44-
`;
45-
4634
const InteractTh = styled.th`
4735
cursor: pointer;
4836
`;
@@ -148,10 +136,6 @@ export default function Table({
148136
surfaceLevel,
149137
]);
150138

151-
function negativeAltitude(datum: WindsAloftAltitude): boolean {
152-
return !!(datum.altitudeInM - surfaceLevel < 0);
153-
}
154-
155139
return (
156140
<TableEl>
157141
<thead>
@@ -182,45 +166,14 @@ export default function Table({
182166

183167
<tbody>
184168
{displayedRapData.map((datum, index) => (
185-
<Row key={index} opaque={negativeAltitude(datum)}>
186-
<td>
187-
<Altitude
188-
heightInMeters={datum.altitudeInM}
189-
surfaceLevelInMeters={surfaceLevel}
190-
pressure={datum.pressure}
191-
/>
192-
</td>
193-
<td>
194-
<Temperature
195-
temperature={datum.temperatureInC}
196-
dewpoint={datum.dewpointInC}
197-
lapseRate={
198-
displayedRapData[index - 1]
199-
? -(
200-
(datum.temperatureInC -
201-
displayedRapData[index - 1].temperatureInC) /
202-
(datum.altitudeInM -
203-
displayedRapData[index - 1].altitudeInM)
204-
)
205-
: undefined
206-
}
207-
pressure={datum.pressure}
208-
hour={new Date(windsAloftHour.date)}
209-
/>
210-
</td>
211-
<td>
212-
<WindDirection
213-
curr={datum.windDirectionInDeg}
214-
prev={displayedRapData[index - 1]?.windDirectionInDeg}
215-
/>
216-
</td>
217-
<td>
218-
<WindSpeed
219-
curr={datum.windSpeedInKph}
220-
prev={displayedRapData[index - 1]?.windSpeedInKph}
221-
/>
222-
</td>
223-
</Row>
169+
<Row
170+
key={index}
171+
datum={datum}
172+
index={index}
173+
surfaceLevel={surfaceLevel}
174+
windsAloftHour={windsAloftHour}
175+
displayedRapData={displayedRapData}
176+
/>
224177
))}
225178
</tbody>
226179
</TableEl>

src/features/rap/cells/WindDirection.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,21 +40,27 @@ const Container = styled.div<{ shear: boolean }>`
4040
interface WindDirectionProps {
4141
curr: number;
4242
prev?: number;
43+
shearEligible: boolean;
4344
}
4445

45-
export default function WindDirection({ curr, prev }: WindDirectionProps) {
46+
export default function WindDirection({
47+
curr,
48+
prev,
49+
shearEligible,
50+
}: WindDirectionProps) {
4651
const content = useMemo(() => {
4752
return (
4853
<Container
4954
shear={
50-
Math.abs(getAngleDifference(curr, prev === undefined ? curr : prev)) >
51-
25
55+
!!shearEligible &&
56+
!!prev &&
57+
Math.abs(getAngleDifference(curr, prev)) > 25
5258
}
5359
>
5460
{Math.round(curr)} <WindIndicator direction={curr} />
5561
</Container>
5662
);
57-
}, [curr, prev]);
63+
}, [curr, prev, shearEligible]);
5864

5965
return content;
6066
}

src/helpers/vector.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
export function vectorDifferenceMagnitude(
2+
speed1: number,
3+
direction1: number,
4+
speed2: number,
5+
direction2: number,
6+
): number {
7+
// Convert directions from degrees to radians
8+
const radian1 = (Math.PI / 180) * direction1;
9+
const radian2 = (Math.PI / 180) * direction2;
10+
11+
// Convert polar coordinates to Cartesian coordinates
12+
const x1 = speed1 * Math.cos(radian1);
13+
const y1 = speed1 * Math.sin(radian1);
14+
const x2 = speed2 * Math.cos(radian2);
15+
const y2 = speed2 * Math.sin(radian2);
16+
17+
// Calculate the difference in Cartesian coordinates
18+
const dx = x2 - x1;
19+
const dy = y2 - y1;
20+
21+
// Calculate the magnitude of the difference vector
22+
return Math.sqrt(dx * dx + dy * dy);
23+
}

0 commit comments

Comments
 (0)