gnss-js 1.8.0 → 1.10.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-W4YMQKWH.js → chunk-77VUSDNI.js} +87 -1
- package/dist/{chunk-MN2DBDJL.js → chunk-AK6LNWZX.js} +32 -3
- package/dist/{chunk-GXK4MMHS.js → chunk-ZTFKRZMM.js} +1 -1
- package/dist/index.cjs +120 -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 +33 -3
- package/dist/orbit.d.cts +18 -3
- package/dist/orbit.d.ts +18 -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
|
@@ -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
|
};
|
|
@@ -437,15 +437,35 @@ 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);
|
|
468
|
+
const visibleBySystem = {};
|
|
449
469
|
const pdop = new Array(times.length).fill(null);
|
|
450
470
|
const gdop = new Array(times.length).fill(null);
|
|
451
471
|
const hdop = new Array(times.length).fill(null);
|
|
@@ -455,10 +475,14 @@ function computeVisibility(ephemerides, rxPos, startMs, endMs, stepSec = 300, el
|
|
|
455
475
|
const series = all.positions[prn];
|
|
456
476
|
elevation[prn] = series.map((p) => p ? p.el : null);
|
|
457
477
|
azimuth[prn] = series.map((p) => p ? p.az : null);
|
|
478
|
+
subLat[prn] = series.map((p) => p ? p.lat : null);
|
|
479
|
+
subLon[prn] = series.map((p) => p ? p.lon : null);
|
|
458
480
|
for (let i = 0; i < series.length; i++) {
|
|
459
481
|
const p = series[i];
|
|
460
|
-
if (p && p.el >=
|
|
482
|
+
if (p && p.el >= maskRadFor(p.az)) {
|
|
461
483
|
visibleCount[i]++;
|
|
484
|
+
const sys = prn[0];
|
|
485
|
+
(visibleBySystem[sys] ??= new Array(times.length).fill(0))[i]++;
|
|
462
486
|
visiblePerEpoch[i].push({ az: p.az, el: p.el });
|
|
463
487
|
}
|
|
464
488
|
}
|
|
@@ -478,7 +502,8 @@ function computeVisibility(ephemerides, rxPos, startMs, endMs, stepSec = 300, el
|
|
|
478
502
|
let peakTime = 0;
|
|
479
503
|
for (let i = 0; i <= els.length; i++) {
|
|
480
504
|
const el = i < els.length ? els[i] : null;
|
|
481
|
-
const
|
|
505
|
+
const az = all.positions[prn][i]?.az ?? 0;
|
|
506
|
+
const above = el !== null && el !== void 0 && el >= maskRadFor(az);
|
|
482
507
|
if (above) {
|
|
483
508
|
if (start === -1) {
|
|
484
509
|
start = i;
|
|
@@ -506,7 +531,10 @@ function computeVisibility(ephemerides, rxPos, startMs, endMs, stepSec = 300, el
|
|
|
506
531
|
times,
|
|
507
532
|
elevation,
|
|
508
533
|
azimuth,
|
|
534
|
+
subLat,
|
|
535
|
+
subLon,
|
|
509
536
|
visibleCount,
|
|
537
|
+
visibleBySystem,
|
|
510
538
|
pdop,
|
|
511
539
|
gdop,
|
|
512
540
|
hdop,
|
|
@@ -526,5 +554,6 @@ export {
|
|
|
526
554
|
computeAllPositions,
|
|
527
555
|
ephInfoToEphemeris,
|
|
528
556
|
computeLiveSkyPositions,
|
|
557
|
+
maskRadForAzimuth,
|
|
529
558
|
computeVisibility
|
|
530
559
|
};
|
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,15 +4514,35 @@ 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);
|
|
4545
|
+
const visibleBySystem = {};
|
|
4439
4546
|
const pdop = new Array(times.length).fill(null);
|
|
4440
4547
|
const gdop = new Array(times.length).fill(null);
|
|
4441
4548
|
const hdop = new Array(times.length).fill(null);
|
|
@@ -4445,10 +4552,14 @@ function computeVisibility(ephemerides, rxPos, startMs, endMs, stepSec = 300, el
|
|
|
4445
4552
|
const series = all.positions[prn];
|
|
4446
4553
|
elevation[prn] = series.map((p) => p ? p.el : null);
|
|
4447
4554
|
azimuth[prn] = series.map((p) => p ? p.az : null);
|
|
4555
|
+
subLat[prn] = series.map((p) => p ? p.lat : null);
|
|
4556
|
+
subLon[prn] = series.map((p) => p ? p.lon : null);
|
|
4448
4557
|
for (let i = 0; i < series.length; i++) {
|
|
4449
4558
|
const p = series[i];
|
|
4450
|
-
if (p && p.el >=
|
|
4559
|
+
if (p && p.el >= maskRadFor(p.az)) {
|
|
4451
4560
|
visibleCount[i]++;
|
|
4561
|
+
const sys = prn[0];
|
|
4562
|
+
(visibleBySystem[sys] ??= new Array(times.length).fill(0))[i]++;
|
|
4452
4563
|
visiblePerEpoch[i].push({ az: p.az, el: p.el });
|
|
4453
4564
|
}
|
|
4454
4565
|
}
|
|
@@ -4468,7 +4579,8 @@ function computeVisibility(ephemerides, rxPos, startMs, endMs, stepSec = 300, el
|
|
|
4468
4579
|
let peakTime = 0;
|
|
4469
4580
|
for (let i = 0; i <= els.length; i++) {
|
|
4470
4581
|
const el = i < els.length ? els[i] : null;
|
|
4471
|
-
const
|
|
4582
|
+
const az = all.positions[prn][i]?.az ?? 0;
|
|
4583
|
+
const above = el !== null && el !== void 0 && el >= maskRadFor(az);
|
|
4472
4584
|
if (above) {
|
|
4473
4585
|
if (start === -1) {
|
|
4474
4586
|
start = i;
|
|
@@ -4496,7 +4608,10 @@ function computeVisibility(ephemerides, rxPos, startMs, endMs, stepSec = 300, el
|
|
|
4496
4608
|
times,
|
|
4497
4609
|
elevation,
|
|
4498
4610
|
azimuth,
|
|
4611
|
+
subLat,
|
|
4612
|
+
subLon,
|
|
4499
4613
|
visibleCount,
|
|
4614
|
+
visibleBySystem,
|
|
4500
4615
|
pdop,
|
|
4501
4616
|
gdop,
|
|
4502
4617
|
hdop,
|
|
@@ -7353,6 +7468,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
7353
7468
|
horizonDistance,
|
|
7354
7469
|
ionoFree,
|
|
7355
7470
|
keplerPosition,
|
|
7471
|
+
maskRadForAzimuth,
|
|
7356
7472
|
msmEpochToDate,
|
|
7357
7473
|
navTimesFromEph,
|
|
7358
7474
|
nmeaCoordToDecimal,
|
|
@@ -7360,6 +7476,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
7360
7476
|
padR,
|
|
7361
7477
|
parseAntex,
|
|
7362
7478
|
parseCrxDataLine,
|
|
7479
|
+
parseIonex,
|
|
7363
7480
|
parseNavFile,
|
|
7364
7481
|
parseNmeaFile,
|
|
7365
7482
|
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-ZTFKRZMM.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-AK6LNWZX.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,15 +591,35 @@ 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);
|
|
622
|
+
const visibleBySystem = {};
|
|
602
623
|
const pdop = new Array(times.length).fill(null);
|
|
603
624
|
const gdop = new Array(times.length).fill(null);
|
|
604
625
|
const hdop = new Array(times.length).fill(null);
|
|
@@ -608,10 +629,14 @@ function computeVisibility(ephemerides, rxPos, startMs, endMs, stepSec = 300, el
|
|
|
608
629
|
const series = all.positions[prn];
|
|
609
630
|
elevation[prn] = series.map((p) => p ? p.el : null);
|
|
610
631
|
azimuth[prn] = series.map((p) => p ? p.az : null);
|
|
632
|
+
subLat[prn] = series.map((p) => p ? p.lat : null);
|
|
633
|
+
subLon[prn] = series.map((p) => p ? p.lon : null);
|
|
611
634
|
for (let i = 0; i < series.length; i++) {
|
|
612
635
|
const p = series[i];
|
|
613
|
-
if (p && p.el >=
|
|
636
|
+
if (p && p.el >= maskRadFor(p.az)) {
|
|
614
637
|
visibleCount[i]++;
|
|
638
|
+
const sys = prn[0];
|
|
639
|
+
(visibleBySystem[sys] ??= new Array(times.length).fill(0))[i]++;
|
|
615
640
|
visiblePerEpoch[i].push({ az: p.az, el: p.el });
|
|
616
641
|
}
|
|
617
642
|
}
|
|
@@ -631,7 +656,8 @@ function computeVisibility(ephemerides, rxPos, startMs, endMs, stepSec = 300, el
|
|
|
631
656
|
let peakTime = 0;
|
|
632
657
|
for (let i = 0; i <= els.length; i++) {
|
|
633
658
|
const el = i < els.length ? els[i] : null;
|
|
634
|
-
const
|
|
659
|
+
const az = all.positions[prn][i]?.az ?? 0;
|
|
660
|
+
const above = el !== null && el !== void 0 && el >= maskRadFor(az);
|
|
635
661
|
if (above) {
|
|
636
662
|
if (start === -1) {
|
|
637
663
|
start = i;
|
|
@@ -659,7 +685,10 @@ function computeVisibility(ephemerides, rxPos, startMs, endMs, stepSec = 300, el
|
|
|
659
685
|
times,
|
|
660
686
|
elevation,
|
|
661
687
|
azimuth,
|
|
688
|
+
subLat,
|
|
689
|
+
subLon,
|
|
662
690
|
visibleCount,
|
|
691
|
+
visibleBySystem,
|
|
663
692
|
pdop,
|
|
664
693
|
gdop,
|
|
665
694
|
hdop,
|
|
@@ -680,6 +709,7 @@ function computeVisibility(ephemerides, rxPos, startMs, endMs, stepSec = 300, el
|
|
|
680
709
|
geodeticToEcef,
|
|
681
710
|
glonassPosition,
|
|
682
711
|
keplerPosition,
|
|
712
|
+
maskRadForAzimuth,
|
|
683
713
|
navTimesFromEph,
|
|
684
714
|
selectEphemeris
|
|
685
715
|
});
|
package/dist/orbit.d.cts
CHANGED
|
@@ -135,8 +135,14 @@ 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[];
|
|
144
|
+
/** Per-system visible counts per epoch (system letter → counts). */
|
|
145
|
+
visibleBySystem: Record<string, number[]>;
|
|
140
146
|
/** PDOP per epoch (null when < 4 satellites above the mask). */
|
|
141
147
|
pdop: (number | null)[];
|
|
142
148
|
/** GDOP per epoch (null when < 4 satellites above the mask). */
|
|
@@ -148,6 +154,12 @@ interface VisibilityResult {
|
|
|
148
154
|
/** Discrete above-mask passes, sorted by rise time. */
|
|
149
155
|
passes: VisibilityPass[];
|
|
150
156
|
}
|
|
157
|
+
/**
|
|
158
|
+
* Build a mask lookup (radians) from a scalar or per-azimuth array of
|
|
159
|
+
* mask values in degrees. Array entries span 0–360° uniformly and are
|
|
160
|
+
* linearly interpolated.
|
|
161
|
+
*/
|
|
162
|
+
declare function maskRadForAzimuth(maskDeg: number | number[]): (azRad: number) => number;
|
|
151
163
|
/**
|
|
152
164
|
* Predict satellite visibility and DOP over a time window for a fixed
|
|
153
165
|
* receiver location.
|
|
@@ -157,8 +169,11 @@ interface VisibilityResult {
|
|
|
157
169
|
* @param startMs Window start (Unix ms).
|
|
158
170
|
* @param endMs Window end (Unix ms).
|
|
159
171
|
* @param stepSec Sample spacing in seconds (default 300).
|
|
160
|
-
* @param elevationMaskDeg Elevation mask in degrees (default 10)
|
|
172
|
+
* @param elevationMaskDeg Elevation mask in degrees (default 10) — a
|
|
173
|
+
* scalar, or an array of per-azimuth mask values in degrees
|
|
174
|
+
* (uniformly spanning 0–360°, e.g. 36 sectors of 10°) describing a
|
|
175
|
+
* local horizon/obstruction profile.
|
|
161
176
|
*/
|
|
162
|
-
declare function computeVisibility(ephemerides: Ephemeris[], rxPos: [number, number, number], startMs: number, endMs: number, stepSec?: number, elevationMaskDeg?: number): VisibilityResult;
|
|
177
|
+
declare function computeVisibility(ephemerides: Ephemeris[], rxPos: [number, number, number], startMs: number, endMs: number, stepSec?: number, elevationMaskDeg?: number | number[]): VisibilityResult;
|
|
163
178
|
|
|
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 };
|
|
179
|
+
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,8 +135,14 @@ 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[];
|
|
144
|
+
/** Per-system visible counts per epoch (system letter → counts). */
|
|
145
|
+
visibleBySystem: Record<string, number[]>;
|
|
140
146
|
/** PDOP per epoch (null when < 4 satellites above the mask). */
|
|
141
147
|
pdop: (number | null)[];
|
|
142
148
|
/** GDOP per epoch (null when < 4 satellites above the mask). */
|
|
@@ -148,6 +154,12 @@ interface VisibilityResult {
|
|
|
148
154
|
/** Discrete above-mask passes, sorted by rise time. */
|
|
149
155
|
passes: VisibilityPass[];
|
|
150
156
|
}
|
|
157
|
+
/**
|
|
158
|
+
* Build a mask lookup (radians) from a scalar or per-azimuth array of
|
|
159
|
+
* mask values in degrees. Array entries span 0–360° uniformly and are
|
|
160
|
+
* linearly interpolated.
|
|
161
|
+
*/
|
|
162
|
+
declare function maskRadForAzimuth(maskDeg: number | number[]): (azRad: number) => number;
|
|
151
163
|
/**
|
|
152
164
|
* Predict satellite visibility and DOP over a time window for a fixed
|
|
153
165
|
* receiver location.
|
|
@@ -157,8 +169,11 @@ interface VisibilityResult {
|
|
|
157
169
|
* @param startMs Window start (Unix ms).
|
|
158
170
|
* @param endMs Window end (Unix ms).
|
|
159
171
|
* @param stepSec Sample spacing in seconds (default 300).
|
|
160
|
-
* @param elevationMaskDeg Elevation mask in degrees (default 10)
|
|
172
|
+
* @param elevationMaskDeg Elevation mask in degrees (default 10) — a
|
|
173
|
+
* scalar, or an array of per-azimuth mask values in degrees
|
|
174
|
+
* (uniformly spanning 0–360°, e.g. 36 sectors of 10°) describing a
|
|
175
|
+
* local horizon/obstruction profile.
|
|
161
176
|
*/
|
|
162
|
-
declare function computeVisibility(ephemerides: Ephemeris[], rxPos: [number, number, number], startMs: number, endMs: number, stepSec?: number, elevationMaskDeg?: number): VisibilityResult;
|
|
177
|
+
declare function computeVisibility(ephemerides: Ephemeris[], rxPos: [number, number, number], startMs: number, endMs: number, stepSec?: number, elevationMaskDeg?: number | number[]): VisibilityResult;
|
|
163
178
|
|
|
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 };
|
|
179
|
+
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-AK6LNWZX.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-ZTFKRZMM.js";
|
|
6
|
+
import "./chunk-AK6LNWZX.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.10.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,
|