diff --git a/src/features/rap/Row.tsx b/src/features/rap/Row.tsx
new file mode 100644
index 0000000..bf08c33
--- /dev/null
+++ b/src/features/rap/Row.tsx
@@ -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 (
+
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+ |
+
+ );
+}
diff --git a/src/features/rap/Table.tsx b/src/features/rap/Table.tsx
index a3cb4ea..a4336d8 100644
--- a/src/features/rap/Table.tsx
+++ b/src/features/rap/Table.tsx
@@ -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 {
@@ -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%;
@@ -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;
`;
@@ -148,10 +136,6 @@ export default function Table({
surfaceLevel,
]);
- function negativeAltitude(datum: WindsAloftAltitude): boolean {
- return !!(datum.altitudeInM - surfaceLevel < 0);
- }
-
return (
@@ -182,45 +166,14 @@ export default function Table({
{displayedRapData.map((datum, index) => (
-
-
-
- |
-
-
- |
-
-
- |
-
-
- |
-
+
))}
diff --git a/src/features/rap/cells/WindDirection.tsx b/src/features/rap/cells/WindDirection.tsx
index b0a4ae4..fe0dc1f 100644
--- a/src/features/rap/cells/WindDirection.tsx
+++ b/src/features/rap/cells/WindDirection.tsx
@@ -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 (
- 25
+ !!shearEligible &&
+ !!prev &&
+ Math.abs(getAngleDifference(curr, prev)) > 25
}
>
{Math.round(curr)}
);
- }, [curr, prev]);
+ }, [curr, prev, shearEligible]);
return content;
}
diff --git a/src/helpers/vector.ts b/src/helpers/vector.ts
new file mode 100644
index 0000000..11feac3
--- /dev/null
+++ b/src/helpers/vector.ts
@@ -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);
+}