@squawk/flightplan 0.6.4 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -120,15 +120,21 @@ Each element has a `type` discriminant and a `raw` field with the original token
120
120
  | Type | Description | Key fields |
121
121
  | --------------- | ----------------------------------------- | ----------------------------------------------------------- |
122
122
  | `airport` | Resolved airport (ICAO or FAA ID) | `airport` |
123
- | `sid` | Standard Instrument Departure | `procedure`, `legs` |
124
- | `star` | Standard Terminal Arrival Route | `procedure`, `legs` |
125
- | `airway` | Airway segment between entry and exit fix | `airway`, `entryFix`, `exitFix`, `waypoints` |
123
+ | `sid` | Standard Instrument Departure | `procedure`, `legs`, `transition` |
124
+ | `star` | Standard Terminal Arrival Route | `procedure`, `legs`, `transition` |
125
+ | `airway` | Airway segment between entry and exit fix | `airway`, `entryFix`, `exitFix`, `waypoints`, `gaps` |
126
126
  | `direct` | DCT (direct) indicator | - |
127
127
  | `waypoint` | Resolved fix or navaid | `fix` and/or `navaid`, `lat`, `lon` |
128
128
  | `coordinate` | Lat/lon specified in the route string | `lat`, `lon` |
129
129
  | `speedAltitude` | Speed/altitude group (e.g. N0450F350) | `speedKt`/`speedKmPerHr`/`mach`, `flightLevel`/`altitudeFt` |
130
130
  | `unresolved` | Token that could not be resolved | - |
131
131
 
132
+ An airway element's `gaps` lists any published discontinuity its expansion
133
+ crosses (the FAA discontinues some airways partway, such as J60 between JOT and
134
+ DJB). The waypoints on both sides are still returned so the route can be drawn
135
+ and measured, but a non-empty `gaps` means the route files the airway where it
136
+ is not defined and is not valid as filed.
137
+
132
138
  ### Coordinate formats
133
139
 
134
140
  - `DDMMN/DDDMMEW` (e.g. `4030N07045W` for 40 deg 30 min N, 70 deg 45 min W)
@@ -146,8 +152,24 @@ Each element has a `type` discriminant and a `raw` field with the original token
146
152
  When a token matches an airway designation and both a previous waypoint
147
153
  and a next token (exit fix) are available, the resolver expands the airway
148
154
  between those fixes. The exit fix token is consumed as part of the airway
149
- element. If expansion fails, the airway token falls through to other
150
- resolution strategies.
155
+ element. If expansion fails, the airway token is marked `unresolved` and the
156
+ exit fix token is parsed on its own.
157
+
158
+ ### Procedure handling
159
+
160
+ A token that names a SID or STAR is expanded through the procedure provider.
161
+ The dotted `PROCEDURE.TRANSITION` form (`DEEZZ6.CANDR`) merges the named
162
+ transition into the expansion. Without a dotted transition, the resolver looks
163
+ at the adjacent fix - the token after a SID, or the waypoint before a STAR -
164
+ and merges that transition when the procedure publishes one by that name,
165
+ which is how routes are usually filed (`KJFK DEEZZ6 CANDR`). Otherwise the
166
+ common route alone is expanded. The `sid` or `star` element records the merged
167
+ transition in `transition`.
168
+
169
+ A procedure that cannot be expanded is marked `unresolved`: either the dotted
170
+ transition is not one of its transitions, or the procedure has no common route
171
+ (some SIDs and STARs are published as transitions only) and no adjacent fix
172
+ names one of its transitions.
151
173
 
152
174
  ### Identifier ambiguity
153
175
 
@@ -191,7 +213,7 @@ console.log(result.totalDistanceNm, result.estimatedTimeEnrouteHrs);
191
213
 
192
214
  **Returns:** `RouteDistanceResult` with:
193
215
 
194
- - `legs` - ordered `RouteLeg` values, each with `from`/`to` point labels, their `fromLat`/`fromLon`/`toLat`/`toLon` coordinates in decimal degrees, `distanceNm`, and `cumulativeDistanceNm`
216
+ - `legs` - ordered `RouteLeg` values, each with `from`/`to` point labels, their `fromLat`/`fromLon`/`toLat`/`toLon` coordinates in decimal degrees, `distanceNm`, `cumulativeDistanceNm`, and `crossesGap`, which is true when the leg spans a published gap in the airway it came from (the leg is a straight line that counts toward the total but is not a flyable airway segment)
195
217
  - `totalDistanceNm` - total great-circle distance in nautical miles
196
218
  - `estimatedTimeEnrouteHrs` - ETE in hours, or `undefined` when no ground speed was given
197
219
  - `unresolvedElements` - route elements that could not contribute coordinates
@@ -1,4 +1,4 @@
1
- import type { Airport, Airway, AirwayWaypoint, Fix, Navaid, Procedure, ProcedureLeg } from '@squawk/types';
1
+ import type { Airport, Airway, AirwayGap, AirwayWaypoint, Fix, Navaid, Procedure, ProcedureLeg } from '@squawk/types';
2
2
  /**
3
3
  * Minimal airport lookup interface consumed by the flightplan resolver.
4
4
  * Structurally compatible with the `AirportResolver` shape in `@squawk/airports`.
@@ -46,10 +46,16 @@ export interface FlightplanFixLookup {
46
46
  export interface FlightplanAirwayLookup {
47
47
  /** Looks up airways by designation (e.g. "V16", "J60"). Returns an empty array if none found. */
48
48
  byDesignation(designation: string): Airway[];
49
- /** Expands an airway between entry and exit fixes, returning ordered waypoints. */
49
+ /**
50
+ * Expands an airway between entry and exit fixes, returning ordered
51
+ * waypoints. `gaps` lists any published discontinuity the expansion crosses;
52
+ * a lookup that cannot report gaps may omit it, and the route then reports
53
+ * none.
54
+ */
50
55
  expand(designation: string, entryFix: string, exitFix: string): {
51
56
  airway: Airway;
52
57
  waypoints: AirwayWaypoint[];
58
+ gaps?: AirwayGap[];
53
59
  } | undefined;
54
60
  }
55
61
  /**
@@ -86,6 +92,8 @@ export interface SidRouteElement {
86
92
  raw: string;
87
93
  /** Resolved procedure record. */
88
94
  procedure: Procedure;
95
+ /** Name of the transition merged into `legs`: the one named in a dotted token (`DEEZZ6.CANDR`), or the fix following the SID when it names one of the procedure's transitions. Absent when only the common route was expanded. */
96
+ transition?: string;
89
97
  /** Ordered legs for the procedure expansion. */
90
98
  legs: ProcedureLeg[];
91
99
  }
@@ -99,6 +107,8 @@ export interface StarRouteElement {
99
107
  raw: string;
100
108
  /** Resolved procedure record. */
101
109
  procedure: Procedure;
110
+ /** Name of the transition merged into `legs`: the one named in a dotted token (`AALLE4.BBOTL`), or the waypoint preceding the STAR when it names one of the procedure's transitions. Absent when only the common route was expanded. */
111
+ transition?: string;
102
112
  /** Ordered legs for the procedure expansion. */
103
113
  legs: ProcedureLeg[];
104
114
  }
@@ -118,6 +128,14 @@ export interface AirwayRouteElement {
118
128
  exitFix: string;
119
129
  /** Ordered waypoints from entry to exit fix (inclusive). */
120
130
  waypoints: AirwayWaypoint[];
131
+ /**
132
+ * Published discontinuities the expansion crosses, in traversal order. Empty
133
+ * when the airway is continuous between the entry and exit fixes. A
134
+ * non-empty list means the route files the airway where it is not defined,
135
+ * so the route is not valid as filed; the waypoints are still returned so
136
+ * the route can be drawn and measured.
137
+ */
138
+ gaps: AirwayGap[];
121
139
  }
122
140
  /**
123
141
  * A DCT (direct) indicator between two waypoints.
@@ -1 +1 @@
1
- {"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../src/resolver.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../src/resolver.ts"],"names":[],"mappings":"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"}
package/dist/resolver.js CHANGED
@@ -105,17 +105,26 @@ function tryAirport(token, airports) {
105
105
  * the most recent airport is the best available hint).
106
106
  *
107
107
  * Accepts both the bare CIFP identifier (e.g. `DEEZZ6`) and the dotted
108
- * identifier-with-transition form (e.g. `DEEZZ6.CANDR`). When a
109
- * transition is supplied it is forwarded to the procedure resolver so
110
- * that the transition's legs are merged into the expansion.
108
+ * identifier-with-transition form (e.g. `DEEZZ6.CANDR`). A dotted
109
+ * transition is forwarded to the procedure resolver so that the
110
+ * transition's legs are merged into the expansion. Without one, the
111
+ * adjacent fix is tried as the transition name: the token after a SID
112
+ * or the waypoint before a STAR, which is how routes are usually filed
113
+ * (`KJFK DEEZZ6 CANDR`). When neither names a transition the common
114
+ * route alone is expanded.
115
+ *
116
+ * Returns `undefined` when the token is not a known SID or STAR. Returns
117
+ * an `unresolved` element when the procedure is known but cannot be
118
+ * expanded: the dotted transition is not one of its transitions, or it
119
+ * has no common route and no adjacent fix names a transition.
111
120
  */
112
- function tryProcedure(token, procedures, airportContext) {
121
+ function tryProcedure(token, procedures, airportContext, previousWaypoint, nextToken) {
113
122
  if (!procedures) {
114
123
  return undefined;
115
124
  }
116
125
  const dotIndex = token.indexOf('.');
117
126
  const identifier = dotIndex >= 0 ? token.slice(0, dotIndex) : token;
118
- const transitionName = dotIndex >= 0 ? token.slice(dotIndex + 1) : undefined;
127
+ const dottedTransition = dotIndex >= 0 ? token.slice(dotIndex + 1) : undefined;
119
128
  if (identifier.length === 0) {
120
129
  return undefined;
121
130
  }
@@ -135,13 +144,34 @@ function tryProcedure(token, procedures, airportContext) {
135
144
  return undefined;
136
145
  }
137
146
  const airportForExpansion = proc.airports[0];
138
- const legs = airportForExpansion === undefined
139
- ? []
140
- : (procedures.expand(airportForExpansion, identifier, transitionName)?.legs ?? []);
141
- if (proc.type === 'SID') {
142
- return { type: 'sid', raw: token, procedure: proc, legs };
147
+ if (airportForExpansion === undefined) {
148
+ return { type: 'unresolved', raw: token };
149
+ }
150
+ const adjacentFix = proc.type === 'SID' ? nextToken : previousWaypoint;
151
+ const transitionName = dottedTransition ?? inferTransitionName(proc, adjacentFix);
152
+ const expansion = procedures.expand(airportForExpansion, identifier, transitionName);
153
+ if (expansion === undefined) {
154
+ return { type: 'unresolved', raw: token };
155
+ }
156
+ const element = proc.type === 'SID'
157
+ ? { type: 'sid', raw: token, procedure: proc, legs: expansion.legs }
158
+ : { type: 'star', raw: token, procedure: proc, legs: expansion.legs };
159
+ if (transitionName !== undefined) {
160
+ element.transition = transitionName;
161
+ }
162
+ return element;
163
+ }
164
+ /**
165
+ * Returns the procedure's transition whose name matches the adjacent fix
166
+ * token, in the procedure's own spelling, or `undefined` when there is
167
+ * no adjacent fix or no transition by that name.
168
+ */
169
+ function inferTransitionName(procedure, adjacentFix) {
170
+ if (adjacentFix === undefined) {
171
+ return undefined;
143
172
  }
144
- return { type: 'star', raw: token, procedure: proc, legs };
173
+ const upper = adjacentFix.toUpperCase();
174
+ return procedure.transitions.find((t) => t.name.toUpperCase() === upper)?.name;
145
175
  }
146
176
  /**
147
177
  * Attempts to resolve a token as a fix waypoint. When an anchor is supplied and
@@ -269,6 +299,7 @@ export function createFlightplanResolver(options) {
269
299
  entryFix: lastWaypointIdent,
270
300
  exitFix,
271
301
  waypoints: expansion.waypoints,
302
+ gaps: expansion.gaps ?? [],
272
303
  });
273
304
  // The exit fix is consumed as part of the airway; update last waypoint
274
305
  lastWaypointIdent = exitFix;
@@ -311,20 +342,26 @@ export function createFlightplanResolver(options) {
311
342
  i++;
312
343
  continue;
313
344
  }
314
- // Try procedure (SID/STAR)
315
- const procElement = tryProcedure(token, procedures, lastAirportIdent);
345
+ // Try procedure (SID/STAR). The fix after a SID or before a STAR may
346
+ // name the transition when the token itself does not.
347
+ const procElement = tryProcedure(token, procedures, lastAirportIdent, lastWaypointIdent, tokens[i + 1]?.toUpperCase());
316
348
  if (procElement) {
317
349
  elements.push(procElement);
318
- // Update last waypoint to the last fix in the procedure expansion
319
- // that actually terminates at a fix (some leg types have no fix).
320
- for (let j = procElement.legs.length - 1; j >= 0; j--) {
321
- const leg = procElement.legs[j];
322
- if (leg?.fixIdentifier !== undefined) {
323
- lastWaypointIdent = leg.fixIdentifier;
324
- if (leg.lat !== undefined && leg.lon !== undefined) {
325
- lastPosition = { lat: leg.lat, lon: leg.lon };
350
+ if (procElement.type === 'unresolved') {
351
+ lastWaypointIdent = undefined;
352
+ }
353
+ else {
354
+ // Update last waypoint to the last fix in the procedure expansion
355
+ // that actually terminates at a fix (some leg types have no fix).
356
+ for (let j = procElement.legs.length - 1; j >= 0; j--) {
357
+ const leg = procElement.legs[j];
358
+ if (leg?.fixIdentifier !== undefined) {
359
+ lastWaypointIdent = leg.fixIdentifier;
360
+ if (leg.lat !== undefined && leg.lon !== undefined) {
361
+ lastPosition = { lat: leg.lat, lon: leg.lon };
362
+ }
363
+ break;
326
364
  }
327
- break;
328
365
  }
329
366
  }
330
367
  i++;
@@ -24,6 +24,13 @@ export interface RouteLeg {
24
24
  distanceNm: number;
25
25
  /** Cumulative distance from the route start through the end of this leg in nautical miles. */
26
26
  cumulativeDistanceNm: number;
27
+ /**
28
+ * Whether this leg spans a published gap in the airway it was expanded
29
+ * from. The airway is not defined between the two points, so the leg is a
30
+ * straight line that counts toward the total but is not a flyable airway
31
+ * segment, and the route is not valid as filed.
32
+ */
33
+ crossesGap: boolean;
27
34
  }
28
35
  /**
29
36
  * Result of computing route distance and estimated time enroute from a
@@ -57,7 +64,9 @@ export interface RouteDistanceResult {
57
64
  *
58
65
  * Airway segments use the FAA-published `distanceToNextNm` value where the
59
66
  * source publishes a positive one, falling back to great-circle computation
60
- * otherwise.
67
+ * otherwise. A leg that spans a published gap in its airway is still measured
68
+ * as a straight line and counted, but is flagged with `crossesGap` so the
69
+ * caller can see that the route is not valid as filed.
61
70
  *
62
71
  * ```typescript
63
72
  * import { createFlightplanResolver, computeRouteDistance } from '@squawk/flightplan';
@@ -1 +1 @@
1
- {"version":3,"file":"route-distance.d.ts","sourceRoot":"","sources":["../src/route-distance.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAO/D;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,EAAE,EAAE,MAAM,CAAC;IACX,yEAAyE;IACzE,OAAO,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,OAAO,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAC;IACd,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,UAAU,EAAE,MAAM,CAAC;IACnB,8FAA8F;IAC9F,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,0DAA0D;IAC1D,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,2DAA2D;IAC3D,eAAe,EAAE,MAAM,CAAC;IACxB,uFAAuF;IACvF,uBAAuB,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C;;;;OAIG;IACH,kBAAkB,EAAE,YAAY,EAAE,CAAC;CACpC;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,WAAW,EAClB,aAAa,CAAC,EAAE,MAAM,GACrB,mBAAmB,CAsCrB"}
1
+ {"version":3,"file":"route-distance.d.ts","sourceRoot":"","sources":["../src/route-distance.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAO/D;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,EAAE,EAAE,MAAM,CAAC;IACX,yEAAyE;IACzE,OAAO,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,OAAO,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAC;IACd,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,UAAU,EAAE,MAAM,CAAC;IACnB,8FAA8F;IAC9F,oBAAoB,EAAE,MAAM,CAAC;IAC7B;;;;;OAKG;IACH,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,0DAA0D;IAC1D,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,2DAA2D;IAC3D,eAAe,EAAE,MAAM,CAAC;IACxB,uFAAuF;IACvF,uBAAuB,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C;;;;OAIG;IACH,kBAAkB,EAAE,YAAY,EAAE,CAAC;CACpC;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,WAAW,EAClB,aAAa,CAAC,EAAE,MAAM,GACrB,mBAAmB,CAuCrB"}
@@ -22,7 +22,9 @@ import { extractGeoPoints } from './route-geometry.js';
22
22
  *
23
23
  * Airway segments use the FAA-published `distanceToNextNm` value where the
24
24
  * source publishes a positive one, falling back to great-circle computation
25
- * otherwise.
25
+ * otherwise. A leg that spans a published gap in its airway is still measured
26
+ * as a straight line and counted, but is flagged with `crossesGap` so the
27
+ * caller can see that the route is not valid as filed.
26
28
  *
27
29
  * ```typescript
28
30
  * import { createFlightplanResolver, computeRouteDistance } from '@squawk/flightplan';
@@ -58,6 +60,7 @@ export function computeRouteDistance(route, groundSpeedKt) {
58
60
  toLon: to.lon,
59
61
  distanceNm: legDistanceNm,
60
62
  cumulativeDistanceNm: totalDistanceNm,
63
+ crossesGap: from.gapToNext === true,
61
64
  });
62
65
  }
63
66
  const estimatedTimeEnrouteHrs = groundSpeedKt !== undefined && groundSpeedKt > 0 ? totalDistanceNm / groundSpeedKt : undefined;
@@ -40,6 +40,11 @@ export interface GeoPoint {
40
40
  * nautical miles, when the source data publishes a positive value.
41
41
  */
42
42
  precomputedDistanceToNextNm?: number;
43
+ /**
44
+ * Set when the leg from this point to the next crosses a published gap in
45
+ * the airway it was expanded from.
46
+ */
47
+ gapToNext?: true;
43
48
  }
44
49
  /**
45
50
  * Walks the route elements and extracts an ordered array of geographic
@@ -1 +1 @@
1
- {"version":3,"file":"route-geometry.d.ts","sourceRoot":"","sources":["../src/route-geometry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAM/D;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd,mDAAmD;IACnD,GAAG,EAAE,MAAM,CAAC;IACZ,mDAAmD;IACnD,GAAG,EAAE,MAAM,CAAC;CACb;AAMD;;;;;;GAMG;AACH,MAAM,WAAW,QAAQ;IACvB,+CAA+C;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,mDAAmD;IACnD,GAAG,EAAE,MAAM,CAAC;IACZ,mDAAmD;IACnD,GAAG,EAAE,MAAM,CAAC;IACZ;;;OAGG;IACH,2BAA2B,CAAC,EAAE,MAAM,CAAC;CACtC;AAuBD;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG;IAC1D,MAAM,EAAE,QAAQ,EAAE,CAAC;IACnB,kBAAkB,EAAE,YAAY,EAAE,CAAC;CACpC,CA8EA;AAMD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,GAAG,UAAU,EAAE,CAGnE;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,WAAW,GAAG,UAAU,GAAG,SAAS,CAS5E"}
1
+ {"version":3,"file":"route-geometry.d.ts","sourceRoot":"","sources":["../src/route-geometry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAM/D;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd,mDAAmD;IACnD,GAAG,EAAE,MAAM,CAAC;IACZ,mDAAmD;IACnD,GAAG,EAAE,MAAM,CAAC;CACb;AAMD;;;;;;GAMG;AACH,MAAM,WAAW,QAAQ;IACvB,+CAA+C;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,mDAAmD;IACnD,GAAG,EAAE,MAAM,CAAC;IACZ,mDAAmD;IACnD,GAAG,EAAE,MAAM,CAAC;IACZ;;;OAGG;IACH,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC;;;OAGG;IACH,SAAS,CAAC,EAAE,IAAI,CAAC;CAClB;AAuBD;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG;IAC1D,MAAM,EAAE,QAAQ,EAAE,CAAC;IACnB,kBAAkB,EAAE,YAAY,EAAE,CAAC;CACpC,CAwFA;AAMD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,GAAG,UAAU,EAAE,CAGnE;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,WAAW,GAAG,UAAU,GAAG,SAAS,CAS5E"}
@@ -53,6 +53,11 @@ export function extractGeoPoints(elements) {
53
53
  last.precomputedDistanceToNextNm === undefined) {
54
54
  last.precomputedDistanceToNextNm = point.precomputedDistanceToNextNm;
55
55
  }
56
+ // Likewise carry a gap marker, so the leg out of the merged point is
57
+ // still reported as crossing the gap.
58
+ if (point.gapToNext) {
59
+ last.gapToNext = true;
60
+ }
56
61
  return;
57
62
  }
58
63
  points.push(point);
@@ -68,7 +73,8 @@ export function extractGeoPoints(elements) {
68
73
  case 'coordinate':
69
74
  emit({ label: el.raw, lat: el.lat, lon: el.lon });
70
75
  break;
71
- case 'airway':
76
+ case 'airway': {
77
+ const gapIndexes = new Set(el.gaps.map((gap) => gap.index));
72
78
  for (let i = 0; i < el.waypoints.length; i++) {
73
79
  const wp = el.waypoints[i];
74
80
  const isLast = i === el.waypoints.length - 1;
@@ -83,9 +89,13 @@ export function extractGeoPoints(elements) {
83
89
  if (!isLast && wp.distanceToNextNm !== undefined && wp.distanceToNextNm > 0) {
84
90
  point.precomputedDistanceToNextNm = wp.distanceToNextNm;
85
91
  }
92
+ if (!isLast && gapIndexes.has(i)) {
93
+ point.gapToNext = true;
94
+ }
86
95
  emit(point);
87
96
  }
88
97
  break;
98
+ }
89
99
  case 'sid':
90
100
  case 'star':
91
101
  for (const leg of el.legs) {
@@ -68,6 +68,8 @@ export interface RouteTimingLeg {
68
68
  distanceNm: number;
69
69
  /** Cumulative distance from the route start through the end of this leg in nautical miles. */
70
70
  cumulativeDistanceNm: number;
71
+ /** Whether this leg spans a published gap in the airway it was expanded from, as on `RouteLeg`. */
72
+ crossesGap: boolean;
71
73
  /** Initial great-circle true course for the leg in degrees (0-360). */
72
74
  trueCourseDeg: number;
73
75
  /** True heading to fly to hold the course given the wind, in degrees (0-360). */
@@ -1 +1 @@
1
- {"version":3,"file":"route-timing.d.ts","sourceRoot":"","sources":["../src/route-timing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAGtD,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAO/D;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,UAAU,GAAG,SAAS,CAAC;AAEhF;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,iDAAiD;IACjD,cAAc,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,EAAE,EAAE,MAAM,CAAC;IACX,yEAAyE;IACzE,OAAO,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,OAAO,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAC;IACd,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,UAAU,EAAE,MAAM,CAAC;IACnB,8FAA8F;IAC9F,oBAAoB,EAAE,MAAM,CAAC;IAC7B,uEAAuE;IACvE,aAAa,EAAE,MAAM,CAAC;IACtB,iFAAiF;IACjF,cAAc,EAAE,MAAM,CAAC;IACvB,6FAA6F;IAC7F,sBAAsB,EAAE,MAAM,CAAC;IAC/B,mDAAmD;IACnD,aAAa,EAAE,MAAM,CAAC;IACtB,8EAA8E;IAC9E,IAAI,EAAE,UAAU,GAAG,SAAS,CAAC;IAC7B,mGAAmG;IACnG,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B;;;OAGG;IACH,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC;;;OAGG;IACH,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,qDAAqD;IACrD,IAAI,EAAE,cAAc,EAAE,CAAC;IACvB,2DAA2D;IAC3D,eAAe,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC;;;OAGG;IACH,iBAAiB,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC;;;OAGG;IACH,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC;;;OAGG;IACH,cAAc,EAAE,OAAO,GAAG,SAAS,CAAC;IACpC;;;OAGG;IACH,kBAAkB,EAAE,YAAY,EAAE,CAAC;CACpC;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,kBAAkB,GAC1B,iBAAiB,CAwFnB"}
1
+ {"version":3,"file":"route-timing.d.ts","sourceRoot":"","sources":["../src/route-timing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAGtD,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAO/D;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,UAAU,GAAG,SAAS,CAAC;AAEhF;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,iDAAiD;IACjD,cAAc,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,EAAE,EAAE,MAAM,CAAC;IACX,yEAAyE;IACzE,OAAO,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,OAAO,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAC;IACd,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,UAAU,EAAE,MAAM,CAAC;IACnB,8FAA8F;IAC9F,oBAAoB,EAAE,MAAM,CAAC;IAC7B,mGAAmG;IACnG,UAAU,EAAE,OAAO,CAAC;IACpB,uEAAuE;IACvE,aAAa,EAAE,MAAM,CAAC;IACtB,iFAAiF;IACjF,cAAc,EAAE,MAAM,CAAC;IACvB,6FAA6F;IAC7F,sBAAsB,EAAE,MAAM,CAAC;IAC/B,mDAAmD;IACnD,aAAa,EAAE,MAAM,CAAC;IACtB,8EAA8E;IAC9E,IAAI,EAAE,UAAU,GAAG,SAAS,CAAC;IAC7B,mGAAmG;IACnG,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B;;;OAGG;IACH,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC;;;OAGG;IACH,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,qDAAqD;IACrD,IAAI,EAAE,cAAc,EAAE,CAAC;IACvB,2DAA2D;IAC3D,eAAe,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC;;;OAGG;IACH,iBAAiB,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC;;;OAGG;IACH,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC;;;OAGG;IACH,cAAc,EAAE,OAAO,GAAG,SAAS,CAAC;IACpC;;;OAGG;IACH,kBAAkB,EAAE,YAAY,EAAE,CAAC;CACpC;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,kBAAkB,GAC1B,iBAAiB,CAyFnB"}
@@ -100,6 +100,7 @@ export function computeRouteTiming(route, options) {
100
100
  toLon: leg.toLon,
101
101
  distanceNm: leg.distanceNm,
102
102
  cumulativeDistanceNm: leg.cumulativeDistanceNm,
103
+ crossesGap: leg.crossesGap,
103
104
  trueCourseDeg,
104
105
  trueHeadingDeg: triangle.trueHeadingDeg,
105
106
  windCorrectionAngleDeg: triangle.windCorrectionAngleDeg,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@squawk/flightplan",
3
- "version": "0.6.4",
3
+ "version": "0.8.0",
4
4
  "type": "module",
5
5
  "description": "Flight plan route string parsing and resolution using composed navigation resolvers",
6
6
  "author": "Neil Cochran",
@@ -43,21 +43,21 @@
43
43
  },
44
44
  "dependencies": {
45
45
  "@squawk/flight-math": "^0.5.9",
46
- "@squawk/geo": "^0.5.0",
47
- "@squawk/types": "^0.10.0",
46
+ "@squawk/geo": "^0.5.2",
47
+ "@squawk/types": "^0.12.0",
48
48
  "@types/geojson": "^7946.0.16"
49
49
  },
50
50
  "devDependencies": {
51
- "@squawk/airport-data": "^0.8.2",
52
- "@squawk/airports": "^0.7.3",
53
- "@squawk/airway-data": "^0.6.3",
54
- "@squawk/airways": "^0.5.3",
55
- "@squawk/fix-data": "^0.7.2",
56
- "@squawk/fixes": "^0.5.3",
57
- "@squawk/navaid-data": "^0.7.2",
58
- "@squawk/navaids": "^0.6.3",
59
- "@squawk/procedure-data": "^0.8.2",
60
- "@squawk/procedures": "^0.7.2",
51
+ "@squawk/airport-data": "^0.8.4",
52
+ "@squawk/airports": "^0.7.5",
53
+ "@squawk/airway-data": "^0.6.5",
54
+ "@squawk/airways": "^0.6.1",
55
+ "@squawk/fix-data": "^0.7.4",
56
+ "@squawk/fixes": "^0.5.5",
57
+ "@squawk/navaid-data": "^0.7.4",
58
+ "@squawk/navaids": "^0.6.5",
59
+ "@squawk/procedure-data": "^0.9.0",
60
+ "@squawk/procedures": "^0.8.0",
61
61
  "@types/node": "^26.6.4"
62
62
  },
63
63
  "keywords": [