Sign In

@squawk/procedures

Package Overview
Dependencies
Maintainers
1
Versions
20
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@squawk/procedures - npm Package Compare versions

Comparing version
0.6.0
to
0.7.0
+89
dist/leg-geometry.d.ts
/**
* Drawable geometry extraction for expanded instrument-procedure leg
* sequences. Walks the ordered {@link ProcedureLeg} array returned by
* {@link ProcedureResolver.expand} into the subset of legs that terminate at
* a known fix and exposes that sequence both as plain
* {@link ProcedureLegPoint} values and as a GeoJSON `LineString` for map
* rendering.
*
* Many ARINC 424 path terminators end at an altitude, DME distance, radial,
* intercept, or manual event rather than at a fix (for example `CA`, `FA`,
* `VA`, `CD`, `FD`, `VD`, `CR`, `VR`, `CI`, `VI`, `FM`, `VM`, and the `HA` /
* `HM` holds). Those legs carry no `lat` / `lon` and therefore contribute no
* point, so a path drawn through the result is not a precise flyable track:
* it omits the non-positional legs and breaks across them.
*/
import type { LineString } from 'geojson';
import type { ProcedureLeg } from '@squawk/types';
/**
* A single drawable geographic point along an expanded procedure, in leg
* order.
*/
export interface ProcedureLegPoint {
/** Fix identifier at the leg termination. */
label: string;
/** Latitude in decimal degrees, positive north. */
lat: number;
/** Longitude in decimal degrees, positive east. */
lon: number;
}
/**
* Extracts the ordered sequence of drawable geographic points from an
* expanded procedure leg sequence (the `legs` array of a
* {@link ProcedureExpansionResult}).
*
* Only legs that terminate at a known fix contribute a point: a leg is
* drawable when it carries a `fixIdentifier`, `lat`, and `lon`. Legs whose
* path terminator ends at an altitude, DME distance, radial, intercept, or
* manual event (`CA`, `FA`, `VA`, `CD`, `FD`, `VD`, `CR`, `VR`, `CI`, `VI`,
* `FM`, `VM`, and the `HA` / `HM` holds) have no coordinate and are skipped.
* Because a skipped leg leaves a gap, the returned points are not guaranteed
* to be contiguous: a non-positional leg in the middle of a sequence creates
* a break in any line drawn through the points, and such legs cannot be
* rendered from this data alone (they need a flyable geometry computed from
* the aircraft state, navaid, or altitude).
*
* Consecutive duplicate points (within a small epsilon) are suppressed, so a
* hold or fix repeated back-to-back yields a single point.
*
* ```typescript
* import { createProcedureResolver, extractLegPoints } from '@squawk/procedures';
*
* const resolver = createProcedureResolver({ data: procedures });
* const expansion = resolver.expand('KDEN', 'AALLE4');
* const points = expansion ? extractLegPoints(expansion.legs) : [];
* ```
*
* @param legs - Ordered procedure legs, e.g. `expand(...).legs`.
* @returns Ordered drawable points along the procedure.
*/
export declare function extractLegPoints(legs: ProcedureLeg[]): ProcedureLegPoint[];
/**
* Builds a GeoJSON `LineString` from an expanded procedure leg sequence,
* ready to render as a polyline on a map (e.g. MapLibre, Leaflet).
*
* Coordinates follow the GeoJSON `[lon, lat]` ordering. Returns `undefined`
* when the legs yield fewer than two drawable points, since a `LineString`
* requires at least two positions to be valid.
*
* Non-positional legs are skipped (see {@link extractLegPoints}), so the
* line connects only the fix-terminated legs in order. When a procedure
* mixes positional and non-positional legs the line is an approximation that
* omits the non-drawable segments rather than a precise flyable track.
*
* ```typescript
* import { createProcedureResolver, expansionToLineString } from '@squawk/procedures';
*
* const resolver = createProcedureResolver({ data: procedures });
* const expansion = resolver.expand('KDEN', 'AALLE4');
* const line = expansion ? expansionToLineString(expansion.legs) : undefined;
* if (line) {
* map.addSource('procedure', { type: 'geojson', data: line });
* }
* ```
*
* @param legs - Ordered procedure legs, e.g. `expand(...).legs`.
* @returns A GeoJSON `LineString`, or `undefined` if fewer than two points.
*/
export declare function expansionToLineString(legs: ProcedureLeg[]): LineString | undefined;
//# sourceMappingURL=leg-geometry.d.ts.map
{"version":3,"file":"leg-geometry.d.ts","sourceRoot":"","sources":["../src/leg-geometry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,6CAA6C;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,mDAAmD;IACnD,GAAG,EAAE,MAAM,CAAC;IACZ,mDAAmD;IACnD,GAAG,EAAE,MAAM,CAAC;CACb;AAYD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,YAAY,EAAE,GAAG,iBAAiB,EAAE,CAa1E;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,YAAY,EAAE,GAAG,UAAU,GAAG,SAAS,CASlF"}
/**
* Drawable geometry extraction for expanded instrument-procedure leg
* sequences. Walks the ordered {@link ProcedureLeg} array returned by
* {@link ProcedureResolver.expand} into the subset of legs that terminate at
* a known fix and exposes that sequence both as plain
* {@link ProcedureLegPoint} values and as a GeoJSON `LineString` for map
* rendering.
*
* Many ARINC 424 path terminators end at an altitude, DME distance, radial,
* intercept, or manual event rather than at a fix (for example `CA`, `FA`,
* `VA`, `CD`, `FD`, `VD`, `CR`, `VR`, `CI`, `VI`, `FM`, `VM`, and the `HA` /
* `HM` holds). Those legs carry no `lat` / `lon` and therefore contribute no
* point, so a path drawn through the result is not a precise flyable track:
* it omits the non-positional legs and breaks across them.
*/
/** Epsilon for comparing coordinates to detect duplicate points. */
const COORD_EPSILON = 1e-9;
/**
* Returns true if two points share the same coordinates (within epsilon).
*/
function samePosition(a, b) {
return Math.abs(a.lat - b.lat) < COORD_EPSILON && Math.abs(a.lon - b.lon) < COORD_EPSILON;
}
/**
* Extracts the ordered sequence of drawable geographic points from an
* expanded procedure leg sequence (the `legs` array of a
* {@link ProcedureExpansionResult}).
*
* Only legs that terminate at a known fix contribute a point: a leg is
* drawable when it carries a `fixIdentifier`, `lat`, and `lon`. Legs whose
* path terminator ends at an altitude, DME distance, radial, intercept, or
* manual event (`CA`, `FA`, `VA`, `CD`, `FD`, `VD`, `CR`, `VR`, `CI`, `VI`,
* `FM`, `VM`, and the `HA` / `HM` holds) have no coordinate and are skipped.
* Because a skipped leg leaves a gap, the returned points are not guaranteed
* to be contiguous: a non-positional leg in the middle of a sequence creates
* a break in any line drawn through the points, and such legs cannot be
* rendered from this data alone (they need a flyable geometry computed from
* the aircraft state, navaid, or altitude).
*
* Consecutive duplicate points (within a small epsilon) are suppressed, so a
* hold or fix repeated back-to-back yields a single point.
*
* ```typescript
* import { createProcedureResolver, extractLegPoints } from '@squawk/procedures';
*
* const resolver = createProcedureResolver({ data: procedures });
* const expansion = resolver.expand('KDEN', 'AALLE4');
* const points = expansion ? extractLegPoints(expansion.legs) : [];
* ```
*
* @param legs - Ordered procedure legs, e.g. `expand(...).legs`.
* @returns Ordered drawable points along the procedure.
*/
export function extractLegPoints(legs) {
const points = [];
for (const leg of legs) {
if (leg.fixIdentifier === undefined || leg.lat === undefined || leg.lon === undefined) {
continue;
}
const point = { label: leg.fixIdentifier, lat: leg.lat, lon: leg.lon };
if (points.length > 0 && samePosition(points[points.length - 1], point)) {
continue;
}
points.push(point);
}
return points;
}
/**
* Builds a GeoJSON `LineString` from an expanded procedure leg sequence,
* ready to render as a polyline on a map (e.g. MapLibre, Leaflet).
*
* Coordinates follow the GeoJSON `[lon, lat]` ordering. Returns `undefined`
* when the legs yield fewer than two drawable points, since a `LineString`
* requires at least two positions to be valid.
*
* Non-positional legs are skipped (see {@link extractLegPoints}), so the
* line connects only the fix-terminated legs in order. When a procedure
* mixes positional and non-positional legs the line is an approximation that
* omits the non-drawable segments rather than a precise flyable track.
*
* ```typescript
* import { createProcedureResolver, expansionToLineString } from '@squawk/procedures';
*
* const resolver = createProcedureResolver({ data: procedures });
* const expansion = resolver.expand('KDEN', 'AALLE4');
* const line = expansion ? expansionToLineString(expansion.legs) : undefined;
* if (line) {
* map.addSource('procedure', { type: 'geojson', data: line });
* }
* ```
*
* @param legs - Ordered procedure legs, e.g. `expand(...).legs`.
* @returns A GeoJSON `LineString`, or `undefined` if fewer than two points.
*/
export function expansionToLineString(legs) {
const points = extractLegPoints(legs);
if (points.length < 2) {
return undefined;
}
return {
type: 'LineString',
coordinates: points.map((p) => [p.lon, p.lat]),
};
}
+2
-0

@@ -9,2 +9,4 @@ /**

export type { ProcedureResolver, ProcedureResolverOptions, ProcedureExpansionResult, ProcedureSearchField, ProcedureSearchQuery, ProcedureSearchResult, } from './resolver.js';
export { extractLegPoints, expansionToLineString } from './leg-geometry.js';
export type { ProcedureLegPoint } from './leg-geometry.js';
//# sourceMappingURL=index.d.ts.map
+1
-1

@@ -1,1 +0,1 @@

{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,YAAY,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACxD,YAAY,EACV,iBAAiB,EACjB,wBAAwB,EACxB,wBAAwB,EACxB,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,eAAe,CAAC"}
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,YAAY,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACxD,YAAY,EACV,iBAAiB,EACjB,wBAAwB,EACxB,wBAAwB,EACxB,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC5E,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC"}
export { createProcedureResolver } from './resolver.js';
export { extractLegPoints, expansionToLineString } from './leg-geometry.js';
{
"name": "@squawk/procedures",
"version": "0.6.0",
"version": "0.7.0",
"type": "module",

@@ -45,3 +45,4 @@ "description": "Instrument procedure lookup and expansion for SIDs, STARs, and Instrument Approach Procedures (IAPs)",

"@squawk/search": "^0.1.0",
"@squawk/types": "^0.8.0"
"@squawk/types": "^0.8.0",
"@types/geojson": "^7946.0.16"
},

@@ -48,0 +49,0 @@ "devDependencies": {

@@ -19,3 +19,7 @@ <h1><img src="../../../assets/squawk-logo.svg" alt="squawk logo" width="48" height="48" style="vertical-align: middle">&nbsp; @squawk/procedures</h1>

import { usBundledProcedures } from '@squawk/procedure-data';
import { createProcedureResolver } from '@squawk/procedures';
import {
createProcedureResolver,
expansionToLineString,
extractLegPoints,
} from '@squawk/procedures';

@@ -55,2 +59,9 @@ const resolver = createProcedureResolver({ data: usBundledProcedures.records });

console.log(results[0]?.procedure.identifier, results[0]?.score);
// Turn an expansion into renderable map geometry (non-positional legs are skipped)
if (withTransition) {
const points = extractLegPoints(withTransition.legs);
const line = expansionToLineString(withTransition.legs);
// `line` is a GeoJSON LineString, or undefined when fewer than two fixes are drawable
}
```

@@ -175,1 +186,22 @@

```
### `extractLegPoints(legs)`
Extracts the ordered drawable points from an expanded leg sequence (the `legs`
array of a `ProcedureExpansionResult`). Only legs that terminate at a known fix
contribute a point; legs whose ARINC 424 path terminator ends at an altitude,
DME distance, radial, intercept, or manual event (`CA`, `FA`, `VA`, `CD`, `FD`,
`VD`, `CR`, `VR`, `CI`, `VI`, `FM`, `VM`, and the `HA`/`HM` holds) carry no
coordinate and are skipped, so a non-positional leg in the middle of a sequence
leaves a gap. Consecutive duplicate points are suppressed. Returns
`ProcedureLegPoint[]`, each with `label`, `lat`, and `lon`.
### `expansionToLineString(legs)`
Builds a GeoJSON `LineString` from an expanded leg sequence, ready to render as a
polyline on a map (for example MapLibre or Leaflet). Coordinates follow the
GeoJSON `[lon, lat]` ordering. Because non-positional legs are skipped (see
`extractLegPoints`), the line connects only the fix-terminated legs and is an
approximation that omits the non-drawable segments rather than a precise flyable
track. Returns `LineString | undefined` - `undefined` when the legs yield fewer
than two drawable points, since a `LineString` requires at least two positions.