@idm-plugin/geo 2.2.1 → 2.2.3
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/index.js +709 -629
- package/dist/index.umd.cjs +6 -6
- package/dist/json/src/index.d.ts +1 -0
- package/dist/lane/src/index.d.ts +14 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as T from "@turf/turf";
|
|
2
2
|
import b from "moment";
|
|
3
|
-
import
|
|
3
|
+
import G from "@log4js-node/log4js-api";
|
|
4
4
|
import "moment-timezone";
|
|
5
|
-
import
|
|
6
|
-
import
|
|
5
|
+
import V from "tz-lookup";
|
|
6
|
+
import J from "shpjs";
|
|
7
7
|
class d {
|
|
8
8
|
/**
|
|
9
9
|
* 基于输入的经度,计算出时区
|
|
@@ -12,8 +12,8 @@ class d {
|
|
|
12
12
|
*/
|
|
13
13
|
static guessTimeZoneOffset(t, e) {
|
|
14
14
|
t = d.convertToStdLng(t);
|
|
15
|
-
const n =
|
|
16
|
-
return d.roundPrecision(
|
|
15
|
+
const n = V(e, t), s = b().tz(n).utcOffset();
|
|
16
|
+
return d.roundPrecision(s / 60, 1);
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
19
19
|
* 将时间offset转换为时区,例如:8.5 => +08:30
|
|
@@ -31,20 +31,20 @@ class d {
|
|
|
31
31
|
*/
|
|
32
32
|
static lng2pretty(t, e = 6, n = "H°M′") {
|
|
33
33
|
t = d.convertToStdLng(t, e);
|
|
34
|
-
let
|
|
35
|
-
t < 0 && (
|
|
36
|
-
let o = t * 3600, r,
|
|
37
|
-
r = o % 3600 % 60, n.indexOf("S") !== -1 && (o = o - r,
|
|
38
|
-
const
|
|
34
|
+
let s = "E";
|
|
35
|
+
t < 0 && (s = "W"), t = Math.abs(t), n = n.toUpperCase();
|
|
36
|
+
let o = t * 3600, r, i, c, a, l, u;
|
|
37
|
+
r = o % 3600 % 60, n.indexOf("S") !== -1 && (o = o - r, i = d.padNumber(r, 2, 2)), c = o / 60 % 60, n.indexOf("M") !== -1 && (n.indexOf("S") !== -1 ? a = d.roundPrecision(c, e).toString().padStart(2, "0") : a = d.padNumber(c, 2, 3), o = o - c * 60), l = o / 3600, n.indexOf("M") !== -1 ? u = d.roundPrecision(l, e).toString().padStart(3, "0") : u = d.padNumber(l, 3, 6), Number(i) >= 60 && (a = Number(a) + 1, i = 0), Number(a) >= 60 && (u = Number(u) + 1, a = 0);
|
|
38
|
+
const f = `${n.replace(/S+/gi, i).replace(/M+/gi, a).replace(/H+/gi, u)}${s}`;
|
|
39
39
|
return {
|
|
40
|
-
direction:
|
|
41
|
-
degree: d.roundPrecision(
|
|
40
|
+
direction: s,
|
|
41
|
+
degree: d.roundPrecision(l, e),
|
|
42
42
|
minute: d.roundPrecision(c, e),
|
|
43
43
|
second: d.roundPrecision(r, e),
|
|
44
|
-
pretty:
|
|
45
|
-
S:
|
|
44
|
+
pretty: f,
|
|
45
|
+
S: i,
|
|
46
46
|
M: a,
|
|
47
|
-
H:
|
|
47
|
+
H: u
|
|
48
48
|
};
|
|
49
49
|
}
|
|
50
50
|
/**
|
|
@@ -55,35 +55,35 @@ class d {
|
|
|
55
55
|
*/
|
|
56
56
|
static lat2pretty(t, e = 6, n = "H°M′") {
|
|
57
57
|
t = t % 180;
|
|
58
|
-
let
|
|
59
|
-
t < 0 && (
|
|
60
|
-
let o = t * 3600, r,
|
|
61
|
-
r = o % 3600 % 60, n.indexOf("S") !== -1 && (o = o - r,
|
|
62
|
-
const
|
|
58
|
+
let s = "N";
|
|
59
|
+
t < 0 && (s = "S"), t = Math.abs(t), n = n.toUpperCase();
|
|
60
|
+
let o = t * 3600, r, i, c, a, l, u;
|
|
61
|
+
r = o % 3600 % 60, n.indexOf("S") !== -1 && (o = o - r, i = d.padNumber(r, 2, 2)), c = o / 60 % 60, n.indexOf("M") !== -1 && (n.indexOf("S") !== -1 ? a = d.roundPrecision(c, e).toString().padStart(2, "0") : a = d.padNumber(c, 2, 3), o = o - c * 60), l = o / 3600, n.indexOf("M") !== -1 ? u = d.roundPrecision(l, e).toString().padStart(2, "0") : u = d.padNumber(l, 2, 6), Number(i) >= 60 && (a = Number(a) + 1, i = 0), Number(a) >= 60 && (u = Number(u) + 1, a = 0);
|
|
62
|
+
const f = `${n.replace(/S+/gi, i).replace(/M+/gi, a).replace(/H+/gi, u)}${s}`;
|
|
63
63
|
return {
|
|
64
|
-
direction:
|
|
65
|
-
degree: d.roundPrecision(
|
|
64
|
+
direction: s,
|
|
65
|
+
degree: d.roundPrecision(l, e),
|
|
66
66
|
minute: d.roundPrecision(c, e),
|
|
67
67
|
second: d.roundPrecision(r, e),
|
|
68
|
-
pretty:
|
|
69
|
-
S:
|
|
68
|
+
pretty: f,
|
|
69
|
+
S: i,
|
|
70
70
|
M: a,
|
|
71
|
-
H:
|
|
71
|
+
H: u
|
|
72
72
|
};
|
|
73
73
|
}
|
|
74
74
|
static str2Lng(t, e = 6) {
|
|
75
75
|
let n;
|
|
76
76
|
if (isNaN(t)) {
|
|
77
77
|
t = d.strReplace(t, "LNG");
|
|
78
|
-
const
|
|
78
|
+
const s = t[t.length - 1].toUpperCase();
|
|
79
79
|
t = t.substring(0, t.length - 1).trim();
|
|
80
80
|
const o = t.split(" ").filter((a) => a !== "").map((a) => Math.abs(Number(a)));
|
|
81
|
-
let [r,
|
|
82
|
-
if (
|
|
81
|
+
let [r, i, c] = o;
|
|
82
|
+
if (i = i || 0, i = i > 60 ? i / Math.pow(10, String(i).length - 2) : i, c = c || 0, c = c > 60 ? c / Math.pow(10, String(c).length - 2) : c, r > 360 && !i) {
|
|
83
83
|
const a = this.roundPrecision(r / 100, 0);
|
|
84
|
-
|
|
84
|
+
i = r - a * 100, r = a;
|
|
85
85
|
}
|
|
86
|
-
n = r +
|
|
86
|
+
n = r + i / 60 + c / 3600, s === "W" && (n = n * -1);
|
|
87
87
|
} else
|
|
88
88
|
n = Number(t);
|
|
89
89
|
return d.convertToStdLng(n, e);
|
|
@@ -92,25 +92,25 @@ class d {
|
|
|
92
92
|
let n;
|
|
93
93
|
if (isNaN(t)) {
|
|
94
94
|
t = d.strReplace(t, "LAT");
|
|
95
|
-
const
|
|
95
|
+
const s = t[t.length - 1].toUpperCase();
|
|
96
96
|
t = t.substring(0, t.length - 1).trim();
|
|
97
97
|
const o = t.split(" ").filter((a) => a !== "").map((a) => Math.abs(Number(a)));
|
|
98
|
-
let [r,
|
|
99
|
-
if (c = c || 0,
|
|
98
|
+
let [r, i, c] = o;
|
|
99
|
+
if (c = c || 0, i = i || 0, i = i > 60 ? i / Math.pow(10, String(i).length - 2) : i, c = c > 60 ? c / Math.pow(10, String(c).length - 2) : c, r > 90 && !i) {
|
|
100
100
|
const a = this.roundPrecision(r / 100, 0);
|
|
101
|
-
|
|
101
|
+
i = r - a * 100, r = a;
|
|
102
102
|
}
|
|
103
|
-
if (n = r +
|
|
104
|
-
throw new Error(`latitude out of range: ${t}${
|
|
105
|
-
|
|
103
|
+
if (n = r + i / 60 + c / 3600, n > 90)
|
|
104
|
+
throw new Error(`latitude out of range: ${t}${s}`);
|
|
105
|
+
s === "S" && (n = n * -1);
|
|
106
106
|
} else
|
|
107
107
|
n = Number(t);
|
|
108
108
|
return d.roundPrecision(n, e);
|
|
109
109
|
}
|
|
110
110
|
static str2LngOrLat(t, e = 6, n = "LAT") {
|
|
111
111
|
t = d.strReplace(t, n);
|
|
112
|
-
const
|
|
113
|
-
return ["N", "S"].includes(
|
|
112
|
+
const s = t[t.length - 1].toUpperCase();
|
|
113
|
+
return ["N", "S"].includes(s) ? {
|
|
114
114
|
lat: d.str2Lat(t, e)
|
|
115
115
|
} : {
|
|
116
116
|
lng: d.str2Lng(t, e)
|
|
@@ -145,10 +145,10 @@ class d {
|
|
|
145
145
|
t = t.replace(/([0-9]+)\.([0-9]+\.[0-9]+)/g, "$1 $2").replace(/([0-9]+)-([0-9]+\.[0-9]+)/g, "$1 $2").replace(/°/, " ").replace(/(\d+)-(\d?)/g, "$1 $2").replace(/'/g, " ").replace(/′/g, " ").replace(/"/g, " ").replace(/∼/g, " ").replace(/°/g, " ").replace(/,/g, ".").replace(/^ /g, "").replace(/ $/g, "").trim();
|
|
146
146
|
const n = t[t.length - 1].toUpperCase();
|
|
147
147
|
if (!["N", "S", "E", "W"].includes(n)) {
|
|
148
|
-
const
|
|
148
|
+
const s = t, o = Number(s.split(" ")[0]);
|
|
149
149
|
if (isNaN(o))
|
|
150
150
|
throw new Error(`invalid Lat/Lng: ${t}`);
|
|
151
|
-
o >= 90 ? t = `${
|
|
151
|
+
o >= 90 ? t = `${s}E` : o <= -90 ? t = `${s}W` : ["LAN", "LNG"].includes(e == null ? void 0 : e.toUpperCase()) ? t = `${s}${o > 0 ? "E" : "W"}` : t = `${s}${o > 0 ? "N" : "S"}`;
|
|
152
152
|
}
|
|
153
153
|
return t;
|
|
154
154
|
}
|
|
@@ -160,55 +160,55 @@ class d {
|
|
|
160
160
|
* @param dcmPrecision 小数位数
|
|
161
161
|
*/
|
|
162
162
|
static padNumber(t, e = 2, n = 2) {
|
|
163
|
-
const
|
|
164
|
-
return
|
|
163
|
+
const s = d.roundPrecision(t - Math.trunc(t), n), o = s >= 1 ? Math.trunc(t + 1).toString().padStart(e, "0") : Math.trunc(t).toString().padStart(e, "0");
|
|
164
|
+
return s >= 1 ? o : n > 0 ? `${o}.${Math.trunc(s * Math.pow(10, n)).toString().padStart(n, "0")}` : o;
|
|
165
165
|
}
|
|
166
166
|
}
|
|
167
|
-
class
|
|
167
|
+
class K {
|
|
168
168
|
static json2Str(t) {
|
|
169
169
|
const e = t.type ? t.type[0].toUpperCase() : "A";
|
|
170
170
|
return `${t.lat}|${t.lng}|${t.positionTime}|${t.sog}|${t.cog}|${t.hdg}|${t.draught}|${e}|${JSON.stringify(t.meteo || {})}|${t.vendor}|${t.deleted}`;
|
|
171
171
|
}
|
|
172
172
|
static str2Json(t) {
|
|
173
|
-
const [e, n,
|
|
173
|
+
const [e, n, s, o, r, i, c, a, l, u, f] = t.split("|");
|
|
174
174
|
return {
|
|
175
175
|
lat: Number(e),
|
|
176
176
|
lng: Number(n),
|
|
177
|
-
positionTime: Number(
|
|
177
|
+
positionTime: Number(s),
|
|
178
178
|
sog: Number(o),
|
|
179
179
|
cog: Number(r),
|
|
180
|
-
hdg: Number(
|
|
180
|
+
hdg: Number(i),
|
|
181
181
|
//@ts-ignore
|
|
182
182
|
draught: isNaN(c) ? null : Number(c),
|
|
183
183
|
type: a,
|
|
184
184
|
important: a !== "A",
|
|
185
|
-
meteo:
|
|
186
|
-
vendor:
|
|
187
|
-
deleted:
|
|
185
|
+
meteo: l ? JSON.parse(l) : void 0,
|
|
186
|
+
vendor: u,
|
|
187
|
+
deleted: f === "true"
|
|
188
188
|
};
|
|
189
189
|
}
|
|
190
190
|
static inspectStoppages(t, e = 1, n = !0) {
|
|
191
|
-
const
|
|
192
|
-
|
|
191
|
+
const s = t.at(0).positionTime < t.at(-1).positionTime;
|
|
192
|
+
s || t.sort((c, a) => c.positionTime - a.positionTime);
|
|
193
193
|
const o = [];
|
|
194
|
-
let r,
|
|
194
|
+
let r, i;
|
|
195
195
|
for (let c = 0; c < t.length - 1; c++) {
|
|
196
196
|
const a = t[c];
|
|
197
197
|
if (!(n && ["N", "B", "E", "NOON", "BOSP", "EOSP"].includes(a.type))) {
|
|
198
|
-
for (let
|
|
199
|
-
const
|
|
198
|
+
for (let l = c + 1; l < t.length; l++) {
|
|
199
|
+
const u = t[l - 1], f = t[l];
|
|
200
200
|
if (n && ["N", "B", "E", "NOON", "BOSP", "EOSP"].includes(a.type))
|
|
201
201
|
continue;
|
|
202
|
-
const h =
|
|
203
|
-
if (
|
|
204
|
-
r || (r = a),
|
|
202
|
+
const h = f.positionTime - u.positionTime;
|
|
203
|
+
if (v.calculateDistance(f, u, !0, 4) / (h / 3600) < e)
|
|
204
|
+
r || (r = a), l === t.length - 1 && (i = f, c = l);
|
|
205
205
|
else {
|
|
206
|
-
r && (
|
|
206
|
+
r && (i = t[l - 1], c = l);
|
|
207
207
|
break;
|
|
208
208
|
}
|
|
209
209
|
}
|
|
210
|
-
if ((
|
|
211
|
-
const
|
|
210
|
+
if ((i == null ? void 0 : i.positionTime) > (r == null ? void 0 : r.positionTime) && r) {
|
|
211
|
+
const l = {
|
|
212
212
|
start: {
|
|
213
213
|
lat: r.lat,
|
|
214
214
|
lng: r.lng,
|
|
@@ -217,20 +217,20 @@ class j {
|
|
|
217
217
|
utc: b.unix(r.positionTime).utc().format()
|
|
218
218
|
},
|
|
219
219
|
end: {
|
|
220
|
-
lat:
|
|
221
|
-
lng:
|
|
222
|
-
sog:
|
|
223
|
-
positionTime:
|
|
224
|
-
utc: b.unix(
|
|
220
|
+
lat: i.lat,
|
|
221
|
+
lng: i.lng,
|
|
222
|
+
sog: i.sog,
|
|
223
|
+
positionTime: i.positionTime,
|
|
224
|
+
utc: b.unix(i.positionTime).utc().format()
|
|
225
225
|
},
|
|
226
|
-
duration:
|
|
227
|
-
},
|
|
228
|
-
|
|
226
|
+
duration: i.positionTime - r.positionTime
|
|
227
|
+
}, u = t.filter((h) => h.positionTime >= l.start.positionTime && h.positionTime <= l.end.positionTime), f = v.divideAccordingToLng(u);
|
|
228
|
+
l.distance = v.calculateRouteDistance(f), l.hours = Math.round(l.duration / 3600 * 10) / 10, l.avgSog = Math.round(l.distance / l.hours * 10) / 10, o.push(l);
|
|
229
229
|
}
|
|
230
|
-
r = void 0,
|
|
230
|
+
r = void 0, i = void 0;
|
|
231
231
|
}
|
|
232
232
|
}
|
|
233
|
-
return
|
|
233
|
+
return s || t.sort((c, a) => a.positionTime - c.positionTime), o;
|
|
234
234
|
}
|
|
235
235
|
/**
|
|
236
236
|
* 计算轨迹摘要
|
|
@@ -239,25 +239,70 @@ class j {
|
|
|
239
239
|
* @param etm
|
|
240
240
|
*/
|
|
241
241
|
static inspectSummary(t, e, n) {
|
|
242
|
-
const
|
|
243
|
-
let
|
|
242
|
+
const s = b(e), o = b(n), r = t.filter((l) => l.positionTime >= s.unix() && l.positionTime <= o.unix());
|
|
243
|
+
let i = 0, c = 0;
|
|
244
244
|
if (r.length > 1)
|
|
245
|
-
for (let
|
|
246
|
-
const
|
|
247
|
-
|
|
245
|
+
for (let l = 0; l < r.length - 1; l++) {
|
|
246
|
+
const u = r[l], f = r[l + 1];
|
|
247
|
+
i += v.calculateDistance(u, f, !0, 4), c += Math.abs(f.positionTime - u.positionTime);
|
|
248
248
|
}
|
|
249
|
-
|
|
250
|
-
const a = c ? Math.round(
|
|
251
|
-
return { distance:
|
|
249
|
+
i = Math.round(i * 100) / 100, c = Math.round(c / 3600 * 100) / 100;
|
|
250
|
+
const a = c ? Math.round(i / c * 100) / 100 : 0;
|
|
251
|
+
return { distance: i, interval: c, avgSpd: a };
|
|
252
252
|
}
|
|
253
253
|
}
|
|
254
|
-
let
|
|
254
|
+
let X;
|
|
255
255
|
try {
|
|
256
|
-
|
|
256
|
+
X = G.getLogger("meteo");
|
|
257
257
|
} catch {
|
|
258
258
|
} finally {
|
|
259
259
|
}
|
|
260
|
-
|
|
260
|
+
const Q = (() => {
|
|
261
|
+
const C = new Uint32Array(256);
|
|
262
|
+
for (let t = 0; t < 256; t++) {
|
|
263
|
+
let e = t;
|
|
264
|
+
for (let n = 0; n < 8; n++)
|
|
265
|
+
e = e & 1 ? 3988292384 ^ e >>> 1 : e >>> 1;
|
|
266
|
+
C[t] = e;
|
|
267
|
+
}
|
|
268
|
+
return C;
|
|
269
|
+
})();
|
|
270
|
+
function Y(C) {
|
|
271
|
+
let t = 4294967295;
|
|
272
|
+
for (let e = 0; e < C.length; e++)
|
|
273
|
+
t = Q[(t ^ C[e]) & 255] ^ t >>> 8;
|
|
274
|
+
return (t ^ 4294967295) >>> 0;
|
|
275
|
+
}
|
|
276
|
+
function _(C) {
|
|
277
|
+
const t = new TextEncoder(), e = [], n = [];
|
|
278
|
+
let s = 0;
|
|
279
|
+
for (const h of C) {
|
|
280
|
+
const g = t.encode(h.name), m = Y(h.data), p = new Uint8Array(30 + g.length), S = new DataView(p.buffer);
|
|
281
|
+
S.setUint32(0, 67324752, !0), S.setUint16(4, 20, !0), S.setUint16(8, 0, !0), S.setUint32(14, m, !0), S.setUint32(18, h.data.length, !0), S.setUint32(22, h.data.length, !0), S.setUint16(26, g.length, !0), p.set(g, 30), e.push({ nameBytes: g, data: h.data, crc: m, offset: s }), s += p.length + h.data.length, n.push(p, h.data);
|
|
282
|
+
}
|
|
283
|
+
const o = s, r = [];
|
|
284
|
+
let i = 0;
|
|
285
|
+
for (const h of e) {
|
|
286
|
+
const g = new Uint8Array(46 + h.nameBytes.length), m = new DataView(g.buffer);
|
|
287
|
+
m.setUint32(0, 33639248, !0), m.setUint16(4, 20, !0), m.setUint16(6, 20, !0), m.setUint16(10, 0, !0), m.setUint32(16, h.crc, !0), m.setUint32(20, h.data.length, !0), m.setUint32(24, h.data.length, !0), m.setUint16(28, h.nameBytes.length, !0), m.setUint32(42, h.offset, !0), g.set(h.nameBytes, 46), i += g.length, r.push(g);
|
|
288
|
+
}
|
|
289
|
+
const c = new Uint8Array(22), a = new DataView(c.buffer);
|
|
290
|
+
a.setUint32(0, 101010256, !0), a.setUint16(8, e.length, !0), a.setUint16(10, e.length, !0), a.setUint32(12, i, !0), a.setUint32(16, o, !0);
|
|
291
|
+
const l = n.reduce((h, g) => h + g.length, 0) + i + 22, u = new Uint8Array(l);
|
|
292
|
+
let f = 0;
|
|
293
|
+
for (const h of n)
|
|
294
|
+
u.set(h, f), f += h.length;
|
|
295
|
+
for (const h of r)
|
|
296
|
+
u.set(h, f), f += h.length;
|
|
297
|
+
return u.set(c, f), u;
|
|
298
|
+
}
|
|
299
|
+
function z(C) {
|
|
300
|
+
let t = "", e = C;
|
|
301
|
+
for (; e >= 0; )
|
|
302
|
+
t = String.fromCharCode(65 + e % 26) + t, e = Math.floor(e / 26) - 1;
|
|
303
|
+
return t;
|
|
304
|
+
}
|
|
305
|
+
class v {
|
|
261
306
|
/**
|
|
262
307
|
* 计算方位角
|
|
263
308
|
* @param from 坐标 {lng, lat}
|
|
@@ -266,13 +311,13 @@ class y {
|
|
|
266
311
|
* @param precision
|
|
267
312
|
* @returns {number} 单位度
|
|
268
313
|
*/
|
|
269
|
-
static calculateBearing(t, e, n = !0,
|
|
270
|
-
const o =
|
|
314
|
+
static calculateBearing(t, e, n = !0, s = 4) {
|
|
315
|
+
const o = T.points([
|
|
271
316
|
[t.lng, t.lat],
|
|
272
317
|
[e.lng, e.lat]
|
|
273
318
|
]);
|
|
274
319
|
let r;
|
|
275
|
-
return n ? r =
|
|
320
|
+
return n ? r = T.rhumbBearing(o.features[0], o.features[1]) : r = T.bearing(o.features[0], o.features[1]), r < 0 && (r += 360), d.roundPrecision(r, s);
|
|
276
321
|
}
|
|
277
322
|
/**
|
|
278
323
|
* 计算两点间距离
|
|
@@ -283,14 +328,14 @@ class y {
|
|
|
283
328
|
* @param units 单位,默认 nm(海里)
|
|
284
329
|
* @returns {number}
|
|
285
330
|
*/
|
|
286
|
-
static calculateDistance(t, e, n = !0,
|
|
287
|
-
t = { ...t }, e = { ...e }, t.lng = d.convertToStdLng(t.lng,
|
|
288
|
-
const r =
|
|
331
|
+
static calculateDistance(t, e, n = !0, s = 4, o = "nauticalmiles") {
|
|
332
|
+
t = { ...t }, e = { ...e }, t.lng = d.convertToStdLng(t.lng, s), e.lng = d.convertToStdLng(e.lng, s);
|
|
333
|
+
const r = T.points([
|
|
289
334
|
[t.lng, t.lat],
|
|
290
335
|
[e.lng, e.lat]
|
|
291
336
|
]);
|
|
292
|
-
let
|
|
293
|
-
return n ?
|
|
337
|
+
let i;
|
|
338
|
+
return n ? i = T.rhumbDistance(r.features[0], r.features[1], { units: o }) : i = T.distance(r.features[0], r.features[1], { units: o }), d.roundPrecision(i, s);
|
|
294
339
|
}
|
|
295
340
|
/**
|
|
296
341
|
* 计算航线距离
|
|
@@ -299,15 +344,15 @@ class y {
|
|
|
299
344
|
* @param units
|
|
300
345
|
*/
|
|
301
346
|
static calculateRouteDistance(t, e = 4, n = "nauticalmiles") {
|
|
302
|
-
let
|
|
347
|
+
let s = 0, o;
|
|
303
348
|
for (const r of t)
|
|
304
|
-
for (let
|
|
305
|
-
const c = { lng: r[
|
|
306
|
-
|
|
307
|
-
const a = { lng: r[
|
|
308
|
-
|
|
349
|
+
for (let i = 0; i < r.length - 1; i++) {
|
|
350
|
+
const c = { lng: r[i][0], lat: r[i][1] };
|
|
351
|
+
i === 0 && o && (s += this.calculateDistance(o, c, !0, e, n));
|
|
352
|
+
const a = { lng: r[i + 1][0], lat: r[i + 1][1] };
|
|
353
|
+
s += this.calculateDistance(c, a, !0, e, n), o = a;
|
|
309
354
|
}
|
|
310
|
-
return d.roundPrecision(
|
|
355
|
+
return d.roundPrecision(s, e);
|
|
311
356
|
}
|
|
312
357
|
/**
|
|
313
358
|
* 计算坐标(基于方位角和距离)
|
|
@@ -317,11 +362,11 @@ class y {
|
|
|
317
362
|
* @param units 单位,默认 nm(海里)
|
|
318
363
|
* @param rhumb
|
|
319
364
|
*/
|
|
320
|
-
static calculateCoordinate(t, e, n,
|
|
321
|
-
const r =
|
|
322
|
-
let
|
|
323
|
-
o ?
|
|
324
|
-
const c =
|
|
365
|
+
static calculateCoordinate(t, e, n, s = "nauticalmiles", o = !0) {
|
|
366
|
+
const r = T.point([t.lng, t.lat]);
|
|
367
|
+
let i;
|
|
368
|
+
o ? i = T.rhumbDestination(r, n, e, { units: s }) : i = T.destination(r, n, e, { units: s });
|
|
369
|
+
const c = i.geometry.coordinates;
|
|
325
370
|
return { lng: d.convertToStdLng(c[0], 8), lat: d.roundPrecision(c[1], 8) };
|
|
326
371
|
}
|
|
327
372
|
/**
|
|
@@ -333,13 +378,13 @@ class y {
|
|
|
333
378
|
* @param includeTail true 包含终点 to
|
|
334
379
|
* @param units 单位,默认 nm(海里)
|
|
335
380
|
*/
|
|
336
|
-
static interpolateCoordinates(t, e, n,
|
|
337
|
-
const
|
|
338
|
-
|
|
339
|
-
let
|
|
340
|
-
for (;
|
|
341
|
-
|
|
342
|
-
return o &&
|
|
381
|
+
static interpolateCoordinates(t, e, n, s = !0, o = !0, r = "nauticalmiles") {
|
|
382
|
+
const i = [], c = this.calculateBearing(t, e, !1), a = this.calculateDistance(t, e, !1, 8, r);
|
|
383
|
+
s && i.push({ lng: t.lng, lat: t.lat });
|
|
384
|
+
let l = 0;
|
|
385
|
+
for (; l < a; )
|
|
386
|
+
l += n, l < a && i.push(this.calculateCoordinate(t, c, l, r, !1));
|
|
387
|
+
return o && i.push({ lng: e.lng, lat: e.lat }), i;
|
|
343
388
|
}
|
|
344
389
|
/**
|
|
345
390
|
* 分组坐标(如相邻两个坐标经度差超180度,需以180为界将坐标分为两组)
|
|
@@ -357,34 +402,34 @@ class y {
|
|
|
357
402
|
if ((t == null ? void 0 : t.length) < 2)
|
|
358
403
|
return [];
|
|
359
404
|
t = n ? this.deduplicateCoordinates(t) : t;
|
|
360
|
-
let
|
|
405
|
+
let s = [];
|
|
361
406
|
const o = [];
|
|
362
|
-
let r,
|
|
407
|
+
let r, i;
|
|
363
408
|
for (let c = 0; c < t.length - 1; c++) {
|
|
364
|
-
r = d.convertToStdLng(t[c].lng, 8),
|
|
365
|
-
const a = r -
|
|
409
|
+
r = d.convertToStdLng(t[c].lng, 8), i = d.convertToStdLng(t[c + 1].lng, 8), t[c].lat = d.roundPrecision(t[c].lat, 8), t[c + 1].lat = d.roundPrecision(t[c + 1].lat, 8), s.push([r, t[c].lat]);
|
|
410
|
+
const a = r - i;
|
|
366
411
|
if (Math.abs(a) > 180) {
|
|
367
|
-
const
|
|
412
|
+
const l = d.convertToMonotonicLng2([
|
|
368
413
|
[r, t[c].lat],
|
|
369
|
-
[
|
|
414
|
+
[i, t[c + 1].lat]
|
|
370
415
|
]);
|
|
371
|
-
let
|
|
372
|
-
e ? (
|
|
416
|
+
let u, f;
|
|
417
|
+
e ? (u = T.lineString(l), f = T.lineString([
|
|
373
418
|
[a > 0 ? 180 : -180, 89],
|
|
374
419
|
[a > 0 ? 180 : -180, -89]
|
|
375
|
-
])) : (
|
|
376
|
-
const h =
|
|
377
|
-
let
|
|
420
|
+
])) : (u = T.greatCircle(l[0], l[1]), f = T.greatCircle([a > 0 ? 180 : -180, 89], [a > 0 ? 180 : -180, -89]));
|
|
421
|
+
const h = T.lineIntersect(u, f);
|
|
422
|
+
let g;
|
|
378
423
|
if (h.features.length) {
|
|
379
|
-
const
|
|
380
|
-
|
|
424
|
+
const m = T.getCoord(h.features[0]);
|
|
425
|
+
g = d.roundPrecision(m[1], 8);
|
|
381
426
|
} else
|
|
382
|
-
|
|
383
|
-
a > 0 ? (
|
|
427
|
+
g = t[c].lat;
|
|
428
|
+
a > 0 ? (s.push([180 - 1e-6, g]), o.push([...s]), s = [], s.push([-(180 - 1e-6), g])) : (s.push([-(180 - 1e-6), g]), o.push([...s]), s = [], s.push([180 - 1e-6, g]));
|
|
384
429
|
}
|
|
385
|
-
c === t.length - 2 &&
|
|
430
|
+
c === t.length - 2 && s.push([i, t[c + 1].lat]);
|
|
386
431
|
}
|
|
387
|
-
return o.push(
|
|
432
|
+
return o.push(s), o;
|
|
388
433
|
}
|
|
389
434
|
/**
|
|
390
435
|
* 去除重复坐标
|
|
@@ -393,8 +438,8 @@ class y {
|
|
|
393
438
|
static deduplicateRoute(t) {
|
|
394
439
|
const e = [];
|
|
395
440
|
for (const n of t) {
|
|
396
|
-
const
|
|
397
|
-
e.push(
|
|
441
|
+
const s = n.reduce((o, r) => (o.findIndex((i) => i[0] === r[0] && i[1] === r[1]) === -1 && o.push(r), o), []);
|
|
442
|
+
e.push(s);
|
|
398
443
|
}
|
|
399
444
|
return e;
|
|
400
445
|
}
|
|
@@ -403,7 +448,7 @@ class y {
|
|
|
403
448
|
* @param coordinates
|
|
404
449
|
*/
|
|
405
450
|
static deduplicateCoordinates(t) {
|
|
406
|
-
return t.reduce((e, n) => (e.findIndex((
|
|
451
|
+
return t.reduce((e, n) => (e.findIndex((s) => s.lat === n.lat && s.lng === n.lng) === -1 && e.push(n), e), []);
|
|
407
452
|
}
|
|
408
453
|
/**
|
|
409
454
|
* 移出坐标
|
|
@@ -413,8 +458,8 @@ class y {
|
|
|
413
458
|
static removeCoordinateFromRoute(t, e) {
|
|
414
459
|
t.lng = d.convertToStdLng(t.lng, 8);
|
|
415
460
|
for (const n of e)
|
|
416
|
-
for (let
|
|
417
|
-
d.roundPrecision(n[
|
|
461
|
+
for (let s = n.length - 1; s >= 0; s--)
|
|
462
|
+
d.roundPrecision(n[s][0], 8) === t.lng && d.roundPrecision(n[s][1], 8) === d.roundPrecision(t.lat, 8) && n.splice(s, 1);
|
|
418
463
|
return e;
|
|
419
464
|
}
|
|
420
465
|
/**
|
|
@@ -441,13 +486,13 @@ class y {
|
|
|
441
486
|
*/
|
|
442
487
|
static mergeCoordinateToRoute(t, e) {
|
|
443
488
|
t.lng = d.convertToStdLng(t.lng, 8);
|
|
444
|
-
let n = Number.MAX_VALUE,
|
|
489
|
+
let n = Number.MAX_VALUE, s = 0, o = 0, r, i;
|
|
445
490
|
return e.forEach((c, a) => {
|
|
446
|
-
for (let
|
|
447
|
-
const
|
|
448
|
-
n > h && (n = h, o =
|
|
491
|
+
for (let l = 0; l < c.length - 1; l++) {
|
|
492
|
+
const u = { lng: c[l][0], lat: c[l][1] }, f = { lng: c[l + 1][0], lat: c[l + 1][1] }, h = this.calculatePointToLineDistance(t, u, f);
|
|
493
|
+
n > h && (n = h, o = l, s = a, r = this.calculateDistance(u, t), i = this.calculateDistance(f, t));
|
|
449
494
|
}
|
|
450
|
-
}), r !== 0 &&
|
|
495
|
+
}), r !== 0 && i !== 0 ? e[s].splice(o + 1, 0, [t.lng, t.lat]) : r === 0 ? e[s].splice(o, 1, [t.lng, t.lat]) : i === 0 && e[s].splice(o + 1, 1, [t.lng, t.lat]), e;
|
|
451
496
|
}
|
|
452
497
|
/**
|
|
453
498
|
* 向Route尾加1个坐标
|
|
@@ -456,8 +501,8 @@ class y {
|
|
|
456
501
|
*/
|
|
457
502
|
static appendCoordinateToRoute(t, e) {
|
|
458
503
|
t.lng = d.convertToStdLng(t.lng, 8);
|
|
459
|
-
const n =
|
|
460
|
-
return n.push(t),
|
|
504
|
+
const n = v.convertRouteToCoordinates(e);
|
|
505
|
+
return n.push(t), v.divideAccordingToLng(n);
|
|
461
506
|
}
|
|
462
507
|
/**
|
|
463
508
|
* 向route头加1个坐标
|
|
@@ -465,8 +510,8 @@ class y {
|
|
|
465
510
|
* @param route
|
|
466
511
|
*/
|
|
467
512
|
static unshiftCoordinateToRoute(t, e) {
|
|
468
|
-
const n =
|
|
469
|
-
return n.unshift(t),
|
|
513
|
+
const n = v.convertRouteToCoordinates(e);
|
|
514
|
+
return n.unshift(t), v.divideAccordingToLng(n);
|
|
470
515
|
}
|
|
471
516
|
/**
|
|
472
517
|
* 合并多个waypoints进航线
|
|
@@ -487,21 +532,21 @@ class y {
|
|
|
487
532
|
*/
|
|
488
533
|
static calculateRangeRoute(t, e, n) {
|
|
489
534
|
n = this.mergeWaypointsToRoute([t, e], n);
|
|
490
|
-
const
|
|
535
|
+
const s = [];
|
|
491
536
|
let o = 0;
|
|
492
537
|
return n.forEach((r) => {
|
|
493
538
|
if (o === 2)
|
|
494
539
|
return;
|
|
495
|
-
const
|
|
540
|
+
const i = [];
|
|
496
541
|
for (const c of r) {
|
|
497
542
|
if (d.roundPrecision(e.lng, 8) === d.roundPrecision(c[0], 8) && d.roundPrecision(e.lat, 8) === d.roundPrecision(c[1], 8)) {
|
|
498
|
-
|
|
543
|
+
i.push(c), o === 0 && i.push([t.lng, t.lat]), o = 2;
|
|
499
544
|
break;
|
|
500
545
|
}
|
|
501
|
-
o === 1 ?
|
|
546
|
+
o === 1 ? i.push(c) : d.roundPrecision(t.lng, 8) === d.roundPrecision(c[0], 8) && d.roundPrecision(t.lat, 8) === d.roundPrecision(c[1], 8) && (o = 1, i.push(c));
|
|
502
547
|
}
|
|
503
|
-
|
|
504
|
-
}),
|
|
548
|
+
i.length && s.push(i);
|
|
549
|
+
}), s;
|
|
505
550
|
}
|
|
506
551
|
/**
|
|
507
552
|
* 计算from到to之间的航线
|
|
@@ -511,13 +556,13 @@ class y {
|
|
|
511
556
|
* @param waypoints
|
|
512
557
|
* @return [{lng, lat}]
|
|
513
558
|
*/
|
|
514
|
-
static calculateRangeWaypoints(t, e, n,
|
|
515
|
-
const o = this.convertRouteToCoordinates(n, 0), r = this.mergeCoordinatesToWaypoints([t, e], o.length ? o :
|
|
516
|
-
(
|
|
559
|
+
static calculateRangeWaypoints(t, e, n, s = []) {
|
|
560
|
+
const o = this.convertRouteToCoordinates(n, 0), r = this.mergeCoordinatesToWaypoints([t, e], o.length ? o : s), i = r.findIndex(
|
|
561
|
+
(l) => d.roundPrecision(t.lng, 8) === d.roundPrecision(l.lng, 8) && d.roundPrecision(t.lat, 8) === d.roundPrecision(l.lat, 8)
|
|
517
562
|
), c = r.findIndex(
|
|
518
|
-
(
|
|
563
|
+
(l) => d.roundPrecision(e.lng, 8) === d.roundPrecision(l.lng, 8) && d.roundPrecision(e.lat, 8) === d.roundPrecision(l.lat, 8)
|
|
519
564
|
);
|
|
520
|
-
return r.filter((
|
|
565
|
+
return r.filter((l, u) => u >= i && u <= c);
|
|
521
566
|
}
|
|
522
567
|
/**
|
|
523
568
|
* 计算坐标到航路上的最短距离
|
|
@@ -525,13 +570,13 @@ class y {
|
|
|
525
570
|
* @param route
|
|
526
571
|
*/
|
|
527
572
|
static calculateMinDistanceToRoute(t, e) {
|
|
528
|
-
let n = Number.MAX_VALUE,
|
|
529
|
-
return e.forEach((r,
|
|
573
|
+
let n = Number.MAX_VALUE, s = 0, o = 0;
|
|
574
|
+
return e.forEach((r, i) => {
|
|
530
575
|
for (let c = 0; c < r.length - 1; c++) {
|
|
531
|
-
const a = { lng: r[c][0], lat: r[c][1] },
|
|
532
|
-
n >
|
|
576
|
+
const a = { lng: r[c][0], lat: r[c][1] }, l = { lng: r[c + 1][0], lat: r[c + 1][1] }, u = this.calculatePointToLineDistance(t, a, l);
|
|
577
|
+
n > u && (n = u, s = c, o = i);
|
|
533
578
|
}
|
|
534
|
-
}), { minDist: n, segIndex: o, minIndex:
|
|
579
|
+
}), { minDist: n, segIndex: o, minIndex: s };
|
|
535
580
|
}
|
|
536
581
|
/**
|
|
537
582
|
* 计算子航线
|
|
@@ -540,19 +585,19 @@ class y {
|
|
|
540
585
|
* @return [[[lng, lat]]]
|
|
541
586
|
*/
|
|
542
587
|
static calculateSubRoute(t, e) {
|
|
543
|
-
const n =
|
|
544
|
-
|
|
545
|
-
const { segIndex:
|
|
588
|
+
const n = v.convertRouteToCoordinates(e);
|
|
589
|
+
v.mergeCoordinateToWaypoints(t, n, !0), e = v.divideAccordingToLng(n);
|
|
590
|
+
const { segIndex: s, minIndex: o } = this.calculateMinDistanceToRoute({ ...t }, e);
|
|
546
591
|
t.lng = d.convertToStdLng(t.lng);
|
|
547
592
|
const r = [];
|
|
548
|
-
let
|
|
549
|
-
for (let c =
|
|
550
|
-
if (
|
|
593
|
+
let i = !0;
|
|
594
|
+
for (let c = s; c < e.length; c++)
|
|
595
|
+
if (i) {
|
|
551
596
|
const a = [];
|
|
552
597
|
a.push([t.lng, t.lat]);
|
|
553
|
-
for (let
|
|
554
|
-
t.lng === e[c][
|
|
555
|
-
r.push(a),
|
|
598
|
+
for (let l = o + 1; l < e[c].length; l++)
|
|
599
|
+
t.lng === e[c][l][0] && t.lat === e[c][l][1] || a.push(e[c][l]);
|
|
600
|
+
r.push(a), i = !1;
|
|
556
601
|
} else
|
|
557
602
|
r.push([...e[c]]);
|
|
558
603
|
return r;
|
|
@@ -564,19 +609,19 @@ class y {
|
|
|
564
609
|
* @return [{lng, lat}]
|
|
565
610
|
*/
|
|
566
611
|
static calculateSubWaypoints(t, e) {
|
|
567
|
-
let n = Number.MAX_VALUE,
|
|
612
|
+
let n = Number.MAX_VALUE, s = 0;
|
|
568
613
|
for (let r = 0; r < e.length - 1; r++) {
|
|
569
|
-
const
|
|
570
|
-
if (this.calculateDistance(t,
|
|
614
|
+
const i = e[r], c = e[r + 1];
|
|
615
|
+
if (this.calculateDistance(t, i) === 0)
|
|
571
616
|
return e;
|
|
572
617
|
if (this.calculateDistance(t, c) === 0)
|
|
573
|
-
return e.filter((
|
|
574
|
-
const a = this.calculatePointToLineDistance(t,
|
|
575
|
-
n > a && (n = a,
|
|
618
|
+
return e.filter((l, u) => u > 0);
|
|
619
|
+
const a = this.calculatePointToLineDistance(t, i, c);
|
|
620
|
+
n > a && (n = a, s = r);
|
|
576
621
|
}
|
|
577
622
|
t.lng = d.convertToStdLng(t.lng);
|
|
578
623
|
const o = [t];
|
|
579
|
-
for (let r =
|
|
624
|
+
for (let r = s + 1; r < e.length; r++)
|
|
580
625
|
o.push(e[r]);
|
|
581
626
|
return o;
|
|
582
627
|
}
|
|
@@ -587,15 +632,15 @@ class y {
|
|
|
587
632
|
* @param to { lng, lat }
|
|
588
633
|
* @param options
|
|
589
634
|
*/
|
|
590
|
-
static calculatePointToLineDistance(t, e, n,
|
|
635
|
+
static calculatePointToLineDistance(t, e, n, s = { units: "nauticalmiles", method: "geodesic" }) {
|
|
591
636
|
t.lng = d.convertToStdLng(t.lng, 8), e = { ...e }, n = { ...n }, e.lng = d.convertToStdLng(e.lng, 8), n.lng = d.convertToStdLng(n.lng, 8);
|
|
592
637
|
const o = d.convertToMonotonicLng([e, n]);
|
|
593
638
|
e = o[0], n = o[1];
|
|
594
|
-
const r =
|
|
639
|
+
const r = T.lineString([
|
|
595
640
|
[e.lng, e.lat],
|
|
596
641
|
[n.lng, n.lat]
|
|
597
|
-
]),
|
|
598
|
-
return d.roundPrecision(Math.min(
|
|
642
|
+
]), i = T.pointToLineDistance(T.point([t.lng, t.lat]), r, s), c = T.pointToLineDistance(T.point([t.lng > 0 ? t.lng - 360 : t.lng + 360, t.lat]), r, s);
|
|
643
|
+
return d.roundPrecision(Math.min(i, c), 6);
|
|
599
644
|
}
|
|
600
645
|
/**
|
|
601
646
|
* 计算途经点的COG, Distance等属性
|
|
@@ -605,8 +650,8 @@ class y {
|
|
|
605
650
|
static calculateWaypointsPropInRoute(t, e) {
|
|
606
651
|
e = this.mergeWaypointsToRoute(t, e);
|
|
607
652
|
for (let n = 0; n < t.length - 1; n++) {
|
|
608
|
-
const
|
|
609
|
-
n === 0 && (
|
|
653
|
+
const s = t[n], o = t[n + 1], r = this.calculateRangeRoute(s, o, e);
|
|
654
|
+
n === 0 && (s.distanceFromPrevious = 0, s.distanceFromStart = 0), o.distanceFromPrevious = this.calculateRouteDistance(r), o.distanceFromStart = d.roundPrecision((s.distanceFromStart || 0) + o.distanceFromPrevious);
|
|
610
655
|
}
|
|
611
656
|
return t;
|
|
612
657
|
}
|
|
@@ -616,8 +661,8 @@ class y {
|
|
|
616
661
|
* @param replace true replace the same waypoint with coordinate
|
|
617
662
|
*/
|
|
618
663
|
static mergeCoordinatesToWaypoints(t, e, n = !0) {
|
|
619
|
-
for (const
|
|
620
|
-
this.mergeCoordinateToWaypoints(
|
|
664
|
+
for (const s of t)
|
|
665
|
+
this.mergeCoordinateToWaypoints(s, e, n);
|
|
621
666
|
return e;
|
|
622
667
|
}
|
|
623
668
|
/**
|
|
@@ -634,22 +679,22 @@ class y {
|
|
|
634
679
|
*/
|
|
635
680
|
static mergeCoordinateToWaypoints(t, e, n = !0) {
|
|
636
681
|
t.lng = d.convertToStdLng(t.lng, 8);
|
|
637
|
-
let
|
|
682
|
+
let s = Number.MAX_VALUE, o = 0, r = 0, i = 0;
|
|
638
683
|
if (e.length < 2)
|
|
639
684
|
e.push(t);
|
|
640
685
|
else {
|
|
641
686
|
for (let c = 0; c < e.length - 1; c++) {
|
|
642
|
-
const a = { lng: e[c].lng, lat: e[c].lat },
|
|
643
|
-
|
|
687
|
+
const a = { lng: e[c].lng, lat: e[c].lat }, l = { lng: e[c + 1].lng, lat: e[c + 1].lat }, u = this.calculatePointToLineDistance(t, a, l);
|
|
688
|
+
s >= u && (s = u, o = c, r = this.calculateDistance(a, t, !1, 6), i = this.calculateDistance(l, t, !1, 6));
|
|
644
689
|
}
|
|
645
|
-
r !== 0 &&
|
|
690
|
+
r !== 0 && i !== 0 ? r <= s && o === 0 ? e.unshift(t) : i <= s && o === e.length - 2 ? e.push(t) : e.splice(o + 1, 0, t) : r === 0 ? n ? e.splice(o, 1, t) : e.splice(o + 1, 0, t) : i === 0 && (n ? e.splice(o + 1, 1, t) : e.splice(o + 1, 0, t));
|
|
646
691
|
}
|
|
647
692
|
return e.map((c, a) => {
|
|
648
693
|
c.lng = d.convertToStdLng(c.lng);
|
|
649
|
-
const
|
|
650
|
-
if (
|
|
651
|
-
const
|
|
652
|
-
c.sog = d.roundPrecision(
|
|
694
|
+
const l = e[a + 1];
|
|
695
|
+
if (l && ((c.bearing === null || c.bearing === void 0) && ((c.positionTime || 0) > (l.positionTime || 0) ? c.bearing = this.calculateBearing(l, c, !0) : c.bearing = this.calculateBearing(c, l, !0)), c.cog = c.cog || c.bearing, !c.sog && c.positionTime && l.positionTime)) {
|
|
696
|
+
const u = this.calculateDistance(c, l, !0), f = Math.abs(l.positionTime - c.positionTime) / 3600;
|
|
697
|
+
c.sog = d.roundPrecision(u / f, 2);
|
|
653
698
|
}
|
|
654
699
|
return c;
|
|
655
700
|
});
|
|
@@ -662,16 +707,16 @@ class y {
|
|
|
662
707
|
* @param deduplicate
|
|
663
708
|
*/
|
|
664
709
|
static generateRouteAccordingToWaypoints(t, e = !0, n = !0) {
|
|
665
|
-
const
|
|
710
|
+
const s = [];
|
|
666
711
|
for (let o = 1; o < t.length; o++) {
|
|
667
|
-
const r = t[o - 1],
|
|
668
|
-
if (o === 1 &&
|
|
669
|
-
const c = this.interpolateCoordinates(r,
|
|
670
|
-
|
|
712
|
+
const r = t[o - 1], i = t[o];
|
|
713
|
+
if (o === 1 && s.push(r), i.gcToPrevious) {
|
|
714
|
+
const c = this.interpolateCoordinates(r, i, 200, !1, !0, "nauticalmiles");
|
|
715
|
+
s.push(...c);
|
|
671
716
|
} else
|
|
672
|
-
|
|
717
|
+
s.push(i);
|
|
673
718
|
}
|
|
674
|
-
return this.divideAccordingToLng(
|
|
719
|
+
return this.divideAccordingToLng(s, e, n);
|
|
675
720
|
}
|
|
676
721
|
/**
|
|
677
722
|
* 最近点(从route中找出距离目标点最近的点)
|
|
@@ -679,7 +724,7 @@ class y {
|
|
|
679
724
|
* @param route [[[lng, lat]]]
|
|
680
725
|
*/
|
|
681
726
|
static nearestCoordinateInRoute(t, e) {
|
|
682
|
-
const n =
|
|
727
|
+
const n = T.point([t.lng, t.lat]), o = this.convertRouteToCoordinates(e).map((a) => [a.lng, a.lat]), r = T.lineString(o), i = T.nearestPointOnLine(r, n), c = T.getCoord(i);
|
|
683
728
|
return { lng: d.roundPrecision(c[0], 8), lat: d.roundPrecision(c[1], 8) };
|
|
684
729
|
}
|
|
685
730
|
/**
|
|
@@ -690,14 +735,14 @@ class y {
|
|
|
690
735
|
static calculatePrevWaypoint(t, e) {
|
|
691
736
|
let n = 0;
|
|
692
737
|
this.mergeCoordinateToWaypoints(t, e);
|
|
693
|
-
for (let
|
|
694
|
-
const o = e[
|
|
738
|
+
for (let s = 0; s < e.length - 1; s++) {
|
|
739
|
+
const o = e[s], r = e[s + 1];
|
|
695
740
|
if (this.calculateDistance(t, o) === 0) {
|
|
696
|
-
n =
|
|
741
|
+
n = s;
|
|
697
742
|
break;
|
|
698
743
|
}
|
|
699
744
|
if (this.calculateDistance(t, r) === 0) {
|
|
700
|
-
n =
|
|
745
|
+
n = s + 1;
|
|
701
746
|
break;
|
|
702
747
|
}
|
|
703
748
|
}
|
|
@@ -711,43 +756,43 @@ class y {
|
|
|
711
756
|
* @param units
|
|
712
757
|
* @return { coordinate: {lng, lat}, route: [[[lng, lat]]]}
|
|
713
758
|
*/
|
|
714
|
-
static calculateNextCoordinateAlongRoute(t, e, n,
|
|
715
|
-
var
|
|
759
|
+
static calculateNextCoordinateAlongRoute(t, e, n, s = "nauticalmiles") {
|
|
760
|
+
var f;
|
|
716
761
|
const o = t.speed || 12, r = [];
|
|
717
|
-
let
|
|
718
|
-
if (e && n.length ? (r.push(t), n.forEach((h,
|
|
762
|
+
let i = [], c = !1, a = 0, l = 0, u;
|
|
763
|
+
if (e && n.length ? (r.push(t), n.forEach((h, g) => {
|
|
719
764
|
if (c)
|
|
720
|
-
|
|
765
|
+
i.push(h);
|
|
721
766
|
else {
|
|
722
|
-
const
|
|
723
|
-
let
|
|
724
|
-
for (let
|
|
725
|
-
if (
|
|
726
|
-
|
|
767
|
+
const m = [];
|
|
768
|
+
let p;
|
|
769
|
+
for (let S = 0; S < h.length; S++)
|
|
770
|
+
if (u)
|
|
771
|
+
m.push(h[S]);
|
|
727
772
|
else {
|
|
728
|
-
|
|
729
|
-
const
|
|
730
|
-
if (a +=
|
|
731
|
-
|
|
773
|
+
p = { lng: h[S][0], lat: h[S][1] };
|
|
774
|
+
const x = this.calculateDistance(t, p, !0, 8, s);
|
|
775
|
+
if (a += x, a < e)
|
|
776
|
+
l += x, x && r.push(p), t = p;
|
|
732
777
|
else {
|
|
733
|
-
if (
|
|
734
|
-
|
|
778
|
+
if (l = e, a === e)
|
|
779
|
+
u = p, m.push([u.lng, u.lat]);
|
|
735
780
|
else {
|
|
736
|
-
const M = a - e,
|
|
737
|
-
|
|
781
|
+
const M = a - e, y = this.calculateBearing(p, t);
|
|
782
|
+
u = this.calculateCoordinate(p, y, M, s), m.push([u.lng, u.lat]), m.push([p.lng, p.lat]);
|
|
738
783
|
}
|
|
739
784
|
c = !0;
|
|
740
785
|
}
|
|
741
786
|
}
|
|
742
|
-
|
|
787
|
+
m.length && i.push(m), g === n.length - 1 && !u && (u = p);
|
|
743
788
|
}
|
|
744
|
-
})) : (
|
|
745
|
-
if (r.push(
|
|
746
|
-
const h = { lng:
|
|
747
|
-
|
|
789
|
+
})) : (i = n, u = { ...t }), u)
|
|
790
|
+
if (r.push(u), u.distanceFromPrevious = Math.round(l * 1e4) / 1e4, u.hourFromPrevious = Math.round(l / o * 1e4) / 1e4, ((f = i[0]) == null ? void 0 : f.length) > 1) {
|
|
791
|
+
const h = { lng: i[0][1][0], lat: i[0][1][1] };
|
|
792
|
+
u.bearing = this.calculateBearing(u, h);
|
|
748
793
|
} else
|
|
749
|
-
|
|
750
|
-
return { coordinate:
|
|
794
|
+
u.bearing = 0;
|
|
795
|
+
return { coordinate: u, nextRoute: i, prevRoute: r };
|
|
751
796
|
}
|
|
752
797
|
/**
|
|
753
798
|
* 返回最近点及其是否为垂足(最近点不是起点或终点)
|
|
@@ -756,11 +801,11 @@ class y {
|
|
|
756
801
|
* @param to {lng, lat}
|
|
757
802
|
*/
|
|
758
803
|
static nearestCoordinateInLine(t, e, n) {
|
|
759
|
-
const
|
|
804
|
+
const s = d.convertToStdLng(t.lng, 6), o = T.point([s, t.lat]), r = d.convertToStdLng(e.lng, 6), i = d.convertToStdLng(n.lng, 6), c = T.lineString([
|
|
760
805
|
[r, e.lat],
|
|
761
|
-
[
|
|
762
|
-
]), a =
|
|
763
|
-
return { lng:
|
|
806
|
+
[i, n.lat]
|
|
807
|
+
]), a = T.nearestPointOnLine(c, o), l = T.getCoord(a), u = d.roundPrecision(l[0], 6), f = d.roundPrecision(l[1], 6);
|
|
808
|
+
return { lng: u, lat: f, inline: !(u === r && f === e.lat) && !(u === i && f === n.lat) };
|
|
764
809
|
}
|
|
765
810
|
/**
|
|
766
811
|
* 将route转coordinate
|
|
@@ -769,21 +814,21 @@ class y {
|
|
|
769
814
|
*/
|
|
770
815
|
static convertRouteToCoordinates(t, e = 0) {
|
|
771
816
|
const n = [];
|
|
772
|
-
let
|
|
817
|
+
let s, o;
|
|
773
818
|
return t.forEach((r) => {
|
|
774
|
-
r.forEach((
|
|
775
|
-
const c = { lng: d.roundPrecision(
|
|
819
|
+
r.forEach((i) => {
|
|
820
|
+
const c = { lng: d.roundPrecision(i[0], 8), lat: d.roundPrecision(i[1], 8) };
|
|
776
821
|
if (!o)
|
|
777
822
|
n.push(c), o = c;
|
|
778
823
|
else if (o.bearing === void 0 || o.bearing === null)
|
|
779
824
|
o.bearing = this.calculateBearing(o, c, !0);
|
|
780
825
|
else {
|
|
781
|
-
const a = this.calculateDistance(
|
|
782
|
-
a && a >= e && (
|
|
826
|
+
const a = this.calculateDistance(s, c, !0);
|
|
827
|
+
a && a >= e && (s.bearing = this.calculateBearing(s, c, !0), n.push(s), o = s);
|
|
783
828
|
}
|
|
784
|
-
|
|
829
|
+
s = c;
|
|
785
830
|
});
|
|
786
|
-
}),
|
|
831
|
+
}), s && n.push(s), n;
|
|
787
832
|
}
|
|
788
833
|
/**
|
|
789
834
|
* 抽稀(基于转向点)
|
|
@@ -792,8 +837,8 @@ class y {
|
|
|
792
837
|
* @param distance
|
|
793
838
|
*/
|
|
794
839
|
static simplifyRouteToCoordinates(t, e, n = 1) {
|
|
795
|
-
let
|
|
796
|
-
return
|
|
840
|
+
let s = this.convertRouteToCoordinates(t, n);
|
|
841
|
+
return s = this.simplifyGCCoordinates(s, e), s;
|
|
797
842
|
}
|
|
798
843
|
/**
|
|
799
844
|
* 基于大圆标识抽稀
|
|
@@ -801,23 +846,23 @@ class y {
|
|
|
801
846
|
* @param waypoints
|
|
802
847
|
*/
|
|
803
848
|
static simplifyGCCoordinates(t, e) {
|
|
804
|
-
e.forEach((
|
|
805
|
-
this.mergeCoordinateToWaypoints(
|
|
849
|
+
e.forEach((s) => {
|
|
850
|
+
this.mergeCoordinateToWaypoints(s, t, !0);
|
|
806
851
|
});
|
|
807
|
-
for (let
|
|
808
|
-
const o = e[
|
|
852
|
+
for (let s = 1; s < e.length; s++) {
|
|
853
|
+
const o = e[s - 1], r = e[s];
|
|
809
854
|
if (r.gcToPrevious) {
|
|
810
|
-
const
|
|
811
|
-
for (let a = c - 1; a >
|
|
855
|
+
const i = t.findIndex((a) => a.lng === o.lng && a.lat === o.lat), c = t.findIndex((a) => a.lng === r.lng && a.lat === r.lat);
|
|
856
|
+
for (let a = c - 1; a > i; a--)
|
|
812
857
|
t.splice(a, 1);
|
|
813
858
|
}
|
|
814
859
|
}
|
|
815
860
|
let n = 0;
|
|
816
|
-
for (let
|
|
817
|
-
const o = t[
|
|
861
|
+
for (let s = 1; s < t.length; s++) {
|
|
862
|
+
const o = t[s - 1], r = t[s];
|
|
818
863
|
r.gcToPrevious ? (o.bearing = this.calculateBearing(o, r, !1), r.distanceFromPrevious = this.calculateDistance(o, r, !1)) : (o.bearing = this.calculateBearing(o, r, !0), r.distanceFromPrevious = this.calculateDistance(o, r, !0)), n = d.roundPrecision(n + r.distanceFromPrevious), r.distanceFromStart = n;
|
|
819
864
|
}
|
|
820
|
-
return t.map((
|
|
865
|
+
return t.map((s) => (s.lng = d.convertToStdLng(s.lng), s));
|
|
821
866
|
}
|
|
822
867
|
/**
|
|
823
868
|
* 计算轨迹中心点
|
|
@@ -825,13 +870,13 @@ class y {
|
|
|
825
870
|
*/
|
|
826
871
|
static calculateCenter(t) {
|
|
827
872
|
const e = [];
|
|
828
|
-
for (const
|
|
829
|
-
for (const c of
|
|
873
|
+
for (const i of t)
|
|
874
|
+
for (const c of i)
|
|
830
875
|
e.push(c);
|
|
831
|
-
const n =
|
|
832
|
-
for (const
|
|
833
|
-
n.features.push(
|
|
834
|
-
const r =
|
|
876
|
+
const n = T.featureCollection([]), s = d.convertToMonotonicLng2(e);
|
|
877
|
+
for (const i of s)
|
|
878
|
+
n.features.push(T.point(i));
|
|
879
|
+
const r = T.center(n).geometry.coordinates;
|
|
835
880
|
return { lng: d.convertToStdLng(r[0], 8), lat: d.roundPrecision(r[1], 8) };
|
|
836
881
|
}
|
|
837
882
|
/**
|
|
@@ -851,8 +896,8 @@ class y {
|
|
|
851
896
|
for (const o of t)
|
|
852
897
|
for (const r of o)
|
|
853
898
|
e.push(r);
|
|
854
|
-
const n = d.convertToMonotonicLng2(e),
|
|
855
|
-
return
|
|
899
|
+
const n = d.convertToMonotonicLng2(e), s = T.lineString(n);
|
|
900
|
+
return T.bbox(s);
|
|
856
901
|
}
|
|
857
902
|
/**
|
|
858
903
|
* 计算BBox
|
|
@@ -869,20 +914,20 @@ class y {
|
|
|
869
914
|
* @param angle 三点夹角, 大于此角度时,B点将被忽略(近似走RL)
|
|
870
915
|
*/
|
|
871
916
|
static simplifyCoordinates(t, e = 1, n = 180) {
|
|
872
|
-
const
|
|
917
|
+
const s = [];
|
|
873
918
|
for (let o = 1; o < t.length; o++) {
|
|
874
|
-
const r = t[o - 1],
|
|
875
|
-
let a = !1,
|
|
876
|
-
if ((r.velocity || r.suspend || r.important || r.pilot || o === 1) && (a = !0,
|
|
877
|
-
const
|
|
878
|
-
Math.round(Math.acos(
|
|
919
|
+
const r = t[o - 1], i = t[o], c = t[o + 1];
|
|
920
|
+
let a = !1, l = !1;
|
|
921
|
+
if ((r.velocity || r.suspend || r.important || r.pilot || o === 1) && (a = !0, s.push(r)), i.gcToPrevious && (a || (a = !0, s.push(r)), l = !0, s.push(i), o++), c) {
|
|
922
|
+
const u = v.calculateDistance(r, i, !0), f = v.calculateDistance(i, c, !0), h = v.calculateDistance(r, c, !0), g = (Math.pow(u, 2) + Math.pow(f, 2) - Math.pow(h, 2)) / (2 * u * f);
|
|
923
|
+
Math.round(Math.acos(g) * 180 / Math.PI) < n && h > e && !l && (s.push(i), o++);
|
|
879
924
|
}
|
|
880
925
|
if (o >= t.length - 1) {
|
|
881
|
-
const
|
|
882
|
-
|
|
926
|
+
const u = t.at(-1);
|
|
927
|
+
u && s.push(u);
|
|
883
928
|
}
|
|
884
929
|
}
|
|
885
|
-
return
|
|
930
|
+
return s;
|
|
886
931
|
}
|
|
887
932
|
/**
|
|
888
933
|
* 在时间轨迹上寻找ts最近的点
|
|
@@ -891,10 +936,10 @@ class y {
|
|
|
891
936
|
* @param waypoints 带时间的轨迹, 单位秒
|
|
892
937
|
*/
|
|
893
938
|
static nearestTSPointInWaypoints(t, e, n) {
|
|
894
|
-
const
|
|
895
|
-
(r) =>
|
|
939
|
+
const s = b.unix(t), o = n.filter(
|
|
940
|
+
(r) => s.clone().subtract(e, "hour").unix() <= (r.positionTime || 0) && s.clone().add(e, "h").unix() >= (r.positionTime || 0)
|
|
896
941
|
);
|
|
897
|
-
return o.sort((r,
|
|
942
|
+
return o.sort((r, i) => (r.positionTime || 0) - (i.positionTime || 0)), o.at(-1);
|
|
898
943
|
}
|
|
899
944
|
/**
|
|
900
945
|
* 推测船位
|
|
@@ -902,19 +947,19 @@ class y {
|
|
|
902
947
|
* @param positions 带时间(positionTime)的轨迹
|
|
903
948
|
*/
|
|
904
949
|
static deadReckoning(t, e) {
|
|
905
|
-
var o, r,
|
|
950
|
+
var o, r, i, c;
|
|
906
951
|
t > 1e12 && (t = Math.round(t / 1e3));
|
|
907
952
|
const n = b.unix(t);
|
|
908
|
-
let
|
|
909
|
-
if (!
|
|
910
|
-
const a = (r = (o = e.filter((
|
|
911
|
-
if (a &&
|
|
912
|
-
const
|
|
913
|
-
|
|
953
|
+
let s = e.find((a) => a.positionTime === n.unix());
|
|
954
|
+
if (!s) {
|
|
955
|
+
const a = (r = (o = e.filter((u) => (u == null ? void 0 : u.positionTime) < n.unix())) == null ? void 0 : o.sort((u, f) => (u.positionTime || 0) - (f.positionTime || 0))) == null ? void 0 : r.at(-1), l = (c = (i = e.filter((u) => (u == null ? void 0 : u.positionTime) > n.unix())) == null ? void 0 : i.sort((u, f) => (u.positionTime || 0) - (f.positionTime || 0))) == null ? void 0 : c.at(0);
|
|
956
|
+
if (a && l) {
|
|
957
|
+
const u = v.calculateBearing(a, l, !0), f = v.calculateDistance(a, l), h = (n.unix() - a.positionTime) / (l.positionTime - a.positionTime);
|
|
958
|
+
s = v.calculateCoordinate(a, u, f * h), s.positionTime = n.unix(), s.utc = n.utc().format(), s.cog = u, s.sog = Math.round(f / ((l.positionTime - a.positionTime) / 3600) * 100) / 100;
|
|
914
959
|
} else
|
|
915
|
-
|
|
960
|
+
s = a || l, s && (s.utc = b.unix(s == null ? void 0 : s.positionTime).utc().format());
|
|
916
961
|
}
|
|
917
|
-
return
|
|
962
|
+
return s;
|
|
918
963
|
}
|
|
919
964
|
/**
|
|
920
965
|
* 推测船位时间
|
|
@@ -922,20 +967,20 @@ class y {
|
|
|
922
967
|
* @param positions
|
|
923
968
|
*/
|
|
924
969
|
static deadReckoningTime(t, e) {
|
|
925
|
-
e = JSON.parse(JSON.stringify(e)), e.sort((a,
|
|
926
|
-
let n = Number.MAX_SAFE_INTEGER,
|
|
970
|
+
e = JSON.parse(JSON.stringify(e)), e.sort((a, l) => (a.positionTime || 0) - (l.positionTime || 0));
|
|
971
|
+
let n = Number.MAX_SAFE_INTEGER, s = Number.MAX_SAFE_INTEGER;
|
|
927
972
|
for (let a = 0; a < e.length - 1; a++) {
|
|
928
|
-
const
|
|
929
|
-
|
|
973
|
+
const l = e[a], u = e[a + 1], f = v.calculatePointToLineDistance(t, l, u);
|
|
974
|
+
f < n && (n = f, s = a);
|
|
930
975
|
}
|
|
931
|
-
const o = e[
|
|
932
|
-
if (
|
|
976
|
+
const o = e[s], r = e[s + 1], i = v.calculateDistance(o, t), c = v.calculateDistance(r, t);
|
|
977
|
+
if (i === 0)
|
|
933
978
|
t = o;
|
|
934
979
|
else if (c === 0)
|
|
935
980
|
t = r;
|
|
936
981
|
else {
|
|
937
|
-
const a = o.positionTime || 0,
|
|
938
|
-
t.positionTime = Math.round(a + (
|
|
982
|
+
const a = o.positionTime || 0, l = r.positionTime || 0, u = v.calculateDistance(o, r);
|
|
983
|
+
t.positionTime = Math.round(a + (l - a) * (i / u));
|
|
939
984
|
}
|
|
940
985
|
return t.utc = t.positionTime ? b.unix(t.positionTime).utc().format() : void 0, t.positionTime ? t : void 0;
|
|
941
986
|
}
|
|
@@ -972,8 +1017,8 @@ class y {
|
|
|
972
1017
|
*
|
|
973
1018
|
*/
|
|
974
1019
|
static waypoints2RTZ(t, e) {
|
|
975
|
-
const
|
|
976
|
-
return
|
|
1020
|
+
const s = [];
|
|
1021
|
+
return s.push('<?xml version="1.0" encoding="UTF-8"?>'), s.push('<route xmlns="http://www.cirm.org/RTZ/1/2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2">'), s.push(` <routeInfo routeName="${v.xmlEscape(t)}"></routeInfo>`), s.push(...v.toRTZWaypoints(e, 6)), s.push("</route>"), s.join(`
|
|
977
1022
|
`);
|
|
978
1023
|
}
|
|
979
1024
|
/**
|
|
@@ -984,32 +1029,32 @@ class y {
|
|
|
984
1029
|
*/
|
|
985
1030
|
static waypoints2RTZ10(t, e, n = !0) {
|
|
986
1031
|
const o = [];
|
|
987
|
-
return o.push('<?xml version="1.0" encoding="UTF-8"?>'), o.push('<route xmlns="http://www.cirm.org/RTZ/1/0" version="1.0">'), o.push(` <routeInfo routeName="${
|
|
1032
|
+
return o.push('<?xml version="1.0" encoding="UTF-8"?>'), o.push('<route xmlns="http://www.cirm.org/RTZ/1/0" version="1.0">'), o.push(` <routeInfo routeName="${v.xmlEscape(t)}"></routeInfo>`), o.push(...v.toRTZWaypoints(e, 6, n)), o.push("</route>"), o.join(`
|
|
988
1033
|
`);
|
|
989
1034
|
}
|
|
990
1035
|
static toRTZWaypoints(t, e = 6, n = !0) {
|
|
991
|
-
const
|
|
992
|
-
|
|
1036
|
+
const s = [];
|
|
1037
|
+
s.push(" <waypoints>");
|
|
993
1038
|
for (let o = 0; o < t.length; o++) {
|
|
994
|
-
const r = t[o],
|
|
995
|
-
if (r.name &&
|
|
996
|
-
const
|
|
997
|
-
|
|
1039
|
+
const r = t[o], i = o + 1, c = (r.lat ?? "").toFixed ? r.lat.toFixed(e).padEnd(e + 2, "0") : r.lat, a = (r.lng ?? "").toFixed ? r.lng.toFixed(e).padEnd(e + 2, "0") : r.lng, l = [`id="${i}"`, 'revision="0"'];
|
|
1040
|
+
if (r.name && l.push(`name="${v.xmlEscape(r.name)}"`), s.push(` <waypoint ${l.join(" ")}>`), s.push(` <position lat="${v.xmlEscape(c)}" lon="${v.xmlEscape(a)}" />`), o > 0) {
|
|
1041
|
+
const u = r.gcToPrevious ? "Orthodrome" : "Loxodrome";
|
|
1042
|
+
s.push(` <leg geometryType="${u}" />`);
|
|
998
1043
|
}
|
|
999
1044
|
if (n) {
|
|
1000
|
-
const
|
|
1001
|
-
if (r.description &&
|
|
1002
|
-
|
|
1045
|
+
const u = [];
|
|
1046
|
+
if (r.description && u.push(` <description>${v.xmlEscape(r.description)}</description>`), r.utc)
|
|
1047
|
+
u.push(` <time>${v.xmlEscape(r.utc)}</time>`);
|
|
1003
1048
|
else if (r.positionTime)
|
|
1004
1049
|
try {
|
|
1005
|
-
|
|
1050
|
+
u.push(` <time>${v.xmlEscape(b.unix(r.positionTime).utc().format())}</time>`);
|
|
1006
1051
|
} catch {
|
|
1007
1052
|
}
|
|
1008
|
-
r.cog !== void 0 &&
|
|
1053
|
+
r.cog !== void 0 && u.push(` <cog>${v.xmlEscape(r.cog)}</cog>`), r.sog !== void 0 && u.push(` <sog>${v.xmlEscape(r.sog)}</sog>`), u.length && (s.push(" <extensions>"), s.push(...u), s.push(" </extensions>"));
|
|
1009
1054
|
}
|
|
1010
|
-
|
|
1055
|
+
s.push(" </waypoint>");
|
|
1011
1056
|
}
|
|
1012
|
-
return
|
|
1057
|
+
return s.push(" </waypoints>"), s;
|
|
1013
1058
|
}
|
|
1014
1059
|
/**
|
|
1015
1060
|
* 路径转通用CSV (纯十进制度数、无厂商头、RFC 4180标准)
|
|
@@ -1019,18 +1064,52 @@ class y {
|
|
|
1019
1064
|
* @param options.precision 经纬度小数位数,默认6
|
|
1020
1065
|
*/
|
|
1021
1066
|
static waypoints2CSV(t, e, n) {
|
|
1022
|
-
|
|
1023
|
-
const
|
|
1024
|
-
o &&
|
|
1025
|
-
const
|
|
1026
|
-
|
|
1027
|
-
for (let
|
|
1028
|
-
const
|
|
1029
|
-
|
|
1067
|
+
X.debug("keep name for waypoints2CSV for legacy compatibility only", t);
|
|
1068
|
+
const s = (n == null ? void 0 : n.precision) ?? 6, o = e.some((p) => p.name), r = e.some((p) => p.description), i = e.some((p) => p.port != null), c = e.some((p) => p.stbd != null), a = e.some((p) => p.arrRad != null), l = e.some((p) => p.speed != null), u = e.some((p, S) => S > 0 && p.gcToPrevious != null), f = e.some((p) => p.bearing != null), h = e.some((p) => p.distanceFromPrevious != null), g = ["WPT No.", "Latitude", "Longitude"];
|
|
1069
|
+
o && g.push("Name"), r && g.push("Description"), u && g.push("Leg"), f && g.push("Bearing[deg]"), h && g.push("Distance[NM]"), l && g.push("Speed[kn]"), i && g.push("PORT XTD[NM]"), c && g.push("STBD XTD[NM]"), a && g.push("Arr.Rad[NM]");
|
|
1070
|
+
const m = [];
|
|
1071
|
+
m.push(g.map((p) => v.csvEscapeField(p)).join(","));
|
|
1072
|
+
for (let p = 0; p < e.length; p++) {
|
|
1073
|
+
const S = e[p], x = [];
|
|
1074
|
+
x.push((p + 1).toString()), x.push(S.lat.toFixed(s)), x.push(S.lng.toFixed(s)), o && x.push(S.name ?? ""), r && x.push(S.description ?? ""), u && x.push(p === 0 ? "" : S.gcToPrevious ? "GC" : "RL"), f && x.push(S.bearing != null ? String(S.bearing) : ""), h && x.push(S.distanceFromPrevious != null ? String(S.distanceFromPrevious) : ""), l && x.push(S.speed != null ? String(S.speed) : ""), i && x.push(S.port != null ? String(S.port) : ""), c && x.push(S.stbd != null ? String(S.stbd) : ""), a && x.push(S.arrRad != null ? String(S.arrRad) : ""), m.push(x.map((M) => v.csvEscapeField(M)).join(","));
|
|
1030
1075
|
}
|
|
1031
|
-
return
|
|
1076
|
+
return m.join(`
|
|
1032
1077
|
`);
|
|
1033
1078
|
}
|
|
1079
|
+
/**
|
|
1080
|
+
* 路径导出为 XLSX (Office Open XML 格式,无需第三方依赖)
|
|
1081
|
+
* 兼容 Excel 2007+、LibreOffice、Google Sheets、WPS、macOS Numbers 等所有现代表格软件
|
|
1082
|
+
* const buf = LaneHelper.waypoints2XLSX('route-name', waypoints, { precision: 6 })
|
|
1083
|
+
* 浏览器下载
|
|
1084
|
+
* const blob = new Blob([buf], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })
|
|
1085
|
+
* @param name 工作表名称
|
|
1086
|
+
* @param waypoints 途径点
|
|
1087
|
+
* @param options.precision 经纬度小数位数,默认6
|
|
1088
|
+
* @returns Uint8Array 二进制数据,可直接用于 new Blob([result], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'})
|
|
1089
|
+
*/
|
|
1090
|
+
static waypoints2XLSX(t, e, n) {
|
|
1091
|
+
const s = (n == null ? void 0 : n.precision) ?? 6, o = t || "Route", r = e.some((P) => P.name), i = e.some((P) => P.description), c = e.some((P) => P.port != null), a = e.some((P) => P.stbd != null), l = e.some((P) => P.arrRad != null), u = e.some((P) => P.speed != null), f = e.some((P, I) => I > 0 && P.gcToPrevious != null), h = e.some((P) => P.bearing != null), g = e.some((P) => P.distanceFromPrevious != null), m = ["WPT No.", "Latitude", "Longitude"];
|
|
1092
|
+
r && m.push("Name"), i && m.push("Description"), f && m.push("Leg"), h && m.push("Bearing[deg]"), g && m.push("Distance[NM]"), u && m.push("Speed[kn]"), c && m.push("PORT XTD[NM]"), a && m.push("STBD XTD[NM]"), l && m.push("Arr.Rad[NM]");
|
|
1093
|
+
const p = (P) => P == null ? "" : String(P).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
1094
|
+
let x = `<row r="1">${m.map((P, I) => `<c r="${z(I)}1" s="1" t="inlineStr"><is><t>${p(P)}</t></is></c>`).join("")}</row>`;
|
|
1095
|
+
for (let P = 0; P < e.length; P++) {
|
|
1096
|
+
const I = e[P], U = P + 2, B = [], Z = (W, j) => B.push(`<c r="${z(W)}${U}"><v>${j}</v></c>`), O = (W, j) => B.push(`<c r="${z(W)}${U}" t="inlineStr"><is><t>${p(j)}</t></is></c>`), k = (W, j) => {
|
|
1097
|
+
j != null ? Z(W, j) : O(W, "");
|
|
1098
|
+
};
|
|
1099
|
+
Z(0, P + 1), O(1, d.lat2pretty(I.lat, s).pretty), O(2, d.lng2pretty(I.lng, s).pretty);
|
|
1100
|
+
let D = 3;
|
|
1101
|
+
r && (O(D, I.name ?? ""), D++), i && (O(D, I.description ?? ""), D++), f && (O(D, P === 0 ? "" : I.gcToPrevious ? "GC" : "RL"), D++), h && (k(D, I.bearing), D++), g && (k(D, I.distanceFromPrevious), D++), u && (k(D, I.speed), D++), c && (k(D, I.port), D++), a && (k(D, I.stbd), D++), l && (k(D, I.arrRad), D++), x += `<row r="${U}">${B.join("")}</row>`;
|
|
1102
|
+
}
|
|
1103
|
+
const M = "0." + "0".repeat(s), y = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><sheetData>' + x + "</sheetData></worksheet>", N = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/><Default Extension="xml" ContentType="application/xml"/><Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/><Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/><Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"/></Types>', w = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/></Relationships>', q = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"><sheets><sheet name="' + p(o) + '" sheetId="1" r:id="rId1"/></sheets></workbook>', E = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"/><Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/></Relationships>', L = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><numFmts count="1"><numFmt numFmtId="164" formatCode="' + M + '"/></numFmts><fonts count="2"><font><sz val="11"/><name val="Arial"/></font><font><b/><sz val="11"/><name val="Arial"/></font></fonts><fills count="2"><fill><patternFill patternType="none"/></fill><fill><patternFill patternType="solid"><fgColor rgb="FFD9E1F2"/></patternFill></fill></fills><borders count="2"><border><left/><right/><top/><bottom/><diagonal/></border><border><bottom style="thin"><color auto="1"/></bottom></border></borders><cellStyleXfs count="1"><xf/></cellStyleXfs><cellXfs count="3"><xf/><xf fontId="1" fillId="1" borderId="1" applyFont="1" applyFill="1" applyBorder="1"/><xf numFmtId="164" fontId="0" applyNumberFormat="1"/></cellXfs></styleSheet>', F = new TextEncoder();
|
|
1104
|
+
return _([
|
|
1105
|
+
{ name: "[Content_Types].xml", data: F.encode(N) },
|
|
1106
|
+
{ name: "_rels/.rels", data: F.encode(w) },
|
|
1107
|
+
{ name: "xl/workbook.xml", data: F.encode(q) },
|
|
1108
|
+
{ name: "xl/_rels/workbook.xml.rels", data: F.encode(E) },
|
|
1109
|
+
{ name: "xl/worksheets/sheet1.xml", data: F.encode(y) },
|
|
1110
|
+
{ name: "xl/styles.xml", data: F.encode(L) }
|
|
1111
|
+
]);
|
|
1112
|
+
}
|
|
1034
1113
|
/**
|
|
1035
1114
|
* RFC 4180 CSV字段转义:含逗号、双引号、换行时用双引号包裹,内部双引号翻倍
|
|
1036
1115
|
*/
|
|
@@ -1047,8 +1126,8 @@ class y {
|
|
|
1047
1126
|
* @param isLat true为纬度,false为经度
|
|
1048
1127
|
*/
|
|
1049
1128
|
static decimalToNmeaDm(t, e) {
|
|
1050
|
-
const n = Math.abs(t),
|
|
1051
|
-
return { dm: r, dir:
|
|
1129
|
+
const n = Math.abs(t), s = Math.floor(n), o = (n - s) * 60, r = e ? `${s.toString().padStart(2, "0")}${o.toFixed(2).padStart(5, "0")}` : `${s.toString().padStart(3, "0")}${o.toFixed(2).padStart(5, "0")}`, i = e ? t >= 0 ? "N" : "S" : t >= 0 ? "E" : "W";
|
|
1130
|
+
return { dm: r, dir: i };
|
|
1052
1131
|
}
|
|
1053
1132
|
/**
|
|
1054
1133
|
* 计算NMEA 0183校验和 ($与*之间所有字符的异或,两字符十六进制大写)
|
|
@@ -1068,7 +1147,7 @@ class y {
|
|
|
1068
1147
|
static waypoints2NMEA(t) {
|
|
1069
1148
|
const e = [];
|
|
1070
1149
|
for (let n = 0; n < t.length; n++) {
|
|
1071
|
-
const
|
|
1150
|
+
const s = t[n], o = v.decimalToNmeaDm(s.lat, !0), r = v.decimalToNmeaDm(s.lng, !1), i = s.name ? String(s.name).slice(0, 6) : `WPT${(n + 1).toString().padStart(3, "0")}`, c = `GPWPL,${o.dm},${o.dir},${r.dm},${r.dir},${i}`, a = v.nmeaChecksum(c);
|
|
1072
1151
|
e.push(`$${c}*${a}`);
|
|
1073
1152
|
}
|
|
1074
1153
|
return e.join(`\r
|
|
@@ -1088,19 +1167,19 @@ class y {
|
|
|
1088
1167
|
*/
|
|
1089
1168
|
static coordinatesSummary(t, e = 3) {
|
|
1090
1169
|
if (t.length > 1) {
|
|
1091
|
-
const n = t[0],
|
|
1092
|
-
(h,
|
|
1170
|
+
const n = t[0], s = t[t.length - 1], o = (n == null ? void 0 : n.positionTime) < (s == null ? void 0 : s.positionTime) ? b.unix(n == null ? void 0 : n.positionTime) : b.unix(s == null ? void 0 : s.positionTime), r = (n == null ? void 0 : n.positionTime) > (s == null ? void 0 : s.positionTime) ? b.unix(n == null ? void 0 : n.positionTime) : b.unix(s == null ? void 0 : s.positionTime), i = Math.round(r.diff(o, "hours", !0) * 100) / 100, c = this.generateRouteAccordingToWaypoints(t, !0, !0), a = this.calculateRouteDistance(c), u = K.inspectStoppages(t, e).reduce(
|
|
1171
|
+
(h, g) => (h.duration += g.duration, h.distance += g.distance, h),
|
|
1093
1172
|
{ hours: 0, distance: 0, spd: 0, duration: 0 }
|
|
1094
1173
|
);
|
|
1095
|
-
|
|
1096
|
-
const
|
|
1174
|
+
u.hours = Math.round(u.duration / 3600 * 100) / 100, u.distance = Math.round(u.distance * 100) / 100, u.spd = u.hours ? Math.round(u.distance / u.hours * 100) / 100 : 0;
|
|
1175
|
+
const f = i ? Math.round((a - u.distance) / (i - u.hours) * 100) / 100 : 0;
|
|
1097
1176
|
return {
|
|
1098
1177
|
begin: o.utc().format(),
|
|
1099
1178
|
end: r.utc().format(),
|
|
1100
|
-
distance: Math.round((a -
|
|
1101
|
-
hours: Math.round((
|
|
1102
|
-
avgSpeed:
|
|
1103
|
-
stoppage:
|
|
1179
|
+
distance: Math.round((a - u.distance) * 100) / 100,
|
|
1180
|
+
hours: Math.round((i - u.hours) * 100) / 100,
|
|
1181
|
+
avgSpeed: f,
|
|
1182
|
+
stoppage: u
|
|
1104
1183
|
};
|
|
1105
1184
|
}
|
|
1106
1185
|
return {
|
|
@@ -1121,33 +1200,33 @@ class y {
|
|
|
1121
1200
|
* }
|
|
1122
1201
|
*/
|
|
1123
1202
|
static pickUTCSampleFromSpeed(t, e) {
|
|
1124
|
-
var
|
|
1125
|
-
if (!((
|
|
1203
|
+
var l, u, f;
|
|
1204
|
+
if (!((u = (l = e == null ? void 0 : e.sample) == null ? void 0 : l.hours) != null && u.length))
|
|
1126
1205
|
return { routes: [], hour: void 0 };
|
|
1127
|
-
const n = e.sample.hours.at(0),
|
|
1128
|
-
let
|
|
1129
|
-
if (!
|
|
1130
|
-
const h = e.sample.all.filter((N) => b.utc(N.eta).isBefore(r)).at(-1),
|
|
1131
|
-
|
|
1132
|
-
const { cFactor:
|
|
1133
|
-
|
|
1134
|
-
...
|
|
1135
|
-
cFactor:
|
|
1136
|
-
cog:
|
|
1206
|
+
const n = e.sample.hours.at(0), s = b.utc(t), o = b.utc(e.eta), r = s.isAfter(o) ? o : s;
|
|
1207
|
+
let i = e.sample.all.find((h) => h.eta === r.format());
|
|
1208
|
+
if (!i) {
|
|
1209
|
+
const h = e.sample.all.filter((N) => b.utc(N.eta).isBefore(r)).at(-1), g = this.calculateSubRoute(h, e.route);
|
|
1210
|
+
i = (f = this.calculateNextCoordinateAlongRoute(h, h.speed * r.diff(b(h.etd), "hours", !0), g)) == null ? void 0 : f.coordinate;
|
|
1211
|
+
const { cFactor: m, cog: p, wxFactor: S, meteo: x } = h, M = Math.round(i.distanceFromPrevious * 1e4) / 1e4, y = Math.round((M + h.distanceFromStart) * 1e4) / 1e4;
|
|
1212
|
+
i = {
|
|
1213
|
+
...i,
|
|
1214
|
+
cFactor: m,
|
|
1215
|
+
cog: p,
|
|
1137
1216
|
speed: h.speed,
|
|
1138
|
-
wxFactor:
|
|
1139
|
-
distanceFromStart:
|
|
1217
|
+
wxFactor: S,
|
|
1218
|
+
distanceFromStart: y,
|
|
1140
1219
|
distanceFromPrevious: M,
|
|
1141
|
-
meteo:
|
|
1220
|
+
meteo: x,
|
|
1142
1221
|
eta: r.format(),
|
|
1143
1222
|
etd: r.format()
|
|
1144
1223
|
};
|
|
1145
1224
|
}
|
|
1146
|
-
|
|
1147
|
-
const c = this.calculateRangeWaypoints(n,
|
|
1225
|
+
i.distanceToGo = Math.round((e.distance - i.distanceFromStart) * 100) / 100, i.timeToGo = Math.round(o.diff(i.etd, "hours", !0) * 100) / 100;
|
|
1226
|
+
const c = this.calculateRangeWaypoints(n, i, e.route);
|
|
1148
1227
|
return {
|
|
1149
1228
|
routes: this.generateRouteAccordingToWaypoints(c),
|
|
1150
|
-
hour:
|
|
1229
|
+
hour: i
|
|
1151
1230
|
};
|
|
1152
1231
|
}
|
|
1153
1232
|
/**
|
|
@@ -1162,13 +1241,13 @@ class y {
|
|
|
1162
1241
|
*/
|
|
1163
1242
|
static pickUTCSampleFromRoute(t, e, n) {
|
|
1164
1243
|
var h;
|
|
1165
|
-
const
|
|
1244
|
+
const s = this.calculateSubRoute(e, n), o = this.calculateRouteDistance(s), r = o / e.speed, i = b.utc(t), c = b(e.etd), a = (h = this.calculateNextCoordinateAlongRoute(e, e.speed * i.diff(b(e.etd), "hours", !0), s)) == null ? void 0 : h.coordinate;
|
|
1166
1245
|
a.speed = e.speed;
|
|
1167
|
-
const
|
|
1168
|
-
a.eta = Math.abs(
|
|
1169
|
-
const
|
|
1246
|
+
const l = c.clone().add(a.hourFromPrevious, "hour");
|
|
1247
|
+
a.eta = Math.abs(l.diff(i, "second")) < 2 ? i.format() : l.format(), a.etd = a.eta, a.distanceFromStart = Math.round(a.distanceFromPrevious * 100) / 100, a.distanceToGo = Math.round((o - a.distanceFromStart) * 100) / 100, a.timeToGo = Math.round(c.clone().add(r, "hour").diff(b(a.etd), "hour") * 100) / 100;
|
|
1248
|
+
const u = this.calculateRangeWaypoints(e, a, n);
|
|
1170
1249
|
return {
|
|
1171
|
-
routes: this.generateRouteAccordingToWaypoints(
|
|
1250
|
+
routes: this.generateRouteAccordingToWaypoints(u),
|
|
1172
1251
|
hour: a
|
|
1173
1252
|
};
|
|
1174
1253
|
}
|
|
@@ -1178,123 +1257,123 @@ class y {
|
|
|
1178
1257
|
* @param degree 要素角度,如 swell.degree
|
|
1179
1258
|
*/
|
|
1180
1259
|
static includedAngle(t, e) {
|
|
1181
|
-
|
|
1260
|
+
X == null || X.debug("calculate bearing via: %j", { bearing: t, degree: e });
|
|
1182
1261
|
let n = Math.abs(t % 360 - (e % 360 || 0));
|
|
1183
1262
|
return n = n > 180 ? 360 - n : n, n;
|
|
1184
1263
|
}
|
|
1185
1264
|
}
|
|
1186
|
-
let
|
|
1265
|
+
let $;
|
|
1187
1266
|
try {
|
|
1188
|
-
|
|
1267
|
+
$ = G.getLogger("vessel");
|
|
1189
1268
|
} catch {
|
|
1190
1269
|
} finally {
|
|
1191
1270
|
}
|
|
1192
|
-
class
|
|
1271
|
+
class it {
|
|
1193
1272
|
/**
|
|
1194
1273
|
* 将原始数据转换为geojson
|
|
1195
1274
|
* @param raw
|
|
1196
1275
|
*/
|
|
1197
1276
|
static convert2Geojson(t) {
|
|
1198
|
-
var n,
|
|
1199
|
-
const e =
|
|
1277
|
+
var n, s, o;
|
|
1278
|
+
const e = T.featureCollection([]);
|
|
1200
1279
|
for (const r of t) {
|
|
1201
|
-
const
|
|
1280
|
+
const i = (n = r.history) == null ? void 0 : n[0];
|
|
1202
1281
|
if (r.forecasts) {
|
|
1203
|
-
|
|
1282
|
+
i && i.wind && (i.wind.kts = i.kts);
|
|
1204
1283
|
for (const c of r.forecasts) {
|
|
1205
1284
|
let a;
|
|
1206
|
-
const
|
|
1207
|
-
for (const
|
|
1208
|
-
const
|
|
1209
|
-
a = a ||
|
|
1210
|
-
const
|
|
1285
|
+
const l = [], u = [], f = b(c.date).utc(), h = `${r.name}-${c.model}`;
|
|
1286
|
+
for (const m in c == null ? void 0 : c.hours) {
|
|
1287
|
+
const p = c.hours[m];
|
|
1288
|
+
a = a || p;
|
|
1289
|
+
const S = f.clone().add(Number(m), "hour"), x = T.point([p.lng, p.lat], {
|
|
1211
1290
|
model: c.model,
|
|
1212
1291
|
name: r.name,
|
|
1213
1292
|
nameCn: r.nameCn,
|
|
1214
|
-
date:
|
|
1215
|
-
hour: Number(
|
|
1216
|
-
format:
|
|
1217
|
-
pressure:
|
|
1218
|
-
gusts:
|
|
1219
|
-
wind:
|
|
1220
|
-
movement:
|
|
1293
|
+
date: S.format(),
|
|
1294
|
+
hour: Number(m),
|
|
1295
|
+
format: S.format("MMM-DD/HHmm[Z]"),
|
|
1296
|
+
pressure: p.pressure > 1e4 ? d.roundPrecision(p.pressure / 100, 0) : d.roundPrecision(p.pressure, 0),
|
|
1297
|
+
gusts: p.gusts,
|
|
1298
|
+
wind: p.wind || {},
|
|
1299
|
+
movement: p.movement,
|
|
1221
1300
|
category: h,
|
|
1222
1301
|
type: "forecast"
|
|
1223
1302
|
});
|
|
1224
|
-
|
|
1303
|
+
u.push(x), l.push(x.geometry.coordinates);
|
|
1225
1304
|
}
|
|
1226
|
-
const
|
|
1305
|
+
const g = {
|
|
1227
1306
|
kts: void 0,
|
|
1228
1307
|
deg: void 0
|
|
1229
1308
|
};
|
|
1230
|
-
if (
|
|
1231
|
-
const
|
|
1309
|
+
if (i) {
|
|
1310
|
+
const m = b(i.updated).utc();
|
|
1232
1311
|
if (a) {
|
|
1233
|
-
const
|
|
1234
|
-
|
|
1312
|
+
const S = v.calculateDistance(i, a), x = b(a.utc || a.updated).diff(m, "h", !0);
|
|
1313
|
+
g.kts = Math.round(S / x * 100) / 100, g.deg = v.calculateBearing(i, a, !0, 0);
|
|
1235
1314
|
}
|
|
1236
|
-
const
|
|
1315
|
+
const p = T.point([i.lng, i.lat], {
|
|
1237
1316
|
model: c.model,
|
|
1238
1317
|
name: r.name,
|
|
1239
1318
|
nameCn: r.nameCn,
|
|
1240
|
-
date:
|
|
1319
|
+
date: m.format(),
|
|
1241
1320
|
hour: 0,
|
|
1242
|
-
format:
|
|
1243
|
-
pressure:
|
|
1244
|
-
wind:
|
|
1245
|
-
movement:
|
|
1321
|
+
format: m.format("MMM-DD/HHmm[Z]"),
|
|
1322
|
+
pressure: i.pressure > 1e4 ? d.roundPrecision((i == null ? void 0 : i.pressure) / 100, 0) : d.roundPrecision(i.pressure, 0),
|
|
1323
|
+
wind: i.wind,
|
|
1324
|
+
movement: g,
|
|
1246
1325
|
category: h,
|
|
1247
1326
|
type: "forecast",
|
|
1248
1327
|
important: !0
|
|
1249
1328
|
// 第一个预报点为重要点
|
|
1250
1329
|
});
|
|
1251
|
-
|
|
1330
|
+
u.unshift(p), l.unshift(p.geometry.coordinates);
|
|
1252
1331
|
}
|
|
1253
|
-
if (e.features.push(...
|
|
1254
|
-
const
|
|
1255
|
-
date: (
|
|
1332
|
+
if (e.features.push(...u), (l == null ? void 0 : l.length) > 1) {
|
|
1333
|
+
const m = T.lineString(d.convertToMonotonicLng2(l), {
|
|
1334
|
+
date: (i == null ? void 0 : i.updated) || (f == null ? void 0 : f.format()),
|
|
1256
1335
|
id: r.id || r.name,
|
|
1257
1336
|
model: c.model,
|
|
1258
1337
|
name: r.name,
|
|
1259
1338
|
category: h,
|
|
1260
1339
|
type: "forecast",
|
|
1261
|
-
movement:
|
|
1340
|
+
movement: g
|
|
1262
1341
|
});
|
|
1263
|
-
e.features.push(
|
|
1342
|
+
e.features.push(m);
|
|
1264
1343
|
}
|
|
1265
1344
|
}
|
|
1266
1345
|
}
|
|
1267
|
-
if (e.features.sort((c, a) => c.properties.type === "forecast" && a.properties.type === "forecast" && c.geometry.type === "Point" && a.geometry.type === "Point" ? b(c.properties.date).valueOf() - b(a.properties.date).valueOf() : 0), (
|
|
1268
|
-
const c = [], a = b(
|
|
1269
|
-
for (const
|
|
1270
|
-
const h = b(
|
|
1271
|
-
|
|
1272
|
-
const
|
|
1346
|
+
if (e.features.sort((c, a) => c.properties.type === "forecast" && a.properties.type === "forecast" && c.geometry.type === "Point" && a.geometry.type === "Point" ? b(c.properties.date).valueOf() - b(a.properties.date).valueOf() : 0), (s = r.history) != null && s.length) {
|
|
1347
|
+
const c = [], a = b(i == null ? void 0 : i.updated).utc(), l = b((o = r.history) == null ? void 0 : o.at(-1).updated).utc(), u = a.diff(l, "h") % 24 > 2 ? 24 : 12;
|
|
1348
|
+
for (const f of r.history) {
|
|
1349
|
+
const h = b(f.updated).utc(), g = h.isSameOrBefore(a) || h.isSame(l);
|
|
1350
|
+
g && a.add(-u, "h");
|
|
1351
|
+
const m = T.point([f.lng, f.lat], {
|
|
1273
1352
|
name: r.name,
|
|
1274
1353
|
nameCn: r.nameCn,
|
|
1275
1354
|
date: h.format(),
|
|
1276
1355
|
format: h.format("MMM-DD/HHmm[Z]"),
|
|
1277
|
-
pressure:
|
|
1278
|
-
kts:
|
|
1279
|
-
level:
|
|
1356
|
+
pressure: f.pressure > 1e4 ? d.roundPrecision(f.pressure / 100, 0) : d.roundPrecision(f.pressure, 0),
|
|
1357
|
+
kts: f.kts,
|
|
1358
|
+
level: f.type,
|
|
1280
1359
|
type: "history",
|
|
1281
1360
|
category: `${r.name}-history`,
|
|
1282
|
-
wind:
|
|
1283
|
-
movement:
|
|
1284
|
-
important:
|
|
1361
|
+
wind: f.wind,
|
|
1362
|
+
movement: f.movement,
|
|
1363
|
+
important: g
|
|
1285
1364
|
});
|
|
1286
|
-
e.features.push(
|
|
1365
|
+
e.features.push(m), c.push(m.geometry.coordinates);
|
|
1287
1366
|
}
|
|
1288
1367
|
if (c.length === 1 && c.push(c[0]), c.length > 1) {
|
|
1289
|
-
const
|
|
1368
|
+
const f = T.lineString(d.convertToMonotonicLng2(c), {
|
|
1290
1369
|
name: r.name,
|
|
1291
1370
|
type: "history",
|
|
1292
|
-
updated:
|
|
1293
|
-
pressure: (
|
|
1294
|
-
kts:
|
|
1295
|
-
level:
|
|
1371
|
+
updated: i == null ? void 0 : i.updated,
|
|
1372
|
+
pressure: (i == null ? void 0 : i.pressure) > 1e4 ? d.roundPrecision((i == null ? void 0 : i.pressure) / 100, 0) : d.roundPrecision(i == null ? void 0 : i.pressure, 0),
|
|
1373
|
+
kts: i == null ? void 0 : i.kts,
|
|
1374
|
+
level: i == null ? void 0 : i.type
|
|
1296
1375
|
});
|
|
1297
|
-
e.features.push(
|
|
1376
|
+
e.features.push(f);
|
|
1298
1377
|
}
|
|
1299
1378
|
}
|
|
1300
1379
|
}
|
|
@@ -1306,38 +1385,38 @@ class X {
|
|
|
1306
1385
|
* @param step
|
|
1307
1386
|
*/
|
|
1308
1387
|
static interpolate(t, e = 3) {
|
|
1309
|
-
var o, r,
|
|
1310
|
-
const n = (o = t == null ? void 0 : t.data) == null ? void 0 : o.features.filter((a) => a.geometry.type === "LineString" && a.properties.type === "forecast"),
|
|
1388
|
+
var o, r, i, c;
|
|
1389
|
+
const n = (o = t == null ? void 0 : t.data) == null ? void 0 : o.features.filter((a) => a.geometry.type === "LineString" && a.properties.type === "forecast"), s = [];
|
|
1311
1390
|
for (const a of n) {
|
|
1312
|
-
const
|
|
1313
|
-
let
|
|
1314
|
-
const
|
|
1315
|
-
(M) => M.geometry.type === "Point" && M.properties.type === "forecast" && M.properties.category === `${
|
|
1391
|
+
const l = a.properties.name, u = a.properties.model, f = a.properties.showCircle, h = a.properties.disabled, g = b(a.properties.date).utc();
|
|
1392
|
+
let m = e * 60;
|
|
1393
|
+
const p = (r = t == null ? void 0 : t.data) == null ? void 0 : r.features.filter(
|
|
1394
|
+
(M) => M.geometry.type === "Point" && M.properties.type === "forecast" && M.properties.category === `${l}-${u}`
|
|
1316
1395
|
);
|
|
1317
|
-
let
|
|
1318
|
-
for (;
|
|
1319
|
-
if (
|
|
1320
|
-
const M =
|
|
1321
|
-
name:
|
|
1322
|
-
model:
|
|
1396
|
+
let S, x = g.clone().add(m, "minute").set({ minute: 0, second: 0, millisecond: 0 });
|
|
1397
|
+
for (; S = this.pickIndex(p, x), S <= p.length - 1; ) {
|
|
1398
|
+
if (S > 0) {
|
|
1399
|
+
const M = p[S], y = S === 0 ? void 0 : p[S - 1], N = (m / 60 - ((i = y == null ? void 0 : y.properties) == null ? void 0 : i.hour)) / (M.properties.hour - ((c = y == null ? void 0 : y.properties) == null ? void 0 : c.hour)), w = this.computeNumber(y == null ? void 0 : y.geometry.coordinates[0], M.geometry.coordinates[0], N), q = this.computeNumber(y == null ? void 0 : y.geometry.coordinates[1], M.geometry.coordinates[1], N), E = T.point([w, q], {
|
|
1400
|
+
name: l,
|
|
1401
|
+
model: u,
|
|
1323
1402
|
category: M == null ? void 0 : M.properties.category,
|
|
1324
|
-
date:
|
|
1325
|
-
format:
|
|
1326
|
-
gusts: this.computeNumber(
|
|
1327
|
-
hour: this.computeNumber(
|
|
1328
|
-
movement: this.computeNumber(
|
|
1329
|
-
pressure: this.computeNumber(
|
|
1330
|
-
wind: this.computeNumber(
|
|
1403
|
+
date: x.format(),
|
|
1404
|
+
format: x.format("MMM-DD/HHmm[Z]"),
|
|
1405
|
+
gusts: this.computeNumber(y == null ? void 0 : y.properties.gusts, M.properties.gusts, N),
|
|
1406
|
+
hour: this.computeNumber(y == null ? void 0 : y.properties.hour, M.properties.hour, N),
|
|
1407
|
+
movement: this.computeNumber(y == null ? void 0 : y.properties.movement, M.properties.movement, N),
|
|
1408
|
+
pressure: this.computeNumber(y == null ? void 0 : y.properties.pressure, M.properties.pressure, N),
|
|
1409
|
+
wind: this.computeNumber(y == null ? void 0 : y.properties.wind, M.properties.wind, N),
|
|
1331
1410
|
type: "forecast",
|
|
1332
1411
|
disabled: h,
|
|
1333
|
-
showCircle:
|
|
1412
|
+
showCircle: f
|
|
1334
1413
|
});
|
|
1335
|
-
|
|
1414
|
+
s.push(E);
|
|
1336
1415
|
}
|
|
1337
|
-
|
|
1416
|
+
m += e * 60, x = g.clone().add(m, "minute").set({ minute: 0, second: 0, millisecond: 0 });
|
|
1338
1417
|
}
|
|
1339
1418
|
}
|
|
1340
|
-
return
|
|
1419
|
+
return s;
|
|
1341
1420
|
}
|
|
1342
1421
|
/**
|
|
1343
1422
|
* 计算穿航核验点
|
|
@@ -1346,8 +1425,8 @@ class X {
|
|
|
1346
1425
|
* @param options
|
|
1347
1426
|
*/
|
|
1348
1427
|
static accelPassageAt(t, e) {
|
|
1349
|
-
const { t1: n, t2:
|
|
1350
|
-
return { t1: n, t2:
|
|
1428
|
+
const { t1: n, t2: s, hr: o, hours: r } = this.tropicalCenterTwin(t, 24, e);
|
|
1429
|
+
return { t1: n, t2: s, hr: o, hours: r };
|
|
1351
1430
|
}
|
|
1352
1431
|
/**
|
|
1353
1432
|
* 计算最佳绕航点
|
|
@@ -1360,32 +1439,32 @@ class X {
|
|
|
1360
1439
|
* @param speed 前进速度
|
|
1361
1440
|
* @param options
|
|
1362
1441
|
*/
|
|
1363
|
-
static diversionPassageAt(t, e, n,
|
|
1364
|
-
const { t1: o, t2: r, hr:
|
|
1442
|
+
static diversionPassageAt(t, e, n, s = {}) {
|
|
1443
|
+
const { t1: o, t2: r, hr: i, hours: c } = this.tropicalCenterTwin(e, 24, s);
|
|
1365
1444
|
if (o && r) {
|
|
1366
|
-
if (!
|
|
1367
|
-
const
|
|
1368
|
-
if (
|
|
1369
|
-
return
|
|
1445
|
+
if (!s.debug) {
|
|
1446
|
+
const g = v.calculateDistance(t, o), m = v.calculateDistance(t, r);
|
|
1447
|
+
if (g > 2 * n && m > 2 * n)
|
|
1448
|
+
return $ == null || $.info("[%s] the distance between from and t1(%d) and t2(%d) is enough, no need diversion: %j", s.requestId, g, m, {
|
|
1370
1449
|
from: t,
|
|
1371
1450
|
t1: o,
|
|
1372
1451
|
t2: r,
|
|
1373
|
-
hr:
|
|
1452
|
+
hr: i
|
|
1374
1453
|
}), {};
|
|
1375
1454
|
}
|
|
1376
|
-
const a =
|
|
1377
|
-
let
|
|
1378
|
-
|
|
1379
|
-
const h =
|
|
1380
|
-
return
|
|
1455
|
+
const a = v.calculateBearing(t, o), l = v.calculateBearing(o, r), u = Math.abs(a - l);
|
|
1456
|
+
let f = 0;
|
|
1457
|
+
u < 180 ? f = u + 90 : u >= 180 && (f = u - 90);
|
|
1458
|
+
const h = v.calculateCoordinate(o, f, n);
|
|
1459
|
+
return $ == null || $.info("[%s] the right tangent position: %j", s.requestId, {
|
|
1381
1460
|
from: t,
|
|
1382
1461
|
t1: o,
|
|
1383
1462
|
t2: r,
|
|
1384
1463
|
radius: n,
|
|
1385
1464
|
bearing1: a,
|
|
1386
|
-
bearing2:
|
|
1465
|
+
bearing2: l,
|
|
1387
1466
|
right: h
|
|
1388
|
-
}), { at: h, t1: o, t2: r, hr: Number(
|
|
1467
|
+
}), { at: h, t1: o, t2: r, hr: Number(i), hours: c };
|
|
1389
1468
|
}
|
|
1390
1469
|
return {};
|
|
1391
1470
|
}
|
|
@@ -1399,23 +1478,23 @@ class X {
|
|
|
1399
1478
|
* @param radius 与台风中心的距离
|
|
1400
1479
|
* @param options
|
|
1401
1480
|
*/
|
|
1402
|
-
static driftPassageAt(t, e, n,
|
|
1403
|
-
const { t1: o, t2: r, hr:
|
|
1481
|
+
static driftPassageAt(t, e, n, s = {}) {
|
|
1482
|
+
const { t1: o, t2: r, hr: i, hours: c } = this.tropicalCenterTwin(e, 24, s);
|
|
1404
1483
|
if (o && r) {
|
|
1405
|
-
if (!
|
|
1406
|
-
const h =
|
|
1407
|
-
if (h > 2 * n &&
|
|
1408
|
-
return
|
|
1484
|
+
if (!s.debug) {
|
|
1485
|
+
const h = v.calculateDistance(t, o), g = v.calculateDistance(t, r);
|
|
1486
|
+
if (h > 2 * n && g > 2 * n)
|
|
1487
|
+
return $ == null || $.info("[%s] the distance between from and t1(%d) and t2(%d) is enough, no need drifting: %j", s.requestId, h, g, {
|
|
1409
1488
|
from: t,
|
|
1410
1489
|
t1: o,
|
|
1411
1490
|
t2: r,
|
|
1412
|
-
hr:
|
|
1491
|
+
hr: i
|
|
1413
1492
|
}), {};
|
|
1414
1493
|
}
|
|
1415
|
-
const a =
|
|
1416
|
-
return { at:
|
|
1494
|
+
const a = v.calculateBearing(t, o), l = v.calculateBearing(o, r), u = v.calculateDistance(t, o);
|
|
1495
|
+
return { at: v.calculateCoordinate(o, a - l + 180, n < u ? n : u), t1: o, t2: r, hr: Number(i), hours: c };
|
|
1417
1496
|
} else
|
|
1418
|
-
return
|
|
1497
|
+
return $ == null || $.info("[%s] no need drift: %j", s.requestId, { from: t, t1: o, t2: r, hr: i }), {};
|
|
1419
1498
|
}
|
|
1420
1499
|
/**
|
|
1421
1500
|
* 获取台风中心点对
|
|
@@ -1426,26 +1505,26 @@ class X {
|
|
|
1426
1505
|
* @private
|
|
1427
1506
|
*/
|
|
1428
1507
|
static tropicalCenterTwin(t, e = 24, n = {}) {
|
|
1429
|
-
var
|
|
1430
|
-
let
|
|
1431
|
-
(
|
|
1432
|
-
|
|
1508
|
+
var l, u, f, h, g;
|
|
1509
|
+
let s = {};
|
|
1510
|
+
(l = t.forecasts) == null || l.forEach((m) => {
|
|
1511
|
+
s = { ...m.hours, ...s };
|
|
1433
1512
|
});
|
|
1434
|
-
const o = ((
|
|
1435
|
-
|
|
1436
|
-
let r = (h = Object.keys(
|
|
1437
|
-
r || (r = (
|
|
1438
|
-
const
|
|
1439
|
-
|
|
1440
|
-
const c = Object.keys(
|
|
1441
|
-
for (const
|
|
1442
|
-
a[
|
|
1443
|
-
return { t1: o, t2:
|
|
1513
|
+
const o = ((u = t == null ? void 0 : t.history) == null ? void 0 : u[0]) || (s == null ? void 0 : s[(f = Object.keys(s)) == null ? void 0 : f[0]]);
|
|
1514
|
+
$ == null || $.info("[%s] the first tropical center: %j", n.requestId, o);
|
|
1515
|
+
let r = (h = Object.keys(s || {}).filter((m) => Number(m) <= (e < 0 ? 24 : e))) == null ? void 0 : h.at(-1);
|
|
1516
|
+
r || (r = (g = Object.keys(s || {}).filter((m) => Number(m) <= (e < 0 ? 24 : 2 * e))) == null ? void 0 : g.at(-1));
|
|
1517
|
+
const i = s == null ? void 0 : s[r || -1];
|
|
1518
|
+
$ == null || $.info("[%s] the second tropical center: %j in %d hrs", n.requestId, i, r);
|
|
1519
|
+
const c = Object.keys(s || {}).filter((m) => Number(m) <= Number(r)), a = { 0: o };
|
|
1520
|
+
for (const m of c)
|
|
1521
|
+
a[m] = s[m];
|
|
1522
|
+
return { t1: o, t2: i, hr: Number(r), hours: a };
|
|
1444
1523
|
}
|
|
1445
1524
|
static pickIndex(t, e) {
|
|
1446
1525
|
let n = 0;
|
|
1447
|
-
for (const
|
|
1448
|
-
if (b(
|
|
1526
|
+
for (const s of t) {
|
|
1527
|
+
if (b(s.properties.date).isAfter(e))
|
|
1449
1528
|
return n === 0 ? -1 : n;
|
|
1450
1529
|
n++;
|
|
1451
1530
|
}
|
|
@@ -1455,10 +1534,10 @@ class X {
|
|
|
1455
1534
|
if (t)
|
|
1456
1535
|
if (e) {
|
|
1457
1536
|
if (isNaN(t) && isNaN(e) && typeof t != "string" && typeof e != "string") {
|
|
1458
|
-
const
|
|
1537
|
+
const s = {};
|
|
1459
1538
|
for (const o in t)
|
|
1460
|
-
|
|
1461
|
-
return
|
|
1539
|
+
s[o] = this.computeNumber(t[o], e[o], n);
|
|
1540
|
+
return s;
|
|
1462
1541
|
}
|
|
1463
1542
|
return Math.round((t + (e - t) * n) * 100) / 100;
|
|
1464
1543
|
} else
|
|
@@ -1468,32 +1547,32 @@ class X {
|
|
|
1468
1547
|
}
|
|
1469
1548
|
}
|
|
1470
1549
|
typeof globalThis < "u" && typeof globalThis.Buffer > "u" && (globalThis.Buffer = {
|
|
1471
|
-
isBuffer(
|
|
1472
|
-
return
|
|
1550
|
+
isBuffer(C) {
|
|
1551
|
+
return C instanceof Uint8Array;
|
|
1473
1552
|
},
|
|
1474
|
-
from(
|
|
1475
|
-
if (typeof
|
|
1476
|
-
return new TextEncoder().encode(
|
|
1477
|
-
if (
|
|
1478
|
-
return new Uint8Array(
|
|
1479
|
-
if (Array.isArray(
|
|
1480
|
-
return new Uint8Array(
|
|
1553
|
+
from(C, t) {
|
|
1554
|
+
if (typeof C == "string")
|
|
1555
|
+
return new TextEncoder().encode(C);
|
|
1556
|
+
if (C instanceof ArrayBuffer)
|
|
1557
|
+
return new Uint8Array(C);
|
|
1558
|
+
if (Array.isArray(C))
|
|
1559
|
+
return new Uint8Array(C);
|
|
1481
1560
|
throw new TypeError("Buffer.from: unsupported source type");
|
|
1482
1561
|
}
|
|
1483
1562
|
});
|
|
1484
|
-
let
|
|
1563
|
+
let R;
|
|
1485
1564
|
try {
|
|
1486
|
-
|
|
1565
|
+
R = G.getLogger("meteo");
|
|
1487
1566
|
} catch {
|
|
1488
1567
|
} finally {
|
|
1489
1568
|
}
|
|
1490
|
-
function
|
|
1569
|
+
function H() {
|
|
1491
1570
|
if (typeof DOMParser < "u")
|
|
1492
1571
|
return new DOMParser();
|
|
1493
|
-
const { JSDOM:
|
|
1572
|
+
const { JSDOM: C } = require("jsdom"), { DOMParser: t } = new C("").window;
|
|
1494
1573
|
return new t();
|
|
1495
1574
|
}
|
|
1496
|
-
class
|
|
1575
|
+
class A {
|
|
1497
1576
|
/**
|
|
1498
1577
|
* Buffer to ArrayBuffer
|
|
1499
1578
|
* 将 Node.js Buffer 转换为独立的 ArrayBuffer(byteOffset=0)。
|
|
@@ -1511,11 +1590,11 @@ class R {
|
|
|
1511
1590
|
* @param radius 半径
|
|
1512
1591
|
* @param options 步数、单位等选项
|
|
1513
1592
|
*/
|
|
1514
|
-
static drawCircle(t, e, n,
|
|
1515
|
-
const o = (
|
|
1516
|
-
|
|
1517
|
-
const
|
|
1518
|
-
return
|
|
1593
|
+
static drawCircle(t, e, n, s = {}) {
|
|
1594
|
+
const o = (s == null ? void 0 : s.steps) ?? 64, r = (s == null ? void 0 : s.units) ?? "nauticalmiles", i = (s == null ? void 0 : s.properties) ?? {}, c = T.point([t, e]), a = T.destination(c, n, 90, { units: r }), l = b.utc();
|
|
1595
|
+
i.id = (s == null ? void 0 : s.id) || l.valueOf().toString();
|
|
1596
|
+
const u = "circle";
|
|
1597
|
+
return i.name = (s == null ? void 0 : s.name) || `${u}_${l.format()}`, i.radius = n, i.center = [t, e], i.end = a.geometry.coordinates.map((f) => d.roundPrecision(f, 9)), i.units = r, i.steps = o, i.shape = "circle", R.info("[%s] draw circle with %j", s == null ? void 0 : s.requestId, i), T.circle(c, n, { steps: o, units: r, properties: i });
|
|
1519
1598
|
}
|
|
1520
1599
|
/**
|
|
1521
1600
|
* 基于turf画矩形,返回GeoJSON Feature<Polygon>
|
|
@@ -1524,12 +1603,12 @@ class R {
|
|
|
1524
1603
|
* @param options 选项
|
|
1525
1604
|
*/
|
|
1526
1605
|
static drawRect(t, e, n = {}) {
|
|
1527
|
-
const
|
|
1528
|
-
|
|
1606
|
+
const s = (n == null ? void 0 : n.properties) ?? {}, o = b.utc();
|
|
1607
|
+
s.id = (n == null ? void 0 : n.id) || o.valueOf().toString();
|
|
1529
1608
|
const r = "rect";
|
|
1530
|
-
|
|
1531
|
-
const [
|
|
1532
|
-
return
|
|
1609
|
+
s.name = (n == null ? void 0 : n.name) || `${r}_${o.format()}`, s.start = t.map((l) => d.roundPrecision(l, 9)), s.end = e.map((l) => d.roundPrecision(l, 9)), s.shape = "rect", R.info("[%s] draw rect with %j", n == null ? void 0 : n.requestId, s);
|
|
1610
|
+
const [i, c] = d.convertToMonotonicLng2([t, e]), a = [Math.min(i[0], c[0]), Math.min(i[1], c[1]), Math.max(i[0], c[0]), Math.max(i[1], c[1])];
|
|
1611
|
+
return T.bboxPolygon(a, { properties: s });
|
|
1533
1612
|
}
|
|
1534
1613
|
/**
|
|
1535
1614
|
* 基于turf画线,返回GeoJSON Feature<LineString>
|
|
@@ -1539,12 +1618,12 @@ class R {
|
|
|
1539
1618
|
* @returns
|
|
1540
1619
|
*/
|
|
1541
1620
|
static drawLine(t, e = {}) {
|
|
1542
|
-
const n = (e == null ? void 0 : e.properties) ?? {},
|
|
1543
|
-
n.id = (e == null ? void 0 : e.id) ||
|
|
1621
|
+
const n = (e == null ? void 0 : e.properties) ?? {}, s = b.utc();
|
|
1622
|
+
n.id = (e == null ? void 0 : e.id) || s.valueOf().toString();
|
|
1544
1623
|
const o = "line";
|
|
1545
|
-
n.name = (e == null ? void 0 : e.name) || `${o}_${
|
|
1624
|
+
n.name = (e == null ? void 0 : e.name) || `${o}_${s.format()}`, n.shape = "line", R.info("[%s] draw line with %j", e == null ? void 0 : e.requestId, n);
|
|
1546
1625
|
const r = d.convertToMonotonicLng2(t);
|
|
1547
|
-
return
|
|
1626
|
+
return T.lineString(r, n);
|
|
1548
1627
|
}
|
|
1549
1628
|
/**
|
|
1550
1629
|
* 基于turf画多边形,返回GeoJSON Feature<Polygon>
|
|
@@ -1553,12 +1632,12 @@ class R {
|
|
|
1553
1632
|
* @returns
|
|
1554
1633
|
*/
|
|
1555
1634
|
static drawPolygon(t, e = {}) {
|
|
1556
|
-
const n = (e == null ? void 0 : e.properties) ?? {},
|
|
1557
|
-
n.id = (e == null ? void 0 : e.id) ||
|
|
1635
|
+
const n = (e == null ? void 0 : e.properties) ?? {}, s = b.utc();
|
|
1636
|
+
n.id = (e == null ? void 0 : e.id) || s.valueOf().toString();
|
|
1558
1637
|
const o = "polygon";
|
|
1559
|
-
n.name = (e == null ? void 0 : e.name) || `${o}_${
|
|
1638
|
+
n.name = (e == null ? void 0 : e.name) || `${o}_${s.format()}`, n.coordinates = t.map((i) => i.map((c) => d.roundPrecision(c, 9))), n.shape = "polygon", R.info("[%s] draw polygon with %j", e == null ? void 0 : e.requestId, n);
|
|
1560
1639
|
const r = d.convertToMonotonicLng2(t);
|
|
1561
|
-
return
|
|
1640
|
+
return T.polygon([r], n);
|
|
1562
1641
|
}
|
|
1563
1642
|
/**
|
|
1564
1643
|
* 基于turf画点,返回GeoJSON Feature<Point>
|
|
@@ -1568,10 +1647,10 @@ class R {
|
|
|
1568
1647
|
* @returns
|
|
1569
1648
|
*/
|
|
1570
1649
|
static drawPoint(t, e, n = {}) {
|
|
1571
|
-
const
|
|
1572
|
-
|
|
1650
|
+
const s = (n == null ? void 0 : n.properties) ?? {}, o = b.utc();
|
|
1651
|
+
s.id = (n == null ? void 0 : n.id) || o.valueOf().toString();
|
|
1573
1652
|
const r = "point";
|
|
1574
|
-
return
|
|
1653
|
+
return s.name = (n == null ? void 0 : n.name) || `${r}_${o.format()}`, s.shape = "point", R.info("[%s] draw point with %j", n == null ? void 0 : n.requestId, s), T.point([e, t], s);
|
|
1575
1654
|
}
|
|
1576
1655
|
/**
|
|
1577
1656
|
* 解析ORM GeoJSON Feature (圆), 返回FeatureCollection
|
|
@@ -1581,28 +1660,28 @@ class R {
|
|
|
1581
1660
|
* 如果feature是圆,则返回圆的中心、端点、半径线 和 边线四个Feature
|
|
1582
1661
|
*/
|
|
1583
1662
|
static parseCircle(t, e = {}) {
|
|
1584
|
-
var
|
|
1585
|
-
|
|
1663
|
+
var s, o;
|
|
1664
|
+
R.info("[%s] parse circle with %j", e == null ? void 0 : e.requestId, t.properties);
|
|
1586
1665
|
const n = t.properties || {};
|
|
1587
1666
|
if (n.shape == "circle") {
|
|
1588
1667
|
const r = b.utc();
|
|
1589
1668
|
n.id = (n == null ? void 0 : n.id) || r.valueOf().toString();
|
|
1590
|
-
const
|
|
1669
|
+
const i = n == null ? void 0 : n.id, c = ((s = n == null ? void 0 : n.center) == null ? void 0 : s.length) == 2 ? T.point(n.center) : T.centroid(t);
|
|
1591
1670
|
let a = "center";
|
|
1592
|
-
c.properties = { id: `${a}_${
|
|
1593
|
-
const
|
|
1594
|
-
let
|
|
1595
|
-
if (!
|
|
1596
|
-
const
|
|
1597
|
-
|
|
1671
|
+
c.properties = { id: `${a}_${i}`, parentId: i, name: a };
|
|
1672
|
+
const l = (n == null ? void 0 : n.units) || "nauticalmiles";
|
|
1673
|
+
let u = n == null ? void 0 : n.radius;
|
|
1674
|
+
if (!u) {
|
|
1675
|
+
const g = T.polygonToLine(t);
|
|
1676
|
+
u = T.pointToLineDistance(c, g, { units: l });
|
|
1598
1677
|
}
|
|
1599
1678
|
a = "end";
|
|
1600
|
-
const
|
|
1601
|
-
|
|
1602
|
-
const h =
|
|
1603
|
-
return a = "edge", h.properties = { id: `${a}_${
|
|
1679
|
+
const f = ((o = n == null ? void 0 : n.end) == null ? void 0 : o.length) == 2 ? T.point(n.end) : T.destination(c, u, 90, { units: l });
|
|
1680
|
+
f.properties = { id: `${a}_${i}`, parentId: i, name: a, radius: u, units: l };
|
|
1681
|
+
const h = T.lineString([c.geometry.coordinates, f.geometry.coordinates]);
|
|
1682
|
+
return a = "edge", h.properties = { id: `${a}_${i}`, parentId: i, name: a, radius: u, units: l }, T.featureCollection([c, f, h, t]);
|
|
1604
1683
|
} else
|
|
1605
|
-
return
|
|
1684
|
+
return R.warn("[%s] not a orm-std circle, just return the original feature", e == null ? void 0 : e.requestId), T.featureCollection([t]);
|
|
1606
1685
|
}
|
|
1607
1686
|
/**
|
|
1608
1687
|
* 解析ORM GeoJSON Feature (矩形), 返回FeatureCollection
|
|
@@ -1612,18 +1691,18 @@ class R {
|
|
|
1612
1691
|
* 如果feature是矩形,则返回矩形的四个顶点和矩形Feature
|
|
1613
1692
|
*/
|
|
1614
1693
|
static parseRect(t, e = {}) {
|
|
1615
|
-
|
|
1694
|
+
R.info("[%s] parse rect with %j", e == null ? void 0 : e.requestId, t.properties);
|
|
1616
1695
|
const n = t.properties || {};
|
|
1617
1696
|
if (n.shape == "rect") {
|
|
1618
|
-
const
|
|
1619
|
-
n.id = (n == null ? void 0 : n.id) ||
|
|
1620
|
-
const o = n == null ? void 0 : n.id, r = t.geometry.coordinates[0], c = ["sw", "nw", "ne", "se"].map((a,
|
|
1621
|
-
const
|
|
1622
|
-
return
|
|
1697
|
+
const s = b.utc();
|
|
1698
|
+
n.id = (n == null ? void 0 : n.id) || s.valueOf().toString();
|
|
1699
|
+
const o = n == null ? void 0 : n.id, r = t.geometry.coordinates[0], c = ["sw", "nw", "ne", "se"].map((a, l) => {
|
|
1700
|
+
const u = T.point(r[l]);
|
|
1701
|
+
return u.properties = { id: `${a}_${o}`, parentId: o, name: a }, u;
|
|
1623
1702
|
});
|
|
1624
|
-
return
|
|
1703
|
+
return T.featureCollection([...c, t]);
|
|
1625
1704
|
} else
|
|
1626
|
-
return
|
|
1705
|
+
return R.warn("[%s] not a orm-std rect, just return the original feature", e == null ? void 0 : e.requestId), T.featureCollection([t]);
|
|
1627
1706
|
}
|
|
1628
1707
|
/**
|
|
1629
1708
|
* 解析ORM GeoJSON Feature (线), 返回FeatureCollection
|
|
@@ -1633,18 +1712,18 @@ class R {
|
|
|
1633
1712
|
* 如果feature是线,则返回所有坐标点(首为start、尾为end、中间为point_N)以及线Feature
|
|
1634
1713
|
*/
|
|
1635
1714
|
static parseLine(t, e = {}) {
|
|
1636
|
-
|
|
1715
|
+
R.info("[%s] parse line with %j", e == null ? void 0 : e.requestId, t.properties);
|
|
1637
1716
|
const n = t.properties || {};
|
|
1638
1717
|
if (n.shape == "line") {
|
|
1639
|
-
const
|
|
1640
|
-
n.id = (n == null ? void 0 : n.id) ||
|
|
1641
|
-
const o = n == null ? void 0 : n.id,
|
|
1642
|
-
const
|
|
1643
|
-
return
|
|
1718
|
+
const s = b.utc();
|
|
1719
|
+
n.id = (n == null ? void 0 : n.id) || s.valueOf().toString();
|
|
1720
|
+
const o = n == null ? void 0 : n.id, i = t.geometry.coordinates.map((c, a) => {
|
|
1721
|
+
const l = `point_${a}`, u = T.point(c);
|
|
1722
|
+
return u.properties = { id: `${l}_${o}`, parentId: o, name: l, index: a }, u;
|
|
1644
1723
|
});
|
|
1645
|
-
return
|
|
1724
|
+
return T.featureCollection([...i, t]);
|
|
1646
1725
|
} else
|
|
1647
|
-
return
|
|
1726
|
+
return R.warn("[%s] not a orm-std line, just return the original feature", e == null ? void 0 : e.requestId), T.featureCollection([t]);
|
|
1648
1727
|
}
|
|
1649
1728
|
/**
|
|
1650
1729
|
* 解析ORM GeoJSON Feature (多边形), 返回FeatureCollection
|
|
@@ -1654,18 +1733,18 @@ class R {
|
|
|
1654
1733
|
* 如果feature是多边形,则返回多边形的顶点和多边形Feature
|
|
1655
1734
|
*/
|
|
1656
1735
|
static parsePolygon(t, e = {}) {
|
|
1657
|
-
|
|
1736
|
+
R.info("[%s] parse polygon with %j", e == null ? void 0 : e.requestId, t.properties);
|
|
1658
1737
|
const n = t.properties || {};
|
|
1659
1738
|
if (n.shape == "polygon") {
|
|
1660
|
-
const
|
|
1661
|
-
n.id = (n == null ? void 0 : n.id) ||
|
|
1662
|
-
const o = n == null ? void 0 : n.id,
|
|
1663
|
-
const
|
|
1664
|
-
return
|
|
1739
|
+
const s = b.utc();
|
|
1740
|
+
n.id = (n == null ? void 0 : n.id) || s.valueOf().toString();
|
|
1741
|
+
const o = n == null ? void 0 : n.id, i = t.geometry.coordinates[0].map((c, a) => {
|
|
1742
|
+
const l = T.point(c), u = `corner_${a}`;
|
|
1743
|
+
return l.properties = { id: `${u}_${o}`, parentId: o, name: u, index: a }, l;
|
|
1665
1744
|
});
|
|
1666
|
-
return
|
|
1745
|
+
return T.featureCollection([...i, t]);
|
|
1667
1746
|
} else
|
|
1668
|
-
return
|
|
1747
|
+
return R.warn("[%s] not a orm-std polygon, just return the original feature", e == null ? void 0 : e.requestId), T.featureCollection([t]);
|
|
1669
1748
|
}
|
|
1670
1749
|
// ---------------------------------------------------------------------------
|
|
1671
1750
|
// ZIP / KMZ 内部工具
|
|
@@ -1684,52 +1763,53 @@ class R {
|
|
|
1684
1763
|
}
|
|
1685
1764
|
/**
|
|
1686
1765
|
* 从 ZIP ArrayBuffer 中异步解析所有文件条目(浏览器 DecompressionStream)。
|
|
1766
|
+
* 使用 Central Directory 解析,避免 Data Descriptor 导致的大小不准问题。
|
|
1687
1767
|
*/
|
|
1688
1768
|
static async _parseZipEntries(t) {
|
|
1689
|
-
var
|
|
1690
|
-
const e = new Uint8Array(t), n = e.buffer.slice(e.byteOffset, e.byteOffset + e.byteLength),
|
|
1691
|
-
let
|
|
1692
|
-
for (
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
if ((u & 8) !== 0 || g === 0) {
|
|
1697
|
-
let p = v;
|
|
1698
|
-
for (; p + 4 <= n.byteLength; ) {
|
|
1699
|
-
const N = i.getUint32(p, !0);
|
|
1700
|
-
if (N === 67324752 || N === 33639248)
|
|
1701
|
-
break;
|
|
1702
|
-
p++;
|
|
1703
|
-
}
|
|
1704
|
-
g = p - v;
|
|
1769
|
+
var f;
|
|
1770
|
+
const e = new Uint8Array(t), n = e.buffer.slice(e.byteOffset, e.byteOffset + e.byteLength), s = new DataView(n), o = new Uint8Array(n), r = /* @__PURE__ */ new Map();
|
|
1771
|
+
let i = -1;
|
|
1772
|
+
for (let h = n.byteLength - 22; h >= 0; h--)
|
|
1773
|
+
if (s.getUint32(h, !0) === 101010256) {
|
|
1774
|
+
i = h;
|
|
1775
|
+
break;
|
|
1705
1776
|
}
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1777
|
+
if (i < 0)
|
|
1778
|
+
throw new Error("Invalid ZIP file: EOCD not found");
|
|
1779
|
+
s.getUint16(i + 8, !0);
|
|
1780
|
+
const c = s.getUint32(i + 12, !0), a = s.getUint32(i + 16, !0);
|
|
1781
|
+
let l = a;
|
|
1782
|
+
const u = a + c;
|
|
1783
|
+
for (; l < u; ) {
|
|
1784
|
+
if (s.getUint32(l, !0) !== 33639248)
|
|
1785
|
+
throw new Error(`Invalid ZIP file: Central Directory signature mismatch at offset ${l}`);
|
|
1786
|
+
const g = s.getUint16(l + 10, !0), m = s.getUint32(l + 20, !0), p = s.getUint16(l + 28, !0), S = s.getUint16(l + 30, !0), x = s.getUint16(l + 32, !0), M = s.getUint32(l + 42, !0), y = o.slice(l + 46, l + 46 + p), N = new TextDecoder().decode(y), w = s.getUint16(M + 26, !0), q = s.getUint16(M + 28, !0), E = M + 30 + w + q, L = o.slice(E, E + m);
|
|
1787
|
+
if (g === 0)
|
|
1788
|
+
r.set(N, L);
|
|
1789
|
+
else if (g === 8) {
|
|
1710
1790
|
if (typeof DecompressionStream < "u") {
|
|
1711
|
-
const
|
|
1712
|
-
|
|
1713
|
-
const
|
|
1714
|
-
let
|
|
1791
|
+
const F = new DecompressionStream("deflate-raw"), P = F.writable.getWriter(), I = F.readable.getReader();
|
|
1792
|
+
P.write(L), P.close();
|
|
1793
|
+
const U = [];
|
|
1794
|
+
let B = 0;
|
|
1715
1795
|
for (; ; ) {
|
|
1716
|
-
const { done:
|
|
1717
|
-
if (
|
|
1796
|
+
const { done: k, value: D } = await I.read();
|
|
1797
|
+
if (k)
|
|
1718
1798
|
break;
|
|
1719
|
-
|
|
1799
|
+
U.push(D), B += D.length;
|
|
1720
1800
|
}
|
|
1721
|
-
const
|
|
1722
|
-
let
|
|
1723
|
-
for (const
|
|
1724
|
-
|
|
1725
|
-
r.set(
|
|
1726
|
-
} else if (typeof process < "u" && ((
|
|
1801
|
+
const Z = new Uint8Array(B);
|
|
1802
|
+
let O = 0;
|
|
1803
|
+
for (const k of U)
|
|
1804
|
+
Z.set(k, O), O += k.length;
|
|
1805
|
+
r.set(N, Z);
|
|
1806
|
+
} else if (typeof process < "u" && ((f = process.versions) != null && f.node))
|
|
1727
1807
|
try {
|
|
1728
|
-
r.set(
|
|
1808
|
+
r.set(N, A._inflateRawSync(L));
|
|
1729
1809
|
} catch {
|
|
1730
1810
|
}
|
|
1731
1811
|
}
|
|
1732
|
-
|
|
1812
|
+
l += 46 + p + S + x;
|
|
1733
1813
|
}
|
|
1734
1814
|
return r;
|
|
1735
1815
|
}
|
|
@@ -1743,47 +1823,47 @@ class R {
|
|
|
1743
1823
|
* @returns
|
|
1744
1824
|
*/
|
|
1745
1825
|
static async convertKML2GeoJSON(t, e = {}) {
|
|
1746
|
-
var
|
|
1747
|
-
|
|
1748
|
-
const
|
|
1826
|
+
var i, c;
|
|
1827
|
+
R.info("[%s] convert kml to geojson", e == null ? void 0 : e.requestId);
|
|
1828
|
+
const s = H().parseFromString(t, "application/xml"), o = Array.from(s.querySelectorAll("Placemark")), r = [];
|
|
1749
1829
|
for (const a of o) {
|
|
1750
|
-
const
|
|
1751
|
-
for (const
|
|
1752
|
-
const N =
|
|
1753
|
-
N &&
|
|
1830
|
+
const l = {}, u = Array.from(a.querySelectorAll("ExtendedData > Data"));
|
|
1831
|
+
for (const y of u) {
|
|
1832
|
+
const N = y.getAttribute("name"), w = (c = (i = y.querySelector("value")) == null ? void 0 : i.textContent) == null ? void 0 : c.trim();
|
|
1833
|
+
N && w !== void 0 && w !== null && (l[N] = w);
|
|
1754
1834
|
}
|
|
1755
|
-
const
|
|
1756
|
-
const
|
|
1757
|
-
return [
|
|
1758
|
-
}),
|
|
1759
|
-
if (
|
|
1760
|
-
const
|
|
1761
|
-
if (
|
|
1762
|
-
const N =
|
|
1835
|
+
const f = b.utc(), h = Object.keys(l).find((y) => y.toLowerCase().indexOf("name") !== -1), g = h ? l[h] : void 0, m = `${f.valueOf().toString()}_${Math.random().toString(36).slice(2, 8)}`, p = (y) => y.trim().split(/[\s\n]+/).filter((N) => N.length > 0).map((N) => {
|
|
1836
|
+
const w = N.split(",").map(Number);
|
|
1837
|
+
return [w[0], w[1]];
|
|
1838
|
+
}), S = a.querySelector("LineString > coordinates");
|
|
1839
|
+
if (S) {
|
|
1840
|
+
const y = p(S.textContent || "");
|
|
1841
|
+
if (y.length >= 2) {
|
|
1842
|
+
const N = T.lineString(y, { ...l, shape: "line", id: m, name: g });
|
|
1763
1843
|
r.push(N);
|
|
1764
1844
|
}
|
|
1765
1845
|
continue;
|
|
1766
1846
|
}
|
|
1767
|
-
const
|
|
1768
|
-
if (
|
|
1769
|
-
const
|
|
1770
|
-
if (
|
|
1771
|
-
const N =
|
|
1772
|
-
r.push(
|
|
1847
|
+
const x = a.querySelector("Polygon outerBoundaryIs LinearRing > coordinates");
|
|
1848
|
+
if (x) {
|
|
1849
|
+
const y = p(x.textContent || "");
|
|
1850
|
+
if (y.length >= 4) {
|
|
1851
|
+
const N = y[0][0] === y[y.length - 1][0] && y[0][1] === y[y.length - 1][1] ? y : [...y, y[0]], w = T.polygon([N], { ...l, shape: "polygon", id: m, name: g });
|
|
1852
|
+
r.push(w);
|
|
1773
1853
|
}
|
|
1774
1854
|
continue;
|
|
1775
1855
|
}
|
|
1776
1856
|
const M = a.querySelector("Point > coordinates");
|
|
1777
1857
|
if (M) {
|
|
1778
|
-
const
|
|
1779
|
-
if (
|
|
1780
|
-
const N =
|
|
1858
|
+
const y = p(M.textContent || "");
|
|
1859
|
+
if (y.length >= 1) {
|
|
1860
|
+
const N = T.point(y[0], { ...l, shape: "point", id: m, name: g });
|
|
1781
1861
|
r.push(N);
|
|
1782
1862
|
}
|
|
1783
1863
|
continue;
|
|
1784
1864
|
}
|
|
1785
1865
|
}
|
|
1786
|
-
return
|
|
1866
|
+
return T.featureCollection(r);
|
|
1787
1867
|
}
|
|
1788
1868
|
/**
|
|
1789
1869
|
* 将 KMZ(ZIP 内含 doc.kml 或首个 .kml 文件)异步转换为 GeoJSON。
|
|
@@ -1796,12 +1876,12 @@ class R {
|
|
|
1796
1876
|
*/
|
|
1797
1877
|
static async convertKMZ2GeoJSON(t, e = {}) {
|
|
1798
1878
|
var r;
|
|
1799
|
-
|
|
1800
|
-
const n = await
|
|
1801
|
-
if (!
|
|
1802
|
-
return
|
|
1803
|
-
const o = new TextDecoder().decode(
|
|
1804
|
-
return
|
|
1879
|
+
R.info("[%s] convert kmz to geojson (async)", e == null ? void 0 : e.requestId), typeof Buffer < "u" && Buffer.isBuffer(t) && (t = A.toArrayBuffer(t));
|
|
1880
|
+
const n = await A._parseZipEntries(t), s = n.get("doc.kml") ?? ((r = [...n.entries()].find(([i]) => i.toLowerCase().endsWith(".kml"))) == null ? void 0 : r[1]);
|
|
1881
|
+
if (!s)
|
|
1882
|
+
return R.warn("[%s] no .kml file found in kmz", e == null ? void 0 : e.requestId), T.featureCollection([]);
|
|
1883
|
+
const o = new TextDecoder().decode(s);
|
|
1884
|
+
return A.convertKML2GeoJSON(o, e);
|
|
1805
1885
|
}
|
|
1806
1886
|
/**
|
|
1807
1887
|
* 将 ZIP 文件中所有 .kml 文件合并转换为一个 GeoJSON FeatureCollection(异步)。
|
|
@@ -1813,15 +1893,15 @@ class R {
|
|
|
1813
1893
|
* @param options
|
|
1814
1894
|
*/
|
|
1815
1895
|
static async convertZIP2GeoJSON(t, e = {}) {
|
|
1816
|
-
|
|
1817
|
-
const n = await
|
|
1896
|
+
R.info("[%s] convert zip to geojson (async)", e == null ? void 0 : e.requestId), typeof Buffer < "u" && Buffer.isBuffer(t) && (t = A.toArrayBuffer(t));
|
|
1897
|
+
const n = await A._parseZipEntries(t), s = [];
|
|
1818
1898
|
for (const [o, r] of n) {
|
|
1819
1899
|
if (!o.toLowerCase().endsWith(".kml"))
|
|
1820
1900
|
continue;
|
|
1821
|
-
const
|
|
1822
|
-
|
|
1901
|
+
const i = new TextDecoder().decode(r), c = await A.convertKML2GeoJSON(i, e);
|
|
1902
|
+
s.push(...c.features);
|
|
1823
1903
|
}
|
|
1824
|
-
return
|
|
1904
|
+
return s.length === 0 ? (R.warn("[%s] no .kml files found in zip", e == null ? void 0 : e.requestId), this.convertSHP2GeoJSON(t, e)) : T.featureCollection(s);
|
|
1825
1905
|
}
|
|
1826
1906
|
/**
|
|
1827
1907
|
* 将 Shapefile ZIP(含 .shp/.shx/.dbf/.prj)转换为 GeoJSON FeatureCollection。
|
|
@@ -1832,12 +1912,12 @@ class R {
|
|
|
1832
1912
|
* @param options
|
|
1833
1913
|
*/
|
|
1834
1914
|
static async convertSHP2GeoJSON(t, e = {}) {
|
|
1835
|
-
|
|
1915
|
+
R.info("[%s] convert shp zip to geojson", e == null ? void 0 : e.requestId);
|
|
1836
1916
|
try {
|
|
1837
|
-
typeof Buffer < "u" && Buffer.isBuffer(t) && (t =
|
|
1838
|
-
const n = await
|
|
1917
|
+
typeof Buffer < "u" && Buffer.isBuffer(t) && (t = A.toArrayBuffer(t));
|
|
1918
|
+
const n = await J(t);
|
|
1839
1919
|
if (Array.isArray(n)) {
|
|
1840
|
-
const
|
|
1920
|
+
const s = n.flatMap((c) => c.features || []), o = b.utc(), r = (e == null ? void 0 : e.id) || o.valueOf().toString(), i = {
|
|
1841
1921
|
Point: "point",
|
|
1842
1922
|
MultiPoint: "point",
|
|
1843
1923
|
LineString: "line",
|
|
@@ -1845,24 +1925,24 @@ class R {
|
|
|
1845
1925
|
Polygon: "polygon",
|
|
1846
1926
|
MultiPolygon: "polygon"
|
|
1847
1927
|
};
|
|
1848
|
-
return
|
|
1849
|
-
var
|
|
1850
|
-
const
|
|
1851
|
-
c.properties = c.properties || {}, c.properties.shape =
|
|
1852
|
-
const
|
|
1853
|
-
c.properties.name = h || `${
|
|
1854
|
-
}),
|
|
1928
|
+
return s.forEach((c, a) => {
|
|
1929
|
+
var g;
|
|
1930
|
+
const l = ((g = c.geometry) == null ? void 0 : g.type) || "", u = i[l] || l.toLowerCase();
|
|
1931
|
+
c.properties = c.properties || {}, c.properties.shape = u, c.properties.parentId = r, c.properties.id = `${r}_${a}`;
|
|
1932
|
+
const f = Object.keys(c.properties).find((m) => m.toLowerCase().indexOf("name") !== -1), h = f ? c.properties[f] : void 0;
|
|
1933
|
+
c.properties.name = h || `${u}_${o.format()}_${a}`;
|
|
1934
|
+
}), T.featureCollection(s);
|
|
1855
1935
|
}
|
|
1856
1936
|
return n;
|
|
1857
1937
|
} catch (n) {
|
|
1858
|
-
return
|
|
1938
|
+
return R.warn("[%s] failed to convert shp zip: %s", e == null ? void 0 : e.requestId, n), T.featureCollection([]);
|
|
1859
1939
|
}
|
|
1860
1940
|
}
|
|
1861
1941
|
}
|
|
1862
1942
|
export {
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1943
|
+
K as AisHelper,
|
|
1944
|
+
A as GeoJsonHelper,
|
|
1945
|
+
v as LaneHelper,
|
|
1866
1946
|
d as LngLatHelper,
|
|
1867
|
-
|
|
1947
|
+
it as TropicalHelper
|
|
1868
1948
|
};
|