import computeDestinationPoint from 'geolib/es/computeDestinationPoint'; import getGreatCircleBearing from 'geolib/es/getGreatCircleBearing'; import Parser from '../parser'; import { computeIntersection } from '../utils/computeIntersection'; import { computeSpeed } from '../utils/computeSpeed'; import { computeTurnRate } from '../utils/computeTurnRate'; import { getCourseAndFixForIntercepts } from '../utils/getCourseAndFixForIntercepts'; export const TerminatorsCI = ( leg: CITerminalEntry, nextLeg: TerminalEntry, previousFix: NavFix, lastCourse: number ): [NavFix?, LineSegment[]?] => { const speed = computeSpeed(leg, previousFix); const crsIntoEndpoint = leg.Course.toTrue(previousFix); const [crsToIntercept, nextFix] = getCourseAndFixForIntercepts(nextLeg, previousFix); const line: LineSegment[] = [[previousFix.longitude, previousFix.latitude]]; // Compute overfly arc if (previousFix.isFlyOver && !lastCourse.equal(crsIntoEndpoint)) { const turnRate = computeTurnRate(speed, Parser.AC_BANK); const updatedCrsToIntercept = getGreatCircleBearing(previousFix, nextFix); // Turn Dir if (!leg.TurnDir || leg.TurnDir === 'E') { let prov = lastCourse - crsIntoEndpoint; prov = prov > 180 ? prov - 360 : prov <= -180 ? prov + 360 : prov; leg.TurnDir = prov > 0 ? 'L' : 'R'; } // Generate arc while (!lastCourse.equal(crsIntoEndpoint) && !updatedCrsToIntercept.equal(crsToIntercept)) { let time = 0; if (leg.TurnDir === 'R') { const delta = (crsIntoEndpoint - lastCourse).normaliseDegrees(); const increment = delta < 0.1 ? delta : 0.1; lastCourse = (lastCourse + increment).normaliseDegrees(); time = increment / turnRate; } else { const delta = (lastCourse - crsIntoEndpoint).normaliseDegrees(); const increment = delta < 0.1 ? delta : 0.1; lastCourse = (lastCourse - increment).normaliseDegrees(); time = increment / turnRate; } const arcFix = computeDestinationPoint( { latitude: line.at(-1)![1], longitude: line.at(-1)![0], }, ((speed / 3600) * time).toMetre(), lastCourse ); line.push([arcFix.longitude, arcFix.latitude]); // Update previousFix previousFix.latitude = arcFix.latitude; previousFix.longitude = arcFix.longitude; } } const interceptFix: NavFix = { ...computeIntersection(previousFix, leg.Course.toTrue(nextFix), nextFix, crsToIntercept)!, isFlyOver: leg.IsFlyOver, altitude: leg.Alt ? leg.Alt.parseAltitude() : previousFix.altitude, speed: speed, speedConstraint: leg.SpeedLimit, altitudeConstraint: leg.Alt, IsFAF: leg.IsFAF, IsMAP: leg.IsMAP, }; line.push([interceptFix.longitude, interceptFix.latitude]); return [interceptFix, line]; };