diff --git a/README.md b/README.md index e6a23c8..b49ff74 100644 --- a/README.md +++ b/README.md @@ -707,4 +707,23 @@ This intercept point then becomes the origin fix of the succeeding leg. # Other Fields -- `Vnav`: Angle from IAF to MAP. Useful for RNAV. \ No newline at end of file +- `Vnav`: Angle from IAF to MAP. Useful for RNAV. + + +# How to run + +- `git clone https://git.hofmannnet.myhome-server.de/TFDi_MD-11_QA/NavDataExplorer.git`. +- `cd md11-nav-data`. +- `pnpm install` + +For dev: + +- Copy contents of `tfdidesign-aircraft-md11/Design/Primary` into ? `md11-nav-data/public/NavData` +- `cd md11-nav-data`. +- `pnpm dev` + +For prod: + +- `cd md11-nav-data`. +- `pnpm build` +- Verify Navdata was copied into `dist` \ No newline at end of file diff --git a/md11-nav-data/src/App.tsx b/md11-nav-data/src/App.tsx index fa5645f..dae8a06 100644 --- a/md11-nav-data/src/App.tsx +++ b/md11-nav-data/src/App.tsx @@ -80,11 +80,11 @@ function App() { setSelectedAirport={setSelectedAirport} setSelectedRunway={setSelectedRunway} setSelectedTerminal={setSelectedTerminal} - handleSelection={(selectedTransitions) => { + handleSelection={(selectedTransitions, _terminal) => { let _transitions = selectedTransitions .map((transition) => ({ name: transition, - data: parser.parse(selectedRunway!, transition), + data: parser.parse(selectedRunway!, _terminal, transition), })) .filter( (transition) => diff --git a/md11-nav-data/src/components/ProcedureSelect.tsx b/md11-nav-data/src/components/ProcedureSelect.tsx index 8742f95..ef3fb32 100644 --- a/md11-nav-data/src/components/ProcedureSelect.tsx +++ b/md11-nav-data/src/components/ProcedureSelect.tsx @@ -11,7 +11,7 @@ interface ProcedureSelectProps { setSelectedAirport: Dispatch>; setSelectedRunway: Dispatch>; setSelectedTerminal: Dispatch>; - handleSelection: (transitions: string[]) => void; + handleSelection: (transitions: string[], terminal: Terminal) => void; } export const ProcedureSelect: FC = ({ @@ -125,7 +125,7 @@ export const ProcedureSelect: FC = ({ parser.loadTerminal(terminal.ID).then(() => { setSelectedTerminal(terminal); const transitions = new Set(parser.procedures.map((proc) => proc.Transition)); - handleSelection(Array.from(transitions)); + handleSelection(Array.from(transitions), terminal); setInFlight(undefined); }); }} @@ -148,7 +148,7 @@ export const ProcedureSelect: FC = ({ parser.loadTerminal(terminal.ID).then(() => { setSelectedTerminal(terminal); const transitions = new Set(parser.procedures.map((proc) => proc.Transition)); - handleSelection(Array.from(transitions)); + handleSelection(Array.from(transitions), terminal); }); }} disabled={!!inFlight} @@ -170,7 +170,7 @@ export const ProcedureSelect: FC = ({ parser.loadTerminal(terminal.ID).then(() => { setSelectedTerminal(terminal); const transitions = new Set(parser.procedures.map((proc) => proc.Transition)); - handleSelection(Array.from(transitions)); + handleSelection(Array.from(transitions), terminal); }); }} disabled={!!inFlight} diff --git a/md11-nav-data/src/parser/parser.ts b/md11-nav-data/src/parser/parser.ts index b61e3af..4a1d8a4 100644 --- a/md11-nav-data/src/parser/parser.ts +++ b/md11-nav-data/src/parser/parser.ts @@ -88,7 +88,7 @@ class Parser { ).json()) as TerminalEntry[]; }; - public parse = (runway: Runway, transition: string) => { + public parse = (runway: Runway, terminal: Terminal, transition: string) => { // Private functions /** * @param line Line segments @@ -123,15 +123,19 @@ class Parser { const navFixes: NavFix[] = []; const lineSegments: { line: LineSegment[]; [x: string]: unknown }[] = []; - // Initials - navFixes.push({ - latitude: runway.Latitude, - longitude: runway.Longitude, - altitude: runway.Elevation, - speed: 0, - name: runway.Ident, - }); - let lastCourse = runway.TrueHeading; + let lastCourse = 0; + + // RWY as origin for Departures + if (terminal.Proc === 2) { + navFixes.push({ + latitude: runway.Latitude, + longitude: runway.Longitude, + altitude: runway.Elevation, + speed: 0, + name: runway.Ident, + }); + lastCourse = runway.TrueHeading; + } const legOptions = { isMAP: false }; const procedure = this._procedures.filter( ({ Transition }) => !Transition || Transition === transition || Transition === 'ALL' @@ -143,9 +147,28 @@ class Parser { const leg = procedure[index]; leg.Alt = leg.IsMAP ? String(runway.Elevation + 200).padStart(5, '0') : leg.Alt; + + const waypoint = this.waypoints.find(({ ID }) => ID === leg.WptID); + + if (terminal.Proc !== 2 && navFixes.length === 0) { + if (!leg.WptLat || !leg.WptLon) + throw new Error('Non departure procedure has first leg that has no defined starting point. Cannot render.'); + + navFixes.push({ + latitude: leg.WptLat, + longitude: leg.WptLon, + altitude: leg.Alt ? leg.Alt.parseAltitude() : runway.Elevation, + speed: leg.SpeedLimit ? leg.SpeedLimit : Parser.AC_SPEED, + name: waypoint?.Ident, + speedConstraint: leg.SpeedLimit, + altitudeConstraint: leg.Alt, + IsFAF: leg.IsFAF, + IsMAP: leg.IsMAP, + }); + } + const previousFix = navFixes.at(-1)!; legOptions.isMAP ||= previousFix.IsMAP ?? false; - const waypoint = this.waypoints.find(({ ID }) => ID === leg.WptID); switch (leg.TrackCode) { case 'AF': { diff --git a/md11-nav-data/src/parser/terminators/FD.ts b/md11-nav-data/src/parser/terminators/FD.ts index 8b94420..27a6fce 100644 --- a/md11-nav-data/src/parser/terminators/FD.ts +++ b/md11-nav-data/src/parser/terminators/FD.ts @@ -41,7 +41,7 @@ export const TerminatorsFD = ( // Compute intercept of crs from arc end and distance const targetFix: NavFix = { - ...computeDestinationPoint(arcEnd, remainingDistance, lastCourse), + ...computeDestinationPoint(arcEnd, remainingDistance, crsIntoEndpoint), name: leg.Distance.toString(), isFlyOver: true, altitude: leg.Alt ? leg.Alt.parseAltitude() : previousFix.altitude,