@idm-plugin/geo 2.0.2 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +170 -163
- package/dist/index.umd.cjs +3 -3
- package/dist/lane/src/index.d.ts +2 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as S from "@turf/turf";
|
|
2
2
|
import u from "moment";
|
|
3
3
|
import j from "@log4js-node/log4js-api";
|
|
4
4
|
var n0 = typeof globalThis < "u" ? globalThis : typeof window < "u" ? window : typeof global < "u" ? global : typeof self < "u" ? self : {};
|
|
@@ -31,7 +31,7 @@ var x = { exports: {} };
|
|
|
31
31
|
U = U / 60, E = R(e.charCodeAt(n)), t += E * U;
|
|
32
32
|
return t * Z;
|
|
33
33
|
}
|
|
34
|
-
function
|
|
34
|
+
function N(o) {
|
|
35
35
|
for (var n = 0; n < o.length; n++)
|
|
36
36
|
o[n] = T(o[n]);
|
|
37
37
|
}
|
|
@@ -40,7 +40,7 @@ var x = { exports: {} };
|
|
|
40
40
|
o[X] = Math.round((o[X - 1] || 0) + o[X] * 6e4);
|
|
41
41
|
o[n - 1] = 1 / 0;
|
|
42
42
|
}
|
|
43
|
-
function
|
|
43
|
+
function f(o, n) {
|
|
44
44
|
var X = [], L;
|
|
45
45
|
for (L = 0; L < n.length; L++)
|
|
46
46
|
X[L] = o[n[L]];
|
|
@@ -48,10 +48,10 @@ var x = { exports: {} };
|
|
|
48
48
|
}
|
|
49
49
|
function s(o) {
|
|
50
50
|
var n = o.split("|"), X = n[2].split(" "), L = n[3].split(""), e = n[4].split(" ");
|
|
51
|
-
return
|
|
51
|
+
return N(X), N(L), N(e), i(e, L.length), {
|
|
52
52
|
name: n[0],
|
|
53
|
-
abbrs:
|
|
54
|
-
offsets:
|
|
53
|
+
abbrs: f(n[1].split(" "), L),
|
|
54
|
+
offsets: f(X, L),
|
|
55
55
|
untils: e,
|
|
56
56
|
population: n[5] | 0
|
|
57
57
|
};
|
|
@@ -134,7 +134,7 @@ var x = { exports: {} };
|
|
|
134
134
|
}
|
|
135
135
|
function b0(o, n) {
|
|
136
136
|
var X, L;
|
|
137
|
-
for (
|
|
137
|
+
for (N(n), X = 0; X < n.length; X++)
|
|
138
138
|
L = n[X], A[L] = A[L] || {}, A[L][o] = !0;
|
|
139
139
|
}
|
|
140
140
|
function p0(o) {
|
|
@@ -1135,8 +1135,8 @@ const L0 = "2025b", T0 = [
|
|
|
1135
1135
|
links: i0,
|
|
1136
1136
|
countries: e0
|
|
1137
1137
|
};
|
|
1138
|
-
var
|
|
1139
|
-
|
|
1138
|
+
var S0 = R0;
|
|
1139
|
+
S0.tz.load(N0);
|
|
1140
1140
|
var M0 = { exports: {} };
|
|
1141
1141
|
(function(m) {
|
|
1142
1142
|
function M(z, b) {
|
|
@@ -1152,8 +1152,8 @@ var M0 = { exports: {} };
|
|
|
1152
1152
|
}
|
|
1153
1153
|
m.exports = M;
|
|
1154
1154
|
})(M0);
|
|
1155
|
-
var
|
|
1156
|
-
const r0 = /* @__PURE__ */ X0(
|
|
1155
|
+
var f0 = M0.exports;
|
|
1156
|
+
const r0 = /* @__PURE__ */ X0(f0);
|
|
1157
1157
|
class a {
|
|
1158
1158
|
/**
|
|
1159
1159
|
* 基于输入的经度,计算出时区
|
|
@@ -1308,6 +1308,75 @@ class a {
|
|
|
1308
1308
|
return p >= 1 ? c : b > 0 ? `${c}.${Math.trunc(p * Math.pow(10, b)).toString().padStart(b, "0")}` : c;
|
|
1309
1309
|
}
|
|
1310
1310
|
}
|
|
1311
|
+
class B0 {
|
|
1312
|
+
static json2Str(M) {
|
|
1313
|
+
const z = M.type ? M.type[0].toUpperCase() : "A";
|
|
1314
|
+
return `${M.lat}|${M.lng}|${M.positionTime}|${M.sog}|${M.cog}|${M.hdg}|${M.draught}|${z}|${JSON.stringify(M.meteo || {})}|${M.vendor}|${M.deleted}`;
|
|
1315
|
+
}
|
|
1316
|
+
static str2Json(M) {
|
|
1317
|
+
const [z, b, p, c, O, A, W, q, Y, d, R] = M.split("|");
|
|
1318
|
+
return {
|
|
1319
|
+
lat: Number(z),
|
|
1320
|
+
lng: Number(b),
|
|
1321
|
+
positionTime: Number(p),
|
|
1322
|
+
sog: Number(c),
|
|
1323
|
+
cog: Number(O),
|
|
1324
|
+
hdg: Number(A),
|
|
1325
|
+
//@ts-ignore
|
|
1326
|
+
draught: isNaN(W) ? null : Number(W),
|
|
1327
|
+
type: q,
|
|
1328
|
+
important: q !== "A",
|
|
1329
|
+
meteo: Y ? JSON.parse(Y) : void 0,
|
|
1330
|
+
vendor: d,
|
|
1331
|
+
deleted: R === "true"
|
|
1332
|
+
};
|
|
1333
|
+
}
|
|
1334
|
+
static inspectStoppages(M, z = 1, b = !0) {
|
|
1335
|
+
const p = M.at(0).positionTime < M.at(-1).positionTime;
|
|
1336
|
+
p || M.sort((W, q) => W.positionTime - q.positionTime);
|
|
1337
|
+
const c = [];
|
|
1338
|
+
let O, A;
|
|
1339
|
+
for (let W = 0; W < M.length - 1; W++) {
|
|
1340
|
+
const q = M[W];
|
|
1341
|
+
if (!(b && ["N", "B", "E", "NOON", "BOSP", "EOSP"].includes(q.type))) {
|
|
1342
|
+
for (let Y = W + 1; Y < M.length; Y++) {
|
|
1343
|
+
const d = M[Y - 1], R = M[Y];
|
|
1344
|
+
if (b && ["N", "B", "E", "NOON", "BOSP", "EOSP"].includes(q.type))
|
|
1345
|
+
continue;
|
|
1346
|
+
const T = R.positionTime - d.positionTime;
|
|
1347
|
+
if (r.calculateDistance(R, d, !0, 4) / (T / 3600) < z)
|
|
1348
|
+
O || (O = q), Y === M.length - 1 && (A = R, W = Y);
|
|
1349
|
+
else {
|
|
1350
|
+
O && (A = M[Y - 1], W = Y);
|
|
1351
|
+
break;
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
if ((A == null ? void 0 : A.positionTime) > (O == null ? void 0 : O.positionTime) && O) {
|
|
1355
|
+
const Y = {
|
|
1356
|
+
start: {
|
|
1357
|
+
lat: O.lat,
|
|
1358
|
+
lng: O.lng,
|
|
1359
|
+
sog: O.sog,
|
|
1360
|
+
positionTime: O.positionTime,
|
|
1361
|
+
utc: u.unix(O.positionTime).utc().format()
|
|
1362
|
+
},
|
|
1363
|
+
end: {
|
|
1364
|
+
lat: A.lat,
|
|
1365
|
+
lng: A.lng,
|
|
1366
|
+
sog: A.sog,
|
|
1367
|
+
positionTime: A.positionTime,
|
|
1368
|
+
utc: u.unix(A.positionTime).utc().format()
|
|
1369
|
+
},
|
|
1370
|
+
duration: A.positionTime - O.positionTime
|
|
1371
|
+
}, d = M.filter((T) => T.positionTime >= Y.start.positionTime && T.positionTime <= Y.end.positionTime), R = r.divideAccordingToLng(d);
|
|
1372
|
+
Y.distance = r.calculateRouteDistance(R), Y.hours = Math.round(Y.duration / 3600 * 10) / 10, Y.avgSog = Math.round(Y.distance / Y.hours * 10) / 10, c.push(Y);
|
|
1373
|
+
}
|
|
1374
|
+
O = void 0, A = void 0;
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
return p || M.sort((W, q) => q.positionTime - W.positionTime), c;
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1311
1380
|
let Q;
|
|
1312
1381
|
try {
|
|
1313
1382
|
Q = j.getLogger("meteo");
|
|
@@ -1324,12 +1393,12 @@ class r {
|
|
|
1324
1393
|
* @returns {number} 单位度
|
|
1325
1394
|
*/
|
|
1326
1395
|
static calculateBearing(M, z, b = !0, p = 4) {
|
|
1327
|
-
const c =
|
|
1396
|
+
const c = S.points([
|
|
1328
1397
|
[M.lng, M.lat],
|
|
1329
1398
|
[z.lng, z.lat]
|
|
1330
1399
|
]);
|
|
1331
1400
|
let O;
|
|
1332
|
-
return b ? O =
|
|
1401
|
+
return b ? O = S.rhumbBearing(c.features[0], c.features[1]) : O = S.bearing(c.features[0], c.features[1]), O < 0 && (O += 360), a.roundPrecision(O, p);
|
|
1333
1402
|
}
|
|
1334
1403
|
/**
|
|
1335
1404
|
* 计算两点间距离
|
|
@@ -1342,12 +1411,12 @@ class r {
|
|
|
1342
1411
|
*/
|
|
1343
1412
|
static calculateDistance(M, z, b = !0, p = 4, c = "nauticalmiles") {
|
|
1344
1413
|
M = { ...M }, z = { ...z }, M.lng = a.convertToStdLng(M.lng, p), z.lng = a.convertToStdLng(z.lng, p);
|
|
1345
|
-
const O =
|
|
1414
|
+
const O = S.points([
|
|
1346
1415
|
[M.lng, M.lat],
|
|
1347
1416
|
[z.lng, z.lat]
|
|
1348
1417
|
]);
|
|
1349
1418
|
let A;
|
|
1350
|
-
return b ? A =
|
|
1419
|
+
return b ? A = S.rhumbDistance(O.features[0], O.features[1], { units: c }) : A = S.distance(O.features[0], O.features[1], { units: c }), a.roundPrecision(A, p);
|
|
1351
1420
|
}
|
|
1352
1421
|
/**
|
|
1353
1422
|
* 计算航线距离
|
|
@@ -1375,9 +1444,9 @@ class r {
|
|
|
1375
1444
|
* @param rhumb
|
|
1376
1445
|
*/
|
|
1377
1446
|
static calculateCoordinate(M, z, b, p = "nauticalmiles", c = !0) {
|
|
1378
|
-
const O =
|
|
1447
|
+
const O = S.point([M.lng, M.lat]);
|
|
1379
1448
|
let A;
|
|
1380
|
-
c ? A =
|
|
1449
|
+
c ? A = S.rhumbDestination(O, b, z, { units: p }) : A = S.destination(O, b, z, { units: p });
|
|
1381
1450
|
const W = A.geometry.coordinates;
|
|
1382
1451
|
return { lng: a.convertToStdLng(W[0], 8), lat: a.roundPrecision(W[1], 8) };
|
|
1383
1452
|
}
|
|
@@ -1426,18 +1495,18 @@ class r {
|
|
|
1426
1495
|
[A, M[W + 1].lat]
|
|
1427
1496
|
]);
|
|
1428
1497
|
let d, R;
|
|
1429
|
-
z ? (d =
|
|
1498
|
+
z ? (d = S.lineString(Y), R = S.lineString([
|
|
1430
1499
|
[q > 0 ? 180 : -180, 89],
|
|
1431
1500
|
[q > 0 ? 180 : -180, -89]
|
|
1432
|
-
])) : (d =
|
|
1433
|
-
const T =
|
|
1434
|
-
let
|
|
1501
|
+
])) : (d = S.greatCircle(Y[0], Y[1]), R = S.greatCircle([q > 0 ? 180 : -180, 89], [q > 0 ? 180 : -180, -89]));
|
|
1502
|
+
const T = S.lineIntersect(d, R);
|
|
1503
|
+
let N;
|
|
1435
1504
|
if (T.features.length) {
|
|
1436
|
-
const i =
|
|
1437
|
-
|
|
1505
|
+
const i = S.getCoord(T.features[0]);
|
|
1506
|
+
N = a.roundPrecision(i[1], 8);
|
|
1438
1507
|
} else
|
|
1439
|
-
|
|
1440
|
-
q > 0 ? (p.push([180 - 1e-6,
|
|
1508
|
+
N = M[W].lat;
|
|
1509
|
+
q > 0 ? (p.push([180 - 1e-6, N]), c.push([...p]), p = [], p.push([-(180 - 1e-6), N])) : (p.push([-(180 - 1e-6), N]), c.push([...p]), p = [], p.push([180 - 1e-6, N]));
|
|
1441
1510
|
}
|
|
1442
1511
|
W === M.length - 2 && p.push([A, M[W + 1].lat]);
|
|
1443
1512
|
}
|
|
@@ -1648,10 +1717,10 @@ class r {
|
|
|
1648
1717
|
M.lng = a.convertToStdLng(M.lng, 8), z = { ...z }, b = { ...b }, z.lng = a.convertToStdLng(z.lng, 8), b.lng = a.convertToStdLng(b.lng, 8);
|
|
1649
1718
|
const c = a.convertToMonotonicLng([z, b]);
|
|
1650
1719
|
z = c[0], b = c[1];
|
|
1651
|
-
const O =
|
|
1720
|
+
const O = S.lineString([
|
|
1652
1721
|
[z.lng, z.lat],
|
|
1653
1722
|
[b.lng, b.lat]
|
|
1654
|
-
]), A =
|
|
1723
|
+
]), A = S.pointToLineDistance(S.point([M.lng, M.lat]), O, p), W = S.pointToLineDistance(S.point([M.lng > 0 ? M.lng - 360 : M.lng + 360, M.lat]), O, p);
|
|
1655
1724
|
return a.roundPrecision(Math.min(A, W), 6);
|
|
1656
1725
|
}
|
|
1657
1726
|
/**
|
|
@@ -1736,7 +1805,7 @@ class r {
|
|
|
1736
1805
|
* @param route [[[lng, lat]]]
|
|
1737
1806
|
*/
|
|
1738
1807
|
static nearestCoordinateInRoute(M, z) {
|
|
1739
|
-
const b =
|
|
1808
|
+
const b = S.point([M.lng, M.lat]), c = this.convertRouteToCoordinates(z).map((q) => [q.lng, q.lat]), O = S.lineString(c), A = S.nearestPointOnLine(O, b), W = S.getCoord(A);
|
|
1740
1809
|
return { lng: a.roundPrecision(W[0], 8), lat: a.roundPrecision(W[1], 8) };
|
|
1741
1810
|
}
|
|
1742
1811
|
/**
|
|
@@ -1772,31 +1841,31 @@ class r {
|
|
|
1772
1841
|
var R;
|
|
1773
1842
|
const c = M.speed || 12, O = [];
|
|
1774
1843
|
let A = [], W = !1, q = 0, Y = 0, d;
|
|
1775
|
-
if (z && b.length ? (O.push(M), b.forEach((T,
|
|
1844
|
+
if (z && b.length ? (O.push(M), b.forEach((T, N) => {
|
|
1776
1845
|
if (W)
|
|
1777
1846
|
A.push(T);
|
|
1778
1847
|
else {
|
|
1779
1848
|
const i = [];
|
|
1780
|
-
let
|
|
1849
|
+
let f;
|
|
1781
1850
|
for (let s = 0; s < T.length; s++)
|
|
1782
1851
|
if (d)
|
|
1783
1852
|
i.push(T[s]);
|
|
1784
1853
|
else {
|
|
1785
|
-
|
|
1786
|
-
const P = this.calculateDistance(M,
|
|
1854
|
+
f = { lng: T[s][0], lat: T[s][1] };
|
|
1855
|
+
const P = this.calculateDistance(M, f, !0, 8, p);
|
|
1787
1856
|
if (q += P, q < z)
|
|
1788
|
-
Y += P, P && O.push(
|
|
1857
|
+
Y += P, P && O.push(f), M = f;
|
|
1789
1858
|
else {
|
|
1790
1859
|
if (Y = z, q === z)
|
|
1791
|
-
d =
|
|
1860
|
+
d = f, i.push([d.lng, d.lat]);
|
|
1792
1861
|
else {
|
|
1793
|
-
const l = q - z, B = this.calculateBearing(
|
|
1794
|
-
d = this.calculateCoordinate(
|
|
1862
|
+
const l = q - z, B = this.calculateBearing(f, M);
|
|
1863
|
+
d = this.calculateCoordinate(f, B, l, p), i.push([d.lng, d.lat]), i.push([f.lng, f.lat]);
|
|
1795
1864
|
}
|
|
1796
1865
|
W = !0;
|
|
1797
1866
|
}
|
|
1798
1867
|
}
|
|
1799
|
-
i.length && A.push(i),
|
|
1868
|
+
i.length && A.push(i), N === b.length - 1 && !d && (d = f);
|
|
1800
1869
|
}
|
|
1801
1870
|
})) : (A = b, d = { ...M }), d)
|
|
1802
1871
|
if (O.push(d), d.distanceFromPrevious = Math.round(Y * 1e4) / 1e4, d.hourFromPrevious = Math.round(Y / c * 1e4) / 1e4, ((R = A[0]) == null ? void 0 : R.length) > 1) {
|
|
@@ -1813,10 +1882,10 @@ class r {
|
|
|
1813
1882
|
* @param to {lng, lat}
|
|
1814
1883
|
*/
|
|
1815
1884
|
static nearestCoordinateInLine(M, z, b) {
|
|
1816
|
-
const p = a.convertToStdLng(M.lng, 6), c =
|
|
1885
|
+
const p = a.convertToStdLng(M.lng, 6), c = S.point([p, M.lat]), O = a.convertToStdLng(z.lng, 6), A = a.convertToStdLng(b.lng, 6), W = S.lineString([
|
|
1817
1886
|
[O, z.lat],
|
|
1818
1887
|
[A, b.lat]
|
|
1819
|
-
]), q =
|
|
1888
|
+
]), q = S.nearestPointOnLine(W, c), Y = S.getCoord(q), d = a.roundPrecision(Y[0], 6), R = a.roundPrecision(Y[1], 6);
|
|
1820
1889
|
return { lng: d, lat: R, inline: !(d === O && R === z.lat) && !(d === A && R === b.lat) };
|
|
1821
1890
|
}
|
|
1822
1891
|
/**
|
|
@@ -1885,10 +1954,10 @@ class r {
|
|
|
1885
1954
|
for (const A of M)
|
|
1886
1955
|
for (const W of A)
|
|
1887
1956
|
z.push(W);
|
|
1888
|
-
const b =
|
|
1957
|
+
const b = S.featureCollection([]), p = a.convertToMonotonicLng2(z);
|
|
1889
1958
|
for (const A of p)
|
|
1890
|
-
b.features.push(
|
|
1891
|
-
const O =
|
|
1959
|
+
b.features.push(S.point(A));
|
|
1960
|
+
const O = S.center(b).geometry.coordinates;
|
|
1892
1961
|
return { lng: a.convertToStdLng(O[0], 8), lat: a.roundPrecision(O[1], 8) };
|
|
1893
1962
|
}
|
|
1894
1963
|
/**
|
|
@@ -1908,8 +1977,8 @@ class r {
|
|
|
1908
1977
|
for (const c of M)
|
|
1909
1978
|
for (const O of c)
|
|
1910
1979
|
z.push(O);
|
|
1911
|
-
const b = a.convertToMonotonicLng2(z), p =
|
|
1912
|
-
return
|
|
1980
|
+
const b = a.convertToMonotonicLng2(z), p = S.lineString(b);
|
|
1981
|
+
return S.bbox(p);
|
|
1913
1982
|
}
|
|
1914
1983
|
/**
|
|
1915
1984
|
* 计算BBox
|
|
@@ -1931,8 +2000,8 @@ class r {
|
|
|
1931
2000
|
const O = M[c - 1], A = M[c], W = M[c + 1];
|
|
1932
2001
|
let q = !1, Y = !1;
|
|
1933
2002
|
if ((O.velocity || O.suspend || O.important || O.pilot || c === 1) && (q = !0, p.push(O)), A.gcToPrevious && (q || (q = !0, p.push(O)), Y = !0, p.push(A), c++), W) {
|
|
1934
|
-
const d = r.calculateDistance(O, A, !0), R = r.calculateDistance(A, W, !0), T = r.calculateDistance(O, W, !0),
|
|
1935
|
-
Math.round(Math.acos(
|
|
2003
|
+
const d = r.calculateDistance(O, A, !0), R = r.calculateDistance(A, W, !0), T = r.calculateDistance(O, W, !0), N = (Math.pow(d, 2) + Math.pow(R, 2) - Math.pow(T, 2)) / (2 * d * R);
|
|
2004
|
+
Math.round(Math.acos(N) * 180 / Math.PI) < b && T > z && !Y && (p.push(A), c++);
|
|
1936
2005
|
}
|
|
1937
2006
|
if (c >= M.length - 1) {
|
|
1938
2007
|
const d = M.at(-1);
|
|
@@ -2031,6 +2100,7 @@ class r {
|
|
|
2031
2100
|
/**
|
|
2032
2101
|
* 路径摘要
|
|
2033
2102
|
* @param coordinates 已排序的坐标
|
|
2103
|
+
* @param slowSpd 排出停航时间
|
|
2034
2104
|
* @return {
|
|
2035
2105
|
* begin: string, // 开始时间
|
|
2036
2106
|
* end: string, // 结束时间
|
|
@@ -2039,15 +2109,21 @@ class r {
|
|
|
2039
2109
|
* avgSpeed: number // 平均航速,单位节
|
|
2040
2110
|
* }
|
|
2041
2111
|
*/
|
|
2042
|
-
static coordinatesSummary(M) {
|
|
2112
|
+
static coordinatesSummary(M, z = 3) {
|
|
2043
2113
|
if (M.length > 1) {
|
|
2044
|
-
const
|
|
2114
|
+
const b = M[0], p = M[M.length - 1], c = (b == null ? void 0 : b.positionTime) < (p == null ? void 0 : p.positionTime) ? u.unix(b == null ? void 0 : b.positionTime) : u.unix(p == null ? void 0 : p.positionTime), O = (b == null ? void 0 : b.positionTime) > (p == null ? void 0 : p.positionTime) ? u.unix(b == null ? void 0 : b.positionTime) : u.unix(p == null ? void 0 : p.positionTime), A = Math.round(O.diff(c, "hours", !0) * 100) / 100, W = this.generateRouteAccordingToWaypoints(M, !0, !0), q = this.calculateRouteDistance(W), d = B0.inspectStoppages(M, z).reduce(
|
|
2115
|
+
(T, N) => (T.duration += N.duration, T.distance += N.distance, T),
|
|
2116
|
+
{ hours: 0, distance: 0, spd: 0, duration: 0 }
|
|
2117
|
+
);
|
|
2118
|
+
d.hours = Math.round(d.duration / 3600 * 100) / 100, d.distance = Math.round(d.distance * 100) / 100, d.spd = d.hours ? Math.round(d.distance / d.hours * 100) / 100 : 0;
|
|
2119
|
+
const R = A ? Math.round(q / (A - d.hours) * 100) / 100 : 0;
|
|
2045
2120
|
return {
|
|
2046
|
-
begin:
|
|
2047
|
-
end:
|
|
2048
|
-
distance:
|
|
2049
|
-
hours:
|
|
2050
|
-
avgSpeed:
|
|
2121
|
+
begin: c.utc().format(),
|
|
2122
|
+
end: O.utc().format(),
|
|
2123
|
+
distance: q,
|
|
2124
|
+
hours: A - d.hours,
|
|
2125
|
+
avgSpeed: R,
|
|
2126
|
+
stoppage: d
|
|
2051
2127
|
};
|
|
2052
2128
|
}
|
|
2053
2129
|
return {
|
|
@@ -2074,13 +2150,13 @@ class r {
|
|
|
2074
2150
|
const b = z.sample.hours.at(0), p = u.utc(M), c = u.utc(z.eta), O = p.isAfter(c) ? c : p;
|
|
2075
2151
|
let A = z.sample.hours.find((T) => T.eta === O.format());
|
|
2076
2152
|
if (!A) {
|
|
2077
|
-
const T = z.sample.hours.filter((G) => u.utc(G.eta).isBefore(O)).at(-1),
|
|
2078
|
-
A = (R = this.calculateNextCoordinateAlongRoute(T, T.speed * O.diff(u(T.etd), "hours", !0),
|
|
2079
|
-
const { cFactor: i, cog:
|
|
2153
|
+
const T = z.sample.hours.filter((G) => u.utc(G.eta).isBefore(O)).at(-1), N = this.calculateSubRoute(T, z.route);
|
|
2154
|
+
A = (R = this.calculateNextCoordinateAlongRoute(T, T.speed * O.diff(u(T.etd), "hours", !0), N)) == null ? void 0 : R.coordinate;
|
|
2155
|
+
const { cFactor: i, cog: f, wxFactor: s, meteo: P } = T, l = Math.round(A.distanceFromPrevious * 1e4) / 1e4, B = Math.round((l + T.distanceFromStart) * 1e4) / 1e4;
|
|
2080
2156
|
A = {
|
|
2081
2157
|
...A,
|
|
2082
2158
|
cFactor: i,
|
|
2083
|
-
cog:
|
|
2159
|
+
cog: f,
|
|
2084
2160
|
speed: T.speed,
|
|
2085
2161
|
wxFactor: s,
|
|
2086
2162
|
distanceFromStart: B,
|
|
@@ -2136,14 +2212,14 @@ try {
|
|
|
2136
2212
|
} catch {
|
|
2137
2213
|
} finally {
|
|
2138
2214
|
}
|
|
2139
|
-
class
|
|
2215
|
+
class V0 {
|
|
2140
2216
|
/**
|
|
2141
2217
|
* 将原始数据转换为geojson
|
|
2142
2218
|
* @param raw
|
|
2143
2219
|
*/
|
|
2144
2220
|
static convert2Geojson(M) {
|
|
2145
2221
|
var b, p, c;
|
|
2146
|
-
const z =
|
|
2222
|
+
const z = S.featureCollection([]);
|
|
2147
2223
|
for (const O of M) {
|
|
2148
2224
|
const A = (b = O.history) == null ? void 0 : b[0];
|
|
2149
2225
|
if (O.forecasts) {
|
|
@@ -2152,25 +2228,25 @@ class t0 {
|
|
|
2152
2228
|
let q;
|
|
2153
2229
|
const Y = [], d = [], R = u(W.date).utc(), T = `${O.name}-${W.model}`;
|
|
2154
2230
|
for (const i in W == null ? void 0 : W.hours) {
|
|
2155
|
-
const
|
|
2156
|
-
q = q ||
|
|
2157
|
-
const s = R.clone().add(Number(i), "hour"), P =
|
|
2231
|
+
const f = W.hours[i];
|
|
2232
|
+
q = q || f;
|
|
2233
|
+
const s = R.clone().add(Number(i), "hour"), P = S.point([f.lng, f.lat], {
|
|
2158
2234
|
model: W.model,
|
|
2159
2235
|
name: O.name,
|
|
2160
2236
|
nameCn: O.nameCn,
|
|
2161
2237
|
date: s.format(),
|
|
2162
2238
|
hour: Number(i),
|
|
2163
2239
|
format: s.format("MMM-DD/HHmm[Z]"),
|
|
2164
|
-
pressure:
|
|
2165
|
-
gusts:
|
|
2166
|
-
wind:
|
|
2167
|
-
movement:
|
|
2240
|
+
pressure: f.pressure > 1e4 ? a.roundPrecision(f.pressure / 100, 0) : a.roundPrecision(f.pressure, 0),
|
|
2241
|
+
gusts: f.gusts,
|
|
2242
|
+
wind: f.wind || {},
|
|
2243
|
+
movement: f.movement,
|
|
2168
2244
|
category: T,
|
|
2169
2245
|
type: "forecast"
|
|
2170
2246
|
});
|
|
2171
2247
|
d.push(P), Y.push(P.geometry.coordinates);
|
|
2172
2248
|
}
|
|
2173
|
-
const
|
|
2249
|
+
const N = {
|
|
2174
2250
|
kts: void 0,
|
|
2175
2251
|
deg: void 0
|
|
2176
2252
|
};
|
|
@@ -2178,9 +2254,9 @@ class t0 {
|
|
|
2178
2254
|
const i = u(A.updated).utc();
|
|
2179
2255
|
if (q) {
|
|
2180
2256
|
const s = r.calculateDistance(A, q), P = u(q.utc || q.updated).diff(i, "h", !0);
|
|
2181
|
-
|
|
2257
|
+
N.kts = Math.round(s / P * 100) / 100, N.deg = r.calculateBearing(A, q, !0, 0);
|
|
2182
2258
|
}
|
|
2183
|
-
const
|
|
2259
|
+
const f = S.point([A.lng, A.lat], {
|
|
2184
2260
|
model: W.model,
|
|
2185
2261
|
name: O.name,
|
|
2186
2262
|
nameCn: O.nameCn,
|
|
@@ -2189,23 +2265,23 @@ class t0 {
|
|
|
2189
2265
|
format: i.format("MMM-DD/HHmm[Z]"),
|
|
2190
2266
|
pressure: A.pressure > 1e4 ? a.roundPrecision((A == null ? void 0 : A.pressure) / 100, 0) : a.roundPrecision(A.pressure, 0),
|
|
2191
2267
|
wind: A.wind,
|
|
2192
|
-
movement:
|
|
2268
|
+
movement: N,
|
|
2193
2269
|
category: T,
|
|
2194
2270
|
type: "forecast",
|
|
2195
2271
|
important: !0
|
|
2196
2272
|
// 第一个预报点为重要点
|
|
2197
2273
|
});
|
|
2198
|
-
d.unshift(
|
|
2274
|
+
d.unshift(f), Y.unshift(f.geometry.coordinates);
|
|
2199
2275
|
}
|
|
2200
2276
|
if (z.features.push(...d), (Y == null ? void 0 : Y.length) > 1) {
|
|
2201
|
-
const i =
|
|
2277
|
+
const i = S.lineString(a.convertToMonotonicLng2(Y), {
|
|
2202
2278
|
date: (A == null ? void 0 : A.updated) || (R == null ? void 0 : R.format()),
|
|
2203
2279
|
id: O.id || O.name,
|
|
2204
2280
|
model: W.model,
|
|
2205
2281
|
name: O.name,
|
|
2206
2282
|
category: T,
|
|
2207
2283
|
type: "forecast",
|
|
2208
|
-
movement:
|
|
2284
|
+
movement: N
|
|
2209
2285
|
});
|
|
2210
2286
|
z.features.push(i);
|
|
2211
2287
|
}
|
|
@@ -2214,9 +2290,9 @@ class t0 {
|
|
|
2214
2290
|
if (z.features.sort((W, q) => W.properties.type === "forecast" && q.properties.type === "forecast" && W.geometry.type === "Point" && q.geometry.type === "Point" ? u(W.properties.date).valueOf() - u(q.properties.date).valueOf() : 0), (p = O.history) != null && p.length) {
|
|
2215
2291
|
const W = [], q = u(A == null ? void 0 : A.updated).utc(), Y = u((c = O.history) == null ? void 0 : c.at(-1).updated).utc(), d = q.diff(Y, "h") % 24 > 2 ? 24 : 12;
|
|
2216
2292
|
for (const R of O.history) {
|
|
2217
|
-
const T = u(R.updated).utc(),
|
|
2218
|
-
|
|
2219
|
-
const i =
|
|
2293
|
+
const T = u(R.updated).utc(), N = T.isSameOrBefore(q) || T.isSame(Y);
|
|
2294
|
+
N && q.add(-d, "h");
|
|
2295
|
+
const i = S.point([R.lng, R.lat], {
|
|
2220
2296
|
name: O.name,
|
|
2221
2297
|
nameCn: O.nameCn,
|
|
2222
2298
|
date: T.format(),
|
|
@@ -2228,12 +2304,12 @@ class t0 {
|
|
|
2228
2304
|
category: `${O.name}-history`,
|
|
2229
2305
|
wind: R.wind,
|
|
2230
2306
|
movement: R.movement,
|
|
2231
|
-
important:
|
|
2307
|
+
important: N
|
|
2232
2308
|
});
|
|
2233
2309
|
z.features.push(i), W.push(i.geometry.coordinates);
|
|
2234
2310
|
}
|
|
2235
2311
|
if (W.length === 1 && W.push(W[0]), W.length > 1) {
|
|
2236
|
-
const R =
|
|
2312
|
+
const R = S.lineString(a.convertToMonotonicLng2(W), {
|
|
2237
2313
|
name: O.name,
|
|
2238
2314
|
type: "history",
|
|
2239
2315
|
updated: A == null ? void 0 : A.updated,
|
|
@@ -2256,15 +2332,15 @@ class t0 {
|
|
|
2256
2332
|
var c, O, A, W;
|
|
2257
2333
|
const b = (c = M == null ? void 0 : M.data) == null ? void 0 : c.features.filter((q) => q.geometry.type === "LineString" && q.properties.type === "forecast"), p = [];
|
|
2258
2334
|
for (const q of b) {
|
|
2259
|
-
const Y = q.properties.name, d = q.properties.model, R = q.properties.showCircle, T = q.properties.disabled,
|
|
2335
|
+
const Y = q.properties.name, d = q.properties.model, R = q.properties.showCircle, T = q.properties.disabled, N = u(q.properties.date).utc();
|
|
2260
2336
|
let i = z * 60;
|
|
2261
|
-
const
|
|
2337
|
+
const f = (O = M == null ? void 0 : M.data) == null ? void 0 : O.features.filter(
|
|
2262
2338
|
(l) => l.geometry.type === "Point" && l.properties.type === "forecast" && l.properties.category === `${Y}-${d}`
|
|
2263
2339
|
);
|
|
2264
|
-
let s, P =
|
|
2265
|
-
for (; s = this.pickIndex(
|
|
2340
|
+
let s, P = N.clone().add(i, "minute").set({ minute: 0, second: 0, millisecond: 0 });
|
|
2341
|
+
for (; s = this.pickIndex(f, P), s <= f.length - 1; ) {
|
|
2266
2342
|
if (s > 0) {
|
|
2267
|
-
const l =
|
|
2343
|
+
const l = f[s], B = s === 0 ? void 0 : f[s - 1], G = (i / 60 - ((A = B == null ? void 0 : B.properties) == null ? void 0 : A.hour)) / (l.properties.hour - ((W = B == null ? void 0 : B.properties) == null ? void 0 : W.hour)), H = this.computeNumber(B == null ? void 0 : B.geometry.coordinates[0], l.geometry.coordinates[0], G), F = this.computeNumber(B == null ? void 0 : B.geometry.coordinates[1], l.geometry.coordinates[1], G), $ = S.point([H, F], {
|
|
2268
2344
|
name: Y,
|
|
2269
2345
|
model: d,
|
|
2270
2346
|
category: l == null ? void 0 : l.properties.category,
|
|
@@ -2281,7 +2357,7 @@ class t0 {
|
|
|
2281
2357
|
});
|
|
2282
2358
|
p.push($);
|
|
2283
2359
|
}
|
|
2284
|
-
i += z * 60, P =
|
|
2360
|
+
i += z * 60, P = N.clone().add(i, "minute").set({ minute: 0, second: 0, millisecond: 0 });
|
|
2285
2361
|
}
|
|
2286
2362
|
}
|
|
2287
2363
|
return p;
|
|
@@ -2311,9 +2387,9 @@ class t0 {
|
|
|
2311
2387
|
const { t1: c, t2: O, hr: A, hours: W } = this.tropicalCenterTwin(z, 24, p);
|
|
2312
2388
|
if (c && O) {
|
|
2313
2389
|
if (!p.debug) {
|
|
2314
|
-
const
|
|
2315
|
-
if (
|
|
2316
|
-
return I == null || I.info("[%s] the distance between from and t1(%d) and t2(%d) is enough, no need diversion: %j", p.requestId,
|
|
2390
|
+
const N = r.calculateDistance(M, c), i = r.calculateDistance(M, O);
|
|
2391
|
+
if (N > 2 * b && i > 2 * b)
|
|
2392
|
+
return I == null || I.info("[%s] the distance between from and t1(%d) and t2(%d) is enough, no need diversion: %j", p.requestId, N, i, {
|
|
2317
2393
|
from: M,
|
|
2318
2394
|
t1: c,
|
|
2319
2395
|
t2: O,
|
|
@@ -2350,9 +2426,9 @@ class t0 {
|
|
|
2350
2426
|
const { t1: c, t2: O, hr: A, hours: W } = this.tropicalCenterTwin(z, 24, p);
|
|
2351
2427
|
if (c && O) {
|
|
2352
2428
|
if (!p.debug) {
|
|
2353
|
-
const T = r.calculateDistance(M, c),
|
|
2354
|
-
if (T > 2 * b &&
|
|
2355
|
-
return I == null || I.info("[%s] the distance between from and t1(%d) and t2(%d) is enough, no need drifting: %j", p.requestId, T,
|
|
2429
|
+
const T = r.calculateDistance(M, c), N = r.calculateDistance(M, O);
|
|
2430
|
+
if (T > 2 * b && N > 2 * b)
|
|
2431
|
+
return I == null || I.info("[%s] the distance between from and t1(%d) and t2(%d) is enough, no need drifting: %j", p.requestId, T, N, {
|
|
2356
2432
|
from: M,
|
|
2357
2433
|
t1: c,
|
|
2358
2434
|
t2: O,
|
|
@@ -2373,7 +2449,7 @@ class t0 {
|
|
|
2373
2449
|
* @private
|
|
2374
2450
|
*/
|
|
2375
2451
|
static tropicalCenterTwin(M, z = 24, b = {}) {
|
|
2376
|
-
var Y, d, R, T,
|
|
2452
|
+
var Y, d, R, T, N;
|
|
2377
2453
|
let p = {};
|
|
2378
2454
|
(Y = M.forecasts) == null || Y.forEach((i) => {
|
|
2379
2455
|
p = { ...i.hours, ...p };
|
|
@@ -2381,7 +2457,7 @@ class t0 {
|
|
|
2381
2457
|
const c = ((d = M == null ? void 0 : M.history) == null ? void 0 : d[0]) || (p == null ? void 0 : p[(R = Object.keys(p)) == null ? void 0 : R[0]]);
|
|
2382
2458
|
I == null || I.info("[%s] the first tropical center: %j", b.requestId, c);
|
|
2383
2459
|
let O = (T = Object.keys(p || {}).filter((i) => Number(i) <= (z < 0 ? 24 : z))) == null ? void 0 : T.at(-1);
|
|
2384
|
-
O || (O = (
|
|
2460
|
+
O || (O = (N = Object.keys(p || {}).filter((i) => Number(i) <= (z < 0 ? 24 : 2 * z))) == null ? void 0 : N.at(-1));
|
|
2385
2461
|
const A = p == null ? void 0 : p[O || -1];
|
|
2386
2462
|
I == null || I.info("[%s] the second tropical center: %j in %d hrs", b.requestId, A, O);
|
|
2387
2463
|
const W = Object.keys(p || {}).filter((i) => Number(i) <= Number(O)), q = { 0: c };
|
|
@@ -2414,78 +2490,9 @@ class t0 {
|
|
|
2414
2490
|
return z;
|
|
2415
2491
|
}
|
|
2416
2492
|
}
|
|
2417
|
-
class V0 {
|
|
2418
|
-
static json2Str(M) {
|
|
2419
|
-
const z = M.type ? M.type[0].toUpperCase() : "A";
|
|
2420
|
-
return `${M.lat}|${M.lng}|${M.positionTime}|${M.sog}|${M.cog}|${M.hdg}|${M.draught}|${z}|${JSON.stringify(M.meteo || {})}|${M.vendor}|${M.deleted}`;
|
|
2421
|
-
}
|
|
2422
|
-
static str2Json(M) {
|
|
2423
|
-
const [z, b, p, c, O, A, W, q, Y, d, R] = M.split("|");
|
|
2424
|
-
return {
|
|
2425
|
-
lat: Number(z),
|
|
2426
|
-
lng: Number(b),
|
|
2427
|
-
positionTime: Number(p),
|
|
2428
|
-
sog: Number(c),
|
|
2429
|
-
cog: Number(O),
|
|
2430
|
-
hdg: Number(A),
|
|
2431
|
-
//@ts-ignore
|
|
2432
|
-
draught: isNaN(W) ? null : Number(W),
|
|
2433
|
-
type: q,
|
|
2434
|
-
important: q !== "A",
|
|
2435
|
-
meteo: Y ? JSON.parse(Y) : void 0,
|
|
2436
|
-
vendor: d,
|
|
2437
|
-
deleted: R === "true"
|
|
2438
|
-
};
|
|
2439
|
-
}
|
|
2440
|
-
static inspectStoppages(M, z = 1, b = !0) {
|
|
2441
|
-
const p = M.at(0).positionTime < M.at(-1).positionTime;
|
|
2442
|
-
p || M.sort((W, q) => W.positionTime - q.positionTime);
|
|
2443
|
-
const c = [];
|
|
2444
|
-
let O, A;
|
|
2445
|
-
for (let W = 0; W < M.length - 1; W++) {
|
|
2446
|
-
const q = M[W];
|
|
2447
|
-
if (!(b && ["N", "B", "E", "NOON", "BOSP", "EOSP"].includes(q.type))) {
|
|
2448
|
-
for (let Y = W + 1; Y < M.length; Y++) {
|
|
2449
|
-
const d = M[Y - 1], R = M[Y];
|
|
2450
|
-
if (b && ["N", "B", "E", "NOON", "BOSP", "EOSP"].includes(q.type))
|
|
2451
|
-
continue;
|
|
2452
|
-
const T = R.positionTime - d.positionTime;
|
|
2453
|
-
if (r.calculateDistance(R, d, !0, 4) / (T / 3600) < z)
|
|
2454
|
-
O || (O = q), Y === M.length - 1 && (A = R, W = Y);
|
|
2455
|
-
else {
|
|
2456
|
-
O && (A = M[Y - 1], W = Y);
|
|
2457
|
-
break;
|
|
2458
|
-
}
|
|
2459
|
-
}
|
|
2460
|
-
if ((A == null ? void 0 : A.positionTime) > (O == null ? void 0 : O.positionTime) && O) {
|
|
2461
|
-
const Y = {
|
|
2462
|
-
start: {
|
|
2463
|
-
lat: O.lat,
|
|
2464
|
-
lng: O.lng,
|
|
2465
|
-
sog: O.sog,
|
|
2466
|
-
positionTime: O.positionTime,
|
|
2467
|
-
utc: u.unix(O.positionTime).utc().format()
|
|
2468
|
-
},
|
|
2469
|
-
end: {
|
|
2470
|
-
lat: A.lat,
|
|
2471
|
-
lng: A.lng,
|
|
2472
|
-
sog: A.sog,
|
|
2473
|
-
positionTime: A.positionTime,
|
|
2474
|
-
utc: u.unix(A.positionTime).utc().format()
|
|
2475
|
-
},
|
|
2476
|
-
duration: A.positionTime - O.positionTime
|
|
2477
|
-
}, d = M.filter((T) => T.positionTime >= Y.start.positionTime && T.positionTime <= Y.end.positionTime), R = r.divideAccordingToLng(d);
|
|
2478
|
-
Y.distance = r.calculateRouteDistance(R), Y.hours = Math.round(Y.duration / 3600 * 10) / 10, Y.avgSog = Math.round(Y.distance / Y.hours * 10) / 10, c.push(Y);
|
|
2479
|
-
}
|
|
2480
|
-
O = void 0, A = void 0;
|
|
2481
|
-
}
|
|
2482
|
-
}
|
|
2483
|
-
return p || M.sort((W, q) => q.positionTime - W.positionTime), c;
|
|
2484
|
-
}
|
|
2485
|
-
}
|
|
2486
2493
|
export {
|
|
2487
|
-
|
|
2494
|
+
B0 as AisHelper,
|
|
2488
2495
|
r as LaneHelper,
|
|
2489
2496
|
a as LngLatHelper,
|
|
2490
|
-
|
|
2497
|
+
V0 as TropicalHelper
|
|
2491
2498
|
};
|