MagDec and Loading indicator for parser
This commit is contained in:
parent
4e4b921f79
commit
e9bab0306f
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@ -9,7 +9,7 @@
|
||||
"request": "launch",
|
||||
"name": "Launch Chrome against localhost",
|
||||
"url": "http://localhost:3000",
|
||||
"webRoot": "${workspaceFolder}/browser",
|
||||
"webRoot": "${workspaceFolder}/md11-nav-data",
|
||||
"sourceMaps": true
|
||||
}
|
||||
]
|
||||
|
||||
@ -726,4 +726,4 @@ For prod:
|
||||
|
||||
- `cd md11-nav-data`.
|
||||
- `pnpm build`
|
||||
- Verify Navdata was copied into `dist`
|
||||
- Verify NavData was copied into `dist`
|
||||
@ -16,7 +16,6 @@
|
||||
"geolib": "^3.3.4",
|
||||
"leaflet": "^1.9.4",
|
||||
"leaflet-svg-shape-markers": "^1.4.0",
|
||||
"magvar": "^2.0.0",
|
||||
"navigraph": "^1.4.1",
|
||||
"qrcode.react": "^4.2.0",
|
||||
"react": "^19.1.0",
|
||||
|
||||
8
md11-nav-data/pnpm-lock.yaml
generated
8
md11-nav-data/pnpm-lock.yaml
generated
@ -23,9 +23,6 @@ importers:
|
||||
leaflet-svg-shape-markers:
|
||||
specifier: ^1.4.0
|
||||
version: 1.4.0
|
||||
magvar:
|
||||
specifier: ^2.0.0
|
||||
version: 2.0.0
|
||||
navigraph:
|
||||
specifier: ^1.4.1
|
||||
version: 1.4.1
|
||||
@ -1102,9 +1099,6 @@ packages:
|
||||
magic-string@0.30.17:
|
||||
resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==}
|
||||
|
||||
magvar@2.0.0:
|
||||
resolution: {integrity: sha512-00LpSwEJZcnyX3VsdCM2CHSCvB+M6sVQTawLCB3J9oK7eEueNltNx9GFL4YR+/HIkLM+l8rFKiY77JTKnOf0jw==}
|
||||
|
||||
merge2@1.4.1:
|
||||
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
|
||||
engines: {node: '>= 8'}
|
||||
@ -2339,8 +2333,6 @@ snapshots:
|
||||
dependencies:
|
||||
'@jridgewell/sourcemap-codec': 1.5.4
|
||||
|
||||
magvar@2.0.0: {}
|
||||
|
||||
merge2@1.4.1: {}
|
||||
|
||||
micromatch@4.0.8:
|
||||
|
||||
1
md11-nav-data/public/NavData/README.MD
Normal file
1
md11-nav-data/public/NavData/README.MD
Normal file
@ -0,0 +1 @@
|
||||
Copy over contents of `Data/Primary` retaining the structure.
|
||||
BIN
md11-nav-data/public/NavData/magdec.bgl
Normal file
BIN
md11-nav-data/public/NavData/magdec.bgl
Normal file
Binary file not shown.
@ -1,15 +1,15 @@
|
||||
import type { DeviceFlowParams } from 'navigraph/auth';
|
||||
import { QRCodeSVG } from 'qrcode.react';
|
||||
import { useState } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { ProcedureSelect } from './components//ProcedureSelect';
|
||||
import { Loader } from './components/Loader';
|
||||
import { Map } from './components/Map';
|
||||
import { Sidebar } from './components/Sidebar';
|
||||
import { useNavigraphAuth } from './contexts/NavigraphAuth/NavigraphAuthContext';
|
||||
import Parser from './parser/parser';
|
||||
|
||||
const parser = await Parser.instance();
|
||||
|
||||
function App() {
|
||||
const [parser, setParser] = useState<Parser>();
|
||||
const [selectedAirport, setSelectedAirport] = useState<Airport>();
|
||||
const [selectedRunway, setSelectedRunway] = useState<Runway>();
|
||||
const [selectedTerminal, setSelectedTerminal] = useState<Terminal>();
|
||||
@ -22,13 +22,29 @@ function App() {
|
||||
|
||||
const handleSignIn = () => signIn((p) => setParams(p));
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
setParser(await Parser.instance());
|
||||
})();
|
||||
}, []);
|
||||
|
||||
if (!parser || !initialized) {
|
||||
return (
|
||||
<div className="flex min-h-dvh w-full">
|
||||
<div className="flex h-dvh w-dvw flex-col items-center justify-center gap-2">
|
||||
<Loader size={3} />
|
||||
{!parser && <span className="text-3xl">Initialising Parser...</span>}
|
||||
{!initialized && <span className="text-3xl">Initialising Navigraph SDK...</span>}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{!user ? (
|
||||
<div className="flex min-h-dvh w-full">
|
||||
{!initialized && <div>Loading...</div>}
|
||||
|
||||
{initialized && !params && !user && (
|
||||
{initialized && !params && (
|
||||
<div className="flex h-dvh w-dvw items-center justify-center">
|
||||
<button
|
||||
className="cursor-pointer rounded border border-gray-300 bg-gray-300 px-2 py-1 font-semibold focus:outline-2 focus-visible:outline-2 disabled:bg-gray-100"
|
||||
@ -39,7 +55,7 @@ function App() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{params?.verification_uri_complete && !user && (
|
||||
{params?.verification_uri_complete && (
|
||||
<div className="flex h-dvh w-dvw flex-col items-center justify-center">
|
||||
<QRCodeSVG value={params.verification_uri_complete} size={250} />
|
||||
|
||||
@ -74,6 +90,7 @@ function App() {
|
||||
/>
|
||||
) : (
|
||||
<ProcedureSelect
|
||||
parser={parser}
|
||||
selectedAirport={selectedAirport}
|
||||
selectedRunway={selectedRunway}
|
||||
selectedTerminal={selectedTerminal}
|
||||
|
||||
@ -2,9 +2,8 @@ import { createRef, useMemo, useState, type Dispatch, type FC, type SetStateActi
|
||||
import Parser from '../parser/parser';
|
||||
import { Loader } from './Loader';
|
||||
|
||||
const parser = await Parser.instance();
|
||||
|
||||
interface ProcedureSelectProps {
|
||||
parser: Parser;
|
||||
selectedAirport: Airport | undefined;
|
||||
selectedRunway: Runway | undefined;
|
||||
selectedTerminal: Terminal | undefined;
|
||||
@ -15,6 +14,7 @@ interface ProcedureSelectProps {
|
||||
}
|
||||
|
||||
export const ProcedureSelect: FC<ProcedureSelectProps> = ({
|
||||
parser,
|
||||
selectedAirport,
|
||||
selectedRunway,
|
||||
selectedTerminal,
|
||||
|
||||
@ -25,12 +25,6 @@ import { TerminatorsVM } from './terminators/VM';
|
||||
import { TerminatorsVR } from './terminators/VR';
|
||||
import './utils/extensions';
|
||||
|
||||
/*
|
||||
Runway IDs for LIED
|
||||
26156 - 34L
|
||||
26157 - 34R
|
||||
*/
|
||||
|
||||
class Parser {
|
||||
private static _instance: Parser;
|
||||
|
||||
@ -41,11 +35,19 @@ class Parser {
|
||||
|
||||
private _procedures: TerminalEntry[] = [];
|
||||
|
||||
public static MAGVAR: Uint8Array;
|
||||
public static AC_SPEED = 250;
|
||||
public static AC_BANK = 30;
|
||||
public static AC_VS = 1400;
|
||||
|
||||
private constructor(airports: Airport[], waypoints: Waypoint[], runways: Runway[], terminals: Terminal[]) {
|
||||
private constructor(
|
||||
magVar: Uint8Array,
|
||||
airports: Airport[],
|
||||
waypoints: Waypoint[],
|
||||
runways: Runway[],
|
||||
terminals: Terminal[]
|
||||
) {
|
||||
Parser.MAGVAR = magVar;
|
||||
this._airports = airports;
|
||||
this._waypoints = waypoints;
|
||||
this._runways = runways;
|
||||
@ -54,12 +56,13 @@ class Parser {
|
||||
|
||||
public static instance = async () => {
|
||||
if (!Parser._instance) {
|
||||
const magVar = await (await fetch('NavData/magdec.bgl')).bytes();
|
||||
const airports = await (await fetch('NavData/Airports.json')).json();
|
||||
const waypoints = await (await fetch('NavData/Waypoints.json')).json();
|
||||
const runways = await (await fetch('NavData/Runways.json')).json();
|
||||
const terminals = await (await fetch('NavData/Terminals.json')).json();
|
||||
|
||||
Parser._instance = new Parser(airports, waypoints, runways, terminals);
|
||||
Parser._instance = new Parser(magVar, airports, waypoints, runways, terminals);
|
||||
}
|
||||
|
||||
return Parser._instance;
|
||||
|
||||
@ -59,7 +59,7 @@ export const TerminatorsCF = (
|
||||
if (endDist <= 25 || (endCrs <= crsIntoEndpoint + 1 && endCrs >= crsIntoEndpoint - 1)) arc = arc1;
|
||||
}
|
||||
|
||||
if (previousFix.isFlyOver && (!lastCourse.equal(crsIntoEndpoint) || !lastCourse.equal(crsToIntercept))) {
|
||||
if (!arc && previousFix.isFlyOver && (!lastCourse.equal(crsIntoEndpoint) || !lastCourse.equal(crsToIntercept))) {
|
||||
const turnRate = computeTurnRate(speed, Parser.AC_BANK);
|
||||
let updatedCrsToIntercept = getGreatCircleBearing(previousFix, targetFix);
|
||||
|
||||
|
||||
@ -58,7 +58,7 @@ export const TerminatorsTF = (
|
||||
if (endDist <= 25 || (endCrs <= crsIntoEndpoint + 1 && endCrs >= crsIntoEndpoint - 1)) arc = arc1;
|
||||
}
|
||||
|
||||
if (previousFix.isFlyOver && (!lastCourse.equal(crsIntoEndpoint) || !lastCourse.equal(crsIntoEndpoint))) {
|
||||
if (!arc && previousFix.isFlyOver && (!lastCourse.equal(crsIntoEndpoint) || !lastCourse.equal(crsIntoEndpoint))) {
|
||||
const turnRate = computeTurnRate(speed, Parser.AC_BANK);
|
||||
let updatedCrsToIntercept = getGreatCircleBearing(previousFix, targetFix);
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { magvar } from 'magvar';
|
||||
import Parser from '../parser';
|
||||
|
||||
Number.prototype.toRadians = function () {
|
||||
return ((this as number) * Math.PI) / 180;
|
||||
@ -19,8 +19,42 @@ Number.prototype.normaliseDegrees = function () {
|
||||
: (this as number);
|
||||
};
|
||||
Number.prototype.toTrue = function (fix) {
|
||||
const _magvar = magvar(fix.latitude, fix.longitude); //Magvar is returned + for East
|
||||
return ((this as number) + _magvar).normaliseDegrees();
|
||||
const toOffset = (lat: number, lon: number) =>
|
||||
lon >= 0 ? lon * 362 + lat * 2 + 316 : (lon + 360) * 362 + lat * 2 + 316;
|
||||
|
||||
const magVarTable = Parser.MAGVAR;
|
||||
|
||||
const lowerLat = Math.floor(fix.latitude);
|
||||
const upperLat = Math.ceil(fix.latitude);
|
||||
const ratioLat = fix.latitude - lowerLat;
|
||||
const lowerLon = Math.floor(fix.longitude);
|
||||
const upperLon = Math.ceil(fix.longitude);
|
||||
const ratioLon = fix.longitude - lowerLon;
|
||||
|
||||
const lowerLatLowerLonOffset = toOffset(lowerLat, lowerLon);
|
||||
const lowerLatUpperLonOffset = toOffset(lowerLat, upperLon);
|
||||
const upperLatLowerLonOffset = toOffset(upperLat, lowerLon);
|
||||
const upperLatUpperLonOffset = toOffset(upperLat, upperLon);
|
||||
|
||||
let lowerLatLowerLonMagVar = (magVarTable[lowerLatLowerLonOffset + 1] << 8) + magVarTable[lowerLatLowerLonOffset];
|
||||
lowerLatLowerLonMagVar = (lowerLatLowerLonMagVar * 0x168) / 0x10000;
|
||||
lowerLatLowerLonMagVar = lowerLatLowerLonMagVar > 180 ? lowerLatLowerLonMagVar - 460 : lowerLatLowerLonMagVar;
|
||||
let lowerLatUpperLonMagVar = (magVarTable[lowerLatUpperLonOffset + 1] << 8) + magVarTable[lowerLatUpperLonOffset];
|
||||
lowerLatUpperLonMagVar = (lowerLatUpperLonMagVar * 0x168) / 0x10000;
|
||||
lowerLatUpperLonMagVar = lowerLatUpperLonMagVar > 180 ? lowerLatUpperLonMagVar - 460 : lowerLatUpperLonMagVar;
|
||||
let upperLatLowerLonMagVar = (magVarTable[upperLatLowerLonOffset + 1] << 8) + magVarTable[upperLatLowerLonOffset];
|
||||
upperLatLowerLonMagVar = (upperLatLowerLonMagVar * 0x168) / 0x10000;
|
||||
upperLatLowerLonMagVar = upperLatLowerLonMagVar > 180 ? upperLatLowerLonMagVar - 460 : upperLatLowerLonMagVar;
|
||||
let upperLatUpperLonMagVar = (magVarTable[upperLatUpperLonOffset + 1] << 8) + magVarTable[upperLatUpperLonOffset];
|
||||
upperLatUpperLonMagVar = (upperLatUpperLonMagVar * 0x168) / 0x10000;
|
||||
upperLatUpperLonMagVar = upperLatUpperLonMagVar > 180 ? upperLatUpperLonMagVar - 460 : upperLatUpperLonMagVar;
|
||||
|
||||
const lowerLatRatioLon = lowerLatLowerLonMagVar + ratioLon * (lowerLatUpperLonMagVar - lowerLatLowerLonMagVar);
|
||||
const upperLatRatioLon = upperLatLowerLonMagVar + ratioLon * (upperLatUpperLonMagVar - upperLatLowerLonMagVar);
|
||||
|
||||
const magVar = lowerLatRatioLon + ratioLat + (upperLatRatioLon - lowerLatRatioLon);
|
||||
|
||||
return ((this as number) + magVar).normaliseDegrees();
|
||||
};
|
||||
Number.prototype.toMetre = function () {
|
||||
return (this as number) * 1852.0;
|
||||
|
||||
@ -1,15 +1 @@
|
||||
@import 'tailwindcss';
|
||||
|
||||
@theme {
|
||||
--animate-fade-in-scale: fade-in-scale 0.3s ease-out;
|
||||
@keyframes fade-in-scale {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: scale(0.95);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user