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.
- package/dist/{chunk-MN2DBDJL.js → chunk-647YMBJV.js} +28 -3
- package/dist/{chunk-W4YMQKWH.js → chunk-77VUSDNI.js} +87 -1
- package/dist/{chunk-GXK4MMHS.js → chunk-ZRBRVNHK.js} +1 -1
- package/dist/index.cjs +116 -3
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +7 -3
- package/dist/orbit.cjs +29 -3
- package/dist/orbit.d.cts +16 -3
- package/dist/orbit.d.ts +16 -3
- package/dist/orbit.js +3 -1
- package/dist/positioning.js +2 -2
- package/dist/rinex.cjs +87 -0
- package/dist/rinex.d.cts +23 -1
- package/dist/rinex.d.ts +23 -1
- package/dist/rinex.js +3 -1
- package/package.json +1 -1
|
@@ -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
|
|
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 >=
|
|
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
|
|
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
|
};
|
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
|
|
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 >=
|
|
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
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
|
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 >=
|
|
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
|
|
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-
|
|
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
|
};
|
package/dist/positioning.js
CHANGED
|
@@ -2,8 +2,8 @@ import {
|
|
|
2
2
|
ionoFree,
|
|
3
3
|
satClockCorrection,
|
|
4
4
|
solveSpp
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
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
|
-
|
|
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
|
-
|
|
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-
|
|
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.
|
|
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,
|