feat(map): enhance globe projection handling and improve altitude color representation (#14)

* feat(map): enhance globe projection handling and improve altitude color representation

- Implemented elevation-aware pixel projection for globe mode in `projectLngLatElevationPixelDelta`.
- Refactored north-up animation in `CameraController` to use `setBearing` for smoother transitions.
- Added native GeoJSON support for globe zoom in `FlightLayers`, including dynamic opacity adjustments based on zoom levels.
- Introduced globe-specific pitch and projection settings in `Map` component, ensuring consistent rendering.
- Enhanced UI control panel with a visual separator for better organization.
- Minor formatting adjustments in `altitudeToColor` function for improved readability.

* feat(map): refactor elevation-aware projection handling for improved accuracy

* feat(map): add dark terrain profile support and enhance map styling

* feat: implement trail stitching for merging historical and live flight data

- Added a new module `trail-stitching.ts` to handle the merging of sparse historical track data with high-frequency live trail data.
- Introduced constants for thresholds and parameters to improve code readability and maintainability.
- Implemented a main function `stitchHistoricalTrail` that processes flight tracks, applies smoothing, and merges live tail data.
- Included utility functions for spherical interpolation and cubic easing for altitude transitions.
- Ensured the final path is cleaned of spikes and sharp corners for a smoother representation.

* feat: add centripetal Catmull-Rom spline interpolation for 3D flight trails

- Implemented `catmullRomSpline3D` function to interpolate waypoints into a smooth 3D path.
- Added helper functions for segment density calculation, safe linear interpolation, and endpoint reflection.
- Included support for variable tension based on heading changes to enhance smoothness.
- Introduced utility functions for linear interpolation between elevated points.

* feat(map): enhance layer visibility handling for flight and selection layers

* feat: enhance control panel with new tabs and settings

- Added "Changelog" and "About" tabs to the control panel.
- Introduced new icons for the added tabs using lucide-react.
- Updated the styling of the control panel buttons and dialog.
- Improved accessibility with aria-labels for buttons.

feat: integrate hero banner in flight card

- Added a HeroBanner component to display aircraft photos in the FlightCard.
- Implemented loading and error states for the photo display.
- Enhanced the layout and styling of the FlightCard for better user experience.

fix: update keyboard shortcuts for search functionality

- Added shortcut "⌘K" to open search from anywhere in the application.
- Adjusted keyboard shortcut handling to prevent conflicts with input fields.

fix: optimize flight tracking cache management

- Introduced a maximum cache size for flight tracking to prevent memory growth.
- Implemented a cache eviction strategy for stale entries.

feat: add great-circle utilities for geographical calculations

- Implemented functions for calculating haversine distance, great-circle interpolation, and densifying paths.
- Added functionality to handle antimeridian crossings in geographical paths.

refactor: streamline map styles and terrain handling

- Consolidated terrain DEM source for both terrain mesh and hillshade.
- Adjusted hillshade layer properties for better performance and visual fidelity.

fix: improve bounding box calculations for flight queries

- Enhanced longitude calculations to account for converging meridians at higher latitudes.
- Ensured bounding box calculations are accurate across different latitudes.

* feat(map): refine globe mode functionality and update trail settings
This commit is contained in:
kew
2026-03-11 00:54:51 +05:30
committed by GitHub
parent 3a10da0486
commit 147b69b944
49 changed files with 8662 additions and 3927 deletions

104
src/lib/opensky-types.ts Normal file
View File

@ -0,0 +1,104 @@
/** @see https://openskynetwork.github.io/opensky-api/rest.html */
// ── API Constants ──────────────────────────────────────────────────────
export const OPENSKY_API = "https://opensky-network.org/api";
export const FETCH_TIMEOUT_MS = 15_000;
export const ICAO24_REGEX = /^[0-9a-f]{6}$/i;
/** Callsign lookup scans global /states/all (4 credits); cache longer to reduce spikes. */
export const CALLSIGN_CACHE_TTL_MS = 2 * 60_000;
export const CALLSIGN_CACHE_MAX_ENTRIES = 200;
/** Keep bbox queries inside OpenSky's 025 sq-deg (1 credit) tier. */
export const MAX_1_CREDIT_RADIUS_DEG = 2.49;
/** Delay between sequential segment fetches to avoid burst rate limits. */
export const SEGMENT_DELAY_MS = 200;
// ── Exported Types ─────────────────────────────────────────────────────
export type FlightState = {
icao24: string;
callsign: string | null;
originCountry: string;
longitude: number | null;
latitude: number | null;
baroAltitude: number | null;
onGround: boolean;
velocity: number | null;
trueTrack: number | null;
verticalRate: number | null;
geoAltitude: number | null;
squawk: string | null;
spiFlag: boolean;
positionSource: number;
category: number | null;
};
export type FetchResult = {
flights: FlightState[];
rateLimited: boolean;
creditsRemaining: number | null;
retryAfterSeconds: number | null;
};
export type TrackWaypoint = {
time: number;
latitude: number | null;
longitude: number | null;
baroAltitude: number | null;
trueTrack: number | null;
onGround: boolean;
};
export type FlightTrack = {
icao24: string;
startTime: number;
endTime: number;
callsign: string | null;
path: TrackWaypoint[];
};
export type TrackFetchResult = {
track: FlightTrack | null;
rateLimited: boolean;
creditsRemaining: number | null;
retryAfterSeconds: number | null;
};
// ── Internal Types (used across sub-modules) ───────────────────────────
export type OpenSkyResponse = {
time: number;
states: (string | number | boolean | null)[][] | null;
};
export type ParseStateOptions = {
includeGround?: boolean;
requireBaroAltitude?: boolean;
};
export type RateLimitInfo = {
creditsRemaining: number | null;
retryAfterSeconds: number | null;
};
export type CallsignLookupResult = {
flight: FlightState | null;
creditsRemaining: number | null;
rateLimited: boolean;
retryAfterSeconds: number | null;
};
export type OpenSkyTrackResponse = {
icao24?: unknown;
startTime?: unknown;
endTime?: unknown;
callsign?: unknown;
// Defensive: accept a misspelled field name if present.
calllsign?: unknown;
path?: unknown;
};
// ── Shared Utilities ───────────────────────────────────────────────────
export const clamp = (value: number, min: number, max: number) =>
Math.min(Math.max(value, min), max);