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