Skip to content

Commit

Permalink
Ignore small wind direction changes with insignificant speed magnitu…
Browse files Browse the repository at this point in the history
…de (#164)

* Ignore small wind direction changes if insignificant speed

* lceanup
  • Loading branch information
aeharding authored Jan 4, 2025
1 parent 3ec0cdc commit 10438db
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 60 deletions.
89 changes: 89 additions & 0 deletions src/features/rap/Row.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import styled from "@emotion/styled";
import { WindsAloftAltitude, WindsAloftHour } from "../../models/WindsAloft";
import Altitude from "./cells/Altitude";
import Temperature from "./cells/Temperature";
import WindDirection from "./cells/WindDirection";
import WindSpeed from "./cells/WindSpeed";
import { css } from "@emotion/react";
import { vectorDifferenceMagnitude } from "../../helpers/vector";

const DELTA_WINDSPEED_VECTOR_THRESHOLD_KPH = 10;

const TableRow = styled.tr<{ opaque: boolean }>`
${({ opaque }) =>
opaque &&
css`
opacity: 0.5;
`}
`;

interface RowProps {
datum: WindsAloftAltitude;
index: number;
displayedRapData: WindsAloftAltitude[];
surfaceLevel: number;
windsAloftHour: WindsAloftHour;
}

export default function Row({
datum,
index,
displayedRapData,
surfaceLevel,
windsAloftHour,
}: RowProps) {
function negativeAltitude(datum: WindsAloftAltitude): boolean {
return !!(datum.altitudeInM - surfaceLevel < 0);
}

const shearEligible =
displayedRapData[index - 1] &&
vectorDifferenceMagnitude(
datum.windSpeedInKph,
datum.windDirectionInDeg,
displayedRapData[index - 1]?.windSpeedInKph,
displayedRapData[index - 1]?.windDirectionInDeg,
) > DELTA_WINDSPEED_VECTOR_THRESHOLD_KPH;

return (
<TableRow key={index} opaque={negativeAltitude(datum)}>
<td>
<Altitude
heightInMeters={datum.altitudeInM}
surfaceLevelInMeters={surfaceLevel}
pressure={datum.pressure}
/>
</td>
<td>
<Temperature
temperature={datum.temperatureInC}
dewpoint={datum.dewpointInC}
lapseRate={
displayedRapData[index - 1]
? -(
(datum.temperatureInC -
displayedRapData[index - 1].temperatureInC) /
(datum.altitudeInM - displayedRapData[index - 1].altitudeInM)
)
: undefined
}
pressure={datum.pressure}
hour={new Date(windsAloftHour.date)}
/>
</td>
<td>
<WindDirection
curr={datum.windDirectionInDeg}
prev={displayedRapData[index - 1]?.windDirectionInDeg}
shearEligible={shearEligible}
/>
</td>
<td>
<WindSpeed
curr={datum.windSpeedInKph}
prev={displayedRapData[index - 1]?.windSpeedInKph}
/>
</td>
</TableRow>
);
}
65 changes: 9 additions & 56 deletions src/features/rap/Table.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import { css } from "@emotion/react";
import styled from "@emotion/styled";
import { useAppDispatch, useAppSelector } from "../../hooks";
import Altitude from "./cells/Altitude";
import Temperature from "./cells/Temperature";
import WindDirection from "./cells/WindDirection";
import WindSpeed from "./cells/WindSpeed";
import { headerText } from "./CinCape";
import { WindsAloftAltitude, WindsAloftHour } from "../../models/WindsAloft";
import {
Expand All @@ -22,6 +17,7 @@ import { toggleAltitude } from "../user/userSlice";
import { toggleAltitudeType } from "../../helpers/locale";
import { notEmpty } from "../../helpers/array";
import Tooltip from "../../shared/Tooltip";
import Row from "./Row";

const TableEl = styled.table`
width: 100%;
Expand All @@ -35,14 +31,6 @@ const TableEl = styled.table`
}
`;

const Row = styled.tr<{ opaque: boolean }>`
${({ opaque }) =>
opaque &&
css`
opacity: 0.5;
`}
`;

const InteractTh = styled.th`
cursor: pointer;
`;
Expand Down Expand Up @@ -148,10 +136,6 @@ export default function Table({
surfaceLevel,
]);

function negativeAltitude(datum: WindsAloftAltitude): boolean {
return !!(datum.altitudeInM - surfaceLevel < 0);
}

return (
<TableEl>
<thead>
Expand Down Expand Up @@ -182,45 +166,14 @@ export default function Table({

<tbody>
{displayedRapData.map((datum, index) => (
<Row key={index} opaque={negativeAltitude(datum)}>
<td>
<Altitude
heightInMeters={datum.altitudeInM}
surfaceLevelInMeters={surfaceLevel}
pressure={datum.pressure}
/>
</td>
<td>
<Temperature
temperature={datum.temperatureInC}
dewpoint={datum.dewpointInC}
lapseRate={
displayedRapData[index - 1]
? -(
(datum.temperatureInC -
displayedRapData[index - 1].temperatureInC) /
(datum.altitudeInM -
displayedRapData[index - 1].altitudeInM)
)
: undefined
}
pressure={datum.pressure}
hour={new Date(windsAloftHour.date)}
/>
</td>
<td>
<WindDirection
curr={datum.windDirectionInDeg}
prev={displayedRapData[index - 1]?.windDirectionInDeg}
/>
</td>
<td>
<WindSpeed
curr={datum.windSpeedInKph}
prev={displayedRapData[index - 1]?.windSpeedInKph}
/>
</td>
</Row>
<Row
key={index}
datum={datum}
index={index}
surfaceLevel={surfaceLevel}
windsAloftHour={windsAloftHour}
displayedRapData={displayedRapData}
/>
))}
</tbody>
</TableEl>
Expand Down
14 changes: 10 additions & 4 deletions src/features/rap/cells/WindDirection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,27 @@ const Container = styled.div<{ shear: boolean }>`
interface WindDirectionProps {
curr: number;
prev?: number;
shearEligible: boolean;
}

export default function WindDirection({ curr, prev }: WindDirectionProps) {
export default function WindDirection({
curr,
prev,
shearEligible,
}: WindDirectionProps) {
const content = useMemo(() => {
return (
<Container
shear={
Math.abs(getAngleDifference(curr, prev === undefined ? curr : prev)) >
25
!!shearEligible &&
!!prev &&
Math.abs(getAngleDifference(curr, prev)) > 25
}
>
{Math.round(curr)} <WindIndicator direction={curr} />
</Container>
);
}, [curr, prev]);
}, [curr, prev, shearEligible]);

return content;
}
Expand Down
23 changes: 23 additions & 0 deletions src/helpers/vector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
export function vectorDifferenceMagnitude(
speed1: number,
direction1: number,
speed2: number,
direction2: number,
): number {
// Convert directions from degrees to radians
const radian1 = (Math.PI / 180) * direction1;
const radian2 = (Math.PI / 180) * direction2;

// Convert polar coordinates to Cartesian coordinates
const x1 = speed1 * Math.cos(radian1);
const y1 = speed1 * Math.sin(radian1);
const x2 = speed2 * Math.cos(radian2);
const y2 = speed2 * Math.sin(radian2);

// Calculate the difference in Cartesian coordinates
const dx = x2 - x1;
const dy = y2 - y1;

// Calculate the magnitude of the difference vector
return Math.sqrt(dx * dx + dy * dy);
}

0 comments on commit 10438db

Please sign in to comment.