@idm-plugin/geo 1.1.0 → 1.1.2
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 +397 -341
- package/dist/index.umd.cjs +1 -1
- package/dist/lane/src/index.d.ts +0 -11
- package/dist/tropicals/src/index.d.ts +23 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,7 +1,38 @@
|
|
|
1
1
|
import * as g from "@turf/turf";
|
|
2
|
-
import
|
|
2
|
+
import C from "moment";
|
|
3
3
|
import "moment-timezone";
|
|
4
|
-
import
|
|
4
|
+
import E from "tz-lookup";
|
|
5
|
+
function L(v) {
|
|
6
|
+
return v && v.__esModule && Object.prototype.hasOwnProperty.call(v, "default") ? v.default : v;
|
|
7
|
+
}
|
|
8
|
+
class x {
|
|
9
|
+
log() {
|
|
10
|
+
}
|
|
11
|
+
isLevelEnabled() {
|
|
12
|
+
return !1;
|
|
13
|
+
}
|
|
14
|
+
addContext() {
|
|
15
|
+
}
|
|
16
|
+
removeContext() {
|
|
17
|
+
}
|
|
18
|
+
clearContext() {
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
["Trace", "Debug", "Info", "Warn", "Error", "Fatal", "Mark"].forEach((v) => {
|
|
22
|
+
x.prototype[v.toLowerCase()] = () => {
|
|
23
|
+
}, x.prototype[`is${v}Enabled`] = () => !1;
|
|
24
|
+
});
|
|
25
|
+
const F = () => {
|
|
26
|
+
try {
|
|
27
|
+
return require("log4js");
|
|
28
|
+
} catch {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}, W = F(), k = W ? W.getLogger : () => new x();
|
|
32
|
+
var j = {
|
|
33
|
+
getLogger: k
|
|
34
|
+
};
|
|
35
|
+
const A = /* @__PURE__ */ L(j);
|
|
5
36
|
class l {
|
|
6
37
|
/**
|
|
7
38
|
* 基于输入的经度,计算出时区
|
|
@@ -9,8 +40,8 @@ class l {
|
|
|
9
40
|
* @param lat
|
|
10
41
|
*/
|
|
11
42
|
static guessTimeZoneOffset(e, t) {
|
|
12
|
-
const n =
|
|
13
|
-
return this.roundPrecision(
|
|
43
|
+
const n = E(t, e), i = C().tz(n).utcOffset();
|
|
44
|
+
return this.roundPrecision(i / 60, 1);
|
|
14
45
|
}
|
|
15
46
|
/**
|
|
16
47
|
* 将时间offset转换为时区,例如:8.5 => +08:30
|
|
@@ -23,17 +54,17 @@ class l {
|
|
|
23
54
|
}
|
|
24
55
|
static lng2pretty(e, t = 6, n = "H°M′") {
|
|
25
56
|
e = l.convertToStdLng(e, t);
|
|
26
|
-
let
|
|
27
|
-
e < 0 && (
|
|
28
|
-
let o = e * 3600,
|
|
29
|
-
|
|
30
|
-
const
|
|
57
|
+
let i = "E";
|
|
58
|
+
e < 0 && (i = "W"), e = Math.abs(e), n = n.toUpperCase();
|
|
59
|
+
let o = e * 3600, s, r, c, a, d, u;
|
|
60
|
+
s = o % 3600 % 60, n.indexOf("S") !== -1 && (o = o - s, r = l.padNumber(s, 2, 2)), c = o / 60 % 60, n.indexOf("M") !== -1 && (n.indexOf("S") !== -1 ? a = l.roundPrecision(c, t).toString().padStart(2, "0") : a = l.padNumber(c, 2, 2), o = o - c * 60), d = o / 3600, n.indexOf("M") !== -1 ? u = l.roundPrecision(d, t).toString().padStart(3, "0") : u = l.padNumber(d, 3, 2);
|
|
61
|
+
const p = `${n.replace(/S+/gi, r).replace(/M+/gi, a).replace(/H+/gi, u)}${i}`;
|
|
31
62
|
return {
|
|
32
|
-
direction:
|
|
63
|
+
direction: i,
|
|
33
64
|
degree: l.roundPrecision(d, t),
|
|
34
65
|
minute: l.roundPrecision(c, t),
|
|
35
|
-
second: l.roundPrecision(
|
|
36
|
-
pretty:
|
|
66
|
+
second: l.roundPrecision(s, t),
|
|
67
|
+
pretty: p
|
|
37
68
|
};
|
|
38
69
|
}
|
|
39
70
|
/**
|
|
@@ -44,32 +75,32 @@ class l {
|
|
|
44
75
|
*/
|
|
45
76
|
static lat2pretty(e, t = 6, n = "H°M′") {
|
|
46
77
|
e = e % 180;
|
|
47
|
-
let
|
|
48
|
-
e < 0 && (
|
|
49
|
-
let o = e * 3600,
|
|
50
|
-
|
|
51
|
-
const
|
|
78
|
+
let i = "N";
|
|
79
|
+
e < 0 && (i = "S"), e = Math.abs(e), n = n.toUpperCase();
|
|
80
|
+
let o = e * 3600, s, r, c, a, d, u;
|
|
81
|
+
s = o % 3600 % 60, n.indexOf("S") !== -1 && (o = o - s, r = l.padNumber(s, 2, 2)), c = o / 60 % 60, n.indexOf("M") !== -1 && (n.indexOf("S") !== -1 ? a = l.roundPrecision(c, t).toString().padStart(2, "0") : a = l.padNumber(c, 2, 2), o = o - c * 60), d = o / 3600, n.indexOf("M") !== -1 ? u = l.roundPrecision(d, t).toString().padStart(2, "0") : u = l.padNumber(d, 2, 2);
|
|
82
|
+
const p = `${n.replace(/S+/gi, r).replace(/M+/gi, a).replace(/H+/gi, u)}${i}`;
|
|
52
83
|
return {
|
|
53
|
-
direction:
|
|
84
|
+
direction: i,
|
|
54
85
|
degree: l.roundPrecision(d, t),
|
|
55
86
|
minute: l.roundPrecision(c, t),
|
|
56
|
-
second: l.roundPrecision(
|
|
57
|
-
pretty:
|
|
87
|
+
second: l.roundPrecision(s, t),
|
|
88
|
+
pretty: p
|
|
58
89
|
};
|
|
59
90
|
}
|
|
60
91
|
static str2Lng(e, t = 6) {
|
|
61
92
|
let n;
|
|
62
93
|
if (isNaN(e)) {
|
|
63
94
|
e = l.strReplace(e, "LNG");
|
|
64
|
-
const
|
|
95
|
+
const i = e[e.length - 1].toUpperCase();
|
|
65
96
|
e = e.substring(0, e.length - 1).trim();
|
|
66
97
|
const o = e.split(" ").filter((c) => c !== "").map((c) => Number(c));
|
|
67
|
-
let [
|
|
68
|
-
if (r = r > 60 ? r / Math.pow(10, String(r).length - 2) : r,
|
|
69
|
-
const c = this.roundPrecision(
|
|
70
|
-
r =
|
|
98
|
+
let [s, r] = o;
|
|
99
|
+
if (r = r > 60 ? r / Math.pow(10, String(r).length - 2) : r, s > 360 && !r) {
|
|
100
|
+
const c = this.roundPrecision(s / 100, 0);
|
|
101
|
+
r = s - c * 100, s = c;
|
|
71
102
|
}
|
|
72
|
-
n =
|
|
103
|
+
n = s + (r ?? 0) / 60, i === "W" && (n = n * -1);
|
|
73
104
|
} else
|
|
74
105
|
n = Number(e);
|
|
75
106
|
return l.convertToStdLng(n, t);
|
|
@@ -78,23 +109,23 @@ class l {
|
|
|
78
109
|
let n;
|
|
79
110
|
if (isNaN(e)) {
|
|
80
111
|
e = l.strReplace(e, "LAT");
|
|
81
|
-
const
|
|
112
|
+
const i = e[e.length - 1].toUpperCase();
|
|
82
113
|
e = e.substring(0, e.length - 1).trim();
|
|
83
114
|
const o = e.split(" ").filter((c) => c !== "").map((c) => Number(c));
|
|
84
|
-
let [
|
|
85
|
-
if (r = r > 60 ? r / Math.pow(10, String(r).length - 2) : r,
|
|
86
|
-
const c = this.roundPrecision(
|
|
87
|
-
r =
|
|
115
|
+
let [s, r] = o;
|
|
116
|
+
if (r = r > 60 ? r / Math.pow(10, String(r).length - 2) : r, s > 90 && !r) {
|
|
117
|
+
const c = this.roundPrecision(s / 100, 0);
|
|
118
|
+
r = s - c * 100, s = c;
|
|
88
119
|
}
|
|
89
|
-
n =
|
|
120
|
+
n = s + (r ?? 0) / 60, i === "S" && (n = n * -1);
|
|
90
121
|
} else
|
|
91
122
|
n = Number(e);
|
|
92
123
|
return l.roundPrecision(n, t);
|
|
93
124
|
}
|
|
94
125
|
static str2LngOrLat(e, t = 6, n = "LAT") {
|
|
95
126
|
e = l.strReplace(e, n);
|
|
96
|
-
const
|
|
97
|
-
return ["N", "S"].includes(
|
|
127
|
+
const i = e[e.length - 1].toUpperCase();
|
|
128
|
+
return ["N", "S"].includes(i) ? {
|
|
98
129
|
lat: l.str2Lat(e, t)
|
|
99
130
|
} : {
|
|
100
131
|
lng: l.str2Lng(e, t)
|
|
@@ -132,10 +163,10 @@ class l {
|
|
|
132
163
|
e = e.replace(/([0-9]+)\.([0-9]+\.[0-9]+)/g, "$1 $2").replace(/-/g, " ").replace(/°/, " ").replace(/'/g, " ").replace(/′/g, " ").replace(/"/g, " ").replace(/∼/g, " ").replace(/°/g, " ").replace(/,/g, ".").replace(/^ /g, "").replace(/ $/g, "").trim();
|
|
133
164
|
const n = e[e.length - 1].toUpperCase();
|
|
134
165
|
if (!["N", "S", "E", "W"].includes(n)) {
|
|
135
|
-
const
|
|
166
|
+
const i = e, o = Number(i.split(" ")[0]);
|
|
136
167
|
if (isNaN(o))
|
|
137
168
|
throw new Error(`invalid Lat/Lng: ${e}`);
|
|
138
|
-
o >= 90 ? e = `${
|
|
169
|
+
o >= 90 ? e = `${i}E` : o <= -90 ? e = `${i}W` : ["LAN", "LNG"].includes(t == null ? void 0 : t.toUpperCase()) ? e = `${i}${o > 0 ? "E" : "W"}` : e = `${i}${o > 0 ? "N" : "S"}`;
|
|
139
170
|
}
|
|
140
171
|
return e;
|
|
141
172
|
}
|
|
@@ -147,157 +178,11 @@ class l {
|
|
|
147
178
|
* @param dcmPrecision 小数位数
|
|
148
179
|
*/
|
|
149
180
|
static padNumber(e, t = 2, n = 2) {
|
|
150
|
-
const
|
|
151
|
-
return `${
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
class I {
|
|
155
|
-
static convert2Geojson(e) {
|
|
156
|
-
var n;
|
|
157
|
-
const t = g.featureCollection([]);
|
|
158
|
-
for (const s of e) {
|
|
159
|
-
if (s.forecasts) {
|
|
160
|
-
const o = (n = s.history) == null ? void 0 : n[0];
|
|
161
|
-
for (const i of s.forecasts) {
|
|
162
|
-
const r = [], c = v(i.date).utc(), a = `${s.name}-${i.model}`;
|
|
163
|
-
if (o) {
|
|
164
|
-
const d = v(o.updated).utc(), u = g.point([o.lng, o.lat], {
|
|
165
|
-
model: i.model,
|
|
166
|
-
name: s.name,
|
|
167
|
-
date: d.format(),
|
|
168
|
-
hour: 0,
|
|
169
|
-
format: d.format("MMM-DD/HHmm[Z]"),
|
|
170
|
-
pressure: o.pressure > 1e4 ? l.roundPrecision(o.pressure / 100, 0) : l.roundPrecision(o.pressure, 0),
|
|
171
|
-
wind: { kts: o.kts, spd: o.speed || o.spd },
|
|
172
|
-
category: a,
|
|
173
|
-
type: "forecast"
|
|
174
|
-
});
|
|
175
|
-
t.features.push(u), r.push(u.geometry.coordinates);
|
|
176
|
-
}
|
|
177
|
-
for (const d in i == null ? void 0 : i.hours) {
|
|
178
|
-
const u = i.hours[d];
|
|
179
|
-
u.wind.spd = u.wind.spd || u.wind.speed;
|
|
180
|
-
const f = c.clone().add(Number(d), "hour"), p = g.point([u.lng, u.lat], {
|
|
181
|
-
model: i.model,
|
|
182
|
-
name: s.name,
|
|
183
|
-
date: f.format(),
|
|
184
|
-
hour: Number(d),
|
|
185
|
-
format: f.format("MMM-DD/HHmm[Z]"),
|
|
186
|
-
pressure: u.pressure > 1e4 ? l.roundPrecision(u.pressure / 100, 0) : l.roundPrecision(u.pressure, 0),
|
|
187
|
-
gusts: u.gusts,
|
|
188
|
-
wind: u.wind || {},
|
|
189
|
-
movement: u.movement,
|
|
190
|
-
category: a,
|
|
191
|
-
type: "forecast"
|
|
192
|
-
});
|
|
193
|
-
t.features.push(p), r.push(p.geometry.coordinates);
|
|
194
|
-
}
|
|
195
|
-
if ((r == null ? void 0 : r.length) > 1) {
|
|
196
|
-
const d = g.lineString(l.convertToMonotonicLng2(r), {
|
|
197
|
-
date: i.date,
|
|
198
|
-
id: s.id || s.name,
|
|
199
|
-
model: i.model,
|
|
200
|
-
name: s.name,
|
|
201
|
-
category: a,
|
|
202
|
-
type: "forecast"
|
|
203
|
-
});
|
|
204
|
-
t.features.push(d);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
if (s.history) {
|
|
209
|
-
const o = [];
|
|
210
|
-
for (const r of s.history) {
|
|
211
|
-
const c = v(r.updated).utc(), a = g.point([r.lng, r.lat], {
|
|
212
|
-
name: s.name,
|
|
213
|
-
date: c.format(),
|
|
214
|
-
format: c.format("MMM-DD/HHmm[Z]"),
|
|
215
|
-
pressure: r.pressure > 1e4 ? l.roundPrecision(r.pressure / 100, 0) : l.roundPrecision(r.pressure, 0),
|
|
216
|
-
spd: r.speed || r.spd,
|
|
217
|
-
kts: r.kts,
|
|
218
|
-
source: r.source,
|
|
219
|
-
level: r.type,
|
|
220
|
-
type: "history",
|
|
221
|
-
category: `${s.name}-history`
|
|
222
|
-
});
|
|
223
|
-
t.features.push(a), o.push(a.geometry.coordinates);
|
|
224
|
-
}
|
|
225
|
-
const i = s.history[0];
|
|
226
|
-
if (o.length === 1 && o.push(o[0]), o.length > 1) {
|
|
227
|
-
const r = g.lineString(l.convertToMonotonicLng2(o), {
|
|
228
|
-
name: s.name,
|
|
229
|
-
type: "history",
|
|
230
|
-
updated: i == null ? void 0 : i.updated,
|
|
231
|
-
pressure: (i == null ? void 0 : i.pressure) > 1e4 ? l.roundPrecision((i == null ? void 0 : i.pressure) / 100, 0) : l.roundPrecision(i == null ? void 0 : i.pressure, 0),
|
|
232
|
-
spd: (i == null ? void 0 : i.speed) || (i == null ? void 0 : i.spd),
|
|
233
|
-
kts: i == null ? void 0 : i.kts,
|
|
234
|
-
source: i == null ? void 0 : i.source,
|
|
235
|
-
level: i == null ? void 0 : i.type
|
|
236
|
-
});
|
|
237
|
-
t.features.push(r);
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
return t;
|
|
242
|
-
}
|
|
243
|
-
static interpolate(e, t = 3) {
|
|
244
|
-
var o, i, r, c;
|
|
245
|
-
const n = (o = e == null ? void 0 : e.data) == null ? void 0 : o.features.filter((a) => a.geometry.type === "LineString" && a.properties.type === "forecast"), s = [];
|
|
246
|
-
for (const a of n) {
|
|
247
|
-
const d = a.properties.name, u = a.properties.model, f = v(a.properties.date).utc();
|
|
248
|
-
let p = t * 60 - (f.get("hour") * 60 + f.get("minute")) % (t * 60);
|
|
249
|
-
const b = (i = e == null ? void 0 : e.data) == null ? void 0 : i.features.filter(
|
|
250
|
-
(m) => m.geometry.type === "Point" && m.properties.type === "forecast" && m.properties.category === `${d}-${u}`
|
|
251
|
-
);
|
|
252
|
-
let T, P = f.clone().add(p, "minute").set({ minute: 0, second: 0, millisecond: 0 });
|
|
253
|
-
for (; T = this.pickIndex(b, P), T <= b.length - 1; ) {
|
|
254
|
-
if (T > 0) {
|
|
255
|
-
const m = b[T], h = T === 0 ? void 0 : b[T - 1], S = (p / 60 - ((r = h == null ? void 0 : h.properties) == null ? void 0 : r.hour)) / (m.properties.hour - ((c = h == null ? void 0 : h.properties) == null ? void 0 : c.hour)), M = this.computeNumber(h == null ? void 0 : h.geometry.coordinates[0], m.geometry.coordinates[0], S), C = this.computeNumber(h == null ? void 0 : h.geometry.coordinates[1], m.geometry.coordinates[1], S), N = g.point([M, C], {
|
|
256
|
-
name: d,
|
|
257
|
-
model: u,
|
|
258
|
-
category: m == null ? void 0 : m.properties.category,
|
|
259
|
-
date: P.format(),
|
|
260
|
-
format: P.format("MMM-DD/HHmm[Z]"),
|
|
261
|
-
gusts: this.computeNumber(h == null ? void 0 : h.properties.gusts, m.properties.gusts, S),
|
|
262
|
-
hour: this.computeNumber(h == null ? void 0 : h.properties.hour, m.properties.hour, S),
|
|
263
|
-
movement: this.computeNumber(h == null ? void 0 : h.properties.movement, m.properties.movement, S),
|
|
264
|
-
pressure: this.computeNumber(h == null ? void 0 : h.properties.pressure, m.properties.pressure, S),
|
|
265
|
-
wind: this.computeNumber(h == null ? void 0 : h.properties.wind, m.properties.wind, S),
|
|
266
|
-
type: "forecast"
|
|
267
|
-
});
|
|
268
|
-
s.push(N);
|
|
269
|
-
}
|
|
270
|
-
p += t * 60, P = f.clone().add(p, "minute").set({ minute: 0, second: 0, millisecond: 0 });
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
return s;
|
|
274
|
-
}
|
|
275
|
-
static pickIndex(e, t) {
|
|
276
|
-
let n = 0;
|
|
277
|
-
for (const s of e) {
|
|
278
|
-
if (v(s.properties.date).isAfter(t))
|
|
279
|
-
return n === 0 ? -1 : n;
|
|
280
|
-
n++;
|
|
281
|
-
}
|
|
282
|
-
return n;
|
|
283
|
-
}
|
|
284
|
-
static computeNumber(e, t, n) {
|
|
285
|
-
if (e)
|
|
286
|
-
if (t) {
|
|
287
|
-
if (isNaN(e) && isNaN(t) && typeof e != "string" && typeof t != "string") {
|
|
288
|
-
const s = {};
|
|
289
|
-
for (const o in e)
|
|
290
|
-
s[o] = this.computeNumber(e[o], t[o], n);
|
|
291
|
-
return s;
|
|
292
|
-
}
|
|
293
|
-
return Math.round((e + (t - e) * n) * 100) / 100;
|
|
294
|
-
} else
|
|
295
|
-
return e;
|
|
296
|
-
else
|
|
297
|
-
return t;
|
|
181
|
+
const i = Math.trunc(e).toString().padStart(t, "0"), o = Math.trunc(l.roundPrecision(e - Math.trunc(e), n) * Math.pow(10, n)).toString().padStart(n, "0");
|
|
182
|
+
return `${i}.${o}`;
|
|
298
183
|
}
|
|
299
184
|
}
|
|
300
|
-
class
|
|
185
|
+
class D {
|
|
301
186
|
/**
|
|
302
187
|
* 计算方位角
|
|
303
188
|
* @param from 坐标 {lng, lat}
|
|
@@ -306,13 +191,13 @@ class W {
|
|
|
306
191
|
* @param precision
|
|
307
192
|
* @returns {number} 单位度
|
|
308
193
|
*/
|
|
309
|
-
static calculateBearing(e, t, n = !0,
|
|
194
|
+
static calculateBearing(e, t, n = !0, i = 4) {
|
|
310
195
|
const o = g.points([
|
|
311
196
|
[e.lng, e.lat],
|
|
312
197
|
[t.lng, t.lat]
|
|
313
198
|
]);
|
|
314
|
-
let
|
|
315
|
-
return n ?
|
|
199
|
+
let s;
|
|
200
|
+
return n ? s = g.rhumbBearing(o.features[0], o.features[1]) : s = g.bearing(o.features[0], o.features[1]), s < 0 && (s += 360), l.roundPrecision(s, i);
|
|
316
201
|
}
|
|
317
202
|
/**
|
|
318
203
|
* 计算两点间距离
|
|
@@ -323,14 +208,14 @@ class W {
|
|
|
323
208
|
* @param units 单位,默认 nm(海里)
|
|
324
209
|
* @returns {number}
|
|
325
210
|
*/
|
|
326
|
-
static calculateDistance(e, t, n = !0,
|
|
327
|
-
e = { ...e }, t = { ...t }, e.lng = l.convertToStdLng(e.lng,
|
|
328
|
-
const
|
|
211
|
+
static calculateDistance(e, t, n = !0, i = 4, o = "nauticalmiles") {
|
|
212
|
+
e = { ...e }, t = { ...t }, e.lng = l.convertToStdLng(e.lng, i), t.lng = l.convertToStdLng(t.lng, i);
|
|
213
|
+
const s = g.points([
|
|
329
214
|
[e.lng, e.lat],
|
|
330
215
|
[t.lng, t.lat]
|
|
331
216
|
]);
|
|
332
217
|
let r;
|
|
333
|
-
return n ? r = g.rhumbDistance(
|
|
218
|
+
return n ? r = g.rhumbDistance(s.features[0], s.features[1], { units: o }) : r = g.distance(s.features[0], s.features[1], { units: o }), l.roundPrecision(r, i);
|
|
334
219
|
}
|
|
335
220
|
/**
|
|
336
221
|
* 计算航线距离
|
|
@@ -339,15 +224,15 @@ class W {
|
|
|
339
224
|
* @param units
|
|
340
225
|
*/
|
|
341
226
|
static calculateRouteDistance(e, t = 4, n = "nauticalmiles") {
|
|
342
|
-
let
|
|
343
|
-
for (const
|
|
344
|
-
for (let r = 0; r <
|
|
345
|
-
const c = { lng:
|
|
346
|
-
r === 0 && o && (
|
|
347
|
-
const a = { lng:
|
|
348
|
-
|
|
227
|
+
let i = 0, o;
|
|
228
|
+
for (const s of e)
|
|
229
|
+
for (let r = 0; r < s.length - 1; r++) {
|
|
230
|
+
const c = { lng: s[r][0], lat: s[r][1] };
|
|
231
|
+
r === 0 && o && (i += this.calculateDistance(o, c, !0, t, n));
|
|
232
|
+
const a = { lng: s[r + 1][0], lat: s[r + 1][1] };
|
|
233
|
+
i += this.calculateDistance(c, a, !0, t, n), o = a;
|
|
349
234
|
}
|
|
350
|
-
return l.roundPrecision(
|
|
235
|
+
return l.roundPrecision(i, t);
|
|
351
236
|
}
|
|
352
237
|
/**
|
|
353
238
|
* 计算坐标(基于方位角和距离)
|
|
@@ -357,10 +242,10 @@ class W {
|
|
|
357
242
|
* @param units 单位,默认 nm(海里)
|
|
358
243
|
* @param rhumb
|
|
359
244
|
*/
|
|
360
|
-
static calculateCoordinate(e, t, n,
|
|
361
|
-
const
|
|
245
|
+
static calculateCoordinate(e, t, n, i = "nauticalmiles", o = !0) {
|
|
246
|
+
const s = g.point([e.lng, e.lat]);
|
|
362
247
|
let r;
|
|
363
|
-
o ? r = g.rhumbDestination(
|
|
248
|
+
o ? r = g.rhumbDestination(s, n, t, { units: i }) : r = g.destination(s, n, t, { units: i });
|
|
364
249
|
const c = r.geometry.coordinates;
|
|
365
250
|
return { lng: l.convertToStdLng(c[0], 8), lat: l.roundPrecision(c[1], 8) };
|
|
366
251
|
}
|
|
@@ -373,12 +258,12 @@ class W {
|
|
|
373
258
|
* @param includeTail true 包含终点 to
|
|
374
259
|
* @param units 单位,默认 nm(海里)
|
|
375
260
|
*/
|
|
376
|
-
static interpolateCoordinates(e, t, n,
|
|
377
|
-
const r = [], c = this.calculateBearing(e, t, !1), a = this.calculateDistance(e, t, !1, 8,
|
|
378
|
-
|
|
261
|
+
static interpolateCoordinates(e, t, n, i = !0, o = !0, s = "nauticalmiles") {
|
|
262
|
+
const r = [], c = this.calculateBearing(e, t, !1), a = this.calculateDistance(e, t, !1, 8, s);
|
|
263
|
+
i && r.push({ lng: e.lng, lat: e.lat });
|
|
379
264
|
let d = 0;
|
|
380
265
|
for (; d < a; )
|
|
381
|
-
d += n, d < a && r.push(this.calculateCoordinate(e, c, d,
|
|
266
|
+
d += n, d < a && r.push(this.calculateCoordinate(e, c, d, s, !1));
|
|
382
267
|
return o && r.push({ lng: t.lng, lat: t.lat }), r;
|
|
383
268
|
}
|
|
384
269
|
/**
|
|
@@ -397,33 +282,33 @@ class W {
|
|
|
397
282
|
return [];
|
|
398
283
|
e = this.deduplicateCoordinates(e);
|
|
399
284
|
let n = [];
|
|
400
|
-
const
|
|
401
|
-
let o,
|
|
285
|
+
const i = [];
|
|
286
|
+
let o, s;
|
|
402
287
|
for (let r = 0; r < e.length - 1; r++) {
|
|
403
|
-
o = l.convertToStdLng(e[r].lng, 8),
|
|
404
|
-
const c = o -
|
|
288
|
+
o = l.convertToStdLng(e[r].lng, 8), s = l.convertToStdLng(e[r + 1].lng, 8), n.push([o, e[r].lat]);
|
|
289
|
+
const c = o - s;
|
|
405
290
|
if (Math.abs(c) > 180) {
|
|
406
291
|
const a = l.convertToMonotonicLng2([
|
|
407
292
|
[o, e[r].lat],
|
|
408
|
-
[
|
|
293
|
+
[s, e[r + 1].lat]
|
|
409
294
|
]);
|
|
410
295
|
let d, u;
|
|
411
296
|
t ? (d = g.lineString(a), u = g.lineString([
|
|
412
297
|
[c > 0 ? 180 : -180, 89],
|
|
413
298
|
[c > 0 ? 180 : -180, -89]
|
|
414
299
|
])) : (d = g.greatCircle(a[0], a[1]), u = g.greatCircle([c > 0 ? 180 : -180, 89], [c > 0 ? 180 : -180, -89]));
|
|
415
|
-
const
|
|
416
|
-
let
|
|
417
|
-
if (
|
|
418
|
-
const
|
|
419
|
-
|
|
300
|
+
const p = g.lineIntersect(d, u);
|
|
301
|
+
let f;
|
|
302
|
+
if (p.features.length) {
|
|
303
|
+
const S = g.getCoord(p.features[0]);
|
|
304
|
+
f = l.roundPrecision(S[1], 8);
|
|
420
305
|
} else
|
|
421
|
-
|
|
422
|
-
c > 0 ? (n.push([180 - 1e-6,
|
|
306
|
+
f = e[r].lat;
|
|
307
|
+
c > 0 ? (n.push([180 - 1e-6, f]), i.push([...n]), n = [], n.push([-(180 - 1e-6), f])) : (n.push([-(180 - 1e-6), f]), i.push([...n]), n = [], n.push([180 - 1e-6, f]));
|
|
423
308
|
}
|
|
424
|
-
r === e.length - 2 && n.push([
|
|
309
|
+
r === e.length - 2 && n.push([s, e[r + 1].lat]);
|
|
425
310
|
}
|
|
426
|
-
return
|
|
311
|
+
return i.push(n), i;
|
|
427
312
|
}
|
|
428
313
|
/**
|
|
429
314
|
* 去除重复坐标
|
|
@@ -432,8 +317,8 @@ class W {
|
|
|
432
317
|
static deduplicateRoute(e) {
|
|
433
318
|
const t = [];
|
|
434
319
|
for (const n of e) {
|
|
435
|
-
const
|
|
436
|
-
t.push(
|
|
320
|
+
const i = n.reduce((o, s) => (o.findIndex((r) => r[0] === s[0] && r[1] === s[1]) === -1 && o.push(s), o), []);
|
|
321
|
+
t.push(i);
|
|
437
322
|
}
|
|
438
323
|
return t;
|
|
439
324
|
}
|
|
@@ -442,7 +327,7 @@ class W {
|
|
|
442
327
|
* @param coordinates
|
|
443
328
|
*/
|
|
444
329
|
static deduplicateCoordinates(e) {
|
|
445
|
-
return e.reduce((t, n) => (t.findIndex((
|
|
330
|
+
return e.reduce((t, n) => (t.findIndex((i) => i.lat === n.lat && i.lng === n.lng) === -1 && t.push(n), t), []);
|
|
446
331
|
}
|
|
447
332
|
/**
|
|
448
333
|
* 移出坐标
|
|
@@ -452,8 +337,8 @@ class W {
|
|
|
452
337
|
static removeCoordinateFromRoute(e, t) {
|
|
453
338
|
e.lng = l.convertToStdLng(e.lng, 8);
|
|
454
339
|
for (const n of t)
|
|
455
|
-
for (let
|
|
456
|
-
l.roundPrecision(n[
|
|
340
|
+
for (let i = n.length - 1; i >= 0; i--)
|
|
341
|
+
l.roundPrecision(n[i][0], 8) === e.lng && l.roundPrecision(n[i][1], 8) === l.roundPrecision(e.lat, 8) && n.splice(i, 1);
|
|
457
342
|
return t;
|
|
458
343
|
}
|
|
459
344
|
/**
|
|
@@ -480,13 +365,13 @@ class W {
|
|
|
480
365
|
*/
|
|
481
366
|
static mergeCoordinateToRoute(e, t) {
|
|
482
367
|
e.lng = l.convertToStdLng(e.lng, 8);
|
|
483
|
-
let n = Number.MAX_VALUE,
|
|
368
|
+
let n = Number.MAX_VALUE, i = 0, o = 0, s, r;
|
|
484
369
|
return t.forEach((c, a) => {
|
|
485
370
|
for (let d = 0; d < c.length - 1; d++) {
|
|
486
|
-
const u = { lng: c[d][0], lat: c[d][1] },
|
|
487
|
-
n >
|
|
371
|
+
const u = { lng: c[d][0], lat: c[d][1] }, p = { lng: c[d + 1][0], lat: c[d + 1][1] }, f = this.calculatePointToLineDistance(e, u, p);
|
|
372
|
+
n > f && (n = f, o = d, i = a, s = this.calculateDistance(u, e), r = this.calculateDistance(p, e));
|
|
488
373
|
}
|
|
489
|
-
}),
|
|
374
|
+
}), s !== 0 && r !== 0 ? t[i].splice(o + 1, 0, [e.lng, e.lat]) : s === 0 ? t[i].splice(o, 1, [e.lng, e.lat]) : r === 0 && t[i].splice(o + 1, 1, [e.lng, e.lat]), t;
|
|
490
375
|
}
|
|
491
376
|
/**
|
|
492
377
|
* 合并多个waypoints进航线
|
|
@@ -507,21 +392,21 @@ class W {
|
|
|
507
392
|
*/
|
|
508
393
|
static calculateRangeRoute(e, t, n) {
|
|
509
394
|
n = this.mergeWaypointsToRoute([e, t], n);
|
|
510
|
-
const
|
|
395
|
+
const i = [];
|
|
511
396
|
let o = 0;
|
|
512
|
-
return n.forEach((
|
|
397
|
+
return n.forEach((s) => {
|
|
513
398
|
if (o === 2)
|
|
514
399
|
return;
|
|
515
400
|
const r = [];
|
|
516
|
-
for (const c of
|
|
401
|
+
for (const c of s) {
|
|
517
402
|
if (l.roundPrecision(t.lng, 8) === l.roundPrecision(c[0], 8) && l.roundPrecision(t.lat, 8) === l.roundPrecision(c[1], 8)) {
|
|
518
403
|
r.push(c), o === 0 && r.push([e.lng, e.lat]), o = 2;
|
|
519
404
|
break;
|
|
520
405
|
}
|
|
521
406
|
o === 1 ? r.push(c) : l.roundPrecision(e.lng, 8) === l.roundPrecision(c[0], 8) && l.roundPrecision(e.lat, 8) === l.roundPrecision(c[1], 8) && (o = 1, r.push(c));
|
|
522
407
|
}
|
|
523
|
-
r.length &&
|
|
524
|
-
}),
|
|
408
|
+
r.length && i.push(r);
|
|
409
|
+
}), i;
|
|
525
410
|
}
|
|
526
411
|
/**
|
|
527
412
|
* 计算from到to之间的航线
|
|
@@ -531,13 +416,13 @@ class W {
|
|
|
531
416
|
* @param waypoints
|
|
532
417
|
* @return [{lng, lat}]
|
|
533
418
|
*/
|
|
534
|
-
static calculateRangeWaypoints(e, t, n,
|
|
535
|
-
const o = this.convertRouteToCoordinates(n, 0),
|
|
419
|
+
static calculateRangeWaypoints(e, t, n, i = []) {
|
|
420
|
+
const o = this.convertRouteToCoordinates(n, 0), s = this.mergeCoordinatesToWaypoints([e, t, ...i], o), r = s.findIndex(
|
|
536
421
|
(d) => l.roundPrecision(e.lng, 8) === l.roundPrecision(d.lng, 8) && l.roundPrecision(e.lat, 8) === l.roundPrecision(d.lat, 8)
|
|
537
|
-
), c =
|
|
422
|
+
), c = s.findIndex(
|
|
538
423
|
(d) => l.roundPrecision(t.lng, 8) === l.roundPrecision(d.lng, 8) && l.roundPrecision(t.lat, 8) === l.roundPrecision(d.lat, 8)
|
|
539
424
|
);
|
|
540
|
-
return
|
|
425
|
+
return s.filter((d, u) => u >= r && u <= c);
|
|
541
426
|
}
|
|
542
427
|
/**
|
|
543
428
|
* 计算坐标到航路上的最短距离
|
|
@@ -545,13 +430,13 @@ class W {
|
|
|
545
430
|
* @param route
|
|
546
431
|
*/
|
|
547
432
|
static calculateMinDistanceToRoute(e, t) {
|
|
548
|
-
let n = Number.MAX_VALUE,
|
|
549
|
-
return t.forEach((
|
|
550
|
-
for (let c = 0; c <
|
|
551
|
-
const a = { lng:
|
|
552
|
-
n > u && (n = u,
|
|
433
|
+
let n = Number.MAX_VALUE, i = 0, o = 0;
|
|
434
|
+
return t.forEach((s, r) => {
|
|
435
|
+
for (let c = 0; c < s.length - 1; c++) {
|
|
436
|
+
const a = { lng: s[c][0], lat: s[c][1] }, d = { lng: s[c + 1][0], lat: s[c + 1][1] }, u = this.calculatePointToLineDistance(e, a, d);
|
|
437
|
+
n > u && (n = u, i = c, o = r);
|
|
553
438
|
}
|
|
554
|
-
}), { minDist: n, segIndex: o, minIndex:
|
|
439
|
+
}), { minDist: n, segIndex: o, minIndex: i };
|
|
555
440
|
}
|
|
556
441
|
/**
|
|
557
442
|
* 计算子航线
|
|
@@ -560,17 +445,17 @@ class W {
|
|
|
560
445
|
* @return [[[lng, lat]]]
|
|
561
446
|
*/
|
|
562
447
|
static calculateSubRoute(e, t) {
|
|
563
|
-
const { segIndex: n, minIndex:
|
|
448
|
+
const { segIndex: n, minIndex: i } = this.calculateMinDistanceToRoute({ ...e }, t);
|
|
564
449
|
e.lng = l.convertToStdLng(e.lng);
|
|
565
450
|
const o = [];
|
|
566
|
-
let
|
|
451
|
+
let s = !0;
|
|
567
452
|
for (let r = n; r < t.length; r++)
|
|
568
|
-
if (
|
|
453
|
+
if (s) {
|
|
569
454
|
const c = [];
|
|
570
455
|
c.push([e.lng, e.lat]);
|
|
571
|
-
for (let a =
|
|
456
|
+
for (let a = i + 1; a < t[r].length; a++)
|
|
572
457
|
e.lng === t[r][a][0] && e.lat === t[r][a][1] || c.push(t[r][a]);
|
|
573
|
-
o.push(c),
|
|
458
|
+
o.push(c), s = !1;
|
|
574
459
|
} else
|
|
575
460
|
o.push([...t[r]]);
|
|
576
461
|
return o;
|
|
@@ -582,20 +467,20 @@ class W {
|
|
|
582
467
|
* @return [{lng, lat}]
|
|
583
468
|
*/
|
|
584
469
|
static calculateSubWaypoints(e, t) {
|
|
585
|
-
let n = Number.MAX_VALUE,
|
|
586
|
-
for (let
|
|
587
|
-
const r = t[
|
|
470
|
+
let n = Number.MAX_VALUE, i = 0;
|
|
471
|
+
for (let s = 0; s < t.length - 1; s++) {
|
|
472
|
+
const r = t[s], c = t[s + 1];
|
|
588
473
|
if (this.calculateDistance(e, r) === 0)
|
|
589
474
|
return t;
|
|
590
475
|
if (this.calculateDistance(e, c) === 0)
|
|
591
476
|
return t.filter((d, u) => u > 0);
|
|
592
477
|
const a = this.calculatePointToLineDistance(e, r, c);
|
|
593
|
-
n > a && (n = a,
|
|
478
|
+
n > a && (n = a, i = s);
|
|
594
479
|
}
|
|
595
480
|
e.lng = l.convertToStdLng(e.lng);
|
|
596
481
|
const o = [e];
|
|
597
|
-
for (let
|
|
598
|
-
o.push(t[
|
|
482
|
+
for (let s = i + 1; s < t.length; s++)
|
|
483
|
+
o.push(t[s]);
|
|
599
484
|
return o;
|
|
600
485
|
}
|
|
601
486
|
/**
|
|
@@ -605,14 +490,14 @@ class W {
|
|
|
605
490
|
* @param to { lng, lat }
|
|
606
491
|
* @param options
|
|
607
492
|
*/
|
|
608
|
-
static calculatePointToLineDistance(e, t, n,
|
|
493
|
+
static calculatePointToLineDistance(e, t, n, i = { units: "nauticalmiles", method: "geodesic" }) {
|
|
609
494
|
e.lng = l.convertToStdLng(e.lng), t = { ...t }, n = { ...n }, t.lng = l.convertToStdLng(t.lng, 8), n.lng = l.convertToStdLng(n.lng, 8);
|
|
610
495
|
const o = l.convertToMonotonicLng([t, n]);
|
|
611
496
|
t = o[0], n = o[1];
|
|
612
|
-
const
|
|
497
|
+
const s = g.lineString([
|
|
613
498
|
[t.lng, t.lat],
|
|
614
499
|
[n.lng, n.lat]
|
|
615
|
-
]), r = g.pointToLineDistance(g.point([e.lng, e.lat]),
|
|
500
|
+
]), r = g.pointToLineDistance(g.point([e.lng, e.lat]), s, i), c = g.pointToLineDistance(g.point([e.lng > 0 ? e.lng - 360 : e.lng + 360, e.lat]), s, i);
|
|
616
501
|
return l.roundPrecision(Math.min(r, c), 6);
|
|
617
502
|
}
|
|
618
503
|
/**
|
|
@@ -623,8 +508,8 @@ class W {
|
|
|
623
508
|
static calculateWaypointsPropInRoute(e, t) {
|
|
624
509
|
t = this.mergeWaypointsToRoute(e, t);
|
|
625
510
|
for (let n = 0; n < e.length - 1; n++) {
|
|
626
|
-
const
|
|
627
|
-
n === 0 && (
|
|
511
|
+
const i = e[n], o = e[n + 1], s = this.calculateRangeRoute(i, o, t);
|
|
512
|
+
n === 0 && (i.distanceFromPrevious = 0, i.distanceFromStart = 0), o.distanceFromPrevious = this.calculateRouteDistance(s), o.distanceFromStart = l.roundPrecision((i.distanceFromStart || 0) + o.distanceFromPrevious);
|
|
628
513
|
}
|
|
629
514
|
return e;
|
|
630
515
|
}
|
|
@@ -634,8 +519,8 @@ class W {
|
|
|
634
519
|
* @param replace true replace the same waypoint with coordinate
|
|
635
520
|
*/
|
|
636
521
|
static mergeCoordinatesToWaypoints(e, t, n = !0) {
|
|
637
|
-
for (const
|
|
638
|
-
this.mergeCoordinateToWaypoints(
|
|
522
|
+
for (const i of e)
|
|
523
|
+
this.mergeCoordinateToWaypoints(i, t, n);
|
|
639
524
|
return t;
|
|
640
525
|
}
|
|
641
526
|
/**
|
|
@@ -652,12 +537,12 @@ class W {
|
|
|
652
537
|
*/
|
|
653
538
|
static mergeCoordinateToWaypoints(e, t, n = !0) {
|
|
654
539
|
e.lng = l.convertToStdLng(e.lng, 8);
|
|
655
|
-
let
|
|
540
|
+
let i = Number.MAX_VALUE, o = 0, s = 0, r = 0;
|
|
656
541
|
for (let c = 0; c < t.length - 1; c++) {
|
|
657
542
|
const a = { lng: t[c].lng, lat: t[c].lat }, d = { lng: t[c + 1].lng, lat: t[c + 1].lat }, u = this.calculatePointToLineDistance(e, a, d);
|
|
658
|
-
|
|
543
|
+
i >= u && (i = u, o = c, s = this.calculateDistance(a, e, !1, 6), r = this.calculateDistance(d, e, !1, 6));
|
|
659
544
|
}
|
|
660
|
-
return
|
|
545
|
+
return s !== 0 && r !== 0 ? s < i || s === i && o === 0 ? t.unshift(e) : r < i || r === i && o === t.length - 2 ? t.push(e) : t.splice(o + 1, 0, e) : s === 0 ? n && t.splice(o, 1, e) : r === 0 && n && t.splice(o + 1, 1, e), t.map((c) => (c.lng = l.convertToStdLng(c.lng), c));
|
|
661
546
|
}
|
|
662
547
|
/**
|
|
663
548
|
* 生成航线(基于途经点生成大圆/横向航线,并根据是否跨180度分组)
|
|
@@ -667,10 +552,10 @@ class W {
|
|
|
667
552
|
static generateRouteAccordingToWaypoints(e) {
|
|
668
553
|
const t = [];
|
|
669
554
|
for (let n = 1; n < e.length; n++) {
|
|
670
|
-
const
|
|
671
|
-
if (n === 1 && t.push(
|
|
672
|
-
const
|
|
673
|
-
t.push(...
|
|
555
|
+
const i = e[n - 1], o = e[n];
|
|
556
|
+
if (n === 1 && t.push(i), o.gcToPrevious) {
|
|
557
|
+
const s = this.interpolateCoordinates(i, o, 200, !1, !0, "nauticalmiles");
|
|
558
|
+
t.push(...s);
|
|
674
559
|
} else
|
|
675
560
|
t.push(o);
|
|
676
561
|
}
|
|
@@ -682,12 +567,12 @@ class W {
|
|
|
682
567
|
* @param route [[[lng, lat]]]
|
|
683
568
|
*/
|
|
684
569
|
static nearestCoordinateInRoute(e, t) {
|
|
685
|
-
const n = g.point([e.lng, e.lat]),
|
|
570
|
+
const n = g.point([e.lng, e.lat]), i = [];
|
|
686
571
|
for (const c of t) {
|
|
687
572
|
const a = c.map((d) => g.point(d));
|
|
688
|
-
|
|
573
|
+
i.push(...a);
|
|
689
574
|
}
|
|
690
|
-
const o = g.featureCollection(
|
|
575
|
+
const o = g.featureCollection(i), s = g.nearestPoint(n, o), r = g.getCoord(s);
|
|
691
576
|
return { lng: r[0], lat: r[1] };
|
|
692
577
|
}
|
|
693
578
|
/**
|
|
@@ -698,14 +583,14 @@ class W {
|
|
|
698
583
|
static calculatePrevWaypoint(e, t) {
|
|
699
584
|
let n = 0;
|
|
700
585
|
this.mergeCoordinateToWaypoints(e, t);
|
|
701
|
-
for (let
|
|
702
|
-
const o = t[
|
|
586
|
+
for (let i = 0; i < t.length - 1; i++) {
|
|
587
|
+
const o = t[i], s = t[i + 1];
|
|
703
588
|
if (this.calculateDistance(e, o) === 0) {
|
|
704
|
-
n =
|
|
589
|
+
n = i;
|
|
705
590
|
break;
|
|
706
591
|
}
|
|
707
|
-
if (this.calculateDistance(e,
|
|
708
|
-
n =
|
|
592
|
+
if (this.calculateDistance(e, s) === 0) {
|
|
593
|
+
n = i + 1;
|
|
709
594
|
break;
|
|
710
595
|
}
|
|
711
596
|
}
|
|
@@ -719,43 +604,43 @@ class W {
|
|
|
719
604
|
* @param units
|
|
720
605
|
* @return { coordinate: {lng, lat}, route: [[[lng, lat]]]}
|
|
721
606
|
*/
|
|
722
|
-
static calculateNextCoordinateAlongRoute(e, t, n,
|
|
723
|
-
var
|
|
724
|
-
const o = e.speed || 12,
|
|
607
|
+
static calculateNextCoordinateAlongRoute(e, t, n, i = "nauticalmiles") {
|
|
608
|
+
var p;
|
|
609
|
+
const o = e.speed || 12, s = [];
|
|
725
610
|
let r = [], c = !1, a = 0, d = 0, u;
|
|
726
|
-
if (t && n.length ? (
|
|
611
|
+
if (t && n.length ? (s.push(e), n.forEach((f, S) => {
|
|
727
612
|
if (c)
|
|
728
|
-
r.push(
|
|
613
|
+
r.push(f);
|
|
729
614
|
else {
|
|
730
|
-
const
|
|
615
|
+
const b = [];
|
|
731
616
|
let P;
|
|
732
|
-
for (let m = 0; m <
|
|
617
|
+
for (let m = 0; m < f.length; m++)
|
|
733
618
|
if (u)
|
|
734
|
-
|
|
619
|
+
b.push(f[m]);
|
|
735
620
|
else {
|
|
736
|
-
P = { lng:
|
|
737
|
-
const h = this.calculateDistance(e, P, !0, 8,
|
|
621
|
+
P = { lng: f[m][0], lat: f[m][1] };
|
|
622
|
+
const h = this.calculateDistance(e, P, !0, 8, i);
|
|
738
623
|
if (a += h, a < t)
|
|
739
|
-
d += h,
|
|
624
|
+
d += h, s.push(P), e = P;
|
|
740
625
|
else {
|
|
741
626
|
if (d = t, a === t)
|
|
742
|
-
u = P,
|
|
627
|
+
u = P, b.push([u.lng, u.lat]);
|
|
743
628
|
else {
|
|
744
|
-
const
|
|
745
|
-
u = this.calculateCoordinate(P,
|
|
629
|
+
const T = a - t, R = this.calculateBearing(P, e);
|
|
630
|
+
u = this.calculateCoordinate(P, R, T, i), b.push([u.lng, u.lat]), b.push([P.lng, P.lat]);
|
|
746
631
|
}
|
|
747
632
|
c = !0;
|
|
748
633
|
}
|
|
749
634
|
}
|
|
750
|
-
|
|
635
|
+
b.length && r.push(b), S === n.length - 1 && !u && (u = P);
|
|
751
636
|
}
|
|
752
637
|
})) : (r = n, u = { ...e }), u)
|
|
753
|
-
if (
|
|
754
|
-
const
|
|
755
|
-
u.bearing = this.calculateBearing(u,
|
|
638
|
+
if (s.push(u), u.distanceFromPrevious = d, u.hourFromPrevious = Math.round(d / o * 1e4) / 1e4, ((p = r[0]) == null ? void 0 : p.length) > 1) {
|
|
639
|
+
const f = { lng: r[0][1][0], lat: r[0][1][1] };
|
|
640
|
+
u.bearing = this.calculateBearing(u, f);
|
|
756
641
|
} else
|
|
757
642
|
u.bearing = 0;
|
|
758
|
-
return { coordinate: u, nextRoute: r, prevRoute:
|
|
643
|
+
return { coordinate: u, nextRoute: r, prevRoute: s };
|
|
759
644
|
}
|
|
760
645
|
/**
|
|
761
646
|
* 返回最近点及其是否为垂足(最近点不是起点或终点)
|
|
@@ -764,11 +649,11 @@ class W {
|
|
|
764
649
|
* @param to {lng, lat}
|
|
765
650
|
*/
|
|
766
651
|
static nearestCoordinateInLine(e, t, n) {
|
|
767
|
-
const
|
|
768
|
-
[
|
|
652
|
+
const i = l.convertToStdLng(e.lng, 6), o = g.point([i, e.lat]), s = l.convertToStdLng(t.lng, 6), r = l.convertToStdLng(n.lng, 6), c = g.lineString([
|
|
653
|
+
[s, t.lat],
|
|
769
654
|
[r, n.lat]
|
|
770
|
-
]), a = g.nearestPointOnLine(c, o), d = g.getCoord(a), u = l.roundPrecision(d[0], 6),
|
|
771
|
-
return { lng: u, lat:
|
|
655
|
+
]), a = g.nearestPointOnLine(c, o), d = g.getCoord(a), u = l.roundPrecision(d[0], 6), p = l.roundPrecision(d[1], 6);
|
|
656
|
+
return { lng: u, lat: p, inline: !(u === s && p === t.lat) && !(u === r && p === n.lat) };
|
|
772
657
|
}
|
|
773
658
|
/**
|
|
774
659
|
* 将route转coordinate
|
|
@@ -777,21 +662,21 @@ class W {
|
|
|
777
662
|
*/
|
|
778
663
|
static convertRouteToCoordinates(e, t = 0) {
|
|
779
664
|
const n = [];
|
|
780
|
-
let
|
|
781
|
-
return e.forEach((
|
|
782
|
-
|
|
665
|
+
let i, o;
|
|
666
|
+
return e.forEach((s) => {
|
|
667
|
+
s.forEach((r) => {
|
|
783
668
|
const c = { lng: r[0], lat: r[1] };
|
|
784
669
|
if (!o)
|
|
785
670
|
n.push(c), o = c;
|
|
786
671
|
else if (o.bearing === void 0)
|
|
787
672
|
o.bearing = this.calculateBearing(o, c, !0);
|
|
788
673
|
else {
|
|
789
|
-
const a = this.calculateDistance(
|
|
790
|
-
a && a >= t && (
|
|
674
|
+
const a = this.calculateDistance(i, c, !0);
|
|
675
|
+
a && a >= t && (i.bearing = this.calculateBearing(i, c, !0), n.push(i), o = i);
|
|
791
676
|
}
|
|
792
|
-
|
|
677
|
+
i = c;
|
|
793
678
|
});
|
|
794
|
-
}),
|
|
679
|
+
}), i && n.push(i), n;
|
|
795
680
|
}
|
|
796
681
|
/**
|
|
797
682
|
* 抽稀(基于转向点)
|
|
@@ -800,8 +685,8 @@ class W {
|
|
|
800
685
|
* @param distance
|
|
801
686
|
*/
|
|
802
687
|
static simplifyRouteToCoordinates(e, t, n = 1) {
|
|
803
|
-
let
|
|
804
|
-
return
|
|
688
|
+
let i = this.convertRouteToCoordinates(e, n);
|
|
689
|
+
return i = this.simplifyGCCoordinates(i, t), i;
|
|
805
690
|
}
|
|
806
691
|
/**
|
|
807
692
|
* 基于大圆标识抽稀
|
|
@@ -809,34 +694,23 @@ class W {
|
|
|
809
694
|
* @param waypoints
|
|
810
695
|
*/
|
|
811
696
|
static simplifyGCCoordinates(e, t) {
|
|
812
|
-
t.forEach((
|
|
813
|
-
this.mergeCoordinateToWaypoints(
|
|
697
|
+
t.forEach((i) => {
|
|
698
|
+
this.mergeCoordinateToWaypoints(i, e);
|
|
814
699
|
});
|
|
815
|
-
for (let
|
|
816
|
-
const o = t[
|
|
817
|
-
if (
|
|
818
|
-
const r = e.findIndex((a) => a.lng === o.lng && a.lat === o.lat), c = e.findIndex((a) => a.lng ===
|
|
700
|
+
for (let i = 1; i < t.length; i++) {
|
|
701
|
+
const o = t[i - 1], s = t[i];
|
|
702
|
+
if (s.gcToPrevious) {
|
|
703
|
+
const r = e.findIndex((a) => a.lng === o.lng && a.lat === o.lat), c = e.findIndex((a) => a.lng === s.lng && a.lat === s.lat);
|
|
819
704
|
for (let a = c - 1; a > r; a--)
|
|
820
705
|
e.splice(a, 1);
|
|
821
706
|
}
|
|
822
707
|
}
|
|
823
708
|
let n = 0;
|
|
824
|
-
for (let
|
|
825
|
-
const o = e[
|
|
826
|
-
|
|
709
|
+
for (let i = 1; i < e.length; i++) {
|
|
710
|
+
const o = e[i - 1], s = e[i];
|
|
711
|
+
s.gcToPrevious ? (o.bearing = this.calculateBearing(o, s, !1), s.distanceFromPrevious = this.calculateDistance(o, s, !1)) : (o.bearing = this.calculateBearing(o, s, !0), s.distanceFromPrevious = this.calculateDistance(o, s, !0)), n = l.roundPrecision(n + s.distanceFromPrevious), s.distanceFromStart = n;
|
|
827
712
|
}
|
|
828
|
-
return e.map((
|
|
829
|
-
}
|
|
830
|
-
/**
|
|
831
|
-
* 近似计算右切线
|
|
832
|
-
* @param coord {lat, lng}
|
|
833
|
-
* @param center {lat, lng}
|
|
834
|
-
* @param radius
|
|
835
|
-
* @param units
|
|
836
|
-
*/
|
|
837
|
-
static calculateRightTangent(e, t, n = 100, s = "nauticalmiles") {
|
|
838
|
-
const o = this.calculateBearing(t, e, !0);
|
|
839
|
-
return this.calculateCoordinate(t, o + 90, n, s, !0);
|
|
713
|
+
return e.map((i) => (i.lng = l.convertToStdLng(i.lng), i));
|
|
840
714
|
}
|
|
841
715
|
/**
|
|
842
716
|
* 计算轨迹中心点
|
|
@@ -847,11 +721,11 @@ class W {
|
|
|
847
721
|
for (const r of e)
|
|
848
722
|
for (const c of r)
|
|
849
723
|
t.push(c);
|
|
850
|
-
const n = g.featureCollection([]),
|
|
851
|
-
for (const r of
|
|
724
|
+
const n = g.featureCollection([]), i = l.convertToMonotonicLng2(t);
|
|
725
|
+
for (const r of i)
|
|
852
726
|
n.features.push(g.point(r));
|
|
853
|
-
const
|
|
854
|
-
return { lng: l.convertToStdLng(
|
|
727
|
+
const s = g.center(n).geometry.coordinates;
|
|
728
|
+
return { lng: l.convertToStdLng(s[0], 8), lat: l.roundPrecision(s[1], 8) };
|
|
855
729
|
}
|
|
856
730
|
/**
|
|
857
731
|
* 计算中心点
|
|
@@ -868,10 +742,10 @@ class W {
|
|
|
868
742
|
static calculateBBox(e) {
|
|
869
743
|
const t = [];
|
|
870
744
|
for (const o of e)
|
|
871
|
-
for (const
|
|
872
|
-
t.push(
|
|
873
|
-
const n = l.convertToMonotonicLng2(t),
|
|
874
|
-
return g.bbox(
|
|
745
|
+
for (const s of o)
|
|
746
|
+
t.push(s);
|
|
747
|
+
const n = l.convertToMonotonicLng2(t), i = g.lineString(n);
|
|
748
|
+
return g.bbox(i);
|
|
875
749
|
}
|
|
876
750
|
/**
|
|
877
751
|
* 计算BBox
|
|
@@ -882,8 +756,190 @@ class W {
|
|
|
882
756
|
return this.calculateBBox(t);
|
|
883
757
|
}
|
|
884
758
|
}
|
|
759
|
+
const N = A.getLogger("vessel");
|
|
760
|
+
class q {
|
|
761
|
+
/**
|
|
762
|
+
* 将原始数据转换为geojson
|
|
763
|
+
* @param raw
|
|
764
|
+
*/
|
|
765
|
+
static convert2Geojson(e) {
|
|
766
|
+
var n;
|
|
767
|
+
const t = g.featureCollection([]);
|
|
768
|
+
for (const i of e) {
|
|
769
|
+
if (i.forecasts) {
|
|
770
|
+
const o = (n = i.history) == null ? void 0 : n[0];
|
|
771
|
+
for (const s of i.forecasts) {
|
|
772
|
+
const r = [], c = C(s.date).utc(), a = `${i.name}-${s.model}`;
|
|
773
|
+
if (o) {
|
|
774
|
+
const d = C(o.updated).utc(), u = g.point([o.lng, o.lat], {
|
|
775
|
+
model: s.model,
|
|
776
|
+
name: i.name,
|
|
777
|
+
date: d.format(),
|
|
778
|
+
hour: 0,
|
|
779
|
+
format: d.format("MMM-DD/HHmm[Z]"),
|
|
780
|
+
pressure: o.pressure > 1e4 ? l.roundPrecision(o.pressure / 100, 0) : l.roundPrecision(o.pressure, 0),
|
|
781
|
+
wind: { kts: o.kts, spd: o.speed || o.spd },
|
|
782
|
+
category: a,
|
|
783
|
+
type: "forecast"
|
|
784
|
+
});
|
|
785
|
+
t.features.push(u), r.push(u.geometry.coordinates);
|
|
786
|
+
}
|
|
787
|
+
for (const d in s == null ? void 0 : s.hours) {
|
|
788
|
+
const u = s.hours[d];
|
|
789
|
+
u.wind.spd = u.wind.spd || u.wind.speed;
|
|
790
|
+
const p = c.clone().add(Number(d), "hour"), f = g.point([u.lng, u.lat], {
|
|
791
|
+
model: s.model,
|
|
792
|
+
name: i.name,
|
|
793
|
+
date: p.format(),
|
|
794
|
+
hour: Number(d),
|
|
795
|
+
format: p.format("MMM-DD/HHmm[Z]"),
|
|
796
|
+
pressure: u.pressure > 1e4 ? l.roundPrecision(u.pressure / 100, 0) : l.roundPrecision(u.pressure, 0),
|
|
797
|
+
gusts: u.gusts,
|
|
798
|
+
wind: u.wind || {},
|
|
799
|
+
movement: u.movement,
|
|
800
|
+
category: a,
|
|
801
|
+
type: "forecast"
|
|
802
|
+
});
|
|
803
|
+
t.features.push(f), r.push(f.geometry.coordinates);
|
|
804
|
+
}
|
|
805
|
+
if ((r == null ? void 0 : r.length) > 1) {
|
|
806
|
+
const d = g.lineString(l.convertToMonotonicLng2(r), {
|
|
807
|
+
date: s.date,
|
|
808
|
+
id: i.id || i.name,
|
|
809
|
+
model: s.model,
|
|
810
|
+
name: i.name,
|
|
811
|
+
category: a,
|
|
812
|
+
type: "forecast"
|
|
813
|
+
});
|
|
814
|
+
t.features.push(d);
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
if (i.history) {
|
|
819
|
+
const o = [];
|
|
820
|
+
for (const r of i.history) {
|
|
821
|
+
const c = C(r.updated).utc(), a = g.point([r.lng, r.lat], {
|
|
822
|
+
name: i.name,
|
|
823
|
+
date: c.format(),
|
|
824
|
+
format: c.format("MMM-DD/HHmm[Z]"),
|
|
825
|
+
pressure: r.pressure > 1e4 ? l.roundPrecision(r.pressure / 100, 0) : l.roundPrecision(r.pressure, 0),
|
|
826
|
+
spd: r.speed || r.spd,
|
|
827
|
+
kts: r.kts,
|
|
828
|
+
source: r.source,
|
|
829
|
+
level: r.type,
|
|
830
|
+
type: "history",
|
|
831
|
+
category: `${i.name}-history`
|
|
832
|
+
});
|
|
833
|
+
t.features.push(a), o.push(a.geometry.coordinates);
|
|
834
|
+
}
|
|
835
|
+
const s = i.history[0];
|
|
836
|
+
if (o.length === 1 && o.push(o[0]), o.length > 1) {
|
|
837
|
+
const r = g.lineString(l.convertToMonotonicLng2(o), {
|
|
838
|
+
name: i.name,
|
|
839
|
+
type: "history",
|
|
840
|
+
updated: s == null ? void 0 : s.updated,
|
|
841
|
+
pressure: (s == null ? void 0 : s.pressure) > 1e4 ? l.roundPrecision((s == null ? void 0 : s.pressure) / 100, 0) : l.roundPrecision(s == null ? void 0 : s.pressure, 0),
|
|
842
|
+
spd: (s == null ? void 0 : s.speed) || (s == null ? void 0 : s.spd),
|
|
843
|
+
kts: s == null ? void 0 : s.kts,
|
|
844
|
+
source: s == null ? void 0 : s.source,
|
|
845
|
+
level: s == null ? void 0 : s.type
|
|
846
|
+
});
|
|
847
|
+
t.features.push(r);
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
return t;
|
|
852
|
+
}
|
|
853
|
+
/**
|
|
854
|
+
* 插值台风预报轨迹
|
|
855
|
+
* @param tropicals
|
|
856
|
+
* @param step
|
|
857
|
+
*/
|
|
858
|
+
static interpolate(e, t = 3) {
|
|
859
|
+
var o, s, r, c;
|
|
860
|
+
const n = (o = e == null ? void 0 : e.data) == null ? void 0 : o.features.filter((a) => a.geometry.type === "LineString" && a.properties.type === "forecast"), i = [];
|
|
861
|
+
for (const a of n) {
|
|
862
|
+
const d = a.properties.name, u = a.properties.model, p = C(a.properties.date).utc();
|
|
863
|
+
let f = t * 60 - (p.get("hour") * 60 + p.get("minute")) % (t * 60);
|
|
864
|
+
const S = (s = e == null ? void 0 : e.data) == null ? void 0 : s.features.filter(
|
|
865
|
+
(m) => m.geometry.type === "Point" && m.properties.type === "forecast" && m.properties.category === `${d}-${u}`
|
|
866
|
+
);
|
|
867
|
+
let b, P = p.clone().add(f, "minute").set({ minute: 0, second: 0, millisecond: 0 });
|
|
868
|
+
for (; b = this.pickIndex(S, P), b <= S.length - 1; ) {
|
|
869
|
+
if (b > 0) {
|
|
870
|
+
const m = S[b], h = b === 0 ? void 0 : S[b - 1], T = (f / 60 - ((r = h == null ? void 0 : h.properties) == null ? void 0 : r.hour)) / (m.properties.hour - ((c = h == null ? void 0 : h.properties) == null ? void 0 : c.hour)), R = this.computeNumber(h == null ? void 0 : h.geometry.coordinates[0], m.geometry.coordinates[0], T), y = this.computeNumber(h == null ? void 0 : h.geometry.coordinates[1], m.geometry.coordinates[1], T), I = g.point([R, y], {
|
|
871
|
+
name: d,
|
|
872
|
+
model: u,
|
|
873
|
+
category: m == null ? void 0 : m.properties.category,
|
|
874
|
+
date: P.format(),
|
|
875
|
+
format: P.format("MMM-DD/HHmm[Z]"),
|
|
876
|
+
gusts: this.computeNumber(h == null ? void 0 : h.properties.gusts, m.properties.gusts, T),
|
|
877
|
+
hour: this.computeNumber(h == null ? void 0 : h.properties.hour, m.properties.hour, T),
|
|
878
|
+
movement: this.computeNumber(h == null ? void 0 : h.properties.movement, m.properties.movement, T),
|
|
879
|
+
pressure: this.computeNumber(h == null ? void 0 : h.properties.pressure, m.properties.pressure, T),
|
|
880
|
+
wind: this.computeNumber(h == null ? void 0 : h.properties.wind, m.properties.wind, T),
|
|
881
|
+
type: "forecast"
|
|
882
|
+
});
|
|
883
|
+
i.push(I);
|
|
884
|
+
}
|
|
885
|
+
f += t * 60, P = p.clone().add(f, "minute").set({ minute: 0, second: 0, millisecond: 0 });
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
return i;
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
* 航行方向与台风
|
|
892
|
+
* @param from
|
|
893
|
+
* @param tropical
|
|
894
|
+
* @param radius
|
|
895
|
+
* @param speed
|
|
896
|
+
* @param options
|
|
897
|
+
*/
|
|
898
|
+
static deviationPassageAt(e, t, n, i, o = { requestId: "" }) {
|
|
899
|
+
var d, u, p, f, S, b, P, m, h;
|
|
900
|
+
const s = (u = (d = t == null ? void 0 : t.forecasts) == null ? void 0 : d[0]) == null ? void 0 : u.hours, r = ((p = t == null ? void 0 : t.history) == null ? void 0 : p[0]) || (s == null ? void 0 : s[(f = Object.keys(s)) == null ? void 0 : f[0]]);
|
|
901
|
+
N.info("[%s] the first evasion point: %j", o.requestId, r);
|
|
902
|
+
const c = (S = Object.keys(s || {}).filter((T) => Number(T) <= 24)) == null ? void 0 : S.at(-1), a = s == null ? void 0 : s[c || -1];
|
|
903
|
+
if (N.info("[%s] the second evasion point in %s hrs: %j", o.requestId, c, r), r && a) {
|
|
904
|
+
const T = D.calculateBearing(e, r), R = D.calculateBearing(r, a), y = D.calculateCoordinate(r, T - R + 90, n);
|
|
905
|
+
N.info("[%s] the right tangent point: %j", o.requestId, { from: e, p1: r, p2: a, radius: n, bearing1: T, bearing2: R, right: y });
|
|
906
|
+
const I = D.calculateBearing(e, y);
|
|
907
|
+
let M = D.calculateCoordinate(e, I, i * Number(c));
|
|
908
|
+
M.utc = C((P = (b = t == null ? void 0 : t.forecasts) == null ? void 0 : b[0]) == null ? void 0 : P.date).add(Number(c), "hours").utc().format(), N.info("[%s] the temp evasion point: %j", o.requestId, M);
|
|
909
|
+
const $ = D.calculateDistance(M, a);
|
|
910
|
+
return N.info("[%s] the distance(%d) between tmp & p2: %j - %j", o.requestId, $, M, a), $ < n && (M = D.calculateCoordinate(e, I, i * Number(c) / 2), M.utc = C((h = (m = t == null ? void 0 : t.forecasts) == null ? void 0 : m[0]) == null ? void 0 : h.date).add(Number(c) / 2, "hours").utc().format(), N.warn("[%s] tmp is too close to p2, replace with 1/2 position: %j", o.requestId, M)), M;
|
|
911
|
+
} else {
|
|
912
|
+
N.info("[%s] no need evasion: %j", o.requestId, { from: e, p1: r, p2: a });
|
|
913
|
+
return;
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
static pickIndex(e, t) {
|
|
917
|
+
let n = 0;
|
|
918
|
+
for (const i of e) {
|
|
919
|
+
if (C(i.properties.date).isAfter(t))
|
|
920
|
+
return n === 0 ? -1 : n;
|
|
921
|
+
n++;
|
|
922
|
+
}
|
|
923
|
+
return n;
|
|
924
|
+
}
|
|
925
|
+
static computeNumber(e, t, n) {
|
|
926
|
+
if (e)
|
|
927
|
+
if (t) {
|
|
928
|
+
if (isNaN(e) && isNaN(t) && typeof e != "string" && typeof t != "string") {
|
|
929
|
+
const i = {};
|
|
930
|
+
for (const o in e)
|
|
931
|
+
i[o] = this.computeNumber(e[o], t[o], n);
|
|
932
|
+
return i;
|
|
933
|
+
}
|
|
934
|
+
return Math.round((e + (t - e) * n) * 100) / 100;
|
|
935
|
+
} else
|
|
936
|
+
return e;
|
|
937
|
+
else
|
|
938
|
+
return t;
|
|
939
|
+
}
|
|
940
|
+
}
|
|
885
941
|
export {
|
|
886
|
-
|
|
942
|
+
D as LaneHelper,
|
|
887
943
|
l as LngLatHelper,
|
|
888
|
-
|
|
944
|
+
q as TropicalHelper
|
|
889
945
|
};
|
package/dist/index.umd.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(b,C){typeof exports=="object"&&typeof module<"u"?C(exports,require("@turf/turf"),require("moment"),require("moment-timezone"),require("tz-lookup")):typeof define=="function"&&define.amd?define(["exports","@turf/turf","moment","moment-timezone","tz-lookup"],C):(b=typeof globalThis<"u"?globalThis:b||self,C(b["idm-plugin-rabbitmq"]={},b["@turf/turf"],b.moment,b["moment-timezone"],b["tz-lookup"]))})(this,function(b,C,D,k,R){"use strict";function y(M){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(M){for(const t in M)if(t!=="default"){const n=Object.getOwnPropertyDescriptor(M,t);Object.defineProperty(e,t,n.get?n:{enumerable:!0,get:()=>M[t]})}}return e.default=M,Object.freeze(e)}const g=y(C);class l{static guessTimeZoneOffset(e,t){const n=R(t,e),s=D().tz(n).utcOffset();return this.roundPrecision(s/60,1)}static prettyTimeZoneOffset(e){let t=Math.floor(Math.abs(e)),n=Math.round((Math.abs(e)-t)*60);return n=n>9?n:`0${n}`,t=t>9?t:`0${t}`,e>0?`+${t}:${n}`:`-${t}:${n}`}static lng2pretty(e,t=6,n="H°M′"){e=l.convertToStdLng(e,t);let s="E";e<0&&(s="W"),e=Math.abs(e),n=n.toUpperCase();let o=e*3600,i,r,c,a,d,u;i=o%3600%60,n.indexOf("S")!==-1&&(o=o-i,r=l.padNumber(i,2,2)),c=o/60%60,n.indexOf("M")!==-1&&(n.indexOf("S")!==-1?a=l.roundPrecision(c,t).toString().padStart(2,"0"):a=l.padNumber(c,2,2),o=o-c*60),d=o/3600,n.indexOf("M")!==-1?u=l.roundPrecision(d,t).toString().padStart(3,"0"):u=l.padNumber(d,3,2);const h=`${n.replace(/S+/gi,r).replace(/M+/gi,a).replace(/H+/gi,u)}${s}`;return{direction:s,degree:l.roundPrecision(d,t),minute:l.roundPrecision(c,t),second:l.roundPrecision(i,t),pretty:h}}static lat2pretty(e,t=6,n="H°M′"){e=e%180;let s="N";e<0&&(s="S"),e=Math.abs(e),n=n.toUpperCase();let o=e*3600,i,r,c,a,d,u;i=o%3600%60,n.indexOf("S")!==-1&&(o=o-i,r=l.padNumber(i,2,2)),c=o/60%60,n.indexOf("M")!==-1&&(n.indexOf("S")!==-1?a=l.roundPrecision(c,t).toString().padStart(2,"0"):a=l.padNumber(c,2,2),o=o-c*60),d=o/3600,n.indexOf("M")!==-1?u=l.roundPrecision(d,t).toString().padStart(2,"0"):u=l.padNumber(d,2,2);const h=`${n.replace(/S+/gi,r).replace(/M+/gi,a).replace(/H+/gi,u)}${s}`;return{direction:s,degree:l.roundPrecision(d,t),minute:l.roundPrecision(c,t),second:l.roundPrecision(i,t),pretty:h}}static str2Lng(e,t=6){let n;if(isNaN(e)){e=l.strReplace(e,"LNG");const s=e[e.length-1].toUpperCase();e=e.substring(0,e.length-1).trim();const o=e.split(" ").filter(c=>c!=="").map(c=>Number(c));let[i,r]=o;if(r=r>60?r/Math.pow(10,String(r).length-2):r,i>360&&!r){const c=this.roundPrecision(i/100,0);r=i-c*100,i=c}n=i+(r??0)/60,s==="W"&&(n=n*-1)}else n=Number(e);return l.convertToStdLng(n,t)}static str2Lat(e,t=6){let n;if(isNaN(e)){e=l.strReplace(e,"LAT");const s=e[e.length-1].toUpperCase();e=e.substring(0,e.length-1).trim();const o=e.split(" ").filter(c=>c!=="").map(c=>Number(c));let[i,r]=o;if(r=r>60?r/Math.pow(10,String(r).length-2):r,i>90&&!r){const c=this.roundPrecision(i/100,0);r=i-c*100,i=c}n=i+(r??0)/60,s==="S"&&(n=n*-1)}else n=Number(e);return l.roundPrecision(n,t)}static str2LngOrLat(e,t=6,n="LAT"){e=l.strReplace(e,n);const s=e[e.length-1].toUpperCase();return["N","S"].includes(s)?{lat:l.str2Lat(e,t)}:{lng:l.str2Lng(e,t)}}static convertToStdLng(e,t=4){return e>180?(e=e%360,e=e>180?e-360:e):e<-180&&(e=e%360,e=e<-180?e+360:e),l.roundPrecision(e,t)}static roundPrecision(e,t=4){if(typeof e=="number"){const n=Number("1".padEnd(t+1,"0"));return Math.round(e*n)/n}return e}static convertToMonotonicLng2(e){for(let t=1;t<e.length;t++)e[t][0]+=Math.round((e[t-1][0]-e[t][0])/360)*360;return e}static convertToMonotonicLng(e){for(let t=1;t<e.length;t++)e[t].lng+=Math.round((e[t-1].lng-e[t].lng)/360)*360;return e}static strReplace(e,t="LAT"){e=e.replace(/([0-9]+)\.([0-9]+\.[0-9]+)/g,"$1 $2").replace(/-/g," ").replace(/°/," ").replace(/'/g," ").replace(/′/g," ").replace(/"/g," ").replace(/∼/g," ").replace(/°/g," ").replace(/,/g,".").replace(/^ /g,"").replace(/ $/g,"").trim();const n=e[e.length-1].toUpperCase();if(!["N","S","E","W"].includes(n)){const s=e,o=Number(s.split(" ")[0]);if(isNaN(o))throw new Error(`invalid Lat/Lng: ${e}`);o>=90?e=`${s}E`:o<=-90?e=`${s}W`:["LAN","LNG"].includes(t==null?void 0:t.toUpperCase())?e=`${s}${o>0?"E":"W"}`:e=`${s}${o>0?"N":"S"}`}return e}static padNumber(e,t=2,n=2){const s=Math.trunc(e).toString().padStart(t,"0"),o=Math.trunc(l.roundPrecision(e-Math.trunc(e),n)*Math.pow(10,n)).toString().padStart(n,"0");return`${s}.${o}`}}class x{static convert2Geojson(e){var n;const t=g.featureCollection([]);for(const s of e){if(s.forecasts){const o=(n=s.history)==null?void 0:n[0];for(const i of s.forecasts){const r=[],c=D(i.date).utc(),a=`${s.name}-${i.model}`;if(o){const d=D(o.updated).utc(),u=g.point([o.lng,o.lat],{model:i.model,name:s.name,date:d.format(),hour:0,format:d.format("MMM-DD/HHmm[Z]"),pressure:o.pressure>1e4?l.roundPrecision(o.pressure/100,0):l.roundPrecision(o.pressure,0),wind:{kts:o.kts,spd:o.speed||o.spd},category:a,type:"forecast"});t.features.push(u),r.push(u.geometry.coordinates)}for(const d in i==null?void 0:i.hours){const u=i.hours[d];u.wind.spd=u.wind.spd||u.wind.speed;const h=c.clone().add(Number(d),"hour"),p=g.point([u.lng,u.lat],{model:i.model,name:s.name,date:h.format(),hour:Number(d),format:h.format("MMM-DD/HHmm[Z]"),pressure:u.pressure>1e4?l.roundPrecision(u.pressure/100,0):l.roundPrecision(u.pressure,0),gusts:u.gusts,wind:u.wind||{},movement:u.movement,category:a,type:"forecast"});t.features.push(p),r.push(p.geometry.coordinates)}if((r==null?void 0:r.length)>1){const d=g.lineString(l.convertToMonotonicLng2(r),{date:i.date,id:s.id||s.name,model:i.model,name:s.name,category:a,type:"forecast"});t.features.push(d)}}}if(s.history){const o=[];for(const r of s.history){const c=D(r.updated).utc(),a=g.point([r.lng,r.lat],{name:s.name,date:c.format(),format:c.format("MMM-DD/HHmm[Z]"),pressure:r.pressure>1e4?l.roundPrecision(r.pressure/100,0):l.roundPrecision(r.pressure,0),spd:r.speed||r.spd,kts:r.kts,source:r.source,level:r.type,type:"history",category:`${s.name}-history`});t.features.push(a),o.push(a.geometry.coordinates)}const i=s.history[0];if(o.length===1&&o.push(o[0]),o.length>1){const r=g.lineString(l.convertToMonotonicLng2(o),{name:s.name,type:"history",updated:i==null?void 0:i.updated,pressure:(i==null?void 0:i.pressure)>1e4?l.roundPrecision((i==null?void 0:i.pressure)/100,0):l.roundPrecision(i==null?void 0:i.pressure,0),spd:(i==null?void 0:i.speed)||(i==null?void 0:i.spd),kts:i==null?void 0:i.kts,source:i==null?void 0:i.source,level:i==null?void 0:i.type});t.features.push(r)}}}return t}static interpolate(e,t=3){var o,i,r,c;const n=(o=e==null?void 0:e.data)==null?void 0:o.features.filter(a=>a.geometry.type==="LineString"&&a.properties.type==="forecast"),s=[];for(const a of n){const d=a.properties.name,u=a.properties.model,h=D(a.properties.date).utc();let p=t*60-(h.get("hour")*60+h.get("minute"))%(t*60);const v=(i=e==null?void 0:e.data)==null?void 0:i.features.filter(m=>m.geometry.type==="Point"&&m.properties.type==="forecast"&&m.properties.category===`${d}-${u}`);let T,P=h.clone().add(p,"minute").set({minute:0,second:0,millisecond:0});for(;T=this.pickIndex(v,P),T<=v.length-1;){if(T>0){const m=v[T],f=T===0?void 0:v[T-1],S=(p/60-((r=f==null?void 0:f.properties)==null?void 0:r.hour))/(m.properties.hour-((c=f==null?void 0:f.properties)==null?void 0:c.hour)),N=this.computeNumber(f==null?void 0:f.geometry.coordinates[0],m.geometry.coordinates[0],S),I=this.computeNumber(f==null?void 0:f.geometry.coordinates[1],m.geometry.coordinates[1],S),W=g.point([N,I],{name:d,model:u,category:m==null?void 0:m.properties.category,date:P.format(),format:P.format("MMM-DD/HHmm[Z]"),gusts:this.computeNumber(f==null?void 0:f.properties.gusts,m.properties.gusts,S),hour:this.computeNumber(f==null?void 0:f.properties.hour,m.properties.hour,S),movement:this.computeNumber(f==null?void 0:f.properties.movement,m.properties.movement,S),pressure:this.computeNumber(f==null?void 0:f.properties.pressure,m.properties.pressure,S),wind:this.computeNumber(f==null?void 0:f.properties.wind,m.properties.wind,S),type:"forecast"});s.push(W)}p+=t*60,P=h.clone().add(p,"minute").set({minute:0,second:0,millisecond:0})}}return s}static pickIndex(e,t){let n=0;for(const s of e){if(D(s.properties.date).isAfter(t))return n===0?-1:n;n++}return n}static computeNumber(e,t,n){if(e)if(t){if(isNaN(e)&&isNaN(t)&&typeof e!="string"&&typeof t!="string"){const s={};for(const o in e)s[o]=this.computeNumber(e[o],t[o],n);return s}return Math.round((e+(t-e)*n)*100)/100}else return e;else return t}}class ${static calculateBearing(e,t,n=!0,s=4){const o=g.points([[e.lng,e.lat],[t.lng,t.lat]]);let i;return n?i=g.rhumbBearing(o.features[0],o.features[1]):i=g.bearing(o.features[0],o.features[1]),i<0&&(i+=360),l.roundPrecision(i,s)}static calculateDistance(e,t,n=!0,s=4,o="nauticalmiles"){e={...e},t={...t},e.lng=l.convertToStdLng(e.lng,s),t.lng=l.convertToStdLng(t.lng,s);const i=g.points([[e.lng,e.lat],[t.lng,t.lat]]);let r;return n?r=g.rhumbDistance(i.features[0],i.features[1],{units:o}):r=g.distance(i.features[0],i.features[1],{units:o}),l.roundPrecision(r,s)}static calculateRouteDistance(e,t=4,n="nauticalmiles"){let s=0,o;for(const i of e)for(let r=0;r<i.length-1;r++){const c={lng:i[r][0],lat:i[r][1]};r===0&&o&&(s+=this.calculateDistance(o,c,!0,t,n));const a={lng:i[r+1][0],lat:i[r+1][1]};s+=this.calculateDistance(c,a,!0,t,n),o=a}return l.roundPrecision(s,t)}static calculateCoordinate(e,t,n,s="nauticalmiles",o=!0){const i=g.point([e.lng,e.lat]);let r;o?r=g.rhumbDestination(i,n,t,{units:s}):r=g.destination(i,n,t,{units:s});const c=r.geometry.coordinates;return{lng:l.convertToStdLng(c[0],8),lat:l.roundPrecision(c[1],8)}}static interpolateCoordinates(e,t,n,s=!0,o=!0,i="nauticalmiles"){const r=[],c=this.calculateBearing(e,t,!1),a=this.calculateDistance(e,t,!1,8,i);s&&r.push({lng:e.lng,lat:e.lat});let d=0;for(;d<a;)d+=n,d<a&&r.push(this.calculateCoordinate(e,c,d,i,!1));return o&&r.push({lng:t.lng,lat:t.lat}),r}static divideAccordingToLng(e,t=!1){if((e==null?void 0:e.length)<2)return[];e=this.deduplicateCoordinates(e);let n=[];const s=[];let o,i;for(let r=0;r<e.length-1;r++){o=l.convertToStdLng(e[r].lng,8),i=l.convertToStdLng(e[r+1].lng,8),n.push([o,e[r].lat]);const c=o-i;if(Math.abs(c)>180){const a=l.convertToMonotonicLng2([[o,e[r].lat],[i,e[r+1].lat]]);let d,u;t?(d=g.lineString(a),u=g.lineString([[c>0?180:-180,89],[c>0?180:-180,-89]])):(d=g.greatCircle(a[0],a[1]),u=g.greatCircle([c>0?180:-180,89],[c>0?180:-180,-89]));const h=g.lineIntersect(d,u);let p;if(h.features.length){const v=g.getCoord(h.features[0]);p=l.roundPrecision(v[1],8)}else p=e[r].lat;c>0?(n.push([180-1e-6,p]),s.push([...n]),n=[],n.push([-(180-1e-6),p])):(n.push([-(180-1e-6),p]),s.push([...n]),n=[],n.push([180-1e-6,p]))}r===e.length-2&&n.push([i,e[r+1].lat])}return s.push(n),s}static deduplicateRoute(e){const t=[];for(const n of e){const s=n.reduce((o,i)=>(o.findIndex(r=>r[0]===i[0]&&r[1]===i[1])===-1&&o.push(i),o),[]);t.push(s)}return t}static deduplicateCoordinates(e){return e.reduce((t,n)=>(t.findIndex(s=>s.lat===n.lat&&s.lng===n.lng)===-1&&t.push(n),t),[])}static removeCoordinateFromRoute(e,t){e.lng=l.convertToStdLng(e.lng,8);for(const n of t)for(let s=n.length-1;s>=0;s--)l.roundPrecision(n[s][0],8)===e.lng&&l.roundPrecision(n[s][1],8)===l.roundPrecision(e.lat,8)&&n.splice(s,1);return t}static removeCoordinateFromWaypoints(e,t){e.lng=l.convertToStdLng(e.lng,8);for(let n=t.length-1;n>=0;n--)l.roundPrecision(t[n].lng,8)===e.lng&&l.roundPrecision(t[n].lat,8)===l.roundPrecision(e.lat,8)&&t.splice(n,1);return t}static mergeCoordinateToRoute(e,t){e.lng=l.convertToStdLng(e.lng,8);let n=Number.MAX_VALUE,s=0,o=0,i,r;return t.forEach((c,a)=>{for(let d=0;d<c.length-1;d++){const u={lng:c[d][0],lat:c[d][1]},h={lng:c[d+1][0],lat:c[d+1][1]},p=this.calculatePointToLineDistance(e,u,h);n>p&&(n=p,o=d,s=a,i=this.calculateDistance(u,e),r=this.calculateDistance(h,e))}}),i!==0&&r!==0?t[s].splice(o+1,0,[e.lng,e.lat]):i===0?t[s].splice(o,1,[e.lng,e.lat]):r===0&&t[s].splice(o+1,1,[e.lng,e.lat]),t}static mergeWaypointsToRoute(e,t){for(const n of e)t=this.mergeCoordinateToRoute(n,t);return t}static calculateRangeRoute(e,t,n){n=this.mergeWaypointsToRoute([e,t],n);const s=[];let o=0;return n.forEach(i=>{if(o===2)return;const r=[];for(const c of i){if(l.roundPrecision(t.lng,8)===l.roundPrecision(c[0],8)&&l.roundPrecision(t.lat,8)===l.roundPrecision(c[1],8)){r.push(c),o===0&&r.push([e.lng,e.lat]),o=2;break}o===1?r.push(c):l.roundPrecision(e.lng,8)===l.roundPrecision(c[0],8)&&l.roundPrecision(e.lat,8)===l.roundPrecision(c[1],8)&&(o=1,r.push(c))}r.length&&s.push(r)}),s}static calculateRangeWaypoints(e,t,n,s=[]){const o=this.convertRouteToCoordinates(n,0),i=this.mergeCoordinatesToWaypoints([e,t,...s],o),r=i.findIndex(d=>l.roundPrecision(e.lng,8)===l.roundPrecision(d.lng,8)&&l.roundPrecision(e.lat,8)===l.roundPrecision(d.lat,8)),c=i.findIndex(d=>l.roundPrecision(t.lng,8)===l.roundPrecision(d.lng,8)&&l.roundPrecision(t.lat,8)===l.roundPrecision(d.lat,8));return i.filter((d,u)=>u>=r&&u<=c)}static calculateMinDistanceToRoute(e,t){let n=Number.MAX_VALUE,s=0,o=0;return t.forEach((i,r)=>{for(let c=0;c<i.length-1;c++){const a={lng:i[c][0],lat:i[c][1]},d={lng:i[c+1][0],lat:i[c+1][1]},u=this.calculatePointToLineDistance(e,a,d);n>u&&(n=u,s=c,o=r)}}),{minDist:n,segIndex:o,minIndex:s}}static calculateSubRoute(e,t){const{segIndex:n,minIndex:s}=this.calculateMinDistanceToRoute({...e},t);e.lng=l.convertToStdLng(e.lng);const o=[];let i=!0;for(let r=n;r<t.length;r++)if(i){const c=[];c.push([e.lng,e.lat]);for(let a=s+1;a<t[r].length;a++)e.lng===t[r][a][0]&&e.lat===t[r][a][1]||c.push(t[r][a]);o.push(c),i=!1}else o.push([...t[r]]);return o}static calculateSubWaypoints(e,t){let n=Number.MAX_VALUE,s=0;for(let i=0;i<t.length-1;i++){const r=t[i],c=t[i+1];if(this.calculateDistance(e,r)===0)return t;if(this.calculateDistance(e,c)===0)return t.filter((d,u)=>u>0);const a=this.calculatePointToLineDistance(e,r,c);n>a&&(n=a,s=i)}e.lng=l.convertToStdLng(e.lng);const o=[e];for(let i=s+1;i<t.length;i++)o.push(t[i]);return o}static calculatePointToLineDistance(e,t,n,s={units:"nauticalmiles",method:"geodesic"}){e.lng=l.convertToStdLng(e.lng),t={...t},n={...n},t.lng=l.convertToStdLng(t.lng,8),n.lng=l.convertToStdLng(n.lng,8);const o=l.convertToMonotonicLng([t,n]);t=o[0],n=o[1];const i=g.lineString([[t.lng,t.lat],[n.lng,n.lat]]),r=g.pointToLineDistance(g.point([e.lng,e.lat]),i,s),c=g.pointToLineDistance(g.point([e.lng>0?e.lng-360:e.lng+360,e.lat]),i,s);return l.roundPrecision(Math.min(r,c),6)}static calculateWaypointsPropInRoute(e,t){t=this.mergeWaypointsToRoute(e,t);for(let n=0;n<e.length-1;n++){const s=e[n],o=e[n+1],i=this.calculateRangeRoute(s,o,t);n===0&&(s.distanceFromPrevious=0,s.distanceFromStart=0),o.distanceFromPrevious=this.calculateRouteDistance(i),o.distanceFromStart=l.roundPrecision((s.distanceFromStart||0)+o.distanceFromPrevious)}return e}static mergeCoordinatesToWaypoints(e,t,n=!0){for(const s of e)this.mergeCoordinateToWaypoints(s,t,n);return t}static mergeCoordinateToWaypoints(e,t,n=!0){e.lng=l.convertToStdLng(e.lng,8);let s=Number.MAX_VALUE,o=0,i=0,r=0;for(let c=0;c<t.length-1;c++){const a={lng:t[c].lng,lat:t[c].lat},d={lng:t[c+1].lng,lat:t[c+1].lat},u=this.calculatePointToLineDistance(e,a,d);s>=u&&(s=u,o=c,i=this.calculateDistance(a,e,!1,6),r=this.calculateDistance(d,e,!1,6))}return i!==0&&r!==0?i<s||i===s&&o===0?t.unshift(e):r<s||r===s&&o===t.length-2?t.push(e):t.splice(o+1,0,e):i===0?n&&t.splice(o,1,e):r===0&&n&&t.splice(o+1,1,e),t.map(c=>(c.lng=l.convertToStdLng(c.lng),c))}static generateRouteAccordingToWaypoints(e){const t=[];for(let n=1;n<e.length;n++){const s=e[n-1],o=e[n];if(n===1&&t.push(s),o.gcToPrevious){const i=this.interpolateCoordinates(s,o,200,!1,!0,"nauticalmiles");t.push(...i)}else t.push(o)}return this.divideAccordingToLng(t,!0)}static nearestCoordinateInRoute(e,t){const n=g.point([e.lng,e.lat]),s=[];for(const c of t){const a=c.map(d=>g.point(d));s.push(...a)}const o=g.featureCollection(s),i=g.nearestPoint(n,o),r=g.getCoord(i);return{lng:r[0],lat:r[1]}}static calculatePrevWaypoint(e,t){let n=0;this.mergeCoordinateToWaypoints(e,t);for(let s=0;s<t.length-1;s++){const o=t[s],i=t[s+1];if(this.calculateDistance(e,o)===0){n=s;break}if(this.calculateDistance(e,i)===0){n=s+1;break}}return t[n===0?0:n-1]}static calculateNextCoordinateAlongRoute(e,t,n,s="nauticalmiles"){var h;const o=e.speed||12,i=[];let r=[],c=!1,a=0,d=0,u;if(t&&n.length?(i.push(e),n.forEach((p,v)=>{if(c)r.push(p);else{const T=[];let P;for(let m=0;m<p.length;m++)if(u)T.push(p[m]);else{P={lng:p[m][0],lat:p[m][1]};const f=this.calculateDistance(e,P,!0,8,s);if(a+=f,a<t)d+=f,i.push(P),e=P;else{if(d=t,a===t)u=P,T.push([u.lng,u.lat]);else{const S=a-t,N=this.calculateBearing(P,e);u=this.calculateCoordinate(P,N,S,s),T.push([u.lng,u.lat]),T.push([P.lng,P.lat])}c=!0}}T.length&&r.push(T),v===n.length-1&&!u&&(u=P)}})):(r=n,u={...e}),u)if(i.push(u),u.distanceFromPrevious=d,u.hourFromPrevious=Math.round(d/o*1e4)/1e4,((h=r[0])==null?void 0:h.length)>1){const p={lng:r[0][1][0],lat:r[0][1][1]};u.bearing=this.calculateBearing(u,p)}else u.bearing=0;return{coordinate:u,nextRoute:r,prevRoute:i}}static nearestCoordinateInLine(e,t,n){const s=l.convertToStdLng(e.lng,6),o=g.point([s,e.lat]),i=l.convertToStdLng(t.lng,6),r=l.convertToStdLng(n.lng,6),c=g.lineString([[i,t.lat],[r,n.lat]]),a=g.nearestPointOnLine(c,o),d=g.getCoord(a),u=l.roundPrecision(d[0],6),h=l.roundPrecision(d[1],6);return{lng:u,lat:h,inline:!(u===i&&h===t.lat)&&!(u===r&&h===n.lat)}}static convertRouteToCoordinates(e,t=0){const n=[];let s,o;return e.forEach(i=>{i.forEach(r=>{const c={lng:r[0],lat:r[1]};if(!o)n.push(c),o=c;else if(o.bearing===void 0)o.bearing=this.calculateBearing(o,c,!0);else{const a=this.calculateDistance(s,c,!0);a&&a>=t&&(s.bearing=this.calculateBearing(s,c,!0),n.push(s),o=s)}s=c})}),s&&n.push(s),n}static simplifyRouteToCoordinates(e,t,n=1){let s=this.convertRouteToCoordinates(e,n);return s=this.simplifyGCCoordinates(s,t),s}static simplifyGCCoordinates(e,t){t.forEach(s=>{this.mergeCoordinateToWaypoints(s,e)});for(let s=1;s<t.length;s++){const o=t[s-1],i=t[s];if(i.gcToPrevious){const r=e.findIndex(a=>a.lng===o.lng&&a.lat===o.lat),c=e.findIndex(a=>a.lng===i.lng&&a.lat===i.lat);for(let a=c-1;a>r;a--)e.splice(a,1)}}let n=0;for(let s=1;s<e.length;s++){const o=e[s-1],i=e[s];i.gcToPrevious?(o.bearing=this.calculateBearing(o,i,!1),i.distanceFromPrevious=this.calculateDistance(o,i,!1)):(o.bearing=this.calculateBearing(o,i,!0),i.distanceFromPrevious=this.calculateDistance(o,i,!0)),n=l.roundPrecision(n+i.distanceFromPrevious),i.distanceFromStart=n}return e.map(s=>(s.lng=l.convertToStdLng(s.lng),s))}static calculateRightTangent(e,t,n=100,s="nauticalmiles"){const o=this.calculateBearing(t,e,!0);return this.calculateCoordinate(t,o+90,n,s,!0)}static calculateCenter(e){const t=[];for(const r of e)for(const c of r)t.push(c);const n=g.featureCollection([]),s=l.convertToMonotonicLng2(t);for(const r of s)n.features.push(g.point(r));const i=g.center(n).geometry.coordinates;return{lng:l.convertToStdLng(i[0],8),lat:l.roundPrecision(i[1],8)}}static calculateCenter2(e){const t=this.generateRouteAccordingToWaypoints(e);return this.calculateCenter(t)}static calculateBBox(e){const t=[];for(const o of e)for(const i of o)t.push(i);const n=l.convertToMonotonicLng2(t),s=g.lineString(n);return g.bbox(s)}static calculateBBox2(e){const t=this.generateRouteAccordingToWaypoints(e);return this.calculateBBox(t)}}b.LaneHelper=$,b.LngLatHelper=l,b.TropicalHelper=x,Object.defineProperty(b,Symbol.toStringTag,{value:"Module"})});
|
|
1
|
+
(function(S,I){typeof exports=="object"&&typeof module<"u"?I(exports,require("@turf/turf"),require("moment"),require("moment-timezone"),require("tz-lookup")):typeof define=="function"&&define.amd?define(["exports","@turf/turf","moment","moment-timezone","tz-lookup"],I):(S=typeof globalThis<"u"?globalThis:S||self,I(S["idm-plugin-rabbitmq"]={},S["@turf/turf"],S.moment,S["moment-timezone"],S["tz-lookup"]))})(this,function(S,I,C,q,W){"use strict";function F(b){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(b){for(const t in b)if(t!=="default"){const n=Object.getOwnPropertyDescriptor(b,t);Object.defineProperty(e,t,n.get?n:{enumerable:!0,get:()=>b[t]})}}return e.default=b,Object.freeze(e)}const g=F(I);function O(b){return b&&b.__esModule&&Object.prototype.hasOwnProperty.call(b,"default")?b.default:b}class j{log(){}isLevelEnabled(){return!1}addContext(){}removeContext(){}clearContext(){}}["Trace","Debug","Info","Warn","Error","Fatal","Mark"].forEach(b=>{j.prototype[b.toLowerCase()]=()=>{},j.prototype[`is${b}Enabled`]=()=>!1});const L=(()=>{try{return require("log4js")}catch{return null}})();var E={getLogger:L?L.getLogger:()=>new j};const A=O(E);class l{static guessTimeZoneOffset(e,t){const n=W(t,e),i=C().tz(n).utcOffset();return this.roundPrecision(i/60,1)}static prettyTimeZoneOffset(e){let t=Math.floor(Math.abs(e)),n=Math.round((Math.abs(e)-t)*60);return n=n>9?n:`0${n}`,t=t>9?t:`0${t}`,e>0?`+${t}:${n}`:`-${t}:${n}`}static lng2pretty(e,t=6,n="H°M′"){e=l.convertToStdLng(e,t);let i="E";e<0&&(i="W"),e=Math.abs(e),n=n.toUpperCase();let o=e*3600,s,r,c,a,d,u;s=o%3600%60,n.indexOf("S")!==-1&&(o=o-s,r=l.padNumber(s,2,2)),c=o/60%60,n.indexOf("M")!==-1&&(n.indexOf("S")!==-1?a=l.roundPrecision(c,t).toString().padStart(2,"0"):a=l.padNumber(c,2,2),o=o-c*60),d=o/3600,n.indexOf("M")!==-1?u=l.roundPrecision(d,t).toString().padStart(3,"0"):u=l.padNumber(d,3,2);const p=`${n.replace(/S+/gi,r).replace(/M+/gi,a).replace(/H+/gi,u)}${i}`;return{direction:i,degree:l.roundPrecision(d,t),minute:l.roundPrecision(c,t),second:l.roundPrecision(s,t),pretty:p}}static lat2pretty(e,t=6,n="H°M′"){e=e%180;let i="N";e<0&&(i="S"),e=Math.abs(e),n=n.toUpperCase();let o=e*3600,s,r,c,a,d,u;s=o%3600%60,n.indexOf("S")!==-1&&(o=o-s,r=l.padNumber(s,2,2)),c=o/60%60,n.indexOf("M")!==-1&&(n.indexOf("S")!==-1?a=l.roundPrecision(c,t).toString().padStart(2,"0"):a=l.padNumber(c,2,2),o=o-c*60),d=o/3600,n.indexOf("M")!==-1?u=l.roundPrecision(d,t).toString().padStart(2,"0"):u=l.padNumber(d,2,2);const p=`${n.replace(/S+/gi,r).replace(/M+/gi,a).replace(/H+/gi,u)}${i}`;return{direction:i,degree:l.roundPrecision(d,t),minute:l.roundPrecision(c,t),second:l.roundPrecision(s,t),pretty:p}}static str2Lng(e,t=6){let n;if(isNaN(e)){e=l.strReplace(e,"LNG");const i=e[e.length-1].toUpperCase();e=e.substring(0,e.length-1).trim();const o=e.split(" ").filter(c=>c!=="").map(c=>Number(c));let[s,r]=o;if(r=r>60?r/Math.pow(10,String(r).length-2):r,s>360&&!r){const c=this.roundPrecision(s/100,0);r=s-c*100,s=c}n=s+(r??0)/60,i==="W"&&(n=n*-1)}else n=Number(e);return l.convertToStdLng(n,t)}static str2Lat(e,t=6){let n;if(isNaN(e)){e=l.strReplace(e,"LAT");const i=e[e.length-1].toUpperCase();e=e.substring(0,e.length-1).trim();const o=e.split(" ").filter(c=>c!=="").map(c=>Number(c));let[s,r]=o;if(r=r>60?r/Math.pow(10,String(r).length-2):r,s>90&&!r){const c=this.roundPrecision(s/100,0);r=s-c*100,s=c}n=s+(r??0)/60,i==="S"&&(n=n*-1)}else n=Number(e);return l.roundPrecision(n,t)}static str2LngOrLat(e,t=6,n="LAT"){e=l.strReplace(e,n);const i=e[e.length-1].toUpperCase();return["N","S"].includes(i)?{lat:l.str2Lat(e,t)}:{lng:l.str2Lng(e,t)}}static convertToStdLng(e,t=4){return e>180?(e=e%360,e=e>180?e-360:e):e<-180&&(e=e%360,e=e<-180?e+360:e),l.roundPrecision(e,t)}static roundPrecision(e,t=4){if(typeof e=="number"){const n=Number("1".padEnd(t+1,"0"));return Math.round(e*n)/n}return e}static convertToMonotonicLng2(e){for(let t=1;t<e.length;t++)e[t][0]+=Math.round((e[t-1][0]-e[t][0])/360)*360;return e}static convertToMonotonicLng(e){for(let t=1;t<e.length;t++)e[t].lng+=Math.round((e[t-1].lng-e[t].lng)/360)*360;return e}static strReplace(e,t="LAT"){e=e.replace(/([0-9]+)\.([0-9]+\.[0-9]+)/g,"$1 $2").replace(/-/g," ").replace(/°/," ").replace(/'/g," ").replace(/′/g," ").replace(/"/g," ").replace(/∼/g," ").replace(/°/g," ").replace(/,/g,".").replace(/^ /g,"").replace(/ $/g,"").trim();const n=e[e.length-1].toUpperCase();if(!["N","S","E","W"].includes(n)){const i=e,o=Number(i.split(" ")[0]);if(isNaN(o))throw new Error(`invalid Lat/Lng: ${e}`);o>=90?e=`${i}E`:o<=-90?e=`${i}W`:["LAN","LNG"].includes(t==null?void 0:t.toUpperCase())?e=`${i}${o>0?"E":"W"}`:e=`${i}${o>0?"N":"S"}`}return e}static padNumber(e,t=2,n=2){const i=Math.trunc(e).toString().padStart(t,"0"),o=Math.trunc(l.roundPrecision(e-Math.trunc(e),n)*Math.pow(10,n)).toString().padStart(n,"0");return`${i}.${o}`}}class D{static calculateBearing(e,t,n=!0,i=4){const o=g.points([[e.lng,e.lat],[t.lng,t.lat]]);let s;return n?s=g.rhumbBearing(o.features[0],o.features[1]):s=g.bearing(o.features[0],o.features[1]),s<0&&(s+=360),l.roundPrecision(s,i)}static calculateDistance(e,t,n=!0,i=4,o="nauticalmiles"){e={...e},t={...t},e.lng=l.convertToStdLng(e.lng,i),t.lng=l.convertToStdLng(t.lng,i);const s=g.points([[e.lng,e.lat],[t.lng,t.lat]]);let r;return n?r=g.rhumbDistance(s.features[0],s.features[1],{units:o}):r=g.distance(s.features[0],s.features[1],{units:o}),l.roundPrecision(r,i)}static calculateRouteDistance(e,t=4,n="nauticalmiles"){let i=0,o;for(const s of e)for(let r=0;r<s.length-1;r++){const c={lng:s[r][0],lat:s[r][1]};r===0&&o&&(i+=this.calculateDistance(o,c,!0,t,n));const a={lng:s[r+1][0],lat:s[r+1][1]};i+=this.calculateDistance(c,a,!0,t,n),o=a}return l.roundPrecision(i,t)}static calculateCoordinate(e,t,n,i="nauticalmiles",o=!0){const s=g.point([e.lng,e.lat]);let r;o?r=g.rhumbDestination(s,n,t,{units:i}):r=g.destination(s,n,t,{units:i});const c=r.geometry.coordinates;return{lng:l.convertToStdLng(c[0],8),lat:l.roundPrecision(c[1],8)}}static interpolateCoordinates(e,t,n,i=!0,o=!0,s="nauticalmiles"){const r=[],c=this.calculateBearing(e,t,!1),a=this.calculateDistance(e,t,!1,8,s);i&&r.push({lng:e.lng,lat:e.lat});let d=0;for(;d<a;)d+=n,d<a&&r.push(this.calculateCoordinate(e,c,d,s,!1));return o&&r.push({lng:t.lng,lat:t.lat}),r}static divideAccordingToLng(e,t=!1){if((e==null?void 0:e.length)<2)return[];e=this.deduplicateCoordinates(e);let n=[];const i=[];let o,s;for(let r=0;r<e.length-1;r++){o=l.convertToStdLng(e[r].lng,8),s=l.convertToStdLng(e[r+1].lng,8),n.push([o,e[r].lat]);const c=o-s;if(Math.abs(c)>180){const a=l.convertToMonotonicLng2([[o,e[r].lat],[s,e[r+1].lat]]);let d,u;t?(d=g.lineString(a),u=g.lineString([[c>0?180:-180,89],[c>0?180:-180,-89]])):(d=g.greatCircle(a[0],a[1]),u=g.greatCircle([c>0?180:-180,89],[c>0?180:-180,-89]));const p=g.lineIntersect(d,u);let h;if(p.features.length){const M=g.getCoord(p.features[0]);h=l.roundPrecision(M[1],8)}else h=e[r].lat;c>0?(n.push([180-1e-6,h]),i.push([...n]),n=[],n.push([-(180-1e-6),h])):(n.push([-(180-1e-6),h]),i.push([...n]),n=[],n.push([180-1e-6,h]))}r===e.length-2&&n.push([s,e[r+1].lat])}return i.push(n),i}static deduplicateRoute(e){const t=[];for(const n of e){const i=n.reduce((o,s)=>(o.findIndex(r=>r[0]===s[0]&&r[1]===s[1])===-1&&o.push(s),o),[]);t.push(i)}return t}static deduplicateCoordinates(e){return e.reduce((t,n)=>(t.findIndex(i=>i.lat===n.lat&&i.lng===n.lng)===-1&&t.push(n),t),[])}static removeCoordinateFromRoute(e,t){e.lng=l.convertToStdLng(e.lng,8);for(const n of t)for(let i=n.length-1;i>=0;i--)l.roundPrecision(n[i][0],8)===e.lng&&l.roundPrecision(n[i][1],8)===l.roundPrecision(e.lat,8)&&n.splice(i,1);return t}static removeCoordinateFromWaypoints(e,t){e.lng=l.convertToStdLng(e.lng,8);for(let n=t.length-1;n>=0;n--)l.roundPrecision(t[n].lng,8)===e.lng&&l.roundPrecision(t[n].lat,8)===l.roundPrecision(e.lat,8)&&t.splice(n,1);return t}static mergeCoordinateToRoute(e,t){e.lng=l.convertToStdLng(e.lng,8);let n=Number.MAX_VALUE,i=0,o=0,s,r;return t.forEach((c,a)=>{for(let d=0;d<c.length-1;d++){const u={lng:c[d][0],lat:c[d][1]},p={lng:c[d+1][0],lat:c[d+1][1]},h=this.calculatePointToLineDistance(e,u,p);n>h&&(n=h,o=d,i=a,s=this.calculateDistance(u,e),r=this.calculateDistance(p,e))}}),s!==0&&r!==0?t[i].splice(o+1,0,[e.lng,e.lat]):s===0?t[i].splice(o,1,[e.lng,e.lat]):r===0&&t[i].splice(o+1,1,[e.lng,e.lat]),t}static mergeWaypointsToRoute(e,t){for(const n of e)t=this.mergeCoordinateToRoute(n,t);return t}static calculateRangeRoute(e,t,n){n=this.mergeWaypointsToRoute([e,t],n);const i=[];let o=0;return n.forEach(s=>{if(o===2)return;const r=[];for(const c of s){if(l.roundPrecision(t.lng,8)===l.roundPrecision(c[0],8)&&l.roundPrecision(t.lat,8)===l.roundPrecision(c[1],8)){r.push(c),o===0&&r.push([e.lng,e.lat]),o=2;break}o===1?r.push(c):l.roundPrecision(e.lng,8)===l.roundPrecision(c[0],8)&&l.roundPrecision(e.lat,8)===l.roundPrecision(c[1],8)&&(o=1,r.push(c))}r.length&&i.push(r)}),i}static calculateRangeWaypoints(e,t,n,i=[]){const o=this.convertRouteToCoordinates(n,0),s=this.mergeCoordinatesToWaypoints([e,t,...i],o),r=s.findIndex(d=>l.roundPrecision(e.lng,8)===l.roundPrecision(d.lng,8)&&l.roundPrecision(e.lat,8)===l.roundPrecision(d.lat,8)),c=s.findIndex(d=>l.roundPrecision(t.lng,8)===l.roundPrecision(d.lng,8)&&l.roundPrecision(t.lat,8)===l.roundPrecision(d.lat,8));return s.filter((d,u)=>u>=r&&u<=c)}static calculateMinDistanceToRoute(e,t){let n=Number.MAX_VALUE,i=0,o=0;return t.forEach((s,r)=>{for(let c=0;c<s.length-1;c++){const a={lng:s[c][0],lat:s[c][1]},d={lng:s[c+1][0],lat:s[c+1][1]},u=this.calculatePointToLineDistance(e,a,d);n>u&&(n=u,i=c,o=r)}}),{minDist:n,segIndex:o,minIndex:i}}static calculateSubRoute(e,t){const{segIndex:n,minIndex:i}=this.calculateMinDistanceToRoute({...e},t);e.lng=l.convertToStdLng(e.lng);const o=[];let s=!0;for(let r=n;r<t.length;r++)if(s){const c=[];c.push([e.lng,e.lat]);for(let a=i+1;a<t[r].length;a++)e.lng===t[r][a][0]&&e.lat===t[r][a][1]||c.push(t[r][a]);o.push(c),s=!1}else o.push([...t[r]]);return o}static calculateSubWaypoints(e,t){let n=Number.MAX_VALUE,i=0;for(let s=0;s<t.length-1;s++){const r=t[s],c=t[s+1];if(this.calculateDistance(e,r)===0)return t;if(this.calculateDistance(e,c)===0)return t.filter((d,u)=>u>0);const a=this.calculatePointToLineDistance(e,r,c);n>a&&(n=a,i=s)}e.lng=l.convertToStdLng(e.lng);const o=[e];for(let s=i+1;s<t.length;s++)o.push(t[s]);return o}static calculatePointToLineDistance(e,t,n,i={units:"nauticalmiles",method:"geodesic"}){e.lng=l.convertToStdLng(e.lng),t={...t},n={...n},t.lng=l.convertToStdLng(t.lng,8),n.lng=l.convertToStdLng(n.lng,8);const o=l.convertToMonotonicLng([t,n]);t=o[0],n=o[1];const s=g.lineString([[t.lng,t.lat],[n.lng,n.lat]]),r=g.pointToLineDistance(g.point([e.lng,e.lat]),s,i),c=g.pointToLineDistance(g.point([e.lng>0?e.lng-360:e.lng+360,e.lat]),s,i);return l.roundPrecision(Math.min(r,c),6)}static calculateWaypointsPropInRoute(e,t){t=this.mergeWaypointsToRoute(e,t);for(let n=0;n<e.length-1;n++){const i=e[n],o=e[n+1],s=this.calculateRangeRoute(i,o,t);n===0&&(i.distanceFromPrevious=0,i.distanceFromStart=0),o.distanceFromPrevious=this.calculateRouteDistance(s),o.distanceFromStart=l.roundPrecision((i.distanceFromStart||0)+o.distanceFromPrevious)}return e}static mergeCoordinatesToWaypoints(e,t,n=!0){for(const i of e)this.mergeCoordinateToWaypoints(i,t,n);return t}static mergeCoordinateToWaypoints(e,t,n=!0){e.lng=l.convertToStdLng(e.lng,8);let i=Number.MAX_VALUE,o=0,s=0,r=0;for(let c=0;c<t.length-1;c++){const a={lng:t[c].lng,lat:t[c].lat},d={lng:t[c+1].lng,lat:t[c+1].lat},u=this.calculatePointToLineDistance(e,a,d);i>=u&&(i=u,o=c,s=this.calculateDistance(a,e,!1,6),r=this.calculateDistance(d,e,!1,6))}return s!==0&&r!==0?s<i||s===i&&o===0?t.unshift(e):r<i||r===i&&o===t.length-2?t.push(e):t.splice(o+1,0,e):s===0?n&&t.splice(o,1,e):r===0&&n&&t.splice(o+1,1,e),t.map(c=>(c.lng=l.convertToStdLng(c.lng),c))}static generateRouteAccordingToWaypoints(e){const t=[];for(let n=1;n<e.length;n++){const i=e[n-1],o=e[n];if(n===1&&t.push(i),o.gcToPrevious){const s=this.interpolateCoordinates(i,o,200,!1,!0,"nauticalmiles");t.push(...s)}else t.push(o)}return this.divideAccordingToLng(t,!0)}static nearestCoordinateInRoute(e,t){const n=g.point([e.lng,e.lat]),i=[];for(const c of t){const a=c.map(d=>g.point(d));i.push(...a)}const o=g.featureCollection(i),s=g.nearestPoint(n,o),r=g.getCoord(s);return{lng:r[0],lat:r[1]}}static calculatePrevWaypoint(e,t){let n=0;this.mergeCoordinateToWaypoints(e,t);for(let i=0;i<t.length-1;i++){const o=t[i],s=t[i+1];if(this.calculateDistance(e,o)===0){n=i;break}if(this.calculateDistance(e,s)===0){n=i+1;break}}return t[n===0?0:n-1]}static calculateNextCoordinateAlongRoute(e,t,n,i="nauticalmiles"){var p;const o=e.speed||12,s=[];let r=[],c=!1,a=0,d=0,u;if(t&&n.length?(s.push(e),n.forEach((h,M)=>{if(c)r.push(h);else{const T=[];let P;for(let m=0;m<h.length;m++)if(u)T.push(h[m]);else{P={lng:h[m][0],lat:h[m][1]};const f=this.calculateDistance(e,P,!0,8,i);if(a+=f,a<t)d+=f,s.push(P),e=P;else{if(d=t,a===t)u=P,T.push([u.lng,u.lat]);else{const v=a-t,R=this.calculateBearing(P,e);u=this.calculateCoordinate(P,R,v,i),T.push([u.lng,u.lat]),T.push([P.lng,P.lat])}c=!0}}T.length&&r.push(T),M===n.length-1&&!u&&(u=P)}})):(r=n,u={...e}),u)if(s.push(u),u.distanceFromPrevious=d,u.hourFromPrevious=Math.round(d/o*1e4)/1e4,((p=r[0])==null?void 0:p.length)>1){const h={lng:r[0][1][0],lat:r[0][1][1]};u.bearing=this.calculateBearing(u,h)}else u.bearing=0;return{coordinate:u,nextRoute:r,prevRoute:s}}static nearestCoordinateInLine(e,t,n){const i=l.convertToStdLng(e.lng,6),o=g.point([i,e.lat]),s=l.convertToStdLng(t.lng,6),r=l.convertToStdLng(n.lng,6),c=g.lineString([[s,t.lat],[r,n.lat]]),a=g.nearestPointOnLine(c,o),d=g.getCoord(a),u=l.roundPrecision(d[0],6),p=l.roundPrecision(d[1],6);return{lng:u,lat:p,inline:!(u===s&&p===t.lat)&&!(u===r&&p===n.lat)}}static convertRouteToCoordinates(e,t=0){const n=[];let i,o;return e.forEach(s=>{s.forEach(r=>{const c={lng:r[0],lat:r[1]};if(!o)n.push(c),o=c;else if(o.bearing===void 0)o.bearing=this.calculateBearing(o,c,!0);else{const a=this.calculateDistance(i,c,!0);a&&a>=t&&(i.bearing=this.calculateBearing(i,c,!0),n.push(i),o=i)}i=c})}),i&&n.push(i),n}static simplifyRouteToCoordinates(e,t,n=1){let i=this.convertRouteToCoordinates(e,n);return i=this.simplifyGCCoordinates(i,t),i}static simplifyGCCoordinates(e,t){t.forEach(i=>{this.mergeCoordinateToWaypoints(i,e)});for(let i=1;i<t.length;i++){const o=t[i-1],s=t[i];if(s.gcToPrevious){const r=e.findIndex(a=>a.lng===o.lng&&a.lat===o.lat),c=e.findIndex(a=>a.lng===s.lng&&a.lat===s.lat);for(let a=c-1;a>r;a--)e.splice(a,1)}}let n=0;for(let i=1;i<e.length;i++){const o=e[i-1],s=e[i];s.gcToPrevious?(o.bearing=this.calculateBearing(o,s,!1),s.distanceFromPrevious=this.calculateDistance(o,s,!1)):(o.bearing=this.calculateBearing(o,s,!0),s.distanceFromPrevious=this.calculateDistance(o,s,!0)),n=l.roundPrecision(n+s.distanceFromPrevious),s.distanceFromStart=n}return e.map(i=>(i.lng=l.convertToStdLng(i.lng),i))}static calculateCenter(e){const t=[];for(const r of e)for(const c of r)t.push(c);const n=g.featureCollection([]),i=l.convertToMonotonicLng2(t);for(const r of i)n.features.push(g.point(r));const s=g.center(n).geometry.coordinates;return{lng:l.convertToStdLng(s[0],8),lat:l.roundPrecision(s[1],8)}}static calculateCenter2(e){const t=this.generateRouteAccordingToWaypoints(e);return this.calculateCenter(t)}static calculateBBox(e){const t=[];for(const o of e)for(const s of o)t.push(s);const n=l.convertToMonotonicLng2(t),i=g.lineString(n);return g.bbox(i)}static calculateBBox2(e){const t=this.generateRouteAccordingToWaypoints(e);return this.calculateBBox(t)}}const y=A.getLogger("vessel");class B{static convert2Geojson(e){var n;const t=g.featureCollection([]);for(const i of e){if(i.forecasts){const o=(n=i.history)==null?void 0:n[0];for(const s of i.forecasts){const r=[],c=C(s.date).utc(),a=`${i.name}-${s.model}`;if(o){const d=C(o.updated).utc(),u=g.point([o.lng,o.lat],{model:s.model,name:i.name,date:d.format(),hour:0,format:d.format("MMM-DD/HHmm[Z]"),pressure:o.pressure>1e4?l.roundPrecision(o.pressure/100,0):l.roundPrecision(o.pressure,0),wind:{kts:o.kts,spd:o.speed||o.spd},category:a,type:"forecast"});t.features.push(u),r.push(u.geometry.coordinates)}for(const d in s==null?void 0:s.hours){const u=s.hours[d];u.wind.spd=u.wind.spd||u.wind.speed;const p=c.clone().add(Number(d),"hour"),h=g.point([u.lng,u.lat],{model:s.model,name:i.name,date:p.format(),hour:Number(d),format:p.format("MMM-DD/HHmm[Z]"),pressure:u.pressure>1e4?l.roundPrecision(u.pressure/100,0):l.roundPrecision(u.pressure,0),gusts:u.gusts,wind:u.wind||{},movement:u.movement,category:a,type:"forecast"});t.features.push(h),r.push(h.geometry.coordinates)}if((r==null?void 0:r.length)>1){const d=g.lineString(l.convertToMonotonicLng2(r),{date:s.date,id:i.id||i.name,model:s.model,name:i.name,category:a,type:"forecast"});t.features.push(d)}}}if(i.history){const o=[];for(const r of i.history){const c=C(r.updated).utc(),a=g.point([r.lng,r.lat],{name:i.name,date:c.format(),format:c.format("MMM-DD/HHmm[Z]"),pressure:r.pressure>1e4?l.roundPrecision(r.pressure/100,0):l.roundPrecision(r.pressure,0),spd:r.speed||r.spd,kts:r.kts,source:r.source,level:r.type,type:"history",category:`${i.name}-history`});t.features.push(a),o.push(a.geometry.coordinates)}const s=i.history[0];if(o.length===1&&o.push(o[0]),o.length>1){const r=g.lineString(l.convertToMonotonicLng2(o),{name:i.name,type:"history",updated:s==null?void 0:s.updated,pressure:(s==null?void 0:s.pressure)>1e4?l.roundPrecision((s==null?void 0:s.pressure)/100,0):l.roundPrecision(s==null?void 0:s.pressure,0),spd:(s==null?void 0:s.speed)||(s==null?void 0:s.spd),kts:s==null?void 0:s.kts,source:s==null?void 0:s.source,level:s==null?void 0:s.type});t.features.push(r)}}}return t}static interpolate(e,t=3){var o,s,r,c;const n=(o=e==null?void 0:e.data)==null?void 0:o.features.filter(a=>a.geometry.type==="LineString"&&a.properties.type==="forecast"),i=[];for(const a of n){const d=a.properties.name,u=a.properties.model,p=C(a.properties.date).utc();let h=t*60-(p.get("hour")*60+p.get("minute"))%(t*60);const M=(s=e==null?void 0:e.data)==null?void 0:s.features.filter(m=>m.geometry.type==="Point"&&m.properties.type==="forecast"&&m.properties.category===`${d}-${u}`);let T,P=p.clone().add(h,"minute").set({minute:0,second:0,millisecond:0});for(;T=this.pickIndex(M,P),T<=M.length-1;){if(T>0){const m=M[T],f=T===0?void 0:M[T-1],v=(h/60-((r=f==null?void 0:f.properties)==null?void 0:r.hour))/(m.properties.hour-((c=f==null?void 0:f.properties)==null?void 0:c.hour)),R=this.computeNumber(f==null?void 0:f.geometry.coordinates[0],m.geometry.coordinates[0],v),x=this.computeNumber(f==null?void 0:f.geometry.coordinates[1],m.geometry.coordinates[1],v),$=g.point([R,x],{name:d,model:u,category:m==null?void 0:m.properties.category,date:P.format(),format:P.format("MMM-DD/HHmm[Z]"),gusts:this.computeNumber(f==null?void 0:f.properties.gusts,m.properties.gusts,v),hour:this.computeNumber(f==null?void 0:f.properties.hour,m.properties.hour,v),movement:this.computeNumber(f==null?void 0:f.properties.movement,m.properties.movement,v),pressure:this.computeNumber(f==null?void 0:f.properties.pressure,m.properties.pressure,v),wind:this.computeNumber(f==null?void 0:f.properties.wind,m.properties.wind,v),type:"forecast"});i.push($)}h+=t*60,P=p.clone().add(h,"minute").set({minute:0,second:0,millisecond:0})}}return i}static deviationPassageAt(e,t,n,i,o={requestId:""}){var d,u,p,h,M,T,P,m,f;const s=(u=(d=t==null?void 0:t.forecasts)==null?void 0:d[0])==null?void 0:u.hours,r=((p=t==null?void 0:t.history)==null?void 0:p[0])||(s==null?void 0:s[(h=Object.keys(s))==null?void 0:h[0]]);y.info("[%s] the first evasion point: %j",o.requestId,r);const c=(M=Object.keys(s||{}).filter(v=>Number(v)<=24))==null?void 0:M.at(-1),a=s==null?void 0:s[c||-1];if(y.info("[%s] the second evasion point in %s hrs: %j",o.requestId,c,r),r&&a){const v=D.calculateBearing(e,r),R=D.calculateBearing(r,a),x=D.calculateCoordinate(r,v-R+90,n);y.info("[%s] the right tangent point: %j",o.requestId,{from:e,p1:r,p2:a,radius:n,bearing1:v,bearing2:R,right:x});const $=D.calculateBearing(e,x);let N=D.calculateCoordinate(e,$,i*Number(c));N.utc=C((P=(T=t==null?void 0:t.forecasts)==null?void 0:T[0])==null?void 0:P.date).add(Number(c),"hours").utc().format(),y.info("[%s] the temp evasion point: %j",o.requestId,N);const k=D.calculateDistance(N,a);return y.info("[%s] the distance(%d) between tmp & p2: %j - %j",o.requestId,k,N,a),k<n&&(N=D.calculateCoordinate(e,$,i*Number(c)/2),N.utc=C((f=(m=t==null?void 0:t.forecasts)==null?void 0:m[0])==null?void 0:f.date).add(Number(c)/2,"hours").utc().format(),y.warn("[%s] tmp is too close to p2, replace with 1/2 position: %j",o.requestId,N)),N}else{y.info("[%s] no need evasion: %j",o.requestId,{from:e,p1:r,p2:a});return}}static pickIndex(e,t){let n=0;for(const i of e){if(C(i.properties.date).isAfter(t))return n===0?-1:n;n++}return n}static computeNumber(e,t,n){if(e)if(t){if(isNaN(e)&&isNaN(t)&&typeof e!="string"&&typeof t!="string"){const i={};for(const o in e)i[o]=this.computeNumber(e[o],t[o],n);return i}return Math.round((e+(t-e)*n)*100)/100}else return e;else return t}}S.LaneHelper=D,S.LngLatHelper=l,S.TropicalHelper=B,Object.defineProperty(S,Symbol.toStringTag,{value:"Module"})});
|
package/dist/lane/src/index.d.ts
CHANGED
|
@@ -261,17 +261,6 @@ export declare class LaneHelper {
|
|
|
261
261
|
* @param waypoints
|
|
262
262
|
*/
|
|
263
263
|
static simplifyGCCoordinates(coordinates: Coordinate[], waypoints: Coordinate[]): Coordinate[];
|
|
264
|
-
/**
|
|
265
|
-
* 近似计算右切线
|
|
266
|
-
* @param coord {lat, lng}
|
|
267
|
-
* @param center {lat, lng}
|
|
268
|
-
* @param radius
|
|
269
|
-
* @param units
|
|
270
|
-
*/
|
|
271
|
-
static calculateRightTangent(coord: Coordinate, center: Coordinate, radius?: number, units?: any): {
|
|
272
|
-
lng: number;
|
|
273
|
-
lat: number;
|
|
274
|
-
};
|
|
275
264
|
/**
|
|
276
265
|
* 计算轨迹中心点
|
|
277
266
|
* @param route
|
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
import * as turf from '@turf/turf';
|
|
2
2
|
export declare class TropicalHelper {
|
|
3
|
+
/**
|
|
4
|
+
* 将原始数据转换为geojson
|
|
5
|
+
* @param raw
|
|
6
|
+
*/
|
|
3
7
|
static convert2Geojson(raw: {
|
|
4
8
|
id: string;
|
|
5
9
|
name: string;
|
|
6
10
|
forecasts: any[];
|
|
7
11
|
history: any[];
|
|
8
12
|
}[]): turf.helpers.FeatureCollection<turf.helpers.Geometry, turf.helpers.Properties>;
|
|
13
|
+
/**
|
|
14
|
+
* 插值台风预报轨迹
|
|
15
|
+
* @param tropicals
|
|
16
|
+
* @param step
|
|
17
|
+
*/
|
|
9
18
|
static interpolate(tropicals: any, step?: number): turf.helpers.Feature<turf.helpers.Point, {
|
|
10
19
|
name: any;
|
|
11
20
|
model: any;
|
|
@@ -19,6 +28,20 @@ export declare class TropicalHelper {
|
|
|
19
28
|
wind: any;
|
|
20
29
|
type: string;
|
|
21
30
|
}>[];
|
|
31
|
+
/**
|
|
32
|
+
* 航行方向与台风
|
|
33
|
+
* @param from
|
|
34
|
+
* @param tropical
|
|
35
|
+
* @param radius
|
|
36
|
+
* @param speed
|
|
37
|
+
* @param options
|
|
38
|
+
*/
|
|
39
|
+
static deviationPassageAt(from: {
|
|
40
|
+
lat: number;
|
|
41
|
+
lng: number;
|
|
42
|
+
}, tropical: any, radius: number, speed: number, options?: {
|
|
43
|
+
requestId: string;
|
|
44
|
+
}): any;
|
|
22
45
|
private static pickIndex;
|
|
23
46
|
private static computeNumber;
|
|
24
47
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@idm-plugin/geo",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "1.1.
|
|
4
|
+
"version": "1.1.2",
|
|
5
5
|
"description": "idm plugin for geo",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"keywords": [
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"release": "yarn build && yarn publish --access public"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
+
"@log4js-node/log4js-api": "^1.0.2",
|
|
30
31
|
"@turf/turf": "^6.5.0",
|
|
31
|
-
"log4js": "^6.9.1",
|
|
32
32
|
"moment": "^2.30.1",
|
|
33
33
|
"moment-timezone": "^0.5.45",
|
|
34
34
|
"tz-lookup": "^6.1.25"
|