flight-planner
Version:
Plan and route VFR flights
109 lines (108 loc) • 3.84 kB
JavaScript
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(' ');
};