UNPKG

flight-planner

Version:

Plan and route VFR flights

177 lines (176 loc) 6.71 kB
import { calculateWindVector } from './utils'; import { bearing, bearingToAzimuth, distance } from "@turf/turf"; /** * Represents a waypoint in the flight planning system * * A waypoint is a specified geographical location used for navigation purposes. * It can be associated with a METAR weather observation station. * * @example * ```typescript * const location: WaypointLocation = { lat: 37.62, lng: -122.38 }; * const sfo = new Waypoint("KSFO", location); * ``` */ export class Waypoint { name; location; metarStation; /** * @param name The name of the waypoint * @param location The location of the waypoint * @returns An instance of the Waypoint class */ constructor(name, location) { this.name = name; this.location = location; } /** * Returns a string representation of the waypoint. * * @returns A string representation of the waypoint */ toString() { return `${this.name}`; } /** * Calculates the distance to the given waypoint. * * @param waypoint The waypoint to calculate the distance to * @returns The distance in nautical miles */ getDistanceTo(waypoint) { const distanceInKm = distance(this.location, waypoint.location); const distanceInNm = distanceInKm * 0.539957; // TODO: Move to constants return distanceInNm; } /** * Calculates the heading to the given waypoint. * * @param waypoint The waypoint to calculate the heading to * @returns The heading in degrees */ getHeadingTo(waypoint) { const bearingValue = bearing(this.location, waypoint.location); return bearingToAzimuth(bearingValue); } } /** * Represents a reporting point in the flight plan. * A reporting point is a waypoint that may be required for the flight. * * @extends Waypoint */ export class ReportingPoint extends Waypoint { required; /** * @param name The name of the reporting point * @param location The location of the reporting point * @param required Whether the reporting point is required * @returns An instance of the ReportingPoint class */ constructor(name, location, required = false) { super(name, location); this.required = required; } } /** * Enum representing various types of airport radio frequencies. * * @enum {number} * @readonly */ export var FrequencyType; (function (FrequencyType) { FrequencyType[FrequencyType["Approach"] = 0] = "Approach"; FrequencyType[FrequencyType["APRON"] = 1] = "APRON"; FrequencyType[FrequencyType["Arrival"] = 2] = "Arrival"; FrequencyType[FrequencyType["Center"] = 3] = "Center"; FrequencyType[FrequencyType["CTAF"] = 4] = "CTAF"; FrequencyType[FrequencyType["Delivery"] = 5] = "Delivery"; FrequencyType[FrequencyType["Departure"] = 6] = "Departure"; FrequencyType[FrequencyType["FIS"] = 7] = "FIS"; FrequencyType[FrequencyType["Gliding"] = 8] = "Gliding"; FrequencyType[FrequencyType["Ground"] = 9] = "Ground"; FrequencyType[FrequencyType["Information"] = 10] = "Information"; FrequencyType[FrequencyType["Multicom"] = 11] = "Multicom"; FrequencyType[FrequencyType["Unicom"] = 12] = "Unicom"; FrequencyType[FrequencyType["Radar"] = 13] = "Radar"; FrequencyType[FrequencyType["Tower"] = 14] = "Tower"; FrequencyType[FrequencyType["ATIS"] = 15] = "ATIS"; FrequencyType[FrequencyType["Radio"] = 16] = "Radio"; FrequencyType[FrequencyType["Other"] = 17] = "Other"; FrequencyType[FrequencyType["AIRMET"] = 18] = "AIRMET"; FrequencyType[FrequencyType["AWOS"] = 19] = "AWOS"; FrequencyType[FrequencyType["Lights"] = 20] = "Lights"; FrequencyType[FrequencyType["VOLMET"] = 21] = "VOLMET"; FrequencyType[FrequencyType["AFIS"] = 22] = "AFIS"; })(FrequencyType || (FrequencyType = {})); /** * Defines the various types of aerodromes. * * @enum {number} * @readonly */ export var AerodromeType; (function (AerodromeType) { AerodromeType[AerodromeType["Airport"] = 0] = "Airport"; AerodromeType[AerodromeType["GliderSite"] = 1] = "GliderSite"; AerodromeType[AerodromeType["AirfieldCivil"] = 2] = "AirfieldCivil"; AerodromeType[AerodromeType["InternationalAirport"] = 3] = "InternationalAirport"; AerodromeType[AerodromeType["HeliportMilitary"] = 4] = "HeliportMilitary"; AerodromeType[AerodromeType["MilitaryAerodrome"] = 5] = "MilitaryAerodrome"; AerodromeType[AerodromeType["UltraLightFlyingSite"] = 6] = "UltraLightFlyingSite"; AerodromeType[AerodromeType["HeliportCivil"] = 7] = "HeliportCivil"; AerodromeType[AerodromeType["AerodromeClosed"] = 8] = "AerodromeClosed"; AerodromeType[AerodromeType["AirportIFR"] = 9] = "AirportIFR"; AerodromeType[AerodromeType["AirfieldWater"] = 10] = "AirfieldWater"; AerodromeType[AerodromeType["LandingStrip"] = 11] = "LandingStrip"; AerodromeType[AerodromeType["AgriculturalLandingStrip"] = 12] = "AgriculturalLandingStrip"; AerodromeType[AerodromeType["Altiport"] = 13] = "Altiport"; })(AerodromeType || (AerodromeType = {})); export class Aerodrome extends Waypoint { ICAO; runways; frequencies; /** * @param name The name of the airport * @param ICAO The ICAO code of the airport * @param location The location of the airport * @param runways The runways of the airport * @param frequencies The frequencies of the airport * @returns An instance of the Airport class */ constructor(name, ICAO, location, runways, options) { super(name, location); this.ICAO = ICAO; this.runways = runways; this.frequencies = options?.frequencies || []; } /** * Returns a string representation of the airport. * * @returns A string representation of the airport */ toString() { return `${this.name} (${this.ICAO})`; } /** * Calculates the wind vectors for all runways of the airport. * * @returns The wind vectors for the runways in descending order of headwind */ runwayWind() { const windDirection = this.metarStation?.metarData.windDirection ?? 0; const windSpeed = this.metarStation?.metarData.windSpeed ?? 0; return this.runways.map(runway => { const windVector = calculateWindVector({ direction: windDirection, speed: windSpeed }, runway.heading); return { runway, windAngle: windVector.angle, headwind: windVector.headwind, crosswind: windVector.crosswind, }; }).sort((a, b) => b.headwind - a.headwind); } }