gnss-js 1.11.0 → 1.12.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-77VUSDNI.js → chunk-HXF7XVW7.js} +499 -1
- package/dist/index.cjs +508 -2
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +19 -3
- package/dist/rinex.cjs +508 -2
- package/dist/rinex.d.cts +129 -1
- package/dist/rinex.d.ts +129 -1
- package/dist/rinex.js +19 -3
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -118,6 +118,7 @@ __export(src_exports, {
|
|
|
118
118
|
computeStats: () => computeStats2,
|
|
119
119
|
computeVisibility: () => computeVisibility,
|
|
120
120
|
connectToMountpoint: () => connectToMountpoint,
|
|
121
|
+
createGzipLineSink: () => createGzipLineSink,
|
|
121
122
|
createStationMeta: () => createStationMeta,
|
|
122
123
|
createStreamStats: () => createStreamStats,
|
|
123
124
|
crxDecompress: () => crxDecompress,
|
|
@@ -216,6 +217,7 @@ __export(src_exports, {
|
|
|
216
217
|
parseRinexStream: () => parseRinexStream,
|
|
217
218
|
parseSinexBiasDcb: () => parseSinexBiasDcb,
|
|
218
219
|
parseSourcetable: () => parseSourcetable,
|
|
220
|
+
parseSp3: () => parseSp3,
|
|
219
221
|
phiAltBOC: () => phiAltBOC,
|
|
220
222
|
phiBOCc: () => phiBOCc,
|
|
221
223
|
phiBOCs: () => phiBOCs,
|
|
@@ -232,6 +234,8 @@ __export(src_exports, {
|
|
|
232
234
|
setGloFreqNumber: () => setGloFreqNumber,
|
|
233
235
|
setRtcm3DebugHandler: () => setRtcm3DebugHandler,
|
|
234
236
|
solveSpp: () => solveSpp,
|
|
237
|
+
sp3Position: () => sp3Position,
|
|
238
|
+
stationHeaderLines: () => stationHeaderLines,
|
|
235
239
|
systemCmp: () => systemCmp,
|
|
236
240
|
systemName: () => systemName,
|
|
237
241
|
transformFrame: () => transformFrame,
|
|
@@ -239,7 +243,11 @@ __export(src_exports, {
|
|
|
239
243
|
updateStreamStats: () => updateStreamStats,
|
|
240
244
|
verifyChecksum: () => verifyChecksum,
|
|
241
245
|
vincenty: () => vincenty,
|
|
242
|
-
|
|
246
|
+
writeModernObsBlob: () => writeModernObsBlob,
|
|
247
|
+
writeRinex2ObsBlob: () => writeRinex2ObsBlob,
|
|
248
|
+
writeRinex4ObsBlob: () => writeRinex4ObsBlob,
|
|
249
|
+
writeRinexNav: () => writeRinexNav,
|
|
250
|
+
writeRinexObsBlob: () => writeRinexObsBlob
|
|
243
251
|
});
|
|
244
252
|
module.exports = __toCommonJS(src_exports);
|
|
245
253
|
|
|
@@ -2665,6 +2673,496 @@ function parseIonex(text) {
|
|
|
2665
2673
|
return { epochs, lats, lons, maps };
|
|
2666
2674
|
}
|
|
2667
2675
|
|
|
2676
|
+
// src/rinex/sp3.ts
|
|
2677
|
+
var BAD_CLOCK = 999999.999999;
|
|
2678
|
+
function parseSp3(text) {
|
|
2679
|
+
const lines = text.split("\n");
|
|
2680
|
+
const epochs = [];
|
|
2681
|
+
const satellites = {};
|
|
2682
|
+
let version = "";
|
|
2683
|
+
let intervalSec = 0;
|
|
2684
|
+
let timeSystem = "GPS";
|
|
2685
|
+
let timeSystemSet = false;
|
|
2686
|
+
let epochIdx = -1;
|
|
2687
|
+
for (const line of lines) {
|
|
2688
|
+
if (!version && line.startsWith("#") && line.charAt(1) !== "#") {
|
|
2689
|
+
version = line.charAt(1);
|
|
2690
|
+
}
|
|
2691
|
+
if (line.startsWith("##")) {
|
|
2692
|
+
const f = line.slice(2).trim().split(/\s+/);
|
|
2693
|
+
intervalSec = Number(f[2]) || 0;
|
|
2694
|
+
} else if (line.startsWith("%c") && !timeSystemSet) {
|
|
2695
|
+
const sys = line.slice(9, 12).trim();
|
|
2696
|
+
if (sys && !/^c+$/.test(sys)) {
|
|
2697
|
+
timeSystem = sys;
|
|
2698
|
+
timeSystemSet = true;
|
|
2699
|
+
}
|
|
2700
|
+
} else if (line.startsWith("*")) {
|
|
2701
|
+
const f = line.slice(1).trim().split(/\s+/).map(Number);
|
|
2702
|
+
if (f.length >= 6 && f.every(Number.isFinite)) {
|
|
2703
|
+
const sec = f[5];
|
|
2704
|
+
epochs.push(
|
|
2705
|
+
Date.UTC(
|
|
2706
|
+
f[0],
|
|
2707
|
+
f[1] - 1,
|
|
2708
|
+
f[2],
|
|
2709
|
+
f[3],
|
|
2710
|
+
f[4],
|
|
2711
|
+
Math.floor(sec),
|
|
2712
|
+
Math.round(sec % 1 * 1e3)
|
|
2713
|
+
)
|
|
2714
|
+
);
|
|
2715
|
+
epochIdx++;
|
|
2716
|
+
}
|
|
2717
|
+
} else if (line.startsWith("P") && epochIdx >= 0) {
|
|
2718
|
+
const prn = line.slice(1, 4).replace(/\s/g, "0");
|
|
2719
|
+
const f = line.slice(4).trim().split(/\s+/).map(Number);
|
|
2720
|
+
if (f.length < 3) continue;
|
|
2721
|
+
const [xKm, yKm, zKm] = f;
|
|
2722
|
+
let arr = satellites[prn];
|
|
2723
|
+
if (!arr) satellites[prn] = arr = [];
|
|
2724
|
+
while (arr.length < epochIdx) arr.push(null);
|
|
2725
|
+
if (xKm === 0 && yKm === 0 && zKm === 0) {
|
|
2726
|
+
arr.push(null);
|
|
2727
|
+
continue;
|
|
2728
|
+
}
|
|
2729
|
+
const clkUs = f[3];
|
|
2730
|
+
arr.push({
|
|
2731
|
+
x: xKm * 1e3,
|
|
2732
|
+
y: yKm * 1e3,
|
|
2733
|
+
z: zKm * 1e3,
|
|
2734
|
+
clk: clkUs !== void 0 && Math.abs(clkUs) < BAD_CLOCK ? clkUs * 1e-6 : null
|
|
2735
|
+
});
|
|
2736
|
+
}
|
|
2737
|
+
}
|
|
2738
|
+
for (const arr of Object.values(satellites)) {
|
|
2739
|
+
while (arr.length < epochs.length) arr.push(null);
|
|
2740
|
+
}
|
|
2741
|
+
return { version, epochs, intervalSec, timeSystem, satellites };
|
|
2742
|
+
}
|
|
2743
|
+
function sp3Position(sp3, prn, tMs, order = 9) {
|
|
2744
|
+
const samples = sp3.satellites[prn];
|
|
2745
|
+
const { epochs } = sp3;
|
|
2746
|
+
const n = epochs.length;
|
|
2747
|
+
if (!samples || n < order) return null;
|
|
2748
|
+
if (tMs < epochs[0] || tMs > epochs[n - 1]) return null;
|
|
2749
|
+
let lo = 0;
|
|
2750
|
+
let hi = n - 1;
|
|
2751
|
+
while (lo < hi) {
|
|
2752
|
+
const mid = lo + hi + 1 >> 1;
|
|
2753
|
+
if (epochs[mid] <= tMs) lo = mid;
|
|
2754
|
+
else hi = mid - 1;
|
|
2755
|
+
}
|
|
2756
|
+
let start = lo - (order >> 1) + (order % 2 === 0 ? 1 : 0);
|
|
2757
|
+
start = Math.max(0, Math.min(n - order, start));
|
|
2758
|
+
for (let i = start; i < start + order; i++) {
|
|
2759
|
+
if (!samples[i]) return null;
|
|
2760
|
+
}
|
|
2761
|
+
const t0 = epochs[start];
|
|
2762
|
+
const t = (tMs - t0) / 1e3;
|
|
2763
|
+
let x = 0;
|
|
2764
|
+
let y = 0;
|
|
2765
|
+
let z = 0;
|
|
2766
|
+
for (let i = 0; i < order; i++) {
|
|
2767
|
+
const ti = (epochs[start + i] - t0) / 1e3;
|
|
2768
|
+
let w = 1;
|
|
2769
|
+
for (let j = 0; j < order; j++) {
|
|
2770
|
+
if (j === i) continue;
|
|
2771
|
+
const tj = (epochs[start + j] - t0) / 1e3;
|
|
2772
|
+
w *= (t - tj) / (ti - tj);
|
|
2773
|
+
}
|
|
2774
|
+
const s = samples[start + i];
|
|
2775
|
+
x += w * s.x;
|
|
2776
|
+
y += w * s.y;
|
|
2777
|
+
z += w * s.z;
|
|
2778
|
+
}
|
|
2779
|
+
let clk = null;
|
|
2780
|
+
const a = samples[lo];
|
|
2781
|
+
const b = samples[Math.min(lo + 1, n - 1)];
|
|
2782
|
+
if (a?.clk != null && b?.clk != null) {
|
|
2783
|
+
const span = epochs[Math.min(lo + 1, n - 1)] - epochs[lo];
|
|
2784
|
+
const f = span > 0 ? (tMs - epochs[lo]) / span : 0;
|
|
2785
|
+
clk = a.clk * (1 - f) + b.clk * f;
|
|
2786
|
+
} else if (a?.clk != null) {
|
|
2787
|
+
clk = a.clk;
|
|
2788
|
+
}
|
|
2789
|
+
return { x, y, z, clk };
|
|
2790
|
+
}
|
|
2791
|
+
|
|
2792
|
+
// src/rinex/obs-writer-common.ts
|
|
2793
|
+
function createGzipLineSink() {
|
|
2794
|
+
const encoder = new TextEncoder();
|
|
2795
|
+
const compressor = new CompressionStream("gzip");
|
|
2796
|
+
const writer = compressor.writable.getWriter();
|
|
2797
|
+
const compressedChunks = [];
|
|
2798
|
+
const readerDone = (async () => {
|
|
2799
|
+
const reader = compressor.readable.getReader();
|
|
2800
|
+
for (; ; ) {
|
|
2801
|
+
const { done, value } = await reader.read();
|
|
2802
|
+
if (done) break;
|
|
2803
|
+
compressedChunks.push(value);
|
|
2804
|
+
}
|
|
2805
|
+
})();
|
|
2806
|
+
let batch = [];
|
|
2807
|
+
async function flush() {
|
|
2808
|
+
if (batch.length === 0) return;
|
|
2809
|
+
await writer.write(encoder.encode(batch.join("\n") + "\n"));
|
|
2810
|
+
batch = [];
|
|
2811
|
+
}
|
|
2812
|
+
return {
|
|
2813
|
+
push(line) {
|
|
2814
|
+
batch.push(line);
|
|
2815
|
+
},
|
|
2816
|
+
flush,
|
|
2817
|
+
async finish() {
|
|
2818
|
+
await flush();
|
|
2819
|
+
await writer.close();
|
|
2820
|
+
await readerDone;
|
|
2821
|
+
return new Blob(compressedChunks, {
|
|
2822
|
+
type: "application/gzip"
|
|
2823
|
+
});
|
|
2824
|
+
}
|
|
2825
|
+
};
|
|
2826
|
+
}
|
|
2827
|
+
function stationHeaderLines(header) {
|
|
2828
|
+
const pos = header.approxPosition ?? [0, 0, 0];
|
|
2829
|
+
const delta = header.antDelta ?? [0, 0, 0];
|
|
2830
|
+
return [
|
|
2831
|
+
hdrLine(header.markerName || "UNKNOWN", "MARKER NAME"),
|
|
2832
|
+
hdrLine("", "MARKER NUMBER"),
|
|
2833
|
+
hdrLine(
|
|
2834
|
+
`${padL(header.observer || "", 20)}${padL(header.agency || "", 40)}`,
|
|
2835
|
+
"OBSERVER / AGENCY"
|
|
2836
|
+
),
|
|
2837
|
+
hdrLine(
|
|
2838
|
+
`${padL(header.receiverNumber || "", 20)}${padL(header.receiverType || "", 20)}${padL(header.receiverVersion || "", 20)}`,
|
|
2839
|
+
"REC # / TYPE / VERS"
|
|
2840
|
+
),
|
|
2841
|
+
hdrLine(
|
|
2842
|
+
`${padL(header.antNumber || "", 20)}${padL(header.antType || "", 20)}`,
|
|
2843
|
+
"ANT # / TYPE"
|
|
2844
|
+
),
|
|
2845
|
+
hdrLine(
|
|
2846
|
+
`${fmtF(pos[0], 14, 4)}${fmtF(pos[1], 14, 4)}${fmtF(pos[2], 14, 4)}`,
|
|
2847
|
+
"APPROX POSITION XYZ"
|
|
2848
|
+
),
|
|
2849
|
+
hdrLine(
|
|
2850
|
+
`${fmtF(delta[0], 14, 4)}${fmtF(delta[1], 14, 4)}${fmtF(delta[2], 14, 4)}`,
|
|
2851
|
+
"ANTENNA: DELTA H/E/N"
|
|
2852
|
+
)
|
|
2853
|
+
];
|
|
2854
|
+
}
|
|
2855
|
+
|
|
2856
|
+
// src/rinex/obs-writer.ts
|
|
2857
|
+
function writeRinexObsBlob(header, epochs, obsTypes) {
|
|
2858
|
+
return writeModernObsBlob(header, epochs, obsTypes, {
|
|
2859
|
+
version: "3.04",
|
|
2860
|
+
comment: "Merged from multiple RINEX files"
|
|
2861
|
+
});
|
|
2862
|
+
}
|
|
2863
|
+
async function writeModernObsBlob(header, epochs, obsTypes, opts) {
|
|
2864
|
+
if (epochs.length === 0) return new Blob([], { type: "application/gzip" });
|
|
2865
|
+
const sink = createGzipLineSink();
|
|
2866
|
+
const BATCH = 200;
|
|
2867
|
+
const systems = [...obsTypes.keys()];
|
|
2868
|
+
const sysChar = systems.length === 1 ? systems[0] : "M";
|
|
2869
|
+
sink.push(
|
|
2870
|
+
hdrLine(
|
|
2871
|
+
` ${opts.version} OBSERVATION DATA ${sysChar}`,
|
|
2872
|
+
"RINEX VERSION / TYPE"
|
|
2873
|
+
)
|
|
2874
|
+
);
|
|
2875
|
+
const now = /* @__PURE__ */ new Date();
|
|
2876
|
+
const dateStr = `${now.getUTCFullYear()}${String(now.getUTCMonth() + 1).padStart(2, "0")}${String(now.getUTCDate()).padStart(2, "0")} ${String(now.getUTCHours()).padStart(2, "0")}${String(now.getUTCMinutes()).padStart(2, "0")}${String(now.getUTCSeconds()).padStart(2, "0")} UTC`;
|
|
2877
|
+
sink.push(
|
|
2878
|
+
hdrLine(
|
|
2879
|
+
`${padL("GNSSCalc", 20)}${padL("", 20)}${dateStr}`,
|
|
2880
|
+
"PGM / RUN BY / DATE"
|
|
2881
|
+
)
|
|
2882
|
+
);
|
|
2883
|
+
sink.push(hdrLine(opts.comment, "COMMENT"));
|
|
2884
|
+
for (const line of stationHeaderLines(header)) sink.push(line);
|
|
2885
|
+
for (const [sys, types] of obsTypes) {
|
|
2886
|
+
for (let i = 0; i < types.length; i += 13) {
|
|
2887
|
+
const chunk = types.slice(i, i + 13);
|
|
2888
|
+
let content;
|
|
2889
|
+
if (i === 0) {
|
|
2890
|
+
content = `${sys} ${padR(String(types.length), 3)}`;
|
|
2891
|
+
} else {
|
|
2892
|
+
content = " ";
|
|
2893
|
+
}
|
|
2894
|
+
content += chunk.map((t) => ` ${padL(t, 3)}`).join("");
|
|
2895
|
+
sink.push(hdrLine(content, "SYS / # / OBS TYPES"));
|
|
2896
|
+
}
|
|
2897
|
+
}
|
|
2898
|
+
const timeSys = systems.includes("R") && systems.length === 1 ? "GLO" : "GPS";
|
|
2899
|
+
const obsTimeLine = (d) => ` ${d.getUTCFullYear()} ${String(d.getUTCMonth() + 1).padStart(2)} ${String(d.getUTCDate()).padStart(2)} ${String(d.getUTCHours()).padStart(2)} ${String(d.getUTCMinutes()).padStart(2)} ${(d.getUTCSeconds() + d.getUTCMilliseconds() / 1e3).toFixed(7).padStart(10)} ${timeSys}`;
|
|
2900
|
+
sink.push(
|
|
2901
|
+
hdrLine(obsTimeLine(new Date(epochs[0].time)), "TIME OF FIRST OBS")
|
|
2902
|
+
);
|
|
2903
|
+
sink.push(
|
|
2904
|
+
hdrLine(
|
|
2905
|
+
obsTimeLine(new Date(epochs[epochs.length - 1].time)),
|
|
2906
|
+
"TIME OF LAST OBS"
|
|
2907
|
+
)
|
|
2908
|
+
);
|
|
2909
|
+
if (epochs.length >= 2) {
|
|
2910
|
+
const interval = (epochs[1].time - epochs[0].time) / 1e3;
|
|
2911
|
+
if (interval > 0 && interval < 3600) {
|
|
2912
|
+
sink.push(hdrLine(fmtF(interval, 10, 3), "INTERVAL"));
|
|
2913
|
+
}
|
|
2914
|
+
}
|
|
2915
|
+
if (header.glonassSlots && Object.keys(header.glonassSlots).length > 0) {
|
|
2916
|
+
const entries = Object.entries(header.glonassSlots).sort(
|
|
2917
|
+
([a], [b]) => Number(a) - Number(b)
|
|
2918
|
+
);
|
|
2919
|
+
for (let i = 0; i < entries.length; i += 8) {
|
|
2920
|
+
const chunk = entries.slice(i, i + 8);
|
|
2921
|
+
let content = i === 0 ? padR(String(entries.length), 3) + " " : " ";
|
|
2922
|
+
for (const [slot, freq] of chunk) {
|
|
2923
|
+
content += `R${padR(slot, 2)} ${padR(String(freq), 2)} `;
|
|
2924
|
+
}
|
|
2925
|
+
sink.push(hdrLine(content, "GLONASS SLOT / FRQ #"));
|
|
2926
|
+
}
|
|
2927
|
+
}
|
|
2928
|
+
sink.push(hdrLine("", "END OF HEADER"));
|
|
2929
|
+
await sink.flush();
|
|
2930
|
+
let epochCount = 0;
|
|
2931
|
+
for (const epoch of epochs) {
|
|
2932
|
+
const t = new Date(epoch.time);
|
|
2933
|
+
const sec = t.getUTCSeconds() + t.getUTCMilliseconds() / 1e3;
|
|
2934
|
+
const prns = [...epoch.sats.keys()].sort();
|
|
2935
|
+
sink.push(
|
|
2936
|
+
`> ${t.getUTCFullYear()} ${String(t.getUTCMonth() + 1).padStart(2, "0")} ${String(t.getUTCDate()).padStart(2, "0")} ${String(t.getUTCHours()).padStart(2, "0")} ${String(t.getUTCMinutes()).padStart(2, "0")}${fmtF(sec, 11, 7)} 0${padR(String(prns.length), 3)}`
|
|
2937
|
+
);
|
|
2938
|
+
for (const prn of prns) {
|
|
2939
|
+
const sys = prn[0];
|
|
2940
|
+
const sysTypes = obsTypes.get(sys);
|
|
2941
|
+
if (!sysTypes) continue;
|
|
2942
|
+
const valArr = epoch.sats.get(prn);
|
|
2943
|
+
let line = prn;
|
|
2944
|
+
for (let i = 0; i < sysTypes.length; i++) {
|
|
2945
|
+
const val = i < valArr.length ? valArr[i] : NaN;
|
|
2946
|
+
if (!isNaN(val)) {
|
|
2947
|
+
line += fmtF(val, 14, 3) + " ";
|
|
2948
|
+
} else {
|
|
2949
|
+
line += " ".repeat(16);
|
|
2950
|
+
}
|
|
2951
|
+
}
|
|
2952
|
+
sink.push(line);
|
|
2953
|
+
}
|
|
2954
|
+
epochCount++;
|
|
2955
|
+
if (epochCount % BATCH === 0) await sink.flush();
|
|
2956
|
+
}
|
|
2957
|
+
return sink.finish();
|
|
2958
|
+
}
|
|
2959
|
+
|
|
2960
|
+
// src/rinex/obs-writer-v2.ts
|
|
2961
|
+
var V3_TO_V2 = {
|
|
2962
|
+
// GPS
|
|
2963
|
+
C1C: "C1",
|
|
2964
|
+
C1S: "C1",
|
|
2965
|
+
C1L: "C1",
|
|
2966
|
+
C1X: "C1",
|
|
2967
|
+
C1W: "P1",
|
|
2968
|
+
C1P: "P1",
|
|
2969
|
+
C2C: "C2",
|
|
2970
|
+
C2S: "P2",
|
|
2971
|
+
C2L: "P2",
|
|
2972
|
+
C2X: "P2",
|
|
2973
|
+
C2W: "P2",
|
|
2974
|
+
C2P: "P2",
|
|
2975
|
+
C5I: "C5",
|
|
2976
|
+
C5Q: "C5",
|
|
2977
|
+
C5X: "C5",
|
|
2978
|
+
L1C: "L1",
|
|
2979
|
+
L1S: "L1",
|
|
2980
|
+
L1L: "L1",
|
|
2981
|
+
L1X: "L1",
|
|
2982
|
+
L1W: "L1",
|
|
2983
|
+
L1P: "L1",
|
|
2984
|
+
L2C: "L2",
|
|
2985
|
+
L2S: "L2",
|
|
2986
|
+
L2L: "L2",
|
|
2987
|
+
L2X: "L2",
|
|
2988
|
+
L2W: "L2",
|
|
2989
|
+
L2P: "L2",
|
|
2990
|
+
L5I: "L5",
|
|
2991
|
+
L5Q: "L5",
|
|
2992
|
+
L5X: "L5",
|
|
2993
|
+
D1C: "D1",
|
|
2994
|
+
D1S: "D1",
|
|
2995
|
+
D1L: "D1",
|
|
2996
|
+
D1X: "D1",
|
|
2997
|
+
D1W: "D1",
|
|
2998
|
+
D1P: "D1",
|
|
2999
|
+
D2C: "D2",
|
|
3000
|
+
D2S: "D2",
|
|
3001
|
+
D2L: "D2",
|
|
3002
|
+
D2X: "D2",
|
|
3003
|
+
D2W: "D2",
|
|
3004
|
+
D2P: "D2",
|
|
3005
|
+
D5I: "D5",
|
|
3006
|
+
D5Q: "D5",
|
|
3007
|
+
D5X: "D5",
|
|
3008
|
+
S1C: "S1",
|
|
3009
|
+
S1S: "S1",
|
|
3010
|
+
S1L: "S1",
|
|
3011
|
+
S1X: "S1",
|
|
3012
|
+
S1W: "S1",
|
|
3013
|
+
S1P: "S1",
|
|
3014
|
+
S2C: "S2",
|
|
3015
|
+
S2S: "S2",
|
|
3016
|
+
S2L: "S2",
|
|
3017
|
+
S2X: "S2",
|
|
3018
|
+
S2W: "S2",
|
|
3019
|
+
S2P: "S2",
|
|
3020
|
+
S5I: "S5",
|
|
3021
|
+
S5Q: "S5",
|
|
3022
|
+
S5X: "S5"
|
|
3023
|
+
};
|
|
3024
|
+
function v3ToV2Code(code3) {
|
|
3025
|
+
return V3_TO_V2[code3] ?? null;
|
|
3026
|
+
}
|
|
3027
|
+
async function writeRinex2ObsBlob(header, epochs, obsTypes) {
|
|
3028
|
+
if (epochs.length === 0) return new Blob([], { type: "application/gzip" });
|
|
3029
|
+
const gpsCodes = obsTypes.get("G") ?? obsTypes.get("R") ?? [];
|
|
3030
|
+
const v2Codes = [];
|
|
3031
|
+
const v2CodeSet = /* @__PURE__ */ new Set();
|
|
3032
|
+
const v3ToV2Map = /* @__PURE__ */ new Map();
|
|
3033
|
+
for (const code3 of gpsCodes) {
|
|
3034
|
+
const code2 = v3ToV2Code(code3);
|
|
3035
|
+
if (!code2) continue;
|
|
3036
|
+
if (!v2CodeSet.has(code2)) {
|
|
3037
|
+
v2CodeSet.add(code2);
|
|
3038
|
+
v3ToV2Map.set(code3, v2Codes.length);
|
|
3039
|
+
v2Codes.push(code2);
|
|
3040
|
+
} else {
|
|
3041
|
+
v3ToV2Map.set(code3, v2Codes.indexOf(code2));
|
|
3042
|
+
}
|
|
3043
|
+
}
|
|
3044
|
+
const gloCodes = obsTypes.get("R") ?? [];
|
|
3045
|
+
for (const code3 of gloCodes) {
|
|
3046
|
+
const code2 = v3ToV2Code(code3);
|
|
3047
|
+
if (!code2) continue;
|
|
3048
|
+
if (!v2CodeSet.has(code2)) {
|
|
3049
|
+
v2CodeSet.add(code2);
|
|
3050
|
+
v3ToV2Map.set(code3, v2Codes.length);
|
|
3051
|
+
v2Codes.push(code2);
|
|
3052
|
+
} else if (!v3ToV2Map.has(code3)) {
|
|
3053
|
+
v3ToV2Map.set(code3, v2Codes.indexOf(code2));
|
|
3054
|
+
}
|
|
3055
|
+
}
|
|
3056
|
+
const sink = createGzipLineSink();
|
|
3057
|
+
const BATCH = 200;
|
|
3058
|
+
const hasSystems = /* @__PURE__ */ new Set();
|
|
3059
|
+
for (const epoch of epochs) {
|
|
3060
|
+
for (const prn of epoch.sats.keys()) {
|
|
3061
|
+
const sys = prn[0];
|
|
3062
|
+
if (sys === "G" || sys === "R") hasSystems.add(sys);
|
|
3063
|
+
}
|
|
3064
|
+
}
|
|
3065
|
+
const sysChar = hasSystems.has("G") && hasSystems.has("R") ? "M" : hasSystems.has("R") ? "R" : "G";
|
|
3066
|
+
sink.push(
|
|
3067
|
+
hdrLine(
|
|
3068
|
+
` 2.11 OBSERVATION DATA ${sysChar}`,
|
|
3069
|
+
"RINEX VERSION / TYPE"
|
|
3070
|
+
)
|
|
3071
|
+
);
|
|
3072
|
+
const now = /* @__PURE__ */ new Date();
|
|
3073
|
+
const dateStr = `${now.getUTCFullYear()}-${String(now.getUTCMonth() + 1).padStart(2, "0")}-${String(now.getUTCDate()).padStart(2, "0")} ${String(now.getUTCHours()).padStart(2, "0")}:${String(now.getUTCMinutes()).padStart(2, "0")}:${String(now.getUTCSeconds()).padStart(2, "0")}`;
|
|
3074
|
+
sink.push(
|
|
3075
|
+
hdrLine(
|
|
3076
|
+
`${padL("GNSSCalc", 20)}${padL("", 20)}${dateStr}`,
|
|
3077
|
+
"PGM / RUN BY / DATE"
|
|
3078
|
+
)
|
|
3079
|
+
);
|
|
3080
|
+
sink.push(hdrLine("Converted from RINEX 3 by GNSSCalc", "COMMENT"));
|
|
3081
|
+
for (const line of stationHeaderLines(header)) sink.push(line);
|
|
3082
|
+
sink.push(hdrLine(" 1 1", "WAVELENGTH FACT L1/2"));
|
|
3083
|
+
for (let i = 0; i < v2Codes.length; i += 9) {
|
|
3084
|
+
const chunk = v2Codes.slice(i, i + 9);
|
|
3085
|
+
let content;
|
|
3086
|
+
if (i === 0) {
|
|
3087
|
+
content = padR(String(v2Codes.length), 6);
|
|
3088
|
+
} else {
|
|
3089
|
+
content = " ";
|
|
3090
|
+
}
|
|
3091
|
+
content += chunk.map((c) => padR(c, 6)).join("");
|
|
3092
|
+
sink.push(hdrLine(content, "# / TYPES OF OBSERV"));
|
|
3093
|
+
}
|
|
3094
|
+
const first = new Date(epochs[0].time);
|
|
3095
|
+
const timeSys = sysChar === "R" ? "GLO" : "GPS";
|
|
3096
|
+
sink.push(
|
|
3097
|
+
hdrLine(
|
|
3098
|
+
` ${first.getUTCFullYear()} ${String(first.getUTCMonth() + 1).padStart(2)} ${String(first.getUTCDate()).padStart(2)} ${String(first.getUTCHours()).padStart(2)} ${String(first.getUTCMinutes()).padStart(2)} ${(first.getUTCSeconds() + first.getUTCMilliseconds() / 1e3).toFixed(7).padStart(10)} ${timeSys}`,
|
|
3099
|
+
"TIME OF FIRST OBS"
|
|
3100
|
+
)
|
|
3101
|
+
);
|
|
3102
|
+
sink.push(hdrLine("", "END OF HEADER"));
|
|
3103
|
+
await sink.flush();
|
|
3104
|
+
let epochCount = 0;
|
|
3105
|
+
for (const epoch of epochs) {
|
|
3106
|
+
const t = new Date(epoch.time);
|
|
3107
|
+
const sec = t.getUTCSeconds() + t.getUTCMilliseconds() / 1e3;
|
|
3108
|
+
const prns = [...epoch.sats.keys()].filter((p) => p[0] === "G" || p[0] === "R").sort();
|
|
3109
|
+
if (prns.length === 0) continue;
|
|
3110
|
+
const yy = t.getUTCFullYear() % 100;
|
|
3111
|
+
const yyS = padR(String(yy), 2);
|
|
3112
|
+
const moS = padR(String(t.getUTCMonth() + 1), 2);
|
|
3113
|
+
const ddS = padR(String(t.getUTCDate()), 2);
|
|
3114
|
+
const hhS = padR(String(t.getUTCHours()), 2);
|
|
3115
|
+
const mmS = padR(String(t.getUTCMinutes()), 2);
|
|
3116
|
+
const secS = fmtF(sec, 11, 7);
|
|
3117
|
+
const nSats = padR(String(prns.length), 3);
|
|
3118
|
+
let epochLine = ` ${yyS} ${moS} ${ddS} ${hhS} ${mmS}${secS} 0${nSats}`;
|
|
3119
|
+
for (let i = 0; i < prns.length; i++) {
|
|
3120
|
+
if (i > 0 && i % 12 === 0) {
|
|
3121
|
+
sink.push(epochLine);
|
|
3122
|
+
epochLine = " ".repeat(32);
|
|
3123
|
+
}
|
|
3124
|
+
epochLine += prns[i];
|
|
3125
|
+
}
|
|
3126
|
+
sink.push(epochLine);
|
|
3127
|
+
for (const prn of prns) {
|
|
3128
|
+
const sys = prn[0];
|
|
3129
|
+
const sysCodes3 = obsTypes.get(sys) ?? [];
|
|
3130
|
+
const valArr = epoch.sats.get(prn);
|
|
3131
|
+
const v2Vals = new Array(v2Codes.length).fill(NaN);
|
|
3132
|
+
for (let j = 0; j < sysCodes3.length; j++) {
|
|
3133
|
+
const v2Idx = v3ToV2Map.get(sysCodes3[j]);
|
|
3134
|
+
if (v2Idx != null && j < valArr.length && !isNaN(valArr[j])) {
|
|
3135
|
+
v2Vals[v2Idx] = valArr[j];
|
|
3136
|
+
}
|
|
3137
|
+
}
|
|
3138
|
+
let line = "";
|
|
3139
|
+
for (let j = 0; j < v2Codes.length; j++) {
|
|
3140
|
+
const val = v2Vals[j];
|
|
3141
|
+
if (!isNaN(val)) {
|
|
3142
|
+
line += fmtF(val, 14, 3) + " ";
|
|
3143
|
+
} else {
|
|
3144
|
+
line += " ".repeat(16);
|
|
3145
|
+
}
|
|
3146
|
+
if ((j + 1) % 5 === 0 || j === v2Codes.length - 1) {
|
|
3147
|
+
sink.push(line);
|
|
3148
|
+
line = "";
|
|
3149
|
+
}
|
|
3150
|
+
}
|
|
3151
|
+
}
|
|
3152
|
+
epochCount++;
|
|
3153
|
+
if (epochCount % BATCH === 0) await sink.flush();
|
|
3154
|
+
}
|
|
3155
|
+
return sink.finish();
|
|
3156
|
+
}
|
|
3157
|
+
|
|
3158
|
+
// src/rinex/obs-writer-v4.ts
|
|
3159
|
+
function writeRinex4ObsBlob(header, epochs, obsTypes) {
|
|
3160
|
+
return writeModernObsBlob(header, epochs, obsTypes, {
|
|
3161
|
+
version: "4.01",
|
|
3162
|
+
comment: "Converted to RINEX 4 by GNSSCalc"
|
|
3163
|
+
});
|
|
3164
|
+
}
|
|
3165
|
+
|
|
2668
3166
|
// src/rtcm3/decoder.ts
|
|
2669
3167
|
var debugHandler = null;
|
|
2670
3168
|
function setRtcm3DebugHandler(fn) {
|
|
@@ -7488,6 +7986,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
7488
7986
|
computeStats,
|
|
7489
7987
|
computeVisibility,
|
|
7490
7988
|
connectToMountpoint,
|
|
7989
|
+
createGzipLineSink,
|
|
7491
7990
|
createStationMeta,
|
|
7492
7991
|
createStreamStats,
|
|
7493
7992
|
crxDecompress,
|
|
@@ -7586,6 +8085,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
7586
8085
|
parseRinexStream,
|
|
7587
8086
|
parseSinexBiasDcb,
|
|
7588
8087
|
parseSourcetable,
|
|
8088
|
+
parseSp3,
|
|
7589
8089
|
phiAltBOC,
|
|
7590
8090
|
phiBOCc,
|
|
7591
8091
|
phiBOCs,
|
|
@@ -7602,6 +8102,8 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
7602
8102
|
setGloFreqNumber,
|
|
7603
8103
|
setRtcm3DebugHandler,
|
|
7604
8104
|
solveSpp,
|
|
8105
|
+
sp3Position,
|
|
8106
|
+
stationHeaderLines,
|
|
7605
8107
|
systemCmp,
|
|
7606
8108
|
systemName,
|
|
7607
8109
|
transformFrame,
|
|
@@ -7609,5 +8111,9 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
7609
8111
|
updateStreamStats,
|
|
7610
8112
|
verifyChecksum,
|
|
7611
8113
|
vincenty,
|
|
7612
|
-
|
|
8114
|
+
writeModernObsBlob,
|
|
8115
|
+
writeRinex2ObsBlob,
|
|
8116
|
+
writeRinex4ObsBlob,
|
|
8117
|
+
writeRinexNav,
|
|
8118
|
+
writeRinexObsBlob
|
|
7613
8119
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -4,7 +4,7 @@ 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, IonexGrid, RinexWarning, RinexWarnings, WarningAccumulator, WarningSeverity, crxDecompress, crxRepair, fmtF, hdrLine, padL, padR, parseCrxDataLine, parseIonex, writeRinexNav } from './rinex.cjs';
|
|
7
|
+
export { CompactEpoch, CrxField, DiffState, EMPTY_WARNINGS, IonexGrid, RinexWarning, RinexWarnings, Sp3File, Sp3Sample, WarningAccumulator, WarningSeverity, createGzipLineSink, crxDecompress, crxRepair, fmtF, hdrLine, padL, padR, parseCrxDataLine, parseIonex, parseSp3, sp3Position, stationHeaderLines, writeModernObsBlob, writeRinex2ObsBlob, writeRinex4ObsBlob, writeRinexNav, writeRinexObsBlob } 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';
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ 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, IonexGrid, RinexWarning, RinexWarnings, WarningAccumulator, WarningSeverity, crxDecompress, crxRepair, fmtF, hdrLine, padL, padR, parseCrxDataLine, parseIonex, writeRinexNav } from './rinex.js';
|
|
7
|
+
export { CompactEpoch, CrxField, DiffState, EMPTY_WARNINGS, IonexGrid, RinexWarning, RinexWarnings, Sp3File, Sp3Sample, WarningAccumulator, WarningSeverity, createGzipLineSink, crxDecompress, crxRepair, fmtF, hdrLine, padL, padR, parseCrxDataLine, parseIonex, parseSp3, sp3Position, stationHeaderLines, writeModernObsBlob, writeRinex2ObsBlob, writeRinex4ObsBlob, writeRinexNav, writeRinexObsBlob } 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';
|
package/dist/index.js
CHANGED
|
@@ -172,14 +172,22 @@ import {
|
|
|
172
172
|
import {
|
|
173
173
|
EMPTY_WARNINGS,
|
|
174
174
|
WarningAccumulator,
|
|
175
|
+
createGzipLineSink,
|
|
175
176
|
fmtF,
|
|
176
177
|
hdrLine,
|
|
177
178
|
padL,
|
|
178
179
|
padR,
|
|
179
180
|
parseIonex,
|
|
180
181
|
parseNavFile,
|
|
181
|
-
|
|
182
|
-
|
|
182
|
+
parseSp3,
|
|
183
|
+
sp3Position,
|
|
184
|
+
stationHeaderLines,
|
|
185
|
+
writeModernObsBlob,
|
|
186
|
+
writeRinex2ObsBlob,
|
|
187
|
+
writeRinex4ObsBlob,
|
|
188
|
+
writeRinexNav,
|
|
189
|
+
writeRinexObsBlob
|
|
190
|
+
} from "./chunk-HXF7XVW7.js";
|
|
183
191
|
import {
|
|
184
192
|
SYSTEM_ORDER,
|
|
185
193
|
crxDecompress,
|
|
@@ -354,6 +362,7 @@ export {
|
|
|
354
362
|
computeStats,
|
|
355
363
|
computeVisibility,
|
|
356
364
|
connectToMountpoint,
|
|
365
|
+
createGzipLineSink,
|
|
357
366
|
createStationMeta,
|
|
358
367
|
createStreamStats,
|
|
359
368
|
crxDecompress,
|
|
@@ -452,6 +461,7 @@ export {
|
|
|
452
461
|
parseRinexStream,
|
|
453
462
|
parseSinexBiasDcb,
|
|
454
463
|
parseSourcetable,
|
|
464
|
+
parseSp3,
|
|
455
465
|
phiAltBOC,
|
|
456
466
|
phiBOCc,
|
|
457
467
|
phiBOCs,
|
|
@@ -468,6 +478,8 @@ export {
|
|
|
468
478
|
setGloFreqNumber,
|
|
469
479
|
setRtcm3DebugHandler,
|
|
470
480
|
solveSpp,
|
|
481
|
+
sp3Position,
|
|
482
|
+
stationHeaderLines,
|
|
471
483
|
systemCmp,
|
|
472
484
|
systemName,
|
|
473
485
|
transformFrame,
|
|
@@ -475,5 +487,9 @@ export {
|
|
|
475
487
|
updateStreamStats,
|
|
476
488
|
verifyChecksum,
|
|
477
489
|
vincenty,
|
|
478
|
-
|
|
490
|
+
writeModernObsBlob,
|
|
491
|
+
writeRinex2ObsBlob,
|
|
492
|
+
writeRinex4ObsBlob,
|
|
493
|
+
writeRinexNav,
|
|
494
|
+
writeRinexObsBlob
|
|
479
495
|
};
|