Skip to content

Commit

Permalink
feat(navdata): allow airports to be used as fixes (#9792)
Browse files Browse the repository at this point in the history
* feat(navdata): allow airports to be used as fixes

Needed for some procedures e.g. the EWR5 transitions.

* fix(navdata): load airport as fix in 2020

* fix(navdata): add airport to fix type

* fix: automatic import... need to fix tsconfig
  • Loading branch information
tracernz authored Jan 25, 2025
1 parent 106db2c commit b080929
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 6 deletions.
1 change: 1 addition & 0 deletions .github/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@
1. [A380X/MFD] Fix wrong Landing weight calculation & block fuel not editable across flights in FUEL & LOAD - @BravoMike99 (bruno_pt99)
1. [A32NX/FMS] Add terminal area database holds for MSFS2024 - @tracernz (Mike)
1. [EFB] Set EFB Auto Brightness to default to On - @MrJigs7 (MrJigs)
1. [FMS] Allow airport to be loaded as fixes in instrument procedures - @tracernz (Mike)

## 0.12.0

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2021, 2022 FlyByWire Simulations
// Copyright (c) 2021, 2022, 2025 FlyByWire Simulations
// SPDX-License-Identifier: GPL-3.0

/* eslint-disable camelcase */
Expand All @@ -19,8 +19,10 @@ import {
JS_FacilityIntersection,
JS_FacilityNDB,
JS_FacilityVOR,
JS_Leg,
} from './FsTypes';
import { Airport, NdbNavaid, VhfNavaid, Waypoint } from '../../../shared';
import { isMsfs2024 } from '../../../../shared/src/MsfsDetect';

// @microsoft/msfs-sdk does not export this, so we declare it
declare class CoherentNearestSearchSession implements NearestSearchSession<string, string> {
Expand Down Expand Up @@ -232,7 +234,7 @@ export class FacilityCache {

private insert(key: string, facility: JS_Facility): void {
if (this.facilityCache.size > FacilityCache.cacheSize - 1) {
const oldestKey: string = this.facilityCache.keys().next().value;
const oldestKey: string = this.facilityCache.keys().next().value!;
this.facilityCache.delete(oldestKey);
}
this.facilityCache.set(key, facility);
Expand All @@ -246,6 +248,56 @@ export class FacilityCache {
return icao.substring(7).trim();
}

private static readonly AIRPORT_REGION_REGEX = /^A[A-Z0-9]{2}/;
private static readonly AIRPORT_REGION_REPLACE = 'A ';

/** Removes the region code from any airport ICAOs in an array of procedure legs. */
private static fixupLegAirportRegions(legs: JS_Leg[]): void {
for (const leg of legs) {
leg.fixIcao = leg.fixIcao.replace(FacilityCache.AIRPORT_REGION_REGEX, FacilityCache.AIRPORT_REGION_REPLACE);
leg.originIcao = leg.originIcao.replace(FacilityCache.AIRPORT_REGION_REGEX, FacilityCache.AIRPORT_REGION_REPLACE);
leg.arcCenterFixIcao = leg.arcCenterFixIcao.replace(
FacilityCache.AIRPORT_REGION_REGEX,
FacilityCache.AIRPORT_REGION_REPLACE,
);
}
}

/**
* Fix up airport ICAOs to a format that MSFS2020 can understand and load.
* Note: this is **not** required for MSFS2024.
* @param airport The airport facility to fix up.
*/
private static fixupAirportRegions(airport: JS_FacilityAirport): void {
for (const appr of airport.approaches) {
for (const trans of appr.transitions) {
FacilityCache.fixupLegAirportRegions(trans.legs);
}
FacilityCache.fixupLegAirportRegions(appr.finalLegs);
FacilityCache.fixupLegAirportRegions(appr.missedLegs);
}

for (const sid of airport.departures) {
for (const trans of sid.runwayTransitions) {
FacilityCache.fixupLegAirportRegions(trans.legs);
}
FacilityCache.fixupLegAirportRegions(sid.commonLegs);
for (const trans of sid.enRouteTransitions) {
FacilityCache.fixupLegAirportRegions(trans.legs);
}
}

for (const star of airport.arrivals) {
for (const trans of star.enRouteTransitions) {
FacilityCache.fixupLegAirportRegions(trans.legs);
}
FacilityCache.fixupLegAirportRegions(star.commonLegs);
for (const trans of star.runwayTransitions) {
FacilityCache.fixupLegAirportRegions(trans.legs);
}
}
}

private receiveFacility(facility: JS_Facility): void {
let loadType: LoadType;
switch (facility.icao.charAt(0)) {
Expand All @@ -270,6 +322,10 @@ export class FacilityCache {
this.addToAirwayCache(facility as any as JS_FacilityIntersection);
}

if (!isMsfs2024() && loadType === LoadType.Airport) {
FacilityCache.fixupAirportRegions(facility as JS_FacilityAirport);
}

const key = FacilityCache.key(facility.icao, loadType);
this.insert(key, facility);
}
Expand Down
18 changes: 15 additions & 3 deletions fbw-common/src/systems/navdata/client/backends/Msfs/Mapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ type FacilityType<T> = T extends JS_FacilityIntersection
? NdbNavaid
: T extends JS_FacilityVOR
? VhfNavaid
: never;
: T extends JS_FacilityAirport
? Airport
: never;

export class MsfsMapping {
private static readonly letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
Expand Down Expand Up @@ -148,11 +150,15 @@ export class MsfsMapping {
? Math.round(msAirport.transitionLevel / 30.48)
: undefined;

const ident = this.mapAirportIdent(msAirport);

return {
databaseId: msAirport.icao,
sectionCode: SectionCode.Airport,
subSectionCode: AirportSubsectionCode.ReferencePoints,
ident: this.mapAirportIdent(msAirport),
area: WaypointArea.Terminal,
ident,
airportIdent: ident, // needed for terminal fix
icaoCode: msAirport.icao.substring(1, 3), // TODO
name: Utils.Translate(msAirport.name),
location: { lat: msAirport.lat, long: msAirport.lon, alt: elevation },
Expand Down Expand Up @@ -936,6 +942,10 @@ export class MsfsMapping {

const icaos = Array.from(icaoSet);

const airports = await this.cache.getFacilities(
icaos.filter((icao) => icao.charAt(0) === 'A'),
LoadType.Airport,
);
const vors = await this.cache.getFacilities(
icaos.filter((icao) => icao.charAt(0) === 'V'),
LoadType.Vor,
Expand All @@ -949,7 +959,7 @@ export class MsfsMapping {
LoadType.Intersection,
);

return new Map<string, JS_Facility>([...wps, ...ndbs, ...vors]);
return new Map<string, JS_Facility>([...wps, ...ndbs, ...vors, ...airports]);
}

private mapApproachTransitions(
Expand Down Expand Up @@ -1290,6 +1300,8 @@ export class MsfsMapping {
class: this.mapVorClass(vor),
} as unknown as FacilityType<T>;
}
case 'A':
return this.mapAirport(facility as JS_FacilityAirport) as FacilityType<T>;
case 'W':
default:
return {
Expand Down
5 changes: 5 additions & 0 deletions fbw-common/src/systems/navdata/shared/types/Airport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Feet, Metres, NauticalMiles } from 'msfs-geo';
import { DatabaseItem, Knots, FlightLevel, ElevatedCoordinates } from './Common';
import { RunwaySurfaceType } from './Runway';
import { AirportSubsectionCode, SectionCode } from './SectionCode';
import { WaypointArea } from './Waypoint';

export interface Airport extends DatabaseItem<SectionCode.Airport> {
subSectionCode: AirportSubsectionCode.ReferencePoints;
Expand Down Expand Up @@ -43,4 +44,8 @@ export interface Airport extends DatabaseItem<SectionCode.Airport> {
* Distance from centre location for nearby airport query
*/
distance?: NauticalMiles;

// These two are needed to satisfy the terminal fix interface, for use as procedure fix.
area: WaypointArea.Terminal;
airportIdent: string;
}
3 changes: 2 additions & 1 deletion fbw-common/src/systems/navdata/shared/types/BaseFix.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { VhfNavaid } from './VhfNavaid';
import { SectionCode } from './SectionCode';
import { Waypoint, WaypointArea } from './Waypoint';
import { NdbNavaid } from './NdbNavaid';
import { Airport } from './Airport';

export interface BaseFix<T extends SectionCode> extends DatabaseItem<T> {
location: Coordinates;
Expand All @@ -14,7 +15,7 @@ export interface BaseFix<T extends SectionCode> extends DatabaseItem<T> {
/**
* Union of all possible fix interfaces
*/
export type Fix = VhfNavaid | NdbNavaid | Waypoint;
export type Fix = Airport | NdbNavaid | VhfNavaid | Waypoint;

export function isFix(o: any): o is Fix {
return typeof o === 'object' && 'location' in o && 'databaseId' in o;
Expand Down

0 comments on commit b080929

Please sign in to comment.