UNPKG

flight-planner

Version:

Plan and route VFR flights

109 lines (108 loc) 3.84 kB
import { degreesToRadians, radiansToDegrees } from '@turf/turf'; /** * Calculates the wind vector relative to the given true track. * * @param wind - An object representing the wind, containing direction and speed. * @param trueTrack - The current true track in degrees. * @returns An object containing the wind angle, headwind, and crosswind components. */ export function calculateWindVector(wind, trueTrack) { const windAngle = wind.direction - trueTrack; const windAngleRad = degreesToRadians(windAngle); const cosAngle = Math.cos(windAngleRad); const sinAngle = Math.sin(windAngleRad); const headwind = wind.speed * cosAngle; const crosswind = wind.speed * sinAngle; return { angle: windAngle, headwind: headwind, crosswind: crosswind, }; } /** * Calculates the wind correction angle for the given wind, true track, and airspeed. * * @param wind - An object representing the wind, containing direction and speed. * @param trueTrack - The true track in degrees. * @param airSpeed - The airspeed in knots. * @returns The wind correction angle in degrees. */ export function calculateWindCorrectionAngle(wind, trueTrack, airSpeed) { // Formula: WCA = arcsin((wind.speed * sin(wind angle)) / airSpeed) // const windAngleRad = degreesToRadians(wind.direction - trueTrack); // const wcaRad = Math.asin((wind.speed * Math.sin(windAngleRad)) / airSpeed); // return radiansToDegrees(wcaRad); const windVector = calculateWindVector(wind, trueTrack); const wca = radiansToDegrees(windVector.crosswind / airSpeed); return windVector.angle > 0 ? -wca : wca; // Positive windAngle means wind from the right } /** * Calculates the groundspeed for the given wind, airspeed, and heading. * * @param wind - An object representing the wind, containing degrees and speed. * @param airSpeed - The airspeed in knots. * @param heading - The heading in degrees. * @returns The groundspeed in knots. */ export function calculateGroundspeed(wind, airSpeed, heading) { const windVector = calculateWindVector(wind, heading); const groundspeedSquared = Math.pow(airSpeed, 2) + Math.pow(wind.speed, 2) - 2 * airSpeed * windVector.headwind; return Math.sqrt(groundspeedSquared); } /** * Checks if the given string is a valid ICAO code. * * @param icao - The string to check * @returns True if the string is a valid ICAO code, false otherwise */ export const isICAO = (icao) => { return /^[A-Z]{4}$/.test(icao.toUpperCase()); }; /** * Normalizes the given ICAO code to uppercase. * * @param icao - The ICAO code to normalize * @returns The normalized ICAO code */ export const normalizeICAO = (icao) => { return icao.toUpperCase(); }; /** * Checks if the given string is a valid IATA code. * * @param iata - The string to check * @returns True if the string is a valid IATA code, false otherwise */ export const isIATA = (iata) => { return /^[A-Z]{3}$/.test(iata.toUpperCase()); }; /** * Normalizes the given IATA code to uppercase. * * @param iata - The IATA code to normalize * @returns The normalized IATA code */ export const normalizeIATA = (iata) => { return iata.toUpperCase(); }; /** * Normalizes the given track angle to a value between 0 and 360 degrees. * * @param track - The track angle to normalize * @returns The normalized track angle */ export const normalizeTrack = (track) => { return ((track % 360) + 360) % 360; }; /** * Capitalizes the first letter of each word in a string * * @param text - The input text to capitalize * @returns The text with the first letter of each word capitalized */ export const capitalizeWords = (text) => { return text.toLowerCase() .split(' ') .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) .join(' '); };