gnss-js 1.8.0 → 1.9.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.
@@ -437,14 +437,33 @@ function computeLiveSkyPositions(ephemerides, rxPos, cn0Map) {
437
437
  }
438
438
  return result;
439
439
  }
440
+ function maskRadForAzimuth(maskDeg) {
441
+ if (typeof maskDeg === "number") {
442
+ const m = maskDeg * Math.PI / 180;
443
+ return () => m;
444
+ }
445
+ const n = maskDeg.length;
446
+ if (n === 0) return () => 0;
447
+ return (azRad) => {
448
+ const azDeg = (azRad * 180 / Math.PI % 360 + 360) % 360;
449
+ const pos = azDeg / 360 * n;
450
+ const i = Math.floor(pos) % n;
451
+ const f = pos - Math.floor(pos);
452
+ const a = maskDeg[i];
453
+ const b = maskDeg[(i + 1) % n];
454
+ return ((1 - f) * a + f * b) * Math.PI / 180;
455
+ };
456
+ }
440
457
  function computeVisibility(ephemerides, rxPos, startMs, endMs, stepSec = 300, elevationMaskDeg = 10) {
441
458
  const stepMs = stepSec * 1e3;
442
459
  const times = [];
443
460
  for (let t = startMs; t <= endMs; t += stepMs) times.push(t);
444
- const maskRad = elevationMaskDeg * Math.PI / 180;
461
+ const maskRadFor = maskRadForAzimuth(elevationMaskDeg);
445
462
  const all = computeAllPositions(ephemerides, times, rxPos);
446
463
  const elevation = {};
447
464
  const azimuth = {};
465
+ const subLat = {};
466
+ const subLon = {};
448
467
  const visibleCount = new Array(times.length).fill(0);
449
468
  const pdop = new Array(times.length).fill(null);
450
469
  const gdop = new Array(times.length).fill(null);
@@ -455,9 +474,11 @@ function computeVisibility(ephemerides, rxPos, startMs, endMs, stepSec = 300, el
455
474
  const series = all.positions[prn];
456
475
  elevation[prn] = series.map((p) => p ? p.el : null);
457
476
  azimuth[prn] = series.map((p) => p ? p.az : null);
477
+ subLat[prn] = series.map((p) => p ? p.lat : null);
478
+ subLon[prn] = series.map((p) => p ? p.lon : null);
458
479
  for (let i = 0; i < series.length; i++) {
459
480
  const p = series[i];
460
- if (p && p.el >= maskRad) {
481
+ if (p && p.el >= maskRadFor(p.az)) {
461
482
  visibleCount[i]++;
462
483
  visiblePerEpoch[i].push({ az: p.az, el: p.el });
463
484
  }
@@ -478,7 +499,8 @@ function computeVisibility(ephemerides, rxPos, startMs, endMs, stepSec = 300, el
478
499
  let peakTime = 0;
479
500
  for (let i = 0; i <= els.length; i++) {
480
501
  const el = i < els.length ? els[i] : null;
481
- const above = el !== null && el !== void 0 && el >= maskRad;
502
+ const az = all.positions[prn][i]?.az ?? 0;
503
+ const above = el !== null && el !== void 0 && el >= maskRadFor(az);
482
504
  if (above) {
483
505
  if (start === -1) {
484
506
  start = i;
@@ -506,6 +528,8 @@ function computeVisibility(ephemerides, rxPos, startMs, endMs, stepSec = 300, el
506
528
  times,
507
529
  elevation,
508
530
  azimuth,
531
+ subLat,
532
+ subLon,
509
533
  visibleCount,
510
534
  pdop,
511
535
  gdop,
@@ -526,5 +550,6 @@ export {
526
550
  computeAllPositions,
527
551
  ephInfoToEphemeris,
528
552
  computeLiveSkyPositions,
553
+ maskRadForAzimuth,
529
554
  computeVisibility
530
555
  };
@@ -610,6 +610,91 @@ function writeRinexNav(nav) {
610
610
  return header + records.join("\n") + "\n";
611
611
  }
612
612
 
613
+ // src/rinex/ionex.ts
614
+ function gridRange(l1, l2, dl) {
615
+ const out = [];
616
+ const n = Math.round((l2 - l1) / dl) + 1;
617
+ for (let i = 0; i < n; i++) out.push(l1 + i * dl);
618
+ return out;
619
+ }
620
+ function parseIonex(text) {
621
+ const lines = text.split("\n");
622
+ let exponent = -1;
623
+ let lats = [];
624
+ let lons = [];
625
+ const epochs = [];
626
+ const maps = [];
627
+ let i = 0;
628
+ for (; i < lines.length; i++) {
629
+ const line = lines[i];
630
+ const label = line.slice(60).trim();
631
+ if (label === "EXPONENT") {
632
+ exponent = parseInt(line.slice(0, 60).trim(), 10);
633
+ } else if (label === "LAT1 / LAT2 / DLAT") {
634
+ const [a, b, d] = line.trim().split(/\s+/).map(Number);
635
+ lats = gridRange(a, b, d);
636
+ } else if (label === "LON1 / LON2 / DLON") {
637
+ const [a, b, d] = line.trim().split(/\s+/).map(Number);
638
+ lons = gridRange(a, b, d);
639
+ } else if (label === "END OF HEADER") {
640
+ i++;
641
+ break;
642
+ }
643
+ }
644
+ if (lats.length === 0 || lons.length === 0) {
645
+ throw new Error("IONEX: missing grid definition");
646
+ }
647
+ const scale = Math.pow(10, exponent);
648
+ while (i < lines.length) {
649
+ const line = lines[i];
650
+ const label = line.slice(60).trim();
651
+ if (label === "START OF TEC MAP") {
652
+ const map = new Float32Array(lats.length * lons.length).fill(NaN);
653
+ let epochMs = 0;
654
+ i++;
655
+ while (i < lines.length) {
656
+ const l = lines[i];
657
+ const lab = l.slice(60).trim();
658
+ if (lab === "EPOCH OF CURRENT MAP") {
659
+ const f = l.slice(0, 60).trim().split(/\s+/).map(Number);
660
+ epochMs = Date.UTC(f[0], f[1] - 1, f[2], f[3], f[4], f[5]);
661
+ i++;
662
+ } else if (lab === "LAT/LON1/LON2/DLON/H") {
663
+ const lat = parseFloat(l.slice(2, 8));
664
+ const latIdx = lats.findIndex((v) => Math.abs(v - lat) < 1e-6);
665
+ i++;
666
+ let lonIdx = 0;
667
+ while (lonIdx < lons.length && i < lines.length) {
668
+ const row = lines[i];
669
+ for (let c = 0; c + 5 <= 80 && lonIdx < lons.length; c += 5) {
670
+ const vStr = row.slice(c, c + 5).trim();
671
+ if (vStr === "") continue;
672
+ const v = parseInt(vStr, 10);
673
+ if (latIdx >= 0) {
674
+ map[latIdx * lons.length + lonIdx] = v === 9999 ? NaN : v * scale;
675
+ }
676
+ lonIdx++;
677
+ }
678
+ i++;
679
+ }
680
+ } else if (lab === "END OF TEC MAP") {
681
+ i++;
682
+ break;
683
+ } else {
684
+ i++;
685
+ }
686
+ }
687
+ epochs.push(epochMs);
688
+ maps.push(map);
689
+ } else if (label === "START OF RMS MAP" || label === "END OF FILE") {
690
+ break;
691
+ } else {
692
+ i++;
693
+ }
694
+ }
695
+ return { epochs, lats, lons, maps };
696
+ }
697
+
613
698
  export {
614
699
  padL,
615
700
  padR,
@@ -618,5 +703,6 @@ export {
618
703
  EMPTY_WARNINGS,
619
704
  WarningAccumulator,
620
705
  parseNavFile,
621
- writeRinexNav
706
+ writeRinexNav,
707
+ parseIonex
622
708
  };
@@ -2,7 +2,7 @@ import {
2
2
  computeDop,
3
3
  computeSatPosition,
4
4
  ecefToAzEl
5
- } from "./chunk-MN2DBDJL.js";
5
+ } from "./chunk-647YMBJV.js";
6
6
  import {
7
7
  C_LIGHT,
8
8
  OMEGA_E
package/dist/index.cjs CHANGED
@@ -200,6 +200,7 @@ __export(src_exports, {
200
200
  horizonDistance: () => horizonDistance,
201
201
  ionoFree: () => ionoFree,
202
202
  keplerPosition: () => keplerPosition,
203
+ maskRadForAzimuth: () => maskRadForAzimuth,
203
204
  msmEpochToDate: () => msmEpochToDate,
204
205
  navTimesFromEph: () => navTimesFromEph,
205
206
  nmeaCoordToDecimal: () => nmeaCoordToDecimal,
@@ -207,6 +208,7 @@ __export(src_exports, {
207
208
  padR: () => padR,
208
209
  parseAntex: () => parseAntex,
209
210
  parseCrxDataLine: () => parseCrxDataLine,
211
+ parseIonex: () => parseIonex,
210
212
  parseNavFile: () => parseNavFile,
211
213
  parseNmeaFile: () => parseNmeaFile,
212
214
  parseRinexStream: () => parseRinexStream,
@@ -2575,6 +2577,91 @@ function writeRinexNav(nav) {
2575
2577
  return header + records.join("\n") + "\n";
2576
2578
  }
2577
2579
 
2580
+ // src/rinex/ionex.ts
2581
+ function gridRange(l1, l2, dl) {
2582
+ const out = [];
2583
+ const n = Math.round((l2 - l1) / dl) + 1;
2584
+ for (let i = 0; i < n; i++) out.push(l1 + i * dl);
2585
+ return out;
2586
+ }
2587
+ function parseIonex(text) {
2588
+ const lines = text.split("\n");
2589
+ let exponent = -1;
2590
+ let lats = [];
2591
+ let lons = [];
2592
+ const epochs = [];
2593
+ const maps = [];
2594
+ let i = 0;
2595
+ for (; i < lines.length; i++) {
2596
+ const line = lines[i];
2597
+ const label2 = line.slice(60).trim();
2598
+ if (label2 === "EXPONENT") {
2599
+ exponent = parseInt(line.slice(0, 60).trim(), 10);
2600
+ } else if (label2 === "LAT1 / LAT2 / DLAT") {
2601
+ const [a, b, d] = line.trim().split(/\s+/).map(Number);
2602
+ lats = gridRange(a, b, d);
2603
+ } else if (label2 === "LON1 / LON2 / DLON") {
2604
+ const [a, b, d] = line.trim().split(/\s+/).map(Number);
2605
+ lons = gridRange(a, b, d);
2606
+ } else if (label2 === "END OF HEADER") {
2607
+ i++;
2608
+ break;
2609
+ }
2610
+ }
2611
+ if (lats.length === 0 || lons.length === 0) {
2612
+ throw new Error("IONEX: missing grid definition");
2613
+ }
2614
+ const scale = Math.pow(10, exponent);
2615
+ while (i < lines.length) {
2616
+ const line = lines[i];
2617
+ const label2 = line.slice(60).trim();
2618
+ if (label2 === "START OF TEC MAP") {
2619
+ const map = new Float32Array(lats.length * lons.length).fill(NaN);
2620
+ let epochMs = 0;
2621
+ i++;
2622
+ while (i < lines.length) {
2623
+ const l = lines[i];
2624
+ const lab = l.slice(60).trim();
2625
+ if (lab === "EPOCH OF CURRENT MAP") {
2626
+ const f = l.slice(0, 60).trim().split(/\s+/).map(Number);
2627
+ epochMs = Date.UTC(f[0], f[1] - 1, f[2], f[3], f[4], f[5]);
2628
+ i++;
2629
+ } else if (lab === "LAT/LON1/LON2/DLON/H") {
2630
+ const lat = parseFloat(l.slice(2, 8));
2631
+ const latIdx = lats.findIndex((v) => Math.abs(v - lat) < 1e-6);
2632
+ i++;
2633
+ let lonIdx = 0;
2634
+ while (lonIdx < lons.length && i < lines.length) {
2635
+ const row = lines[i];
2636
+ for (let c = 0; c + 5 <= 80 && lonIdx < lons.length; c += 5) {
2637
+ const vStr = row.slice(c, c + 5).trim();
2638
+ if (vStr === "") continue;
2639
+ const v = parseInt(vStr, 10);
2640
+ if (latIdx >= 0) {
2641
+ map[latIdx * lons.length + lonIdx] = v === 9999 ? NaN : v * scale;
2642
+ }
2643
+ lonIdx++;
2644
+ }
2645
+ i++;
2646
+ }
2647
+ } else if (lab === "END OF TEC MAP") {
2648
+ i++;
2649
+ break;
2650
+ } else {
2651
+ i++;
2652
+ }
2653
+ }
2654
+ epochs.push(epochMs);
2655
+ maps.push(map);
2656
+ } else if (label2 === "START OF RMS MAP" || label2 === "END OF FILE") {
2657
+ break;
2658
+ } else {
2659
+ i++;
2660
+ }
2661
+ }
2662
+ return { epochs, lats, lons, maps };
2663
+ }
2664
+
2578
2665
  // src/rtcm3/decoder.ts
2579
2666
  var debugHandler = null;
2580
2667
  function setRtcm3DebugHandler(fn) {
@@ -4427,14 +4514,33 @@ function computeLiveSkyPositions(ephemerides, rxPos, cn0Map) {
4427
4514
  }
4428
4515
  return result;
4429
4516
  }
4517
+ function maskRadForAzimuth(maskDeg) {
4518
+ if (typeof maskDeg === "number") {
4519
+ const m = maskDeg * Math.PI / 180;
4520
+ return () => m;
4521
+ }
4522
+ const n = maskDeg.length;
4523
+ if (n === 0) return () => 0;
4524
+ return (azRad) => {
4525
+ const azDeg = (azRad * 180 / Math.PI % 360 + 360) % 360;
4526
+ const pos = azDeg / 360 * n;
4527
+ const i = Math.floor(pos) % n;
4528
+ const f = pos - Math.floor(pos);
4529
+ const a = maskDeg[i];
4530
+ const b = maskDeg[(i + 1) % n];
4531
+ return ((1 - f) * a + f * b) * Math.PI / 180;
4532
+ };
4533
+ }
4430
4534
  function computeVisibility(ephemerides, rxPos, startMs, endMs, stepSec = 300, elevationMaskDeg = 10) {
4431
4535
  const stepMs = stepSec * 1e3;
4432
4536
  const times = [];
4433
4537
  for (let t = startMs; t <= endMs; t += stepMs) times.push(t);
4434
- const maskRad = elevationMaskDeg * Math.PI / 180;
4538
+ const maskRadFor = maskRadForAzimuth(elevationMaskDeg);
4435
4539
  const all = computeAllPositions(ephemerides, times, rxPos);
4436
4540
  const elevation = {};
4437
4541
  const azimuth = {};
4542
+ const subLat = {};
4543
+ const subLon = {};
4438
4544
  const visibleCount = new Array(times.length).fill(0);
4439
4545
  const pdop = new Array(times.length).fill(null);
4440
4546
  const gdop = new Array(times.length).fill(null);
@@ -4445,9 +4551,11 @@ function computeVisibility(ephemerides, rxPos, startMs, endMs, stepSec = 300, el
4445
4551
  const series = all.positions[prn];
4446
4552
  elevation[prn] = series.map((p) => p ? p.el : null);
4447
4553
  azimuth[prn] = series.map((p) => p ? p.az : null);
4554
+ subLat[prn] = series.map((p) => p ? p.lat : null);
4555
+ subLon[prn] = series.map((p) => p ? p.lon : null);
4448
4556
  for (let i = 0; i < series.length; i++) {
4449
4557
  const p = series[i];
4450
- if (p && p.el >= maskRad) {
4558
+ if (p && p.el >= maskRadFor(p.az)) {
4451
4559
  visibleCount[i]++;
4452
4560
  visiblePerEpoch[i].push({ az: p.az, el: p.el });
4453
4561
  }
@@ -4468,7 +4576,8 @@ function computeVisibility(ephemerides, rxPos, startMs, endMs, stepSec = 300, el
4468
4576
  let peakTime = 0;
4469
4577
  for (let i = 0; i <= els.length; i++) {
4470
4578
  const el = i < els.length ? els[i] : null;
4471
- const above = el !== null && el !== void 0 && el >= maskRad;
4579
+ const az = all.positions[prn][i]?.az ?? 0;
4580
+ const above = el !== null && el !== void 0 && el >= maskRadFor(az);
4472
4581
  if (above) {
4473
4582
  if (start === -1) {
4474
4583
  start = i;
@@ -4496,6 +4605,8 @@ function computeVisibility(ephemerides, rxPos, startMs, endMs, stepSec = 300, el
4496
4605
  times,
4497
4606
  elevation,
4498
4607
  azimuth,
4608
+ subLat,
4609
+ subLon,
4499
4610
  visibleCount,
4500
4611
  pdop,
4501
4612
  gdop,
@@ -7353,6 +7464,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
7353
7464
  horizonDistance,
7354
7465
  ionoFree,
7355
7466
  keplerPosition,
7467
+ maskRadForAzimuth,
7356
7468
  msmEpochToDate,
7357
7469
  navTimesFromEph,
7358
7470
  nmeaCoordToDecimal,
@@ -7360,6 +7472,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
7360
7472
  padR,
7361
7473
  parseAntex,
7362
7474
  parseCrxDataLine,
7475
+ parseIonex,
7363
7476
  parseNavFile,
7364
7477
  parseNmeaFile,
7365
7478
  parseRinexStream,
package/dist/index.d.cts CHANGED
@@ -4,12 +4,12 @@ export { A as ARC_GAP_FACTOR, B as BAND_LABELS, a as BDS_SATELLITES, b as BdsSat
4
4
  export { Scale, getBdsTime, getDateFromBdsTime, getDateFromDayOfWeek, getDateFromDayOfYear, getDateFromGalTime, getDateFromGloN, getDateFromGpsData, getDateFromGpsTime, getDateFromHourCode, getDateFromJulianDate, getDateFromMJD, getDateFromMJD2000, getDateFromRINEX, getDateFromTai, getDateFromTimeOfDay, getDateFromTt, getDateFromUnixTime, getDateFromUtc, getDayOfWeek, getDayOfYear, getGalTime, getGloN4, getGloNA, getGpsLeap, getGpsTime, getHourCode, getHoursFromTimeDifference, getJulianDate, getLeap, getMJD, getMJD2000, getMinutesFromTimeDifference, getNtpTime, getRINEX, getSecondsFromTimeDifference, getTaiDate, getTimeDifference, getTimeDifferenceFromDays, getTimeDifferenceFromHours, getTimeDifferenceFromMinutes, getTimeDifferenceFromObject, getTimeDifferenceFromSeconds, getTimeOfDay, getTimeOfWeek, getTotalDaysFromTimeDifference, getTtDate, getUnixTime, getUtcDate, getWeekNumber, getWeekOfYear } from './time.cjs';
5
5
  export { deg2dms, deg2rad, euclidean3D, geodeticToGeohash, geodeticToMaidenhead, geodeticToUtm, greatCircleMidpoint, horizonDistance, rad2deg, rhumbLine, vincenty } from './coordinates.cjs';
6
6
  export { c as clampUnit, e as ecefToGeodetic, g as geodeticToEcef, a as getAer, b as getEnuDifference } from './ecef-CF0uAysr.cjs';
7
- export { CrxField, DiffState, EMPTY_WARNINGS, RinexWarning, RinexWarnings, WarningAccumulator, WarningSeverity, crxDecompress, crxRepair, fmtF, hdrLine, padL, padR, parseCrxDataLine, writeRinexNav } from './rinex.cjs';
7
+ export { CrxField, DiffState, EMPTY_WARNINGS, IonexGrid, RinexWarning, RinexWarnings, WarningAccumulator, WarningSeverity, crxDecompress, crxRepair, fmtF, hdrLine, padL, padR, parseCrxDataLine, parseIonex, writeRinexNav } from './rinex.cjs';
8
8
  export { E as EpochSummary, P as ParseOptions, R as RinexHeader, a as RinexResult, b as RinexStats, S as SYSTEM_ORDER, c as SatObsCallback, p as parseRinexStream, s as systemCmp, d as systemName } from './parser-JPjjFgeP.cjs';
9
9
  export { E as Ephemeris, G as GlonassEphemeris, K as KeplerEphemeris, N as NavHeader, a as NavResult, p as parseNavFile } from './nav-BAI1a9vK.cjs';
10
10
  export { B as BitReader, E as EphemerisInfo, R as Rtcm3DebugHandler, a as Rtcm3Decoder, b as Rtcm3Frame, d as decodeEphemeris, r as readString, c as reportDecodeError, s as setRtcm3DebugHandler } from './ephemeris-Ohl6NAfw.cjs';
11
11
  export { MessageTypeStats, MsmEpoch, MsmSatObs, MsmSignal, RTCM3_MESSAGE_NAMES, SatCn0, SignalCn0, StationMeta, StreamStats, createStationMeta, createStreamStats, decodeMsmFull, msmEpochToDate, resetGloFreqCache, rtcm3Constellation, setGloFreqNumber, updateStationMeta, updateStreamStats } from './rtcm3.cjs';
12
- export { AllPositionsData, DopValues, EpochSkyData, SatAzEl, SatPoint, SatPosition, VisibilityPass, VisibilityResult, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, ecefToAzEl, ephInfoToEphemeris, glonassPosition, keplerPosition, navTimesFromEph, selectEphemeris } from './orbit.cjs';
12
+ export { AllPositionsData, DopValues, EpochSkyData, SatAzEl, SatPoint, SatPosition, VisibilityPass, VisibilityResult, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, ecefToAzEl, ephInfoToEphemeris, glonassPosition, keplerPosition, maskRadForAzimuth, navTimesFromEph, selectEphemeris } from './orbit.cjs';
13
13
  export { Helmert14, REFERENCE_FRAMES, ReferenceFrame, applyHelmert, dateToEpoch, transformFrame } from './frames.cjs';
14
14
  export { SppOptions, SppSolution, ionoFree, satClockCorrection, solveSpp } from './positioning.cjs';
15
15
  export { NtripCaster, NtripConnectionInfo, NtripNetwork, NtripStream, NtripStreamConnection, NtripVersion, Sourcetable, SourcetableEntry, connectToMountpoint, fetchSourcetable, parseSourcetable } from './ntrip.cjs';
package/dist/index.d.ts CHANGED
@@ -4,12 +4,12 @@ export { A as ARC_GAP_FACTOR, B as BAND_LABELS, a as BDS_SATELLITES, b as BdsSat
4
4
  export { Scale, getBdsTime, getDateFromBdsTime, getDateFromDayOfWeek, getDateFromDayOfYear, getDateFromGalTime, getDateFromGloN, getDateFromGpsData, getDateFromGpsTime, getDateFromHourCode, getDateFromJulianDate, getDateFromMJD, getDateFromMJD2000, getDateFromRINEX, getDateFromTai, getDateFromTimeOfDay, getDateFromTt, getDateFromUnixTime, getDateFromUtc, getDayOfWeek, getDayOfYear, getGalTime, getGloN4, getGloNA, getGpsLeap, getGpsTime, getHourCode, getHoursFromTimeDifference, getJulianDate, getLeap, getMJD, getMJD2000, getMinutesFromTimeDifference, getNtpTime, getRINEX, getSecondsFromTimeDifference, getTaiDate, getTimeDifference, getTimeDifferenceFromDays, getTimeDifferenceFromHours, getTimeDifferenceFromMinutes, getTimeDifferenceFromObject, getTimeDifferenceFromSeconds, getTimeOfDay, getTimeOfWeek, getTotalDaysFromTimeDifference, getTtDate, getUnixTime, getUtcDate, getWeekNumber, getWeekOfYear } from './time.js';
5
5
  export { deg2dms, deg2rad, euclidean3D, geodeticToGeohash, geodeticToMaidenhead, geodeticToUtm, greatCircleMidpoint, horizonDistance, rad2deg, rhumbLine, vincenty } from './coordinates.js';
6
6
  export { c as clampUnit, e as ecefToGeodetic, g as geodeticToEcef, a as getAer, b as getEnuDifference } from './ecef-CF0uAysr.js';
7
- export { CrxField, DiffState, EMPTY_WARNINGS, RinexWarning, RinexWarnings, WarningAccumulator, WarningSeverity, crxDecompress, crxRepair, fmtF, hdrLine, padL, padR, parseCrxDataLine, writeRinexNav } from './rinex.js';
7
+ export { CrxField, DiffState, EMPTY_WARNINGS, IonexGrid, RinexWarning, RinexWarnings, WarningAccumulator, WarningSeverity, crxDecompress, crxRepair, fmtF, hdrLine, padL, padR, parseCrxDataLine, parseIonex, writeRinexNav } from './rinex.js';
8
8
  export { E as EpochSummary, P as ParseOptions, R as RinexHeader, a as RinexResult, b as RinexStats, S as SYSTEM_ORDER, c as SatObsCallback, p as parseRinexStream, s as systemCmp, d as systemName } from './parser-JPjjFgeP.js';
9
9
  export { E as Ephemeris, G as GlonassEphemeris, K as KeplerEphemeris, N as NavHeader, a as NavResult, p as parseNavFile } from './nav-BAI1a9vK.js';
10
10
  export { B as BitReader, E as EphemerisInfo, R as Rtcm3DebugHandler, a as Rtcm3Decoder, b as Rtcm3Frame, d as decodeEphemeris, r as readString, c as reportDecodeError, s as setRtcm3DebugHandler } from './ephemeris-Ohl6NAfw.js';
11
11
  export { MessageTypeStats, MsmEpoch, MsmSatObs, MsmSignal, RTCM3_MESSAGE_NAMES, SatCn0, SignalCn0, StationMeta, StreamStats, createStationMeta, createStreamStats, decodeMsmFull, msmEpochToDate, resetGloFreqCache, rtcm3Constellation, setGloFreqNumber, updateStationMeta, updateStreamStats } from './rtcm3.js';
12
- export { AllPositionsData, DopValues, EpochSkyData, SatAzEl, SatPoint, SatPosition, VisibilityPass, VisibilityResult, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, ecefToAzEl, ephInfoToEphemeris, glonassPosition, keplerPosition, navTimesFromEph, selectEphemeris } from './orbit.js';
12
+ export { AllPositionsData, DopValues, EpochSkyData, SatAzEl, SatPoint, SatPosition, VisibilityPass, VisibilityResult, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, ecefToAzEl, ephInfoToEphemeris, glonassPosition, keplerPosition, maskRadForAzimuth, navTimesFromEph, selectEphemeris } from './orbit.js';
13
13
  export { Helmert14, REFERENCE_FRAMES, ReferenceFrame, applyHelmert, dateToEpoch, transformFrame } from './frames.js';
14
14
  export { SppOptions, SppSolution, ionoFree, satClockCorrection, solveSpp } from './positioning.js';
15
15
  export { NtripCaster, NtripConnectionInfo, NtripNetwork, NtripStream, NtripStreamConnection, NtripVersion, Sourcetable, SourcetableEntry, connectToMountpoint, fetchSourcetable, parseSourcetable } from './ntrip.js';
package/dist/index.js CHANGED
@@ -102,7 +102,7 @@ import {
102
102
  ionoFree,
103
103
  satClockCorrection,
104
104
  solveSpp
105
- } from "./chunk-GXK4MMHS.js";
105
+ } from "./chunk-ZRBRVNHK.js";
106
106
  import {
107
107
  computeAllPositions,
108
108
  computeDop,
@@ -113,9 +113,10 @@ import {
113
113
  ephInfoToEphemeris,
114
114
  glonassPosition,
115
115
  keplerPosition,
116
+ maskRadForAzimuth,
116
117
  navTimesFromEph,
117
118
  selectEphemeris
118
- } from "./chunk-MN2DBDJL.js";
119
+ } from "./chunk-647YMBJV.js";
119
120
  import {
120
121
  getBdsTime,
121
122
  getDateFromBdsTime,
@@ -172,9 +173,10 @@ import {
172
173
  hdrLine,
173
174
  padL,
174
175
  padR,
176
+ parseIonex,
175
177
  parseNavFile,
176
178
  writeRinexNav
177
- } from "./chunk-W4YMQKWH.js";
179
+ } from "./chunk-77VUSDNI.js";
178
180
  import {
179
181
  SYSTEM_ORDER,
180
182
  crxDecompress,
@@ -431,6 +433,7 @@ export {
431
433
  horizonDistance,
432
434
  ionoFree,
433
435
  keplerPosition,
436
+ maskRadForAzimuth,
434
437
  msmEpochToDate,
435
438
  navTimesFromEph,
436
439
  nmeaCoordToDecimal,
@@ -438,6 +441,7 @@ export {
438
441
  padR,
439
442
  parseAntex,
440
443
  parseCrxDataLine,
444
+ parseIonex,
441
445
  parseNavFile,
442
446
  parseNmeaFile,
443
447
  parseRinexStream,
package/dist/orbit.cjs CHANGED
@@ -31,6 +31,7 @@ __export(orbit_exports, {
31
31
  geodeticToEcef: () => geodeticToEcef,
32
32
  glonassPosition: () => glonassPosition,
33
33
  keplerPosition: () => keplerPosition,
34
+ maskRadForAzimuth: () => maskRadForAzimuth,
34
35
  navTimesFromEph: () => navTimesFromEph,
35
36
  selectEphemeris: () => selectEphemeris
36
37
  });
@@ -590,14 +591,33 @@ function computeLiveSkyPositions(ephemerides, rxPos, cn0Map) {
590
591
  }
591
592
  return result;
592
593
  }
594
+ function maskRadForAzimuth(maskDeg) {
595
+ if (typeof maskDeg === "number") {
596
+ const m = maskDeg * Math.PI / 180;
597
+ return () => m;
598
+ }
599
+ const n = maskDeg.length;
600
+ if (n === 0) return () => 0;
601
+ return (azRad) => {
602
+ const azDeg = (azRad * 180 / Math.PI % 360 + 360) % 360;
603
+ const pos = azDeg / 360 * n;
604
+ const i = Math.floor(pos) % n;
605
+ const f = pos - Math.floor(pos);
606
+ const a = maskDeg[i];
607
+ const b = maskDeg[(i + 1) % n];
608
+ return ((1 - f) * a + f * b) * Math.PI / 180;
609
+ };
610
+ }
593
611
  function computeVisibility(ephemerides, rxPos, startMs, endMs, stepSec = 300, elevationMaskDeg = 10) {
594
612
  const stepMs = stepSec * 1e3;
595
613
  const times = [];
596
614
  for (let t = startMs; t <= endMs; t += stepMs) times.push(t);
597
- const maskRad = elevationMaskDeg * Math.PI / 180;
615
+ const maskRadFor = maskRadForAzimuth(elevationMaskDeg);
598
616
  const all = computeAllPositions(ephemerides, times, rxPos);
599
617
  const elevation = {};
600
618
  const azimuth = {};
619
+ const subLat = {};
620
+ const subLon = {};
601
621
  const visibleCount = new Array(times.length).fill(0);
602
622
  const pdop = new Array(times.length).fill(null);
603
623
  const gdop = new Array(times.length).fill(null);
@@ -608,9 +628,11 @@ function computeVisibility(ephemerides, rxPos, startMs, endMs, stepSec = 300, el
608
628
  const series = all.positions[prn];
609
629
  elevation[prn] = series.map((p) => p ? p.el : null);
610
630
  azimuth[prn] = series.map((p) => p ? p.az : null);
631
+ subLat[prn] = series.map((p) => p ? p.lat : null);
632
+ subLon[prn] = series.map((p) => p ? p.lon : null);
611
633
  for (let i = 0; i < series.length; i++) {
612
634
  const p = series[i];
613
- if (p && p.el >= maskRad) {
635
+ if (p && p.el >= maskRadFor(p.az)) {
614
636
  visibleCount[i]++;
615
637
  visiblePerEpoch[i].push({ az: p.az, el: p.el });
616
638
  }
@@ -631,7 +653,8 @@ function computeVisibility(ephemerides, rxPos, startMs, endMs, stepSec = 300, el
631
653
  let peakTime = 0;
632
654
  for (let i = 0; i <= els.length; i++) {
633
655
  const el = i < els.length ? els[i] : null;
634
- const above = el !== null && el !== void 0 && el >= maskRad;
656
+ const az = all.positions[prn][i]?.az ?? 0;
657
+ const above = el !== null && el !== void 0 && el >= maskRadFor(az);
635
658
  if (above) {
636
659
  if (start === -1) {
637
660
  start = i;
@@ -659,6 +682,8 @@ function computeVisibility(ephemerides, rxPos, startMs, endMs, stepSec = 300, el
659
682
  times,
660
683
  elevation,
661
684
  azimuth,
685
+ subLat,
686
+ subLon,
662
687
  visibleCount,
663
688
  pdop,
664
689
  gdop,
@@ -680,6 +705,7 @@ function computeVisibility(ephemerides, rxPos, startMs, endMs, stepSec = 300, el
680
705
  geodeticToEcef,
681
706
  glonassPosition,
682
707
  keplerPosition,
708
+ maskRadForAzimuth,
683
709
  navTimesFromEph,
684
710
  selectEphemeris
685
711
  });
package/dist/orbit.d.cts CHANGED
@@ -135,6 +135,10 @@ interface VisibilityResult {
135
135
  elevation: Record<string, (number | null)[]>;
136
136
  /** Azimuth (radians) per PRN per epoch; null when no valid ephemeris. */
137
137
  azimuth: Record<string, (number | null)[]>;
138
+ /** Sub-satellite latitude (radians) per PRN per epoch. */
139
+ subLat: Record<string, (number | null)[]>;
140
+ /** Sub-satellite longitude (radians) per PRN per epoch. */
141
+ subLon: Record<string, (number | null)[]>;
138
142
  /** Number of satellites at or above the mask, per epoch. */
139
143
  visibleCount: number[];
140
144
  /** PDOP per epoch (null when < 4 satellites above the mask). */
@@ -148,6 +152,12 @@ interface VisibilityResult {
148
152
  /** Discrete above-mask passes, sorted by rise time. */
149
153
  passes: VisibilityPass[];
150
154
  }
155
+ /**
156
+ * Build a mask lookup (radians) from a scalar or per-azimuth array of
157
+ * mask values in degrees. Array entries span 0–360° uniformly and are
158
+ * linearly interpolated.
159
+ */
160
+ declare function maskRadForAzimuth(maskDeg: number | number[]): (azRad: number) => number;
151
161
  /**
152
162
  * Predict satellite visibility and DOP over a time window for a fixed
153
163
  * receiver location.
@@ -157,8 +167,11 @@ interface VisibilityResult {
157
167
  * @param startMs Window start (Unix ms).
158
168
  * @param endMs Window end (Unix ms).
159
169
  * @param stepSec Sample spacing in seconds (default 300).
160
- * @param elevationMaskDeg Elevation mask in degrees (default 10).
170
+ * @param elevationMaskDeg Elevation mask in degrees (default 10) — a
171
+ * scalar, or an array of per-azimuth mask values in degrees
172
+ * (uniformly spanning 0–360°, e.g. 36 sectors of 10°) describing a
173
+ * local horizon/obstruction profile.
161
174
  */
162
- declare function computeVisibility(ephemerides: Ephemeris[], rxPos: [number, number, number], startMs: number, endMs: number, stepSec?: number, elevationMaskDeg?: number): VisibilityResult;
175
+ declare function computeVisibility(ephemerides: Ephemeris[], rxPos: [number, number, number], startMs: number, endMs: number, stepSec?: number, elevationMaskDeg?: number | number[]): VisibilityResult;
163
176
 
164
- export { type AllPositionsData, type DopValues, type EpochSkyData, type SatAzEl, type SatPoint, type SatPosition, type VisibilityPass, type VisibilityResult, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, ecefToAzEl, ephInfoToEphemeris, glonassPosition, keplerPosition, navTimesFromEph, selectEphemeris };
177
+ export { type AllPositionsData, type DopValues, type EpochSkyData, type SatAzEl, type SatPoint, type SatPosition, type VisibilityPass, type VisibilityResult, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, ecefToAzEl, ephInfoToEphemeris, glonassPosition, keplerPosition, maskRadForAzimuth, navTimesFromEph, selectEphemeris };
package/dist/orbit.d.ts CHANGED
@@ -135,6 +135,10 @@ interface VisibilityResult {
135
135
  elevation: Record<string, (number | null)[]>;
136
136
  /** Azimuth (radians) per PRN per epoch; null when no valid ephemeris. */
137
137
  azimuth: Record<string, (number | null)[]>;
138
+ /** Sub-satellite latitude (radians) per PRN per epoch. */
139
+ subLat: Record<string, (number | null)[]>;
140
+ /** Sub-satellite longitude (radians) per PRN per epoch. */
141
+ subLon: Record<string, (number | null)[]>;
138
142
  /** Number of satellites at or above the mask, per epoch. */
139
143
  visibleCount: number[];
140
144
  /** PDOP per epoch (null when < 4 satellites above the mask). */
@@ -148,6 +152,12 @@ interface VisibilityResult {
148
152
  /** Discrete above-mask passes, sorted by rise time. */
149
153
  passes: VisibilityPass[];
150
154
  }
155
+ /**
156
+ * Build a mask lookup (radians) from a scalar or per-azimuth array of
157
+ * mask values in degrees. Array entries span 0–360° uniformly and are
158
+ * linearly interpolated.
159
+ */
160
+ declare function maskRadForAzimuth(maskDeg: number | number[]): (azRad: number) => number;
151
161
  /**
152
162
  * Predict satellite visibility and DOP over a time window for a fixed
153
163
  * receiver location.
@@ -157,8 +167,11 @@ interface VisibilityResult {
157
167
  * @param startMs Window start (Unix ms).
158
168
  * @param endMs Window end (Unix ms).
159
169
  * @param stepSec Sample spacing in seconds (default 300).
160
- * @param elevationMaskDeg Elevation mask in degrees (default 10).
170
+ * @param elevationMaskDeg Elevation mask in degrees (default 10) — a
171
+ * scalar, or an array of per-azimuth mask values in degrees
172
+ * (uniformly spanning 0–360°, e.g. 36 sectors of 10°) describing a
173
+ * local horizon/obstruction profile.
161
174
  */
162
- declare function computeVisibility(ephemerides: Ephemeris[], rxPos: [number, number, number], startMs: number, endMs: number, stepSec?: number, elevationMaskDeg?: number): VisibilityResult;
175
+ declare function computeVisibility(ephemerides: Ephemeris[], rxPos: [number, number, number], startMs: number, endMs: number, stepSec?: number, elevationMaskDeg?: number | number[]): VisibilityResult;
163
176
 
164
- export { type AllPositionsData, type DopValues, type EpochSkyData, type SatAzEl, type SatPoint, type SatPosition, type VisibilityPass, type VisibilityResult, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, ecefToAzEl, ephInfoToEphemeris, glonassPosition, keplerPosition, navTimesFromEph, selectEphemeris };
177
+ export { type AllPositionsData, type DopValues, type EpochSkyData, type SatAzEl, type SatPoint, type SatPosition, type VisibilityPass, type VisibilityResult, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, ecefToAzEl, ephInfoToEphemeris, glonassPosition, keplerPosition, maskRadForAzimuth, navTimesFromEph, selectEphemeris };
package/dist/orbit.js CHANGED
@@ -8,9 +8,10 @@ import {
8
8
  ephInfoToEphemeris,
9
9
  glonassPosition,
10
10
  keplerPosition,
11
+ maskRadForAzimuth,
11
12
  navTimesFromEph,
12
13
  selectEphemeris
13
- } from "./chunk-MN2DBDJL.js";
14
+ } from "./chunk-647YMBJV.js";
14
15
  import "./chunk-HVXYFUCB.js";
15
16
  import {
16
17
  ecefToGeodetic,
@@ -31,6 +32,7 @@ export {
31
32
  geodeticToEcef,
32
33
  glonassPosition,
33
34
  keplerPosition,
35
+ maskRadForAzimuth,
34
36
  navTimesFromEph,
35
37
  selectEphemeris
36
38
  };
@@ -2,8 +2,8 @@ import {
2
2
  ionoFree,
3
3
  satClockCorrection,
4
4
  solveSpp
5
- } from "./chunk-GXK4MMHS.js";
6
- import "./chunk-MN2DBDJL.js";
5
+ } from "./chunk-ZRBRVNHK.js";
6
+ import "./chunk-647YMBJV.js";
7
7
  import "./chunk-HVXYFUCB.js";
8
8
  import "./chunk-37QNKGTC.js";
9
9
  import "./chunk-6FAL6P4G.js";
package/dist/rinex.cjs CHANGED
@@ -30,6 +30,7 @@ __export(rinex_exports, {
30
30
  padL: () => padL,
31
31
  padR: () => padR,
32
32
  parseCrxDataLine: () => parseCrxDataLine,
33
+ parseIonex: () => parseIonex,
33
34
  parseNavFile: () => parseNavFile,
34
35
  parseRinexStream: () => parseRinexStream,
35
36
  systemCmp: () => systemCmp,
@@ -1449,6 +1450,91 @@ function writeRinexNav(nav) {
1449
1450
  );
1450
1451
  return header + records.join("\n") + "\n";
1451
1452
  }
1453
+
1454
+ // src/rinex/ionex.ts
1455
+ function gridRange(l1, l2, dl) {
1456
+ const out = [];
1457
+ const n = Math.round((l2 - l1) / dl) + 1;
1458
+ for (let i = 0; i < n; i++) out.push(l1 + i * dl);
1459
+ return out;
1460
+ }
1461
+ function parseIonex(text) {
1462
+ const lines = text.split("\n");
1463
+ let exponent = -1;
1464
+ let lats = [];
1465
+ let lons = [];
1466
+ const epochs = [];
1467
+ const maps = [];
1468
+ let i = 0;
1469
+ for (; i < lines.length; i++) {
1470
+ const line = lines[i];
1471
+ const label = line.slice(60).trim();
1472
+ if (label === "EXPONENT") {
1473
+ exponent = parseInt(line.slice(0, 60).trim(), 10);
1474
+ } else if (label === "LAT1 / LAT2 / DLAT") {
1475
+ const [a, b, d] = line.trim().split(/\s+/).map(Number);
1476
+ lats = gridRange(a, b, d);
1477
+ } else if (label === "LON1 / LON2 / DLON") {
1478
+ const [a, b, d] = line.trim().split(/\s+/).map(Number);
1479
+ lons = gridRange(a, b, d);
1480
+ } else if (label === "END OF HEADER") {
1481
+ i++;
1482
+ break;
1483
+ }
1484
+ }
1485
+ if (lats.length === 0 || lons.length === 0) {
1486
+ throw new Error("IONEX: missing grid definition");
1487
+ }
1488
+ const scale = Math.pow(10, exponent);
1489
+ while (i < lines.length) {
1490
+ const line = lines[i];
1491
+ const label = line.slice(60).trim();
1492
+ if (label === "START OF TEC MAP") {
1493
+ const map = new Float32Array(lats.length * lons.length).fill(NaN);
1494
+ let epochMs = 0;
1495
+ i++;
1496
+ while (i < lines.length) {
1497
+ const l = lines[i];
1498
+ const lab = l.slice(60).trim();
1499
+ if (lab === "EPOCH OF CURRENT MAP") {
1500
+ const f = l.slice(0, 60).trim().split(/\s+/).map(Number);
1501
+ epochMs = Date.UTC(f[0], f[1] - 1, f[2], f[3], f[4], f[5]);
1502
+ i++;
1503
+ } else if (lab === "LAT/LON1/LON2/DLON/H") {
1504
+ const lat = parseFloat(l.slice(2, 8));
1505
+ const latIdx = lats.findIndex((v) => Math.abs(v - lat) < 1e-6);
1506
+ i++;
1507
+ let lonIdx = 0;
1508
+ while (lonIdx < lons.length && i < lines.length) {
1509
+ const row = lines[i];
1510
+ for (let c = 0; c + 5 <= 80 && lonIdx < lons.length; c += 5) {
1511
+ const vStr = row.slice(c, c + 5).trim();
1512
+ if (vStr === "") continue;
1513
+ const v = parseInt(vStr, 10);
1514
+ if (latIdx >= 0) {
1515
+ map[latIdx * lons.length + lonIdx] = v === 9999 ? NaN : v * scale;
1516
+ }
1517
+ lonIdx++;
1518
+ }
1519
+ i++;
1520
+ }
1521
+ } else if (lab === "END OF TEC MAP") {
1522
+ i++;
1523
+ break;
1524
+ } else {
1525
+ i++;
1526
+ }
1527
+ }
1528
+ epochs.push(epochMs);
1529
+ maps.push(map);
1530
+ } else if (label === "START OF RMS MAP" || label === "END OF FILE") {
1531
+ break;
1532
+ } else {
1533
+ i++;
1534
+ }
1535
+ }
1536
+ return { epochs, lats, lons, maps };
1537
+ }
1452
1538
  // Annotate the CommonJS export names for ESM import in node:
1453
1539
  0 && (module.exports = {
1454
1540
  EMPTY_WARNINGS,
@@ -1461,6 +1547,7 @@ function writeRinexNav(nav) {
1461
1547
  padL,
1462
1548
  padR,
1463
1549
  parseCrxDataLine,
1550
+ parseIonex,
1464
1551
  parseNavFile,
1465
1552
  parseRinexStream,
1466
1553
  systemCmp,
package/dist/rinex.d.cts CHANGED
@@ -113,4 +113,26 @@ declare class WarningAccumulator {
113
113
  */
114
114
  declare function writeRinexNav(nav: NavResult): string;
115
115
 
116
- export { type CrxField, type DiffState, EMPTY_WARNINGS, NavResult, RinexHeader, type RinexWarning, type RinexWarnings, WarningAccumulator, type WarningSeverity, crxDecompress, crxRepair, fmtF, hdrLine, padL, padR, parseCrxDataLine, writeRinexNav };
116
+ /**
117
+ * IONEX 1.0 parser — global ionosphere maps (GIMs) as published by
118
+ * the IGS analysis centres (e.g. ESA0OPSRAP_*_GIM.INX).
119
+ *
120
+ * Returns the TEC maps in TECU on a regular lat/lon grid, one map per
121
+ * epoch. RMS maps and the DCB auxiliary block are skipped.
122
+ */
123
+ interface IonexGrid {
124
+ /** Map epochs (Unix ms, UTC). */
125
+ epochs: number[];
126
+ /** Grid latitudes (degrees), in file order (typically 87.5 → −87.5). */
127
+ lats: number[];
128
+ /** Grid longitudes (degrees), in file order (typically −180 → 180). */
129
+ lons: number[];
130
+ /**
131
+ * TEC maps in TECU: maps[epochIdx][latIdx * lons.length + lonIdx].
132
+ * NaN where the file marks no value (9999).
133
+ */
134
+ maps: Float32Array[];
135
+ }
136
+ declare function parseIonex(text: string): IonexGrid;
137
+
138
+ export { type CrxField, type DiffState, EMPTY_WARNINGS, type IonexGrid, NavResult, RinexHeader, type RinexWarning, type RinexWarnings, WarningAccumulator, type WarningSeverity, crxDecompress, crxRepair, fmtF, hdrLine, padL, padR, parseCrxDataLine, parseIonex, writeRinexNav };
package/dist/rinex.d.ts CHANGED
@@ -113,4 +113,26 @@ declare class WarningAccumulator {
113
113
  */
114
114
  declare function writeRinexNav(nav: NavResult): string;
115
115
 
116
- export { type CrxField, type DiffState, EMPTY_WARNINGS, NavResult, RinexHeader, type RinexWarning, type RinexWarnings, WarningAccumulator, type WarningSeverity, crxDecompress, crxRepair, fmtF, hdrLine, padL, padR, parseCrxDataLine, writeRinexNav };
116
+ /**
117
+ * IONEX 1.0 parser — global ionosphere maps (GIMs) as published by
118
+ * the IGS analysis centres (e.g. ESA0OPSRAP_*_GIM.INX).
119
+ *
120
+ * Returns the TEC maps in TECU on a regular lat/lon grid, one map per
121
+ * epoch. RMS maps and the DCB auxiliary block are skipped.
122
+ */
123
+ interface IonexGrid {
124
+ /** Map epochs (Unix ms, UTC). */
125
+ epochs: number[];
126
+ /** Grid latitudes (degrees), in file order (typically 87.5 → −87.5). */
127
+ lats: number[];
128
+ /** Grid longitudes (degrees), in file order (typically −180 → 180). */
129
+ lons: number[];
130
+ /**
131
+ * TEC maps in TECU: maps[epochIdx][latIdx * lons.length + lonIdx].
132
+ * NaN where the file marks no value (9999).
133
+ */
134
+ maps: Float32Array[];
135
+ }
136
+ declare function parseIonex(text: string): IonexGrid;
137
+
138
+ export { type CrxField, type DiffState, EMPTY_WARNINGS, type IonexGrid, NavResult, RinexHeader, type RinexWarning, type RinexWarnings, WarningAccumulator, type WarningSeverity, crxDecompress, crxRepair, fmtF, hdrLine, padL, padR, parseCrxDataLine, parseIonex, writeRinexNav };
package/dist/rinex.js CHANGED
@@ -5,9 +5,10 @@ import {
5
5
  hdrLine,
6
6
  padL,
7
7
  padR,
8
+ parseIonex,
8
9
  parseNavFile,
9
10
  writeRinexNav
10
- } from "./chunk-W4YMQKWH.js";
11
+ } from "./chunk-77VUSDNI.js";
11
12
  import {
12
13
  SYSTEM_ORDER,
13
14
  crxDecompress,
@@ -29,6 +30,7 @@ export {
29
30
  padL,
30
31
  padR,
31
32
  parseCrxDataLine,
33
+ parseIonex,
32
34
  parseNavFile,
33
35
  parseRinexStream,
34
36
  systemCmp,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gnss-js",
3
- "version": "1.8.0",
3
+ "version": "1.9.0",
4
4
  "description": "Comprehensive GNSS library for JavaScript — time scales, coordinates, RINEX parsing, RTCM3 decoding, orbit computation, and signal analysis",
5
5
  "type": "module",
6
6
  "sideEffects": false,