diff --git a/TODO.md b/TODO.md index e1c6495..e69de29 100644 --- a/TODO.md +++ b/TODO.md @@ -1,2 +0,0 @@ -- Revisit CA/FA/VA legs -- Revisit CD/FD/VD/FC legs \ No newline at end of file diff --git a/browser/src/parser/node.ts b/browser/src/parser/node.ts index 39d7f14..7248e6a 100644 --- a/browser/src/parser/node.ts +++ b/browser/src/parser/node.ts @@ -14,4 +14,4 @@ fetch = async (path: string) => { const parser = await Parser.instance(); -console.log(JSON.stringify(await parser.parse(10657))); +console.log(JSON.stringify(await parser.parse(10480))); diff --git a/browser/src/parser/pathGenerators/generateTangentArc.ts b/browser/src/parser/pathGenerators/generateTangentArc.ts index bc42ae1..a6d73e7 100644 --- a/browser/src/parser/pathGenerators/generateTangentArc.ts +++ b/browser/src/parser/pathGenerators/generateTangentArc.ts @@ -19,7 +19,7 @@ export const generateTangentArc = ( const line: LineSegment[] = [[start.longitude, start.latitude]]; // Check if there even is an arc - if (crsFromOrigin !== crsIntoEndpoint) { + if (!crsFromOrigin.equal(crsIntoEndpoint)) { // Course to the end of the arc let crsFromStartToEnd; if (!turnDir || turnDir === "E") { @@ -75,7 +75,7 @@ export const generateTangentArc = ( crsOrthogonalOnOrigin < 1 ? crsOrthogonalOnOrigin : 1; } - while (crsOrthogonalOnOrigin !== crsOrthogonalOnEndpoint) { + while (!crsOrthogonalOnOrigin.equal(crsOrthogonalOnEndpoint)) { if (turnDir === "R") { const delta = ( crsOrthogonalOnEndpoint - crsOrthogonalOnOrigin diff --git a/browser/src/parser/pathGenerators/handleTurnAtFix.ts b/browser/src/parser/pathGenerators/handleTurnAtFix.ts index 7845816..9f6878a 100644 --- a/browser/src/parser/pathGenerators/handleTurnAtFix.ts +++ b/browser/src/parser/pathGenerators/handleTurnAtFix.ts @@ -1,7 +1,6 @@ import * as geolib from "geolib"; import { generateTangentArc } from "./generateTangentArc.ts"; import { generatePerformanceArc } from "./generatePerformanceArc.ts"; -import Parser from "../parser.ts"; /** * @param crsIntoEndpoint Course into endpoint @@ -9,6 +8,7 @@ import Parser from "../parser.ts"; * @param crsFromOrigin Course from arc origin point * @param start Waypoint where leg starts * @param end Waypoint where leg ends + * @param speed Speed for performance arc * @param turnDir Turn direction * @returns Line segments from `start` to `end` */ @@ -18,6 +18,7 @@ export const handleTurnAtFix = ( crsFromOrigin: number, start: NavFix, end: NavFix, + speed: number, turnDir?: TurnDirection ) => { const line: LineSegment[] = []; @@ -36,7 +37,7 @@ export const handleTurnAtFix = ( crsIntoIntercept, crsFromOrigin, start, - start.speed ? start.speed : Parser.AC_SPEED, + speed, turnDir ); diff --git a/browser/src/parser/terminators/CA.ts b/browser/src/parser/terminators/CA.ts index fb6ac9b..ce127dc 100644 --- a/browser/src/parser/terminators/CA.ts +++ b/browser/src/parser/terminators/CA.ts @@ -1,39 +1,59 @@ import * as geolib from "geolib"; -import { handleTurnAtFix } from "../pathGenerators/handleTurnAtFix.ts"; import Parser from "../parser.ts"; import { computeSpeed } from "../utils/computeSpeed.ts"; +import { generatePerformanceArc } from "../pathGenerators/generatePerformanceArc.ts"; export const TerminatorsCA = ( leg: CATerminalEntry, previousFix: NavFix, lastCourse: number ): [NavFix?, LineSegment[]?] => { + const speed = computeSpeed(leg, previousFix); + const crsIntoEndpoint = leg.Course.toTrue(previousFix); + + let line: LineSegment[] = []; + if (previousFix.isFlyOver) { + line = generatePerformanceArc( + crsIntoEndpoint, + lastCourse, + previousFix, + speed, + leg.TurnDir + ); + } else { + line.push([previousFix.longitude, previousFix.latitude]); + } + + const arcEnd = { latitude: line.at(-1)![1], longitude: line.at(-1)![0] }; + if (line.length > 1) { + lastCourse = geolib.getGreatCircleBearing( + { + latitude: line.at(-2)![1], + longitude: line.at(-2)![0], + }, + arcEnd + ); + } + const targetFix: NavFix = { ...geolib.computeDestinationPoint( - previousFix, + arcEnd, ( ((leg.Alt.parseAltitude() - (previousFix.altitude ?? 0)) / Parser.AC_VS) * ((previousFix.speed ? previousFix.speed : Parser.AC_SPEED) / 60) ).toMetre(), - leg.Course.toTrue(previousFix) + crsIntoEndpoint ), name: leg.Alt, isFlyOver: true, - altitude: leg.Alt.parseAltitude(), + altitude: leg.Alt ? leg.Alt.parseAltitude() : previousFix.altitude, speed: computeSpeed(leg, previousFix), speedConstraint: leg.SpeedLimit, altitudeConstraint: leg.Alt, }; - const line = handleTurnAtFix( - leg.Course.toTrue(previousFix), - leg.Course.toTrue(previousFix), - lastCourse, - previousFix, - targetFix, - leg.TurnDir - ); + line.push([targetFix.longitude, targetFix.latitude]); return [targetFix, line]; }; diff --git a/browser/src/parser/terminators/CD.ts b/browser/src/parser/terminators/CD.ts index d73f20b..259d3b1 100644 --- a/browser/src/parser/terminators/CD.ts +++ b/browser/src/parser/terminators/CD.ts @@ -49,7 +49,9 @@ export const TerminatorsCD = ( } // Navaid in front of us else { - remainingDistance = distToNavaid - remainingDistance; + // Navaid will not be passed before distance is hit + if (distToNavaid > remainingDistance) + remainingDistance = distToNavaid - remainingDistance; } const targetFix: NavFix = { ...geolib.computeDestinationPoint(arcEnd, remainingDistance, lastCourse), diff --git a/browser/src/parser/terminators/CF.ts b/browser/src/parser/terminators/CF.ts index a3b1b92..cf4e776 100644 --- a/browser/src/parser/terminators/CF.ts +++ b/browser/src/parser/terminators/CF.ts @@ -7,6 +7,8 @@ export const TerminatorsCF = ( lastCourse: number, waypoint?: Waypoint ): [NavFix?, LineSegment[]?] => { + const speed = computeSpeed(leg, previousFix); + const targetFix: NavFix = { latitude: leg.WptLat, longitude: leg.WptLon, @@ -24,6 +26,7 @@ export const TerminatorsCF = ( lastCourse, previousFix, targetFix, + speed, leg.TurnDir ); diff --git a/browser/src/parser/terminators/CI.ts b/browser/src/parser/terminators/CI.ts index b1623e8..5a9e4d0 100644 --- a/browser/src/parser/terminators/CI.ts +++ b/browser/src/parser/terminators/CI.ts @@ -10,6 +10,7 @@ export const TerminatorsCI = ( lastCourse: number ): [NavFix?, LineSegment[]?] => { const [crs, nextFix] = getCourseAndFixForIntercepts(nextLeg, previousFix); + const speed = computeSpeed(leg, previousFix); // Compute INTC const interceptFix: NavFix = { @@ -32,6 +33,7 @@ export const TerminatorsCI = ( lastCourse, previousFix, interceptFix, + speed, leg.TurnDir ); diff --git a/browser/src/parser/terminators/CR.ts b/browser/src/parser/terminators/CR.ts index 511ad4b..7d4b8de 100644 --- a/browser/src/parser/terminators/CR.ts +++ b/browser/src/parser/terminators/CR.ts @@ -8,6 +8,7 @@ export const TerminatorsCR = ( lastCourse: number ): [NavFix?, LineSegment[]?] => { const crsIntoEndpoint = leg.Course.toTrue(previousFix); + const speed = computeSpeed(leg, previousFix); const interceptFix: NavFix = { ...computeIntersection( @@ -29,6 +30,7 @@ export const TerminatorsCR = ( lastCourse, previousFix, interceptFix, + speed, leg.TurnDir ); diff --git a/browser/src/parser/terminators/FA.ts b/browser/src/parser/terminators/FA.ts index 00ad68b..7497591 100644 --- a/browser/src/parser/terminators/FA.ts +++ b/browser/src/parser/terminators/FA.ts @@ -1,22 +1,53 @@ import * as geolib from "geolib"; -import { handleTurnAtFix } from "../pathGenerators/handleTurnAtFix.ts"; import { computeSpeed } from "../utils/computeSpeed.ts"; import Parser from "../parser.ts"; +import { generatePerformanceArc } from "../pathGenerators/generatePerformanceArc.ts"; export const TerminatorsFA = ( leg: FATerminalEntry, previousFix: NavFix, lastCourse: number ): [NavFix?, LineSegment[]?] => { + const refFix = { + latitude: leg.WptLat, + longitude: leg.WptLon, + }; + const speed = computeSpeed(leg, previousFix); + const crsIntoEndpoint = leg.Course.toTrue(refFix); + + let line: LineSegment[] = []; + if (previousFix.isFlyOver) { + line = generatePerformanceArc( + crsIntoEndpoint, + lastCourse, + previousFix, + speed, + leg.TurnDir + ); + } else { + line.push([previousFix.longitude, previousFix.latitude]); + } + + const arcEnd = { latitude: line.at(-1)![1], longitude: line.at(-1)![0] }; + if (line.length > 1) { + lastCourse = geolib.getGreatCircleBearing( + { + latitude: line.at(-2)![1], + longitude: line.at(-2)![0], + }, + arcEnd + ); + } + const targetFix: NavFix = { ...geolib.computeDestinationPoint( - { latitude: leg.WptLat, longitude: leg.WptLon }, + arcEnd, ( ((leg.Alt.parseAltitude() - (previousFix.altitude ?? 0)) / Parser.AC_VS) * ((previousFix.speed ? previousFix.speed : Parser.AC_SPEED) / 60) ).toMetre(), - leg.Course.toTrue(previousFix) + crsIntoEndpoint ), name: leg.Alt, isFlyOver: true, @@ -26,14 +57,7 @@ export const TerminatorsFA = ( altitudeConstraint: leg.Alt, }; - const line = handleTurnAtFix( - leg.Course.toTrue(previousFix), - leg.Course.toTrue(previousFix), - lastCourse, - previousFix, - targetFix, - leg.TurnDir - ); + line.push([targetFix.longitude, targetFix.latitude]); return [targetFix, line]; }; diff --git a/browser/src/parser/terminators/FD.ts b/browser/src/parser/terminators/FD.ts index 2702210..4d686ca 100644 --- a/browser/src/parser/terminators/FD.ts +++ b/browser/src/parser/terminators/FD.ts @@ -53,7 +53,9 @@ export const TerminatorsFD = ( } // Navaid in front of us else { - remainingDistance = distToNavaid - remainingDistance; + // Navaid will not be passed before distance is hit + if (distToNavaid > remainingDistance) + remainingDistance = distToNavaid - remainingDistance; } const targetFix: NavFix = { ...geolib.computeDestinationPoint(arcEnd, remainingDistance, lastCourse), diff --git a/browser/src/parser/terminators/FM.ts b/browser/src/parser/terminators/FM.ts index b43b8ff..b6d3a22 100644 --- a/browser/src/parser/terminators/FM.ts +++ b/browser/src/parser/terminators/FM.ts @@ -1,11 +1,14 @@ import * as geolib from "geolib"; import { handleTurnAtFix } from "../pathGenerators/handleTurnAtFix.ts"; +import { computeSpeed } from "../utils/computeSpeed.ts"; export const TerminatorsFM = ( leg: FMTerminalEntry, previousFix: NavFix, lastCourse: number ): [NavFix?, LineSegment[]?] => { + const speed = computeSpeed(leg, previousFix); + const endpoint = geolib.computeDestinationPoint( previousFix, (10).toMetre(), @@ -18,6 +21,7 @@ export const TerminatorsFM = ( lastCourse, previousFix, endpoint, + speed, leg.TurnDir ); diff --git a/browser/src/parser/terminators/VA.ts b/browser/src/parser/terminators/VA.ts index 8e9a3f8..32f0e73 100644 --- a/browser/src/parser/terminators/VA.ts +++ b/browser/src/parser/terminators/VA.ts @@ -1,7 +1,7 @@ import * as geolib from "geolib"; -import { handleTurnAtFix } from "../pathGenerators/handleTurnAtFix.ts"; import Parser from "../parser.ts"; import { computeSpeed } from "../utils/computeSpeed.ts"; +import { generatePerformanceArc } from "../pathGenerators/generatePerformanceArc.ts"; // NOTE: No wind adjustments to be made, no clue how *that* would draw export const TerminatorsVA = ( @@ -9,32 +9,52 @@ export const TerminatorsVA = ( previousFix: NavFix, lastCourse: number ): [NavFix?, LineSegment[]?] => { + const speed = computeSpeed(leg, previousFix); + const crsIntoEndpoint = leg.Course.toTrue(previousFix); + + let line: LineSegment[] = []; + if (previousFix.isFlyOver) { + line = generatePerformanceArc( + crsIntoEndpoint, + lastCourse, + previousFix, + speed, + leg.TurnDir + ); + } else { + line.push([previousFix.longitude, previousFix.latitude]); + } + + const arcEnd = { latitude: line.at(-1)![1], longitude: line.at(-1)![0] }; + if (line.length > 1) { + lastCourse = geolib.getGreatCircleBearing( + { + latitude: line.at(-2)![1], + longitude: line.at(-2)![0], + }, + arcEnd + ); + } + const targetFix: NavFix = { ...geolib.computeDestinationPoint( - previousFix, + arcEnd, ( ((leg.Alt.parseAltitude() - (previousFix.altitude ?? 0)) / Parser.AC_VS) * ((previousFix.speed ? previousFix.speed : Parser.AC_SPEED) / 60) ).toMetre(), - leg.Course.toTrue(previousFix) + crsIntoEndpoint ), name: leg.Alt, isFlyOver: true, - altitude: leg.Alt.parseAltitude(), + altitude: leg.Alt ? leg.Alt.parseAltitude() : previousFix.altitude, speed: computeSpeed(leg, previousFix), speedConstraint: leg.SpeedLimit, altitudeConstraint: leg.Alt, }; - const line = handleTurnAtFix( - leg.Course.toTrue(previousFix), - leg.Course.toTrue(previousFix), - lastCourse, - previousFix, - targetFix, - leg.TurnDir - ); + line.push([targetFix.longitude, targetFix.latitude]); return [targetFix, line]; }; diff --git a/browser/src/parser/terminators/VD.ts b/browser/src/parser/terminators/VD.ts index e706abc..f8c8afc 100644 --- a/browser/src/parser/terminators/VD.ts +++ b/browser/src/parser/terminators/VD.ts @@ -50,7 +50,9 @@ export const TerminatorsVD = ( } // Navaid in front of us else { - remainingDistance = distToNavaid - remainingDistance; + // Navaid will not be passed before distance is hit + if (distToNavaid > remainingDistance) + remainingDistance = distToNavaid - remainingDistance; } const targetFix: NavFix = { ...geolib.computeDestinationPoint(arcEnd, remainingDistance, lastCourse), diff --git a/browser/src/parser/terminators/VI.ts b/browser/src/parser/terminators/VI.ts index 6e8d2b2..141865f 100644 --- a/browser/src/parser/terminators/VI.ts +++ b/browser/src/parser/terminators/VI.ts @@ -11,6 +11,7 @@ export const TerminatorsVI = ( lastCourse: number ): [NavFix?, LineSegment[]?] => { const [crs, nextFix] = getCourseAndFixForIntercepts(nextLeg, previousFix); + const speed = computeSpeed(leg, previousFix); // Compute INTC const interceptFix: NavFix = { @@ -33,6 +34,7 @@ export const TerminatorsVI = ( lastCourse, previousFix, interceptFix, + speed, leg.TurnDir ); diff --git a/browser/src/parser/terminators/VM.ts b/browser/src/parser/terminators/VM.ts index def8fc0..0082dab 100644 --- a/browser/src/parser/terminators/VM.ts +++ b/browser/src/parser/terminators/VM.ts @@ -1,5 +1,6 @@ import * as geolib from "geolib"; import { handleTurnAtFix } from "../pathGenerators/handleTurnAtFix.ts"; +import { computeSpeed } from "../utils/computeSpeed.ts"; // NOTE: No wind adjustments to be made, no clue how *that* would draw export const TerminatorsVM = ( @@ -7,6 +8,8 @@ export const TerminatorsVM = ( previousFix: NavFix, lastCourse: number ): [NavFix?, LineSegment[]?] => { + const speed = computeSpeed(leg, previousFix); + const endpoint = geolib.computeDestinationPoint( previousFix, (10).toMetre(), @@ -19,6 +22,7 @@ export const TerminatorsVM = ( lastCourse, previousFix, endpoint, + speed, leg.TurnDir ); diff --git a/browser/src/parser/utils/extensions.ts b/browser/src/parser/utils/extensions.ts index 163c1a1..fdddfed 100644 --- a/browser/src/parser/utils/extensions.ts +++ b/browser/src/parser/utils/extensions.ts @@ -38,7 +38,7 @@ String.prototype.parseAltitude = function () { case 12: { const upper = Number.parseInt(this.substring(0, 5)); const lower = Number.parseInt(this.substring(6, 12)); - return (upper - lower) / 2; + return lower + (upper - lower) / 2; } default: return -1;