79 lines
2.8 KiB
TypeScript
79 lines
2.8 KiB
TypeScript
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];
|
|
};
|