gnss-js 1.27.0 → 1.29.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.
@@ -0,0 +1,120 @@
1
+ // src/rinex/sp3.ts
2
+ var BAD_CLOCK = 999999.999999;
3
+ function parseSp3(text) {
4
+ const lines = text.split("\n");
5
+ const epochs = [];
6
+ const satellites = {};
7
+ let version = "";
8
+ let intervalSec = 0;
9
+ let timeSystem = "GPS";
10
+ let timeSystemSet = false;
11
+ let epochIdx = -1;
12
+ for (const line of lines) {
13
+ if (!version && line.startsWith("#") && line.charAt(1) !== "#") {
14
+ version = line.charAt(1);
15
+ }
16
+ if (line.startsWith("##")) {
17
+ const f = line.slice(2).trim().split(/\s+/);
18
+ intervalSec = Number(f[2]) || 0;
19
+ } else if (line.startsWith("%c") && !timeSystemSet) {
20
+ const sys = line.slice(9, 12).trim();
21
+ if (sys && !/^c+$/.test(sys)) {
22
+ timeSystem = sys;
23
+ timeSystemSet = true;
24
+ }
25
+ } else if (line.startsWith("*")) {
26
+ const f = line.slice(1).trim().split(/\s+/).map(Number);
27
+ if (f.length >= 6 && f.every(Number.isFinite)) {
28
+ const sec = f[5];
29
+ epochs.push(
30
+ Date.UTC(
31
+ f[0],
32
+ f[1] - 1,
33
+ f[2],
34
+ f[3],
35
+ f[4],
36
+ Math.floor(sec),
37
+ Math.round(sec % 1 * 1e3)
38
+ )
39
+ );
40
+ epochIdx++;
41
+ }
42
+ } else if (line.startsWith("P") && epochIdx >= 0) {
43
+ const prn = line.slice(1, 4).replace(/\s/g, "0");
44
+ const f = line.slice(4).trim().split(/\s+/).map(Number);
45
+ if (f.length < 3) continue;
46
+ const [xKm, yKm, zKm] = f;
47
+ let arr = satellites[prn];
48
+ if (!arr) satellites[prn] = arr = [];
49
+ while (arr.length < epochIdx) arr.push(null);
50
+ if (xKm === 0 && yKm === 0 && zKm === 0) {
51
+ arr.push(null);
52
+ continue;
53
+ }
54
+ const clkUs = f[3];
55
+ arr.push({
56
+ x: xKm * 1e3,
57
+ y: yKm * 1e3,
58
+ z: zKm * 1e3,
59
+ clk: clkUs !== void 0 && Math.abs(clkUs) < BAD_CLOCK ? clkUs * 1e-6 : null
60
+ });
61
+ }
62
+ }
63
+ for (const arr of Object.values(satellites)) {
64
+ while (arr.length < epochs.length) arr.push(null);
65
+ }
66
+ return { version, epochs, intervalSec, timeSystem, satellites };
67
+ }
68
+ function sp3Position(sp3, prn, tMs, order = 9) {
69
+ const samples = sp3.satellites[prn];
70
+ const { epochs } = sp3;
71
+ const n = epochs.length;
72
+ if (!samples || n < order) return null;
73
+ if (tMs < epochs[0] || tMs > epochs[n - 1]) return null;
74
+ let lo = 0;
75
+ let hi = n - 1;
76
+ while (lo < hi) {
77
+ const mid = lo + hi + 1 >> 1;
78
+ if (epochs[mid] <= tMs) lo = mid;
79
+ else hi = mid - 1;
80
+ }
81
+ let start = lo - (order >> 1) + (order % 2 === 0 ? 1 : 0);
82
+ start = Math.max(0, Math.min(n - order, start));
83
+ for (let i = start; i < start + order; i++) {
84
+ if (!samples[i]) return null;
85
+ }
86
+ const t0 = epochs[start];
87
+ const t = (tMs - t0) / 1e3;
88
+ let x = 0;
89
+ let y = 0;
90
+ let z = 0;
91
+ for (let i = 0; i < order; i++) {
92
+ const ti = (epochs[start + i] - t0) / 1e3;
93
+ let w = 1;
94
+ for (let j = 0; j < order; j++) {
95
+ if (j === i) continue;
96
+ const tj = (epochs[start + j] - t0) / 1e3;
97
+ w *= (t - tj) / (ti - tj);
98
+ }
99
+ const s = samples[start + i];
100
+ x += w * s.x;
101
+ y += w * s.y;
102
+ z += w * s.z;
103
+ }
104
+ let clk = null;
105
+ const a = samples[lo];
106
+ const b = samples[Math.min(lo + 1, n - 1)];
107
+ if (a?.clk != null && b?.clk != null) {
108
+ const span = epochs[Math.min(lo + 1, n - 1)] - epochs[lo];
109
+ const f = span > 0 ? (tMs - epochs[lo]) / span : 0;
110
+ clk = a.clk * (1 - f) + b.clk * f;
111
+ } else if (a?.clk != null) {
112
+ clk = a.clk;
113
+ }
114
+ return { x, y, z, clk };
115
+ }
116
+
117
+ export {
118
+ parseSp3,
119
+ sp3Position
120
+ };