@idm-plugin/geo 1.0.4 → 1.0.6

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.d.ts CHANGED
@@ -1,2 +1,3 @@
1
- export * from './lngLat/src/';
2
1
  export * from './tropicals/src/';
2
+ export * from './lane/src';
3
+ export * from './lngLat/src/';
package/dist/index.js CHANGED
@@ -1,15 +1,15 @@
1
- import y from "moment";
1
+ import * as g from "@turf/turf";
2
+ import v from "moment";
2
3
  import "moment-timezone";
3
- import T from "tz-lookup";
4
- import * as N from "@turf/turf";
5
- class u {
4
+ import R from "tz-lookup";
5
+ class l {
6
6
  /**
7
7
  * 基于输入的经度,计算出时区
8
8
  * @param lng
9
9
  * @param lat
10
10
  */
11
11
  static guessTimeZoneOffset(e, t) {
12
- const r = T(t, e), s = y().tz(r).utcOffset();
12
+ const n = R(t, e), s = v().tz(n).utcOffset();
13
13
  return this.roundPrecision(s / 60, 1);
14
14
  }
15
15
  /**
@@ -18,22 +18,22 @@ class u {
18
18
  * @return timezone => +08:30
19
19
  */
20
20
  static prettyTimeZoneOffset(e) {
21
- let t = Math.floor(Math.abs(e)), r = Math.round((Math.abs(e) - t) * 60);
22
- return r = r > 9 ? r : `0${r}`, t = t > 9 ? t : `0${t}`, e > 0 ? `+${t}:${r}` : `-${t}:${r}`;
21
+ let t = Math.floor(Math.abs(e)), n = Math.round((Math.abs(e) - t) * 60);
22
+ return n = n > 9 ? n : `0${n}`, t = t > 9 ? t : `0${t}`, e > 0 ? `+${t}:${n}` : `-${t}:${n}`;
23
23
  }
24
- static lng2pretty(e, t = 6, r = "H°M′") {
25
- e = u.convertToStdLng(e, t);
24
+ static lng2pretty(e, t = 6, n = "H°M′") {
25
+ e = l.convertToStdLng(e, t);
26
26
  let s = "E";
27
- e < 0 && (s = "W"), e = Math.abs(e), r = r.toUpperCase();
28
- let i = e * 3600, o, n, c, m, a, p;
29
- o = i % 3600 % 60, r.indexOf("S") !== -1 && (i = i - o, n = u.padNumber(o, 2, 2)), c = i / 60 % 60, r.indexOf("M") !== -1 && (r.indexOf("S") !== -1 ? m = u.roundPrecision(c, t).toString().padStart(2, "0") : m = u.padNumber(c, 2, 2), i = i - c * 60), a = i / 3600, r.indexOf("M") !== -1 ? p = u.roundPrecision(a, t).toString().padStart(3, "0") : p = u.padNumber(a, 3, 2);
30
- const h = `${r.replace(/S+/gi, n).replace(/M+/gi, m).replace(/H+/gi, p)}${s}`;
27
+ e < 0 && (s = "W"), e = Math.abs(e), n = n.toUpperCase();
28
+ let o = e * 3600, i, r, c, a, d, u;
29
+ i = o % 3600 % 60, n.indexOf("S") !== -1 && (o = o - i, r = l.padNumber(i, 2, 2)), c = o / 60 % 60, n.indexOf("M") !== -1 && (n.indexOf("S") !== -1 ? a = l.roundPrecision(c, t).toString().padStart(2, "0") : a = l.padNumber(c, 2, 2), o = o - c * 60), d = o / 3600, n.indexOf("M") !== -1 ? u = l.roundPrecision(d, t).toString().padStart(3, "0") : u = l.padNumber(d, 3, 2);
30
+ const f = `${n.replace(/S+/gi, r).replace(/M+/gi, a).replace(/H+/gi, u)}${s}`;
31
31
  return {
32
32
  direction: s,
33
- degree: u.roundPrecision(a, t),
34
- minute: u.roundPrecision(c, t),
35
- second: u.roundPrecision(o, t),
36
- pretty: h
33
+ degree: l.roundPrecision(d, t),
34
+ minute: l.roundPrecision(c, t),
35
+ second: l.roundPrecision(i, t),
36
+ pretty: f
37
37
  };
38
38
  }
39
39
  /**
@@ -42,71 +42,71 @@ class u {
42
42
  * @param precision 精确度
43
43
  * @param format 格式化
44
44
  */
45
- static lat2pretty(e, t = 6, r = "H°M′") {
45
+ static lat2pretty(e, t = 6, n = "H°M′") {
46
46
  e = e % 180;
47
47
  let s = "N";
48
- e < 0 && (s = "S"), e = Math.abs(e), r = r.toUpperCase();
49
- let i = e * 3600, o, n, c, m, a, p;
50
- o = i % 3600 % 60, r.indexOf("S") !== -1 && (i = i - o, n = u.padNumber(o, 2, 2)), c = i / 60 % 60, r.indexOf("M") !== -1 && (r.indexOf("S") !== -1 ? m = u.roundPrecision(c, t).toString().padStart(2, "0") : m = u.padNumber(c, 2, 2), i = i - c * 60), a = i / 3600, r.indexOf("M") !== -1 ? p = u.roundPrecision(a, t).toString().padStart(2, "0") : p = u.padNumber(a, 2, 2);
51
- const h = `${r.replace(/S+/gi, n).replace(/M+/gi, m).replace(/H+/gi, p)}${s}`;
48
+ e < 0 && (s = "S"), e = Math.abs(e), n = n.toUpperCase();
49
+ let o = e * 3600, i, r, c, a, d, u;
50
+ i = o % 3600 % 60, n.indexOf("S") !== -1 && (o = o - i, r = l.padNumber(i, 2, 2)), c = o / 60 % 60, n.indexOf("M") !== -1 && (n.indexOf("S") !== -1 ? a = l.roundPrecision(c, t).toString().padStart(2, "0") : a = l.padNumber(c, 2, 2), o = o - c * 60), d = o / 3600, n.indexOf("M") !== -1 ? u = l.roundPrecision(d, t).toString().padStart(2, "0") : u = l.padNumber(d, 2, 2);
51
+ const f = `${n.replace(/S+/gi, r).replace(/M+/gi, a).replace(/H+/gi, u)}${s}`;
52
52
  return {
53
53
  direction: s,
54
- degree: u.roundPrecision(a, t),
55
- minute: u.roundPrecision(c, t),
56
- second: u.roundPrecision(o, t),
57
- pretty: h
54
+ degree: l.roundPrecision(d, t),
55
+ minute: l.roundPrecision(c, t),
56
+ second: l.roundPrecision(i, t),
57
+ pretty: f
58
58
  };
59
59
  }
60
60
  static str2Lng(e, t = 6) {
61
- let r;
61
+ let n;
62
62
  if (isNaN(e)) {
63
- e = u.strReplace(e, "LNG");
63
+ e = l.strReplace(e, "LNG");
64
64
  const s = e[e.length - 1].toUpperCase();
65
65
  e = e.substring(0, e.length - 1).trim();
66
- const i = e.split(" ").filter((c) => c !== "").map((c) => Number(c));
67
- let [o, n] = i;
68
- if (o > 360 && !n) {
69
- const c = this.roundPrecision(o / 100, 0);
70
- n = o - c * 100, o = c;
66
+ const o = e.split(" ").filter((c) => c !== "").map((c) => Number(c));
67
+ let [i, r] = o;
68
+ if (i > 360 && !r) {
69
+ const c = this.roundPrecision(i / 100, 0);
70
+ r = i - c * 100, i = c;
71
71
  }
72
- r = o + (n ?? 0) / 60, s === "W" && (r = r * -1);
72
+ n = i + (r ?? 0) / 60, s === "W" && (n = n * -1);
73
73
  } else
74
- r = Number(e);
75
- return u.convertToStdLng(r, t);
74
+ n = Number(e);
75
+ return l.convertToStdLng(n, t);
76
76
  }
77
77
  static str2Lat(e, t = 6) {
78
- let r;
78
+ let n;
79
79
  if (isNaN(e)) {
80
- e = u.strReplace(e, "LAT");
80
+ e = l.strReplace(e, "LAT");
81
81
  const s = e[e.length - 1].toUpperCase();
82
82
  e = e.substring(0, e.length - 1).trim();
83
- const i = e.split(" ").filter((c) => c !== "").map((c) => Number(c));
84
- let [o, n] = i;
85
- if (o > 90 && !n) {
86
- const c = this.roundPrecision(o / 100, 0);
87
- n = o - c * 100, o = c;
83
+ const o = e.split(" ").filter((c) => c !== "").map((c) => Number(c));
84
+ let [i, r] = o;
85
+ if (i > 90 && !r) {
86
+ const c = this.roundPrecision(i / 100, 0);
87
+ r = i - c * 100, i = c;
88
88
  }
89
- r = o + (n ?? 0) / 60, s === "S" && (r = r * -1);
89
+ n = i + (r ?? 0) / 60, s === "S" && (n = n * -1);
90
90
  } else
91
- r = Number(e);
92
- return u.roundPrecision(r, t);
91
+ n = Number(e);
92
+ return l.roundPrecision(n, t);
93
93
  }
94
- static str2LngOrLat(e, t = 6, r = "LAT") {
95
- e = u.strReplace(e, r);
94
+ static str2LngOrLat(e, t = 6, n = "LAT") {
95
+ e = l.strReplace(e, n);
96
96
  const s = e[e.length - 1].toUpperCase();
97
97
  return ["N", "S"].includes(s) ? {
98
- lat: u.str2Lat(e, t)
98
+ lat: l.str2Lat(e, t)
99
99
  } : {
100
- lng: u.str2Lng(e, t)
100
+ lng: l.str2Lng(e, t)
101
101
  };
102
102
  }
103
103
  static convertToStdLng(e, t = 4) {
104
- return e > 180 ? (e = e % 360, e = e > 180 ? e - 360 : e) : e < -180 && (e = e % 360, e = e < -180 ? e + 360 : e), u.roundPrecision(e, t);
104
+ 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);
105
105
  }
106
106
  static roundPrecision(e, t = 4) {
107
107
  if (typeof e == "number") {
108
- const r = Number("1".padEnd(t + 1, "0"));
109
- return Math.round(e * r) / r;
108
+ const n = Number("1".padEnd(t + 1, "0"));
109
+ return Math.round(e * n) / n;
110
110
  }
111
111
  return e;
112
112
  }
@@ -130,12 +130,12 @@ class u {
130
130
  }
131
131
  static strReplace(e, t = "LAT") {
132
132
  e = e.replace(/([0-9]+)\.([0-9]+\.[0-9]+)/g, "$1 $2").replace(/-/g, " ").replace(/°/, " ").replace(/'/g, " ").replace(/′/g, " ").replace(/"/g, " ").replace(/∼/g, " ").replace(/°/g, " ").replace(/,/g, ".").replace(/^ /g, "").replace(/ $/g, "").trim();
133
- const r = e[e.length - 1].toUpperCase();
134
- if (!["N", "S", "E", "W"].includes(r)) {
135
- const s = e, i = Number(s.split(" ")[0]);
136
- if (isNaN(i))
133
+ const n = e[e.length - 1].toUpperCase();
134
+ if (!["N", "S", "E", "W"].includes(n)) {
135
+ const s = e, o = Number(s.split(" ")[0]);
136
+ if (isNaN(o))
137
137
  throw new Error(`invalid Lat/Lng: ${e}`);
138
- i >= 90 ? e = `${s}E` : i <= -90 ? e = `${s}W` : ["LAN", "LNG"].includes(t == null ? void 0 : t.toUpperCase()) ? e = `${s}${i > 0 ? "E" : "W"}` : e = `${s}${i > 0 ? "N" : "S"}`;
138
+ o >= 90 ? e = `${s}E` : o <= -90 ? e = `${s}W` : ["LAN", "LNG"].includes(t == null ? void 0 : t.toUpperCase()) ? e = `${s}${o > 0 ? "E" : "W"}` : e = `${s}${o > 0 ? "N" : "S"}`;
139
139
  }
140
140
  return e;
141
141
  }
@@ -146,157 +146,689 @@ class u {
146
146
  * @param intPrecision 整数位数
147
147
  * @param dcmPrecision 小数位数
148
148
  */
149
- static padNumber(e, t = 2, r = 2) {
150
- const s = Math.trunc(e).toString().padStart(t, "0"), i = Math.trunc(u.roundPrecision(e - Math.trunc(e), r) * Math.pow(10, r)).toString().padStart(r, "0");
151
- return `${s}.${i}`;
149
+ static padNumber(e, t = 2, n = 2) {
150
+ const s = Math.trunc(e).toString().padStart(t, "0"), o = Math.trunc(l.roundPrecision(e - Math.trunc(e), n) * Math.pow(10, n)).toString().padStart(n, "0");
151
+ return `${s}.${o}`;
152
152
  }
153
153
  }
154
- class x {
154
+ class y {
155
155
  static convert2Geojson(e) {
156
- var r;
157
- const t = N.featureCollection([]);
156
+ var n;
157
+ const t = g.featureCollection([]);
158
158
  for (const s of e) {
159
159
  if (s.forecasts) {
160
- const i = (r = s.history) == null ? void 0 : r[0];
161
- for (const o of s.forecasts) {
162
- const n = [], c = y(o.date).utc(), m = `${s.name}-${o.model}`;
163
- if (i) {
164
- const a = y(i.updated).utc(), p = N.point([i.lng, i.lat], {
165
- model: o.model,
160
+ const o = (n = s.history) == null ? void 0 : n[0];
161
+ for (const i of s.forecasts) {
162
+ const r = [], c = v(i.date).utc(), a = `${s.name}-${i.model}`;
163
+ if (o) {
164
+ const d = v(o.updated).utc(), u = g.point([o.lng, o.lat], {
165
+ model: i.model,
166
166
  name: s.name,
167
- date: a.format(),
167
+ date: d.format(),
168
168
  hour: 0,
169
- format: a.format("MMM-DD/HHmm[Z]"),
170
- pressure: i.pressure > 1e4 ? u.roundPrecision(i.pressure / 100, 0) : u.roundPrecision(i.pressure, 0),
171
- wind: { kts: i.kts, spd: i.speed || i.spd },
172
- category: m,
169
+ format: d.format("MMM-DD/HHmm[Z]"),
170
+ pressure: o.pressure > 1e4 ? l.roundPrecision(o.pressure / 100, 0) : l.roundPrecision(o.pressure, 0),
171
+ wind: { kts: o.kts, spd: o.speed || o.spd },
172
+ category: a,
173
173
  type: "forecast"
174
174
  });
175
- t.features.push(p), n.push(p.geometry.coordinates);
175
+ t.features.push(u), r.push(u.geometry.coordinates);
176
176
  }
177
- for (const a in o == null ? void 0 : o.hours) {
178
- const p = o.hours[a];
179
- p.wind.spd = p.wind.spd || p.wind.speed;
180
- const h = c.clone().add(Number(a), "hour"), l = N.point([p.lng, p.lat], {
177
+ for (const d in i == null ? void 0 : i.hours) {
178
+ const u = i.hours[d];
179
+ u.wind.spd = u.wind.spd || u.wind.speed;
180
+ const f = c.clone().add(Number(d), "hour"), p = g.point([u.lng, u.lat], {
181
+ model: i.model,
181
182
  name: s.name,
182
- date: h.format(),
183
- hour: Number(a),
184
- format: h.format("MMM-DD/HHmm[Z]"),
185
- pressure: p.pressure > 1e4 ? u.roundPrecision(p.pressure / 100, 0) : u.roundPrecision(p.pressure, 0),
186
- gusts: p.gusts,
187
- wind: p.wind || {},
188
- movement: p.movement,
189
- category: m,
183
+ date: f.format(),
184
+ hour: Number(d),
185
+ format: f.format("MMM-DD/HHmm[Z]"),
186
+ pressure: u.pressure > 1e4 ? l.roundPrecision(u.pressure / 100, 0) : l.roundPrecision(u.pressure, 0),
187
+ gusts: u.gusts,
188
+ wind: u.wind || {},
189
+ movement: u.movement,
190
+ category: a,
190
191
  type: "forecast"
191
192
  });
192
- t.features.push(l), n.push(l.geometry.coordinates);
193
+ t.features.push(p), r.push(p.geometry.coordinates);
193
194
  }
194
- if ((n == null ? void 0 : n.length) > 1) {
195
- const a = N.lineString(u.convertToMonotonicLng2(n), {
196
- date: o.date,
195
+ if ((r == null ? void 0 : r.length) > 1) {
196
+ const d = g.lineString(l.convertToMonotonicLng2(r), {
197
+ date: i.date,
197
198
  id: s.id || s.name,
198
- model: o.model,
199
+ model: i.model,
199
200
  name: s.name,
200
- category: m,
201
+ category: a,
201
202
  type: "forecast"
202
203
  });
203
- t.features.push(a);
204
+ t.features.push(d);
204
205
  }
205
206
  }
206
207
  }
207
208
  if (s.history) {
208
- const i = [];
209
- for (const n of s.history) {
210
- const c = y(n.updated).utc(), m = N.point([n.lng, n.lat], {
209
+ const o = [];
210
+ for (const r of s.history) {
211
+ const c = v(r.updated).utc(), a = g.point([r.lng, r.lat], {
211
212
  name: s.name,
212
213
  date: c.format(),
213
214
  format: c.format("MMM-DD/HHmm[Z]"),
214
- pressure: n.pressure > 1e4 ? u.roundPrecision(n.pressure / 100, 0) : u.roundPrecision(n.pressure, 0),
215
- spd: n.speed || n.spd,
216
- kts: n.kts,
217
- source: n.source,
218
- level: n.type,
215
+ pressure: r.pressure > 1e4 ? l.roundPrecision(r.pressure / 100, 0) : l.roundPrecision(r.pressure, 0),
216
+ spd: r.speed || r.spd,
217
+ kts: r.kts,
218
+ source: r.source,
219
+ level: r.type,
219
220
  type: "history",
220
221
  category: `${s.name}-history`
221
222
  });
222
- t.features.push(m), i.push(m.geometry.coordinates);
223
+ t.features.push(a), o.push(a.geometry.coordinates);
223
224
  }
224
- const o = s.history[0];
225
- if (i.length === 1 && i.push(i[0]), i.length > 1) {
226
- const n = N.lineString(u.convertToMonotonicLng2(i), {
225
+ const i = s.history[0];
226
+ if (o.length === 1 && o.push(o[0]), o.length > 1) {
227
+ const r = g.lineString(l.convertToMonotonicLng2(o), {
227
228
  name: s.name,
228
229
  type: "history",
229
- updated: o == null ? void 0 : o.updated,
230
- pressure: (o == null ? void 0 : o.pressure) > 1e4 ? u.roundPrecision((o == null ? void 0 : o.pressure) / 100, 0) : u.roundPrecision(o == null ? void 0 : o.pressure, 0),
231
- spd: (o == null ? void 0 : o.speed) || (o == null ? void 0 : o.spd),
232
- kts: o == null ? void 0 : o.kts,
233
- source: o == null ? void 0 : o.source,
234
- level: o == null ? void 0 : o.type
230
+ updated: i == null ? void 0 : i.updated,
231
+ pressure: (i == null ? void 0 : i.pressure) > 1e4 ? l.roundPrecision((i == null ? void 0 : i.pressure) / 100, 0) : l.roundPrecision(i == null ? void 0 : i.pressure, 0),
232
+ spd: (i == null ? void 0 : i.speed) || (i == null ? void 0 : i.spd),
233
+ kts: i == null ? void 0 : i.kts,
234
+ source: i == null ? void 0 : i.source,
235
+ level: i == null ? void 0 : i.type
235
236
  });
236
- t.features.push(n);
237
+ t.features.push(r);
237
238
  }
238
239
  }
239
240
  }
240
241
  return t;
241
242
  }
242
243
  static interpolate(e, t = 3) {
243
- var i, o, n, c;
244
- const r = (i = e == null ? void 0 : e.data) == null ? void 0 : i.features.filter((m) => m.geometry.type === "LineString" && m.properties.type === "forecast"), s = [];
245
- for (const m of r) {
246
- const a = m.properties.name, p = m.properties.model, h = y(m.properties.date).utc();
247
- let l = t * 60 - (h.get("hour") * 60 + h.get("minute")) % (t * 60);
248
- const b = (o = e == null ? void 0 : e.data) == null ? void 0 : o.features.filter(
249
- (f) => !f.properties.disabled && f.geometry.type === "Point" && f.properties.type === "forecast" && f.properties.category === `${a}-${p}`
244
+ var o, i, r, c;
245
+ const n = (o = e == null ? void 0 : e.data) == null ? void 0 : o.features.filter((a) => a.geometry.type === "LineString" && a.properties.type === "forecast"), s = [];
246
+ for (const a of n) {
247
+ const d = a.properties.name, u = a.properties.model, f = v(a.properties.date).utc();
248
+ let p = t * 60 - (f.get("hour") * 60 + f.get("minute")) % (t * 60);
249
+ const b = (i = e == null ? void 0 : e.data) == null ? void 0 : i.features.filter(
250
+ (m) => m.geometry.type === "Point" && m.properties.type === "forecast" && m.properties.category === `${d}-${u}`
250
251
  );
251
- let M, S = h.clone().add(l, "minute").set({ minute: 0, second: 0, millisecond: 0 });
252
- for (; M = this.pickIndex(b, S), M <= b.length - 1; ) {
253
- if (M > 0) {
254
- const f = b[M], d = M === 0 ? void 0 : b[M - 1], g = (l / 60 - ((n = d == null ? void 0 : d.properties) == null ? void 0 : n.hour)) / (f.properties.hour - ((c = d == null ? void 0 : d.properties) == null ? void 0 : c.hour)), $ = this.computeNumber(d == null ? void 0 : d.geometry.coordinates[0], f.geometry.coordinates[0], g), P = this.computeNumber(d == null ? void 0 : d.geometry.coordinates[1], f.geometry.coordinates[1], g), w = N.point([$, P], {
255
- name: a,
256
- model: p,
257
- category: f == null ? void 0 : f.properties.category,
258
- date: S.format(),
259
- format: S.format("MMM-DD/HHmm[Z]"),
260
- gusts: this.computeNumber(d == null ? void 0 : d.properties.gusts, f.properties.gusts, g),
261
- hour: this.computeNumber(d == null ? void 0 : d.properties.hour, f.properties.hour, g),
262
- movement: this.computeNumber(d == null ? void 0 : d.properties.movement, f.properties.movement, g),
263
- pressure: this.computeNumber(d == null ? void 0 : d.properties.pressure, f.properties.pressure, g),
264
- wind: this.computeNumber(d == null ? void 0 : d.properties.wind, f.properties.wind, g),
252
+ let T, P = f.clone().add(p, "minute").set({ minute: 0, second: 0, millisecond: 0 });
253
+ for (; T = this.pickIndex(b, P), T <= b.length - 1; ) {
254
+ if (T > 0) {
255
+ const m = b[T], h = T === 0 ? void 0 : b[T - 1], S = (p / 60 - ((r = h == null ? void 0 : h.properties) == null ? void 0 : r.hour)) / (m.properties.hour - ((c = h == null ? void 0 : h.properties) == null ? void 0 : c.hour)), M = this.computeNumber(h == null ? void 0 : h.geometry.coordinates[0], m.geometry.coordinates[0], S), N = this.computeNumber(h == null ? void 0 : h.geometry.coordinates[1], m.geometry.coordinates[1], S), C = g.point([M, N], {
256
+ name: d,
257
+ model: u,
258
+ category: m == null ? void 0 : m.properties.category,
259
+ date: P.format(),
260
+ format: P.format("MMM-DD/HHmm[Z]"),
261
+ gusts: this.computeNumber(h == null ? void 0 : h.properties.gusts, m.properties.gusts, S),
262
+ hour: this.computeNumber(h == null ? void 0 : h.properties.hour, m.properties.hour, S),
263
+ movement: this.computeNumber(h == null ? void 0 : h.properties.movement, m.properties.movement, S),
264
+ pressure: this.computeNumber(h == null ? void 0 : h.properties.pressure, m.properties.pressure, S),
265
+ wind: this.computeNumber(h == null ? void 0 : h.properties.wind, m.properties.wind, S),
265
266
  type: "forecast"
266
267
  });
267
- s.push(w);
268
+ s.push(C);
268
269
  }
269
- l += t * 60, S = h.clone().add(l, "minute").set({ minute: 0, second: 0, millisecond: 0 });
270
+ p += t * 60, P = f.clone().add(p, "minute").set({ minute: 0, second: 0, millisecond: 0 });
270
271
  }
271
272
  }
272
273
  return s;
273
274
  }
274
275
  static pickIndex(e, t) {
275
- let r = 0;
276
+ let n = 0;
276
277
  for (const s of e) {
277
- if (y(s.properties.date).isAfter(t))
278
- return r === 0 ? -1 : r;
279
- r++;
278
+ if (v(s.properties.date).isAfter(t))
279
+ return n === 0 ? -1 : n;
280
+ n++;
280
281
  }
281
- return r;
282
+ return n;
282
283
  }
283
- static computeNumber(e, t, r) {
284
+ static computeNumber(e, t, n) {
284
285
  if (e)
285
286
  if (t) {
286
287
  if (isNaN(e) && isNaN(t) && typeof e != "string" && typeof t != "string") {
287
288
  const s = {};
288
- for (const i in e)
289
- s[i] = this.computeNumber(e[i], t[i], r);
289
+ for (const o in e)
290
+ s[o] = this.computeNumber(e[o], t[o], n);
290
291
  return s;
291
292
  }
292
- return Math.round((e + (t - e) * r) * 100) / 100;
293
+ return Math.round((e + (t - e) * n) * 100) / 100;
293
294
  } else
294
295
  return e;
295
296
  else
296
297
  return t;
297
298
  }
298
299
  }
300
+ class W {
301
+ /**
302
+ * 计算方位角
303
+ * @param from 坐标 {lng, lat}
304
+ * @param to 坐标 {lng, lat}
305
+ * @param rhumb true 横向方位角,false 大圆方位角
306
+ * @param precision
307
+ * @returns {number} 单位度
308
+ */
309
+ static calculateBearing(e, t, n = !0, s = 4) {
310
+ const o = g.points([
311
+ [e.lng, e.lat],
312
+ [t.lng, t.lat]
313
+ ]);
314
+ let i;
315
+ return n ? i = g.rhumbBearing(o.features[0], o.features[1]) : i = g.bearing(o.features[0], o.features[1]), i < 0 && (i += 360), l.roundPrecision(i, s);
316
+ }
317
+ /**
318
+ * 计算两点间距离
319
+ * @param from 坐标 {lng, lat}
320
+ * @param to 坐标 {lng, lat}
321
+ * @param rhumb true 横向距离,false 大圆距离
322
+ * @param precision
323
+ * @param units 单位,默认 nm(海里)
324
+ * @returns {number}
325
+ */
326
+ static calculateDistance(e, t, n = !0, s = 4, o = "nauticalmiles") {
327
+ e = { ...e }, t = { ...t }, e.lng = l.convertToStdLng(e.lng, s), t.lng = l.convertToStdLng(t.lng, s);
328
+ const i = g.points([
329
+ [e.lng, e.lat],
330
+ [t.lng, t.lat]
331
+ ]);
332
+ let r;
333
+ return n ? r = g.rhumbDistance(i.features[0], i.features[1], { units: o }) : r = g.distance(i.features[0], i.features[1], { units: o }), l.roundPrecision(r, s);
334
+ }
335
+ /**
336
+ * 计算航线距离
337
+ * @param route [[[lng, lat],[lng, lat]]]
338
+ * @param precision
339
+ * @param units
340
+ */
341
+ static calculateRouteDistance(e, t = 4, n = "nauticalmiles") {
342
+ let s = 0, o;
343
+ for (const i of e)
344
+ for (let r = 0; r < i.length - 1; r++) {
345
+ const c = { lng: i[r][0], lat: i[r][1] };
346
+ r === 0 && o && (s += this.calculateDistance(o, c, !0, t, n));
347
+ const a = { lng: i[r + 1][0], lat: i[r + 1][1] };
348
+ s += this.calculateDistance(c, a, !0, t, n), o = a;
349
+ }
350
+ return l.roundPrecision(s, t);
351
+ }
352
+ /**
353
+ * 计算坐标(基于方位角和距离)
354
+ * @param from 坐标 {lng, lat}
355
+ * @param bearing 方位角,单位度
356
+ * @param distance 距离
357
+ * @param units 单位,默认 nm(海里)
358
+ * @param rhumb
359
+ */
360
+ static calculateCoordinate(e, t, n, s = "nauticalmiles", o = !0) {
361
+ const i = g.point([e.lng, e.lat]);
362
+ let r;
363
+ o ? r = g.rhumbDestination(i, n, t, { units: s }) : r = g.destination(i, n, t, { units: s });
364
+ const c = r.geometry.coordinates;
365
+ return { lng: l.convertToStdLng(c[0], 8), lat: l.roundPrecision(c[1], 8) };
366
+ }
367
+ /**
368
+ * 插值大圆坐标(基于两点方位角和间距)
369
+ * @param from 坐标 {lng, lat}
370
+ * @param to 坐标 {lng, lat}
371
+ * @param spacing 间距
372
+ * @param includeHead true 包含起点 from
373
+ * @param includeTail true 包含终点 to
374
+ * @param units 单位,默认 nm(海里)
375
+ */
376
+ static interpolateCoordinates(e, t, n, s = !0, o = !0, i = "nauticalmiles") {
377
+ const r = [], c = this.calculateBearing(e, t, !1), a = this.calculateDistance(e, t, !1, 8, i);
378
+ s && r.push({ lng: e.lng, lat: e.lat });
379
+ let d = 0;
380
+ for (; d < a; )
381
+ d += n, d < a && r.push(this.calculateCoordinate(e, c, d, i, !1));
382
+ return o && r.push({ lng: t.lng, lat: t.lat }), r;
383
+ }
384
+ /**
385
+ * 分组坐标(如相邻两个坐标经度差超180度,需以180为界将坐标分为两组)
386
+ * @param coordinates [{lng, lat}]
387
+ * @param rhumb
388
+ * @example
389
+ * coordinates: [{lng: 160,lat: 30}, {lng: 170, lat: 40},{lng: -170, lat: 40},{lng: -160, lat: 30}]
390
+ * @return [
391
+ * [[160, 30],[170,40]],
392
+ * [[-170,40],[-160,30]]
393
+ * ]
394
+ */
395
+ static divideAccordingToLng(e, t = !1) {
396
+ if ((e == null ? void 0 : e.length) < 2)
397
+ return [];
398
+ e = this.deduplicateCoordinates(e);
399
+ let n = [];
400
+ const s = [];
401
+ let o, i;
402
+ for (let r = 0; r < e.length - 1; r++) {
403
+ o = l.convertToStdLng(e[r].lng, 8), i = l.convertToStdLng(e[r + 1].lng, 8), n.push([o, e[r].lat]);
404
+ const c = o - i;
405
+ if (Math.abs(c) > 180) {
406
+ const a = l.convertToMonotonicLng2([
407
+ [o, e[r].lat],
408
+ [i, e[r + 1].lat]
409
+ ]);
410
+ let d, u;
411
+ t ? (d = g.lineString(a), u = g.lineString([
412
+ [c > 0 ? 180 : -180, 89],
413
+ [c > 0 ? 180 : -180, -89]
414
+ ])) : (d = g.greatCircle(a[0], a[1]), u = g.greatCircle([c > 0 ? 180 : -180, 89], [c > 0 ? 180 : -180, -89]));
415
+ const f = g.lineIntersect(d, u);
416
+ let p;
417
+ if (f.features.length) {
418
+ const b = g.getCoord(f.features[0]);
419
+ p = l.roundPrecision(b[1], 8);
420
+ } else
421
+ p = e[r].lat;
422
+ c > 0 ? (n.push([180 - 1e-6, p]), s.push([...n]), n = [], n.push([-(180 - 1e-6), p])) : (n.push([-(180 - 1e-6), p]), s.push([...n]), n = [], n.push([180 - 1e-6, p]));
423
+ }
424
+ r === e.length - 2 && n.push([i, e[r + 1].lat]);
425
+ }
426
+ return s.push(n), s;
427
+ }
428
+ /**
429
+ * 去除重复坐标
430
+ * @param route
431
+ */
432
+ static deduplicateRoute(e) {
433
+ const t = [];
434
+ for (const n of e) {
435
+ const s = n.reduce((o, i) => (o.findIndex((r) => r[0] === i[0] && r[1] === i[1]) === -1 && o.push(i), o), []);
436
+ t.push(s);
437
+ }
438
+ return t;
439
+ }
440
+ /**
441
+ * 去除重新坐标
442
+ * @param coordinates
443
+ */
444
+ static deduplicateCoordinates(e) {
445
+ return e.reduce((t, n) => (t.findIndex((s) => s.lat === n.lat && s.lng === n.lng) === -1 && t.push(n), t), []);
446
+ }
447
+ /**
448
+ * 移出坐标
449
+ * @param coordinate {lng, lat}
450
+ * @param route 航线[[[lng, lat],[lng, lat]]]
451
+ */
452
+ static removeCoordinateFromRoute(e, t) {
453
+ e.lng = l.convertToStdLng(e.lng, 8);
454
+ for (const n of t)
455
+ for (let s = n.length - 1; s >= 0; s--)
456
+ l.roundPrecision(n[s][0], 8) === e.lng && l.roundPrecision(n[s][1], 8) === l.roundPrecision(e.lat, 8) && n.splice(s, 1);
457
+ return t;
458
+ }
459
+ /**
460
+ * 移出坐标
461
+ * @param coordinate {lng, lat}
462
+ * @param waypoints [{lat, lng}, {lat, lng}]
463
+ */
464
+ static removeCoordinateFromWaypoints(e, t) {
465
+ e.lng = l.convertToStdLng(e.lng, 8);
466
+ for (let n = t.length - 1; n >= 0; n--)
467
+ l.roundPrecision(t[n].lng, 8) === e.lng && l.roundPrecision(t[n].lat, 8) === l.roundPrecision(e.lat, 8) && t.splice(n, 1);
468
+ return t;
469
+ }
470
+ /**
471
+ * 合并坐标进航线(基于坐标到线段最短距离边合并)
472
+ * @param coordinate 待合并的坐标 {lng, lat}
473
+ * @param route 航线[[[lng, lat],[lng, lat]]]
474
+ * @example
475
+ * coordinate {lng: 122, lat: 35}
476
+ *
477
+ * route: [[[120, 30], [125,40], [130, 37]], [[-150, 40], [-130, 30]]]
478
+ * @return
479
+ * [[[120, 30], [120, 35], [125,40], [130, 37]], [[-150, 40], [-130, 30]]]
480
+ */
481
+ static mergeCoordinateToRoute(e, t) {
482
+ e.lng = l.convertToStdLng(e.lng, 8);
483
+ let n = Number.MAX_VALUE, s = 0, o = 0, i, r;
484
+ return t.forEach((c, a) => {
485
+ for (let d = 0; d < c.length - 1; d++) {
486
+ const u = { lng: c[d][0], lat: c[d][1] }, f = { lng: c[d + 1][0], lat: c[d + 1][1] }, p = this.calculatePointToLineDistance(e, u, f);
487
+ n > p && (n = p, o = d, s = a, i = this.calculateDistance(u, e), r = this.calculateDistance(f, e));
488
+ }
489
+ }), i !== 0 && r !== 0 ? t[s].splice(o + 1, 0, [e.lng, e.lat]) : i === 0 ? t[s].splice(o, 1, [e.lng, e.lat]) : r === 0 && t[s].splice(o + 1, 1, [e.lng, e.lat]), t;
490
+ }
491
+ /**
492
+ * 合并多个waypoints进航线
493
+ * @param waypoints [{lat, lng}, {lat, lng}]
494
+ * @param route 航线 [[[lng, lat],[lng, lat]]]
495
+ */
496
+ static mergeWaypointsToRoute(e, t) {
497
+ for (const n of e)
498
+ t = this.mergeCoordinateToRoute(n, t);
499
+ return t;
500
+ }
501
+ /**
502
+ * 计算区间航线
503
+ * @param from {lng, lat}
504
+ * @param to {lng, lat}
505
+ * @param route [[[lng, lat]]]
506
+ * @return [[[lng, lat]]]
507
+ */
508
+ static calculateRangeRoute(e, t, n) {
509
+ const s = [];
510
+ let o = 0;
511
+ return n.forEach((i) => {
512
+ if (o === 2)
513
+ return;
514
+ const r = [];
515
+ for (const c of i) {
516
+ if (l.roundPrecision(t.lng, 8) === l.roundPrecision(c[0], 8) && l.roundPrecision(t.lat, 8) === l.roundPrecision(c[1], 8)) {
517
+ r.push(c), o === 0 && r.push([e.lng, e.lat]), o = 2;
518
+ break;
519
+ }
520
+ 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));
521
+ }
522
+ r.length && s.push(r);
523
+ }), s;
524
+ }
525
+ /**
526
+ * 计算from到to之间的航线
527
+ * @param from {lng, lat}
528
+ * @param to {lng, lat}
529
+ * @param route [[[lng, lat]]]
530
+ * @param waypoints
531
+ * @return [{lng, lat}]
532
+ */
533
+ static calculateRangeWaypoints(e, t, n, s = []) {
534
+ const o = this.convertRouteToCoordinates(n, 0), i = this.mergeCoordinatesToWaypoints([e, t, ...s], o), r = i.findIndex(
535
+ (d) => l.roundPrecision(e.lng, 8) === l.roundPrecision(d.lng, 8) && l.roundPrecision(e.lat, 8) === l.roundPrecision(d.lat, 8)
536
+ ), c = i.findIndex(
537
+ (d) => l.roundPrecision(t.lng, 8) === l.roundPrecision(d.lng, 8) && l.roundPrecision(t.lat, 8) === l.roundPrecision(d.lat, 8)
538
+ );
539
+ return i.filter((d, u) => u >= r && u <= c);
540
+ }
541
+ /**
542
+ * 计算坐标到航路上的最短距离
543
+ * @param from
544
+ * @param route
545
+ */
546
+ static calculateMinDistanceToRoute(e, t) {
547
+ let n = Number.MAX_VALUE, s = 0, o = 0;
548
+ return t.forEach((i, r) => {
549
+ for (let c = 0; c < i.length - 1; c++) {
550
+ const a = { lng: i[c][0], lat: i[c][1] }, d = { lng: i[c + 1][0], lat: i[c + 1][1] }, u = this.calculatePointToLineDistance(e, a, d);
551
+ n > u && (n = u, s = c, o = r);
552
+ }
553
+ }), { minDist: n, segIndex: o, minIndex: s };
554
+ }
555
+ /**
556
+ * 计算子航线
557
+ * @param from {lng, lat} 起始位置
558
+ * @param route [[[lng, lat]]] 剩余航线
559
+ * @return [[[lng, lat]]]
560
+ */
561
+ static calculateSubRoute(e, t) {
562
+ const { segIndex: n, minIndex: s } = this.calculateMinDistanceToRoute({ ...e }, t);
563
+ e.lng = l.convertToStdLng(e.lng);
564
+ const o = [];
565
+ let i = !0;
566
+ for (let r = n; r < t.length; r++)
567
+ if (i) {
568
+ const c = [];
569
+ c.push([e.lng, e.lat]);
570
+ for (let a = s + 1; a < t[r].length; a++)
571
+ e.lng === t[r][a][0] && e.lat === t[r][a][1] || c.push(t[r][a]);
572
+ o.push(c), i = !1;
573
+ } else
574
+ o.push([...t[r]]);
575
+ return o;
576
+ }
577
+ /**
578
+ * 计算子途经点
579
+ * @param from {lng, lat} 起始位置
580
+ * @param waypoints [{lng, lat}]
581
+ * @return [{lng, lat}]
582
+ */
583
+ static calculateSubWaypoints(e, t) {
584
+ let n = Number.MAX_VALUE, s = 0;
585
+ for (let i = 0; i < t.length - 1; i++) {
586
+ const r = t[i], c = t[i + 1];
587
+ if (this.calculateDistance(e, r) === 0)
588
+ return t;
589
+ if (this.calculateDistance(e, c) === 0)
590
+ return t.filter((d, u) => u > 0);
591
+ const a = this.calculatePointToLineDistance(e, r, c);
592
+ n > a && (n = a, s = i);
593
+ }
594
+ e.lng = l.convertToStdLng(e.lng);
595
+ const o = [e];
596
+ for (let i = s + 1; i < t.length; i++)
597
+ o.push(t[i]);
598
+ return o;
599
+ }
600
+ /**
601
+ * 计算坐标到以(from, to)横向线上的距离
602
+ * @param coordinate { lng, lat }
603
+ * @param from { lng, lat }
604
+ * @param to { lng, lat }
605
+ * @param options
606
+ */
607
+ static calculatePointToLineDistance(e, t, n, s = { units: "nauticalmiles", method: "geodesic" }) {
608
+ e.lng = l.convertToStdLng(e.lng), t = { ...t }, n = { ...n }, t.lng = l.convertToStdLng(t.lng, 8), n.lng = l.convertToStdLng(n.lng, 8);
609
+ const o = l.convertToMonotonicLng([t, n]);
610
+ t = o[0], n = o[1];
611
+ const i = g.lineString([
612
+ [t.lng, t.lat],
613
+ [n.lng, n.lat]
614
+ ]), r = g.pointToLineDistance(g.point([e.lng, e.lat]), i, s), c = g.pointToLineDistance(g.point([e.lng > 0 ? e.lng - 360 : e.lng + 360, e.lat]), i, s);
615
+ return l.roundPrecision(Math.min(r, c), 6);
616
+ }
617
+ /**
618
+ * 计算途经点的COG, Distance等属性
619
+ * @param waypoints
620
+ * @param route
621
+ */
622
+ static calculateWaypointsPropInRoute(e, t) {
623
+ t = this.mergeWaypointsToRoute(e, t);
624
+ for (let n = 0; n < e.length - 1; n++) {
625
+ const s = e[n], o = e[n + 1], i = this.calculateRangeRoute(s, o, t);
626
+ n === 0 && (s.distanceFromPrevious = 0, s.distanceFromStart = 0), o.distanceFromPrevious = this.calculateRouteDistance(i), o.distanceFromStart = l.roundPrecision((s.distanceFromStart || 0) + o.distanceFromPrevious);
627
+ }
628
+ return e;
629
+ }
630
+ /**
631
+ * @param coordinates [{lng, lat}]
632
+ * @param waypoints [{lng, lat}]
633
+ * @param replace true replace the same waypoint with coordinate
634
+ */
635
+ static mergeCoordinatesToWaypoints(e, t, n = !0) {
636
+ for (const s of e)
637
+ this.mergeCoordinateToWaypoints(s, t, n);
638
+ return t;
639
+ }
640
+ /**
641
+ * 合并坐标进航路途经点
642
+ * @param coordinate 坐标 {lng, lat}
643
+ * @param waypoints 途经点 [{lng, lat}, {lng, lat}]
644
+ *
645
+ * @example
646
+ * coordinate: { lng: 179, lat: 50 }
647
+ * waypoints: [{ lng: 160, lat: 30}, { lng: 170, lat: 40}, {lng: -170, lat: 40}, {lng: -160, lat: 30}]
648
+ * @param replace true replace the same waypoint with coordinate
649
+ * @return
650
+ * [{ lng: 160, lat: 30}, { lng: 170, lat: 40}, {lng: 179, lat: 50}, {lng: -170, lat: 40}, {lng: -160, lat: 30}]
651
+ */
652
+ static mergeCoordinateToWaypoints(e, t, n = !0) {
653
+ e.lng = l.convertToStdLng(e.lng, 8);
654
+ let s = Number.MAX_VALUE, o = 0, i = 0, r = 0;
655
+ for (let c = 0; c < t.length - 1; c++) {
656
+ 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);
657
+ s >= u && (s = u, o = c, i = this.calculateDistance(a, e, !1, 6), r = this.calculateDistance(d, e, !1, 6));
658
+ }
659
+ return i !== 0 && r !== 0 ? i < s || i === s && o === 0 ? t.unshift(e) : r < s || r === s && o === t.length - 2 ? t.push(e) : t.splice(o + 1, 0, e) : i === 0 ? n && t.splice(o, 1, e) : r === 0 && n && t.splice(o + 1, 1, e), t.map((c) => (c.lng = l.convertToStdLng(c.lng), c));
660
+ }
661
+ /**
662
+ * 生成航线(基于途经点生成大圆/横向航线,并根据是否跨180度分组)
663
+ * @param waypoints [{lng, lat}, {lng: lat, gcToPrevious: true}]
664
+ * @return [[[lng, lat], [lng, lat]]]
665
+ */
666
+ static generateRouteAccordingToWaypoints(e) {
667
+ const t = [];
668
+ for (let n = 1; n < e.length; n++) {
669
+ const s = e[n - 1], o = e[n];
670
+ if (n === 1 && t.push(s), o.gcToPrevious) {
671
+ const i = this.interpolateCoordinates(s, o, 200, !1, !0, "nauticalmiles");
672
+ t.push(...i);
673
+ } else
674
+ t.push(o);
675
+ }
676
+ return this.divideAccordingToLng(t, !0);
677
+ }
678
+ /**
679
+ * 最近点(从route中找出距离目标点最近的点)
680
+ * @param coordinate 目标点 {lng, lat}
681
+ * @param route [[[lng, lat]]]
682
+ */
683
+ static nearestCoordinateInRoute(e, t) {
684
+ const n = g.point([e.lng, e.lat]), s = [];
685
+ for (const c of t) {
686
+ const a = c.map((d) => g.point(d));
687
+ s.push(...a);
688
+ }
689
+ const o = g.featureCollection(s), i = g.nearestPoint(n, o), r = g.getCoord(i);
690
+ return { lng: r[0], lat: r[1] };
691
+ }
692
+ /**
693
+ * 计算经过方向上的最后一个waypoint
694
+ * @param from
695
+ * @param waypoints
696
+ */
697
+ static calculatePrevWaypoint(e, t) {
698
+ let n = 0;
699
+ this.mergeCoordinateToWaypoints(e, t);
700
+ for (let s = 0; s < t.length - 1; s++) {
701
+ const o = t[s], i = t[s + 1];
702
+ if (this.calculateDistance(e, o) === 0) {
703
+ n = s;
704
+ break;
705
+ }
706
+ if (this.calculateDistance(e, i) === 0) {
707
+ n = s + 1;
708
+ break;
709
+ }
710
+ }
711
+ return t[n === 0 ? 0 : n - 1];
712
+ }
713
+ /**
714
+ * 计算下一个距离单位的坐标及其子航线
715
+ * @param from 起点坐标 {lng, lat}
716
+ * @param distance 航行距离
717
+ * @param route [[[lng, lat]]]
718
+ * @param units
719
+ * @return { coordinate: {lng, lat}, route: [[[lng, lat]]]}
720
+ */
721
+ static calculateNextCoordinateAlongRoute(e, t, n, s = "nauticalmiles") {
722
+ var f;
723
+ const o = e.speed || 12, i = [];
724
+ let r = [], c = !1, a = 0, d = 0, u;
725
+ if (t && n.length ? (i.push(e), n.forEach((p, b) => {
726
+ if (c)
727
+ r.push(p);
728
+ else {
729
+ const T = [];
730
+ let P;
731
+ for (let m = 0; m < p.length; m++)
732
+ if (u)
733
+ T.push(p[m]);
734
+ else {
735
+ P = { lng: p[m][0], lat: p[m][1] };
736
+ const h = this.calculateDistance(e, P, !0, 8, s);
737
+ if (a += h, a < t)
738
+ d += h, i.push(P), e = P;
739
+ else {
740
+ if (d = t, a === t)
741
+ u = P, T.push([u.lng, u.lat]);
742
+ else {
743
+ const S = a - t, M = this.calculateBearing(P, e);
744
+ u = this.calculateCoordinate(P, M, S, s), T.push([u.lng, u.lat]), T.push([P.lng, P.lat]);
745
+ }
746
+ c = !0;
747
+ }
748
+ }
749
+ T.length && r.push(T), b === n.length - 1 && !u && (u = P);
750
+ }
751
+ })) : (r = n, u = { ...e }), u)
752
+ if (i.push(u), u.distanceFromPrevious = d, u.hourFromPrevious = Math.round(d / o * 1e4) / 1e4, ((f = r[0]) == null ? void 0 : f.length) > 1) {
753
+ const p = { lng: r[0][1][0], lat: r[0][1][1] };
754
+ u.bearing = this.calculateBearing(u, p);
755
+ } else
756
+ u.bearing = 0;
757
+ return { coordinate: u, nextRoute: r, prevRoute: i };
758
+ }
759
+ /**
760
+ * 返回最近点及其是否为垂足(最近点不是起点或终点)
761
+ * @param coordinate { lng, lat }
762
+ * @param from {lng, lat}
763
+ * @param to {lng, lat}
764
+ */
765
+ static nearestCoordinateInLine(e, t, n) {
766
+ const s = l.convertToStdLng(e.lng, 6), o = g.point([s, e.lat]), i = l.convertToStdLng(t.lng, 6), r = l.convertToStdLng(n.lng, 6), c = g.lineString([
767
+ [i, t.lat],
768
+ [r, n.lat]
769
+ ]), a = g.nearestPointOnLine(c, o), d = g.getCoord(a), u = l.roundPrecision(d[0], 6), f = l.roundPrecision(d[1], 6);
770
+ return { lng: u, lat: f, inline: !(u === i && f === t.lat) && !(u === r && f === n.lat) };
771
+ }
772
+ /**
773
+ * 将route转coordinate
774
+ * @param route
775
+ * @param distance 临近点过虑
776
+ */
777
+ static convertRouteToCoordinates(e, t = 0) {
778
+ const n = [];
779
+ let s, o;
780
+ return e.forEach((i) => {
781
+ i.forEach((r) => {
782
+ const c = { lng: r[0], lat: r[1] };
783
+ if (!o)
784
+ n.push(c), o = c;
785
+ else if (o.bearing === void 0)
786
+ o.bearing = this.calculateBearing(o, c, !0);
787
+ else {
788
+ const a = this.calculateDistance(s, c, !0);
789
+ a && a >= t && (s.bearing = this.calculateBearing(s, c, !0), n.push(s), o = s);
790
+ }
791
+ s = c;
792
+ });
793
+ }), s && n.push(s), n;
794
+ }
795
+ /**
796
+ * 抽稀(基于转向点)
797
+ * @param route [[lng, lat]]
798
+ * @param waypoints [{ lng, lat, gcToPrevious }]
799
+ * @param distance
800
+ */
801
+ static simplifyRouteToCoordinates(e, t, n = 1) {
802
+ let s = this.convertRouteToCoordinates(e, n);
803
+ return s = this.simplifyGCCoordinates(s, t), s;
804
+ }
805
+ /**
806
+ * 基于大圆标识抽稀
807
+ * @param coordinates
808
+ * @param waypoints
809
+ */
810
+ static simplifyGCCoordinates(e, t) {
811
+ t.forEach((s) => {
812
+ this.mergeCoordinateToWaypoints(s, e);
813
+ });
814
+ for (let s = 1; s < t.length; s++) {
815
+ const o = t[s - 1], i = t[s];
816
+ if (i.gcToPrevious) {
817
+ const r = e.findIndex((a) => a.lng === o.lng && a.lat === o.lat), c = e.findIndex((a) => a.lng === i.lng && a.lat === i.lat);
818
+ for (let a = c - 1; a > r; a--)
819
+ e.splice(a, 1);
820
+ }
821
+ }
822
+ let n = 0;
823
+ for (let s = 1; s < e.length; s++) {
824
+ const o = e[s - 1], i = e[s];
825
+ i.gcToPrevious ? (o.bearing = this.calculateBearing(o, i, !1), i.distanceFromPrevious = this.calculateDistance(o, i, !1)) : (o.bearing = this.calculateBearing(o, i, !0), i.distanceFromPrevious = this.calculateDistance(o, i, !0)), n = l.roundPrecision(n + i.distanceFromPrevious), i.distanceFromStart = n;
826
+ }
827
+ return e.map((s) => (s.lng = l.convertToStdLng(s.lng), s));
828
+ }
829
+ }
299
830
  export {
300
- u as LngLatHelper,
301
- x as TropicalHelper
831
+ W as LaneHelper,
832
+ l as LngLatHelper,
833
+ y as TropicalHelper
302
834
  };
@@ -1 +1 @@
1
- (function(h,g){typeof exports=="object"&&typeof module<"u"?g(exports,require("moment"),require("moment-timezone"),require("tz-lookup"),require("@turf/turf")):typeof define=="function"&&define.amd?define(["exports","moment","moment-timezone","tz-lookup","@turf/turf"],g):(h=typeof globalThis<"u"?globalThis:h||self,g(h["idm-plugin-rabbitmq"]={},h.moment,h["moment-timezone"],h["tz-lookup"],h["@turf/turf"]))})(this,function(h,g,j,T,O){"use strict";function w(b){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(b){for(const t in b)if(t!=="default"){const o=Object.getOwnPropertyDescriptor(b,t);Object.defineProperty(e,t,o.get?o:{enumerable:!0,get:()=>b[t]})}}return e.default=b,Object.freeze(e)}const y=w(O);class s{static guessTimeZoneOffset(e,t){const o=T(t,e),n=g().tz(o).utcOffset();return this.roundPrecision(n/60,1)}static prettyTimeZoneOffset(e){let t=Math.floor(Math.abs(e)),o=Math.round((Math.abs(e)-t)*60);return o=o>9?o:`0${o}`,t=t>9?t:`0${t}`,e>0?`+${t}:${o}`:`-${t}:${o}`}static lng2pretty(e,t=6,o="H°M′"){e=s.convertToStdLng(e,t);let n="E";e<0&&(n="W"),e=Math.abs(e),o=o.toUpperCase();let i=e*3600,r,u,c,a,m,p;r=i%3600%60,o.indexOf("S")!==-1&&(i=i-r,u=s.padNumber(r,2,2)),c=i/60%60,o.indexOf("M")!==-1&&(o.indexOf("S")!==-1?a=s.roundPrecision(c,t).toString().padStart(2,"0"):a=s.padNumber(c,2,2),i=i-c*60),m=i/3600,o.indexOf("M")!==-1?p=s.roundPrecision(m,t).toString().padStart(3,"0"):p=s.padNumber(m,3,2);const l=`${o.replace(/S+/gi,u).replace(/M+/gi,a).replace(/H+/gi,p)}${n}`;return{direction:n,degree:s.roundPrecision(m,t),minute:s.roundPrecision(c,t),second:s.roundPrecision(r,t),pretty:l}}static lat2pretty(e,t=6,o="H°M′"){e=e%180;let n="N";e<0&&(n="S"),e=Math.abs(e),o=o.toUpperCase();let i=e*3600,r,u,c,a,m,p;r=i%3600%60,o.indexOf("S")!==-1&&(i=i-r,u=s.padNumber(r,2,2)),c=i/60%60,o.indexOf("M")!==-1&&(o.indexOf("S")!==-1?a=s.roundPrecision(c,t).toString().padStart(2,"0"):a=s.padNumber(c,2,2),i=i-c*60),m=i/3600,o.indexOf("M")!==-1?p=s.roundPrecision(m,t).toString().padStart(2,"0"):p=s.padNumber(m,2,2);const l=`${o.replace(/S+/gi,u).replace(/M+/gi,a).replace(/H+/gi,p)}${n}`;return{direction:n,degree:s.roundPrecision(m,t),minute:s.roundPrecision(c,t),second:s.roundPrecision(r,t),pretty:l}}static str2Lng(e,t=6){let o;if(isNaN(e)){e=s.strReplace(e,"LNG");const n=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[r,u]=i;if(r>360&&!u){const c=this.roundPrecision(r/100,0);u=r-c*100,r=c}o=r+(u??0)/60,n==="W"&&(o=o*-1)}else o=Number(e);return s.convertToStdLng(o,t)}static str2Lat(e,t=6){let o;if(isNaN(e)){e=s.strReplace(e,"LAT");const n=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[r,u]=i;if(r>90&&!u){const c=this.roundPrecision(r/100,0);u=r-c*100,r=c}o=r+(u??0)/60,n==="S"&&(o=o*-1)}else o=Number(e);return s.roundPrecision(o,t)}static str2LngOrLat(e,t=6,o="LAT"){e=s.strReplace(e,o);const n=e[e.length-1].toUpperCase();return["N","S"].includes(n)?{lat:s.str2Lat(e,t)}:{lng:s.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),s.roundPrecision(e,t)}static roundPrecision(e,t=4){if(typeof e=="number"){const o=Number("1".padEnd(t+1,"0"));return Math.round(e*o)/o}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 o=e[e.length-1].toUpperCase();if(!["N","S","E","W"].includes(o)){const n=e,i=Number(n.split(" ")[0]);if(isNaN(i))throw new Error(`invalid Lat/Lng: ${e}`);i>=90?e=`${n}E`:i<=-90?e=`${n}W`:["LAN","LNG"].includes(t==null?void 0:t.toUpperCase())?e=`${n}${i>0?"E":"W"}`:e=`${n}${i>0?"N":"S"}`}return e}static padNumber(e,t=2,o=2){const n=Math.trunc(e).toString().padStart(t,"0"),i=Math.trunc(s.roundPrecision(e-Math.trunc(e),o)*Math.pow(10,o)).toString().padStart(o,"0");return`${n}.${i}`}}class k{static convert2Geojson(e){var o;const t=y.featureCollection([]);for(const n of e){if(n.forecasts){const i=(o=n.history)==null?void 0:o[0];for(const r of n.forecasts){const u=[],c=g(r.date).utc(),a=`${n.name}-${r.model}`;if(i){const m=g(i.updated).utc(),p=y.point([i.lng,i.lat],{model:r.model,name:n.name,date:m.format(),hour:0,format:m.format("MMM-DD/HHmm[Z]"),pressure:i.pressure>1e4?s.roundPrecision(i.pressure/100,0):s.roundPrecision(i.pressure,0),wind:{kts:i.kts,spd:i.speed||i.spd},category:a,type:"forecast"});t.features.push(p),u.push(p.geometry.coordinates)}for(const m in r==null?void 0:r.hours){const p=r.hours[m];p.wind.spd=p.wind.spd||p.wind.speed;const l=c.clone().add(Number(m),"hour"),M=y.point([p.lng,p.lat],{name:n.name,date:l.format(),hour:Number(m),format:l.format("MMM-DD/HHmm[Z]"),pressure:p.pressure>1e4?s.roundPrecision(p.pressure/100,0):s.roundPrecision(p.pressure,0),gusts:p.gusts,wind:p.wind||{},movement:p.movement,category:a,type:"forecast"});t.features.push(M),u.push(M.geometry.coordinates)}if((u==null?void 0:u.length)>1){const m=y.lineString(s.convertToMonotonicLng2(u),{date:r.date,id:n.id||n.name,model:r.model,name:n.name,category:a,type:"forecast"});t.features.push(m)}}}if(n.history){const i=[];for(const u of n.history){const c=g(u.updated).utc(),a=y.point([u.lng,u.lat],{name:n.name,date:c.format(),format:c.format("MMM-DD/HHmm[Z]"),pressure:u.pressure>1e4?s.roundPrecision(u.pressure/100,0):s.roundPrecision(u.pressure,0),spd:u.speed||u.spd,kts:u.kts,source:u.source,level:u.type,type:"history",category:`${n.name}-history`});t.features.push(a),i.push(a.geometry.coordinates)}const r=n.history[0];if(i.length===1&&i.push(i[0]),i.length>1){const u=y.lineString(s.convertToMonotonicLng2(i),{name:n.name,type:"history",updated:r==null?void 0:r.updated,pressure:(r==null?void 0:r.pressure)>1e4?s.roundPrecision((r==null?void 0:r.pressure)/100,0):s.roundPrecision(r==null?void 0:r.pressure,0),spd:(r==null?void 0:r.speed)||(r==null?void 0:r.spd),kts:r==null?void 0:r.kts,source:r==null?void 0:r.source,level:r==null?void 0:r.type});t.features.push(u)}}}return t}static interpolate(e,t=3){var i,r,u,c;const o=(i=e==null?void 0:e.data)==null?void 0:i.features.filter(a=>a.geometry.type==="LineString"&&a.properties.type==="forecast"),n=[];for(const a of o){const m=a.properties.name,p=a.properties.model,l=g(a.properties.date).utc();let M=t*60-(l.get("hour")*60+l.get("minute"))%(t*60);const P=(r=e==null?void 0:e.data)==null?void 0:r.features.filter(f=>!f.properties.disabled&&f.geometry.type==="Point"&&f.properties.type==="forecast"&&f.properties.category===`${m}-${p}`);let S,$=l.clone().add(M,"minute").set({minute:0,second:0,millisecond:0});for(;S=this.pickIndex(P,$),S<=P.length-1;){if(S>0){const f=P[S],d=S===0?void 0:P[S-1],N=(M/60-((u=d==null?void 0:d.properties)==null?void 0:u.hour))/(f.properties.hour-((c=d==null?void 0:d.properties)==null?void 0:c.hour)),D=this.computeNumber(d==null?void 0:d.geometry.coordinates[0],f.geometry.coordinates[0],N),z=this.computeNumber(d==null?void 0:d.geometry.coordinates[1],f.geometry.coordinates[1],N),C=y.point([D,z],{name:m,model:p,category:f==null?void 0:f.properties.category,date:$.format(),format:$.format("MMM-DD/HHmm[Z]"),gusts:this.computeNumber(d==null?void 0:d.properties.gusts,f.properties.gusts,N),hour:this.computeNumber(d==null?void 0:d.properties.hour,f.properties.hour,N),movement:this.computeNumber(d==null?void 0:d.properties.movement,f.properties.movement,N),pressure:this.computeNumber(d==null?void 0:d.properties.pressure,f.properties.pressure,N),wind:this.computeNumber(d==null?void 0:d.properties.wind,f.properties.wind,N),type:"forecast"});n.push(C)}M+=t*60,$=l.clone().add(M,"minute").set({minute:0,second:0,millisecond:0})}}return n}static pickIndex(e,t){let o=0;for(const n of e){if(g(n.properties.date).isAfter(t))return o===0?-1:o;o++}return o}static computeNumber(e,t,o){if(e)if(t){if(isNaN(e)&&isNaN(t)&&typeof e!="string"&&typeof t!="string"){const n={};for(const i in e)n[i]=this.computeNumber(e[i],t[i],o);return n}return Math.round((e+(t-e)*o)*100)/100}else return e;else return t}}h.LngLatHelper=s,h.TropicalHelper=k,Object.defineProperty(h,Symbol.toStringTag,{value:"Module"})});
1
+ (function(b,N){typeof exports=="object"&&typeof module<"u"?N(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"],N):(b=typeof globalThis<"u"?globalThis:b||self,N(b["idm-plugin-rabbitmq"]={},b["@turf/turf"],b.moment,b["moment-timezone"],b["tz-lookup"]))})(this,function(b,N,D,k,R){"use strict";function y(M){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(M){for(const t in M)if(t!=="default"){const n=Object.getOwnPropertyDescriptor(M,t);Object.defineProperty(e,t,n.get?n:{enumerable:!0,get:()=>M[t]})}}return e.default=M,Object.freeze(e)}const g=y(N);class l{static guessTimeZoneOffset(e,t){const n=R(t,e),s=D().tz(n).utcOffset();return this.roundPrecision(s/60,1)}static prettyTimeZoneOffset(e){let t=Math.floor(Math.abs(e)),n=Math.round((Math.abs(e)-t)*60);return n=n>9?n:`0${n}`,t=t>9?t:`0${t}`,e>0?`+${t}:${n}`:`-${t}:${n}`}static lng2pretty(e,t=6,n="H°M′"){e=l.convertToStdLng(e,t);let s="E";e<0&&(s="W"),e=Math.abs(e),n=n.toUpperCase();let o=e*3600,i,r,c,u,d,a;i=o%3600%60,n.indexOf("S")!==-1&&(o=o-i,r=l.padNumber(i,2,2)),c=o/60%60,n.indexOf("M")!==-1&&(n.indexOf("S")!==-1?u=l.roundPrecision(c,t).toString().padStart(2,"0"):u=l.padNumber(c,2,2),o=o-c*60),d=o/3600,n.indexOf("M")!==-1?a=l.roundPrecision(d,t).toString().padStart(3,"0"):a=l.padNumber(d,3,2);const h=`${n.replace(/S+/gi,r).replace(/M+/gi,u).replace(/H+/gi,a)}${s}`;return{direction:s,degree:l.roundPrecision(d,t),minute:l.roundPrecision(c,t),second:l.roundPrecision(i,t),pretty:h}}static lat2pretty(e,t=6,n="H°M′"){e=e%180;let s="N";e<0&&(s="S"),e=Math.abs(e),n=n.toUpperCase();let o=e*3600,i,r,c,u,d,a;i=o%3600%60,n.indexOf("S")!==-1&&(o=o-i,r=l.padNumber(i,2,2)),c=o/60%60,n.indexOf("M")!==-1&&(n.indexOf("S")!==-1?u=l.roundPrecision(c,t).toString().padStart(2,"0"):u=l.padNumber(c,2,2),o=o-c*60),d=o/3600,n.indexOf("M")!==-1?a=l.roundPrecision(d,t).toString().padStart(2,"0"):a=l.padNumber(d,2,2);const h=`${n.replace(/S+/gi,r).replace(/M+/gi,u).replace(/H+/gi,a)}${s}`;return{direction:s,degree:l.roundPrecision(d,t),minute:l.roundPrecision(c,t),second:l.roundPrecision(i,t),pretty:h}}static str2Lng(e,t=6){let n;if(isNaN(e)){e=l.strReplace(e,"LNG");const s=e[e.length-1].toUpperCase();e=e.substring(0,e.length-1).trim();const o=e.split(" ").filter(c=>c!=="").map(c=>Number(c));let[i,r]=o;if(i>360&&!r){const c=this.roundPrecision(i/100,0);r=i-c*100,i=c}n=i+(r??0)/60,s==="W"&&(n=n*-1)}else n=Number(e);return l.convertToStdLng(n,t)}static str2Lat(e,t=6){let n;if(isNaN(e)){e=l.strReplace(e,"LAT");const s=e[e.length-1].toUpperCase();e=e.substring(0,e.length-1).trim();const o=e.split(" ").filter(c=>c!=="").map(c=>Number(c));let[i,r]=o;if(i>90&&!r){const c=this.roundPrecision(i/100,0);r=i-c*100,i=c}n=i+(r??0)/60,s==="S"&&(n=n*-1)}else n=Number(e);return l.roundPrecision(n,t)}static str2LngOrLat(e,t=6,n="LAT"){e=l.strReplace(e,n);const s=e[e.length-1].toUpperCase();return["N","S"].includes(s)?{lat:l.str2Lat(e,t)}:{lng:l.str2Lng(e,t)}}static convertToStdLng(e,t=4){return e>180?(e=e%360,e=e>180?e-360:e):e<-180&&(e=e%360,e=e<-180?e+360:e),l.roundPrecision(e,t)}static roundPrecision(e,t=4){if(typeof e=="number"){const n=Number("1".padEnd(t+1,"0"));return Math.round(e*n)/n}return e}static convertToMonotonicLng2(e){for(let t=1;t<e.length;t++)e[t][0]+=Math.round((e[t-1][0]-e[t][0])/360)*360;return e}static convertToMonotonicLng(e){for(let t=1;t<e.length;t++)e[t].lng+=Math.round((e[t-1].lng-e[t].lng)/360)*360;return e}static strReplace(e,t="LAT"){e=e.replace(/([0-9]+)\.([0-9]+\.[0-9]+)/g,"$1 $2").replace(/-/g," ").replace(/°/," ").replace(/'/g," ").replace(/′/g," ").replace(/"/g," ").replace(/∼/g," ").replace(/°/g," ").replace(/,/g,".").replace(/^ /g,"").replace(/ $/g,"").trim();const n=e[e.length-1].toUpperCase();if(!["N","S","E","W"].includes(n)){const s=e,o=Number(s.split(" ")[0]);if(isNaN(o))throw new Error(`invalid Lat/Lng: ${e}`);o>=90?e=`${s}E`:o<=-90?e=`${s}W`:["LAN","LNG"].includes(t==null?void 0:t.toUpperCase())?e=`${s}${o>0?"E":"W"}`:e=`${s}${o>0?"N":"S"}`}return e}static padNumber(e,t=2,n=2){const s=Math.trunc(e).toString().padStart(t,"0"),o=Math.trunc(l.roundPrecision(e-Math.trunc(e),n)*Math.pow(10,n)).toString().padStart(n,"0");return`${s}.${o}`}}class x{static convert2Geojson(e){var n;const t=g.featureCollection([]);for(const s of e){if(s.forecasts){const o=(n=s.history)==null?void 0:n[0];for(const i of s.forecasts){const r=[],c=D(i.date).utc(),u=`${s.name}-${i.model}`;if(o){const d=D(o.updated).utc(),a=g.point([o.lng,o.lat],{model:i.model,name:s.name,date:d.format(),hour:0,format:d.format("MMM-DD/HHmm[Z]"),pressure:o.pressure>1e4?l.roundPrecision(o.pressure/100,0):l.roundPrecision(o.pressure,0),wind:{kts:o.kts,spd:o.speed||o.spd},category:u,type:"forecast"});t.features.push(a),r.push(a.geometry.coordinates)}for(const d in i==null?void 0:i.hours){const a=i.hours[d];a.wind.spd=a.wind.spd||a.wind.speed;const h=c.clone().add(Number(d),"hour"),p=g.point([a.lng,a.lat],{model:i.model,name:s.name,date:h.format(),hour:Number(d),format:h.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(p),r.push(p.geometry.coordinates)}if((r==null?void 0:r.length)>1){const d=g.lineString(l.convertToMonotonicLng2(r),{date:i.date,id:s.id||s.name,model:i.model,name:s.name,category:u,type:"forecast"});t.features.push(d)}}}if(s.history){const o=[];for(const r of s.history){const c=D(r.updated).utc(),u=g.point([r.lng,r.lat],{name:s.name,date:c.format(),format:c.format("MMM-DD/HHmm[Z]"),pressure:r.pressure>1e4?l.roundPrecision(r.pressure/100,0):l.roundPrecision(r.pressure,0),spd:r.speed||r.spd,kts:r.kts,source:r.source,level:r.type,type:"history",category:`${s.name}-history`});t.features.push(u),o.push(u.geometry.coordinates)}const i=s.history[0];if(o.length===1&&o.push(o[0]),o.length>1){const r=g.lineString(l.convertToMonotonicLng2(o),{name:s.name,type:"history",updated:i==null?void 0:i.updated,pressure:(i==null?void 0:i.pressure)>1e4?l.roundPrecision((i==null?void 0:i.pressure)/100,0):l.roundPrecision(i==null?void 0:i.pressure,0),spd:(i==null?void 0:i.speed)||(i==null?void 0:i.spd),kts:i==null?void 0:i.kts,source:i==null?void 0:i.source,level:i==null?void 0:i.type});t.features.push(r)}}}return t}static interpolate(e,t=3){var o,i,r,c;const n=(o=e==null?void 0:e.data)==null?void 0:o.features.filter(u=>u.geometry.type==="LineString"&&u.properties.type==="forecast"),s=[];for(const u of n){const d=u.properties.name,a=u.properties.model,h=D(u.properties.date).utc();let p=t*60-(h.get("hour")*60+h.get("minute"))%(t*60);const v=(i=e==null?void 0:e.data)==null?void 0:i.features.filter(m=>m.geometry.type==="Point"&&m.properties.type==="forecast"&&m.properties.category===`${d}-${a}`);let T,P=h.clone().add(p,"minute").set({minute:0,second:0,millisecond:0});for(;T=this.pickIndex(v,P),T<=v.length-1;){if(T>0){const m=v[T],f=T===0?void 0:v[T-1],S=(p/60-((r=f==null?void 0:f.properties)==null?void 0:r.hour))/(m.properties.hour-((c=f==null?void 0:f.properties)==null?void 0:c.hour)),C=this.computeNumber(f==null?void 0:f.geometry.coordinates[0],m.geometry.coordinates[0],S),I=this.computeNumber(f==null?void 0:f.geometry.coordinates[1],m.geometry.coordinates[1],S),W=g.point([C,I],{name:d,model:a,category:m==null?void 0:m.properties.category,date:P.format(),format:P.format("MMM-DD/HHmm[Z]"),gusts:this.computeNumber(f==null?void 0:f.properties.gusts,m.properties.gusts,S),hour:this.computeNumber(f==null?void 0:f.properties.hour,m.properties.hour,S),movement:this.computeNumber(f==null?void 0:f.properties.movement,m.properties.movement,S),pressure:this.computeNumber(f==null?void 0:f.properties.pressure,m.properties.pressure,S),wind:this.computeNumber(f==null?void 0:f.properties.wind,m.properties.wind,S),type:"forecast"});s.push(W)}p+=t*60,P=h.clone().add(p,"minute").set({minute:0,second:0,millisecond:0})}}return s}static pickIndex(e,t){let n=0;for(const s of e){if(D(s.properties.date).isAfter(t))return n===0?-1:n;n++}return n}static computeNumber(e,t,n){if(e)if(t){if(isNaN(e)&&isNaN(t)&&typeof e!="string"&&typeof t!="string"){const s={};for(const o in e)s[o]=this.computeNumber(e[o],t[o],n);return s}return Math.round((e+(t-e)*n)*100)/100}else return e;else return t}}class ${static calculateBearing(e,t,n=!0,s=4){const o=g.points([[e.lng,e.lat],[t.lng,t.lat]]);let i;return n?i=g.rhumbBearing(o.features[0],o.features[1]):i=g.bearing(o.features[0],o.features[1]),i<0&&(i+=360),l.roundPrecision(i,s)}static calculateDistance(e,t,n=!0,s=4,o="nauticalmiles"){e={...e},t={...t},e.lng=l.convertToStdLng(e.lng,s),t.lng=l.convertToStdLng(t.lng,s);const i=g.points([[e.lng,e.lat],[t.lng,t.lat]]);let r;return n?r=g.rhumbDistance(i.features[0],i.features[1],{units:o}):r=g.distance(i.features[0],i.features[1],{units:o}),l.roundPrecision(r,s)}static calculateRouteDistance(e,t=4,n="nauticalmiles"){let s=0,o;for(const i of e)for(let r=0;r<i.length-1;r++){const c={lng:i[r][0],lat:i[r][1]};r===0&&o&&(s+=this.calculateDistance(o,c,!0,t,n));const u={lng:i[r+1][0],lat:i[r+1][1]};s+=this.calculateDistance(c,u,!0,t,n),o=u}return l.roundPrecision(s,t)}static calculateCoordinate(e,t,n,s="nauticalmiles",o=!0){const i=g.point([e.lng,e.lat]);let r;o?r=g.rhumbDestination(i,n,t,{units:s}):r=g.destination(i,n,t,{units:s});const c=r.geometry.coordinates;return{lng:l.convertToStdLng(c[0],8),lat:l.roundPrecision(c[1],8)}}static interpolateCoordinates(e,t,n,s=!0,o=!0,i="nauticalmiles"){const r=[],c=this.calculateBearing(e,t,!1),u=this.calculateDistance(e,t,!1,8,i);s&&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,i,!1));return o&&r.push({lng:t.lng,lat:t.lat}),r}static divideAccordingToLng(e,t=!1){if((e==null?void 0:e.length)<2)return[];e=this.deduplicateCoordinates(e);let n=[];const s=[];let o,i;for(let r=0;r<e.length-1;r++){o=l.convertToStdLng(e[r].lng,8),i=l.convertToStdLng(e[r+1].lng,8),n.push([o,e[r].lat]);const c=o-i;if(Math.abs(c)>180){const u=l.convertToMonotonicLng2([[o,e[r].lat],[i,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 h=g.lineIntersect(d,a);let p;if(h.features.length){const v=g.getCoord(h.features[0]);p=l.roundPrecision(v[1],8)}else p=e[r].lat;c>0?(n.push([180-1e-6,p]),s.push([...n]),n=[],n.push([-(180-1e-6),p])):(n.push([-(180-1e-6),p]),s.push([...n]),n=[],n.push([180-1e-6,p]))}r===e.length-2&&n.push([i,e[r+1].lat])}return s.push(n),s}static deduplicateRoute(e){const t=[];for(const n of e){const s=n.reduce((o,i)=>(o.findIndex(r=>r[0]===i[0]&&r[1]===i[1])===-1&&o.push(i),o),[]);t.push(s)}return t}static deduplicateCoordinates(e){return e.reduce((t,n)=>(t.findIndex(s=>s.lat===n.lat&&s.lng===n.lng)===-1&&t.push(n),t),[])}static removeCoordinateFromRoute(e,t){e.lng=l.convertToStdLng(e.lng,8);for(const n of t)for(let s=n.length-1;s>=0;s--)l.roundPrecision(n[s][0],8)===e.lng&&l.roundPrecision(n[s][1],8)===l.roundPrecision(e.lat,8)&&n.splice(s,1);return t}static removeCoordinateFromWaypoints(e,t){e.lng=l.convertToStdLng(e.lng,8);for(let n=t.length-1;n>=0;n--)l.roundPrecision(t[n].lng,8)===e.lng&&l.roundPrecision(t[n].lat,8)===l.roundPrecision(e.lat,8)&&t.splice(n,1);return t}static mergeCoordinateToRoute(e,t){e.lng=l.convertToStdLng(e.lng,8);let n=Number.MAX_VALUE,s=0,o=0,i,r;return t.forEach((c,u)=>{for(let d=0;d<c.length-1;d++){const a={lng:c[d][0],lat:c[d][1]},h={lng:c[d+1][0],lat:c[d+1][1]},p=this.calculatePointToLineDistance(e,a,h);n>p&&(n=p,o=d,s=u,i=this.calculateDistance(a,e),r=this.calculateDistance(h,e))}}),i!==0&&r!==0?t[s].splice(o+1,0,[e.lng,e.lat]):i===0?t[s].splice(o,1,[e.lng,e.lat]):r===0&&t[s].splice(o+1,1,[e.lng,e.lat]),t}static mergeWaypointsToRoute(e,t){for(const n of e)t=this.mergeCoordinateToRoute(n,t);return t}static calculateRangeRoute(e,t,n){const s=[];let o=0;return n.forEach(i=>{if(o===2)return;const r=[];for(const c of i){if(l.roundPrecision(t.lng,8)===l.roundPrecision(c[0],8)&&l.roundPrecision(t.lat,8)===l.roundPrecision(c[1],8)){r.push(c),o===0&&r.push([e.lng,e.lat]),o=2;break}o===1?r.push(c):l.roundPrecision(e.lng,8)===l.roundPrecision(c[0],8)&&l.roundPrecision(e.lat,8)===l.roundPrecision(c[1],8)&&(o=1,r.push(c))}r.length&&s.push(r)}),s}static calculateRangeWaypoints(e,t,n,s=[]){const o=this.convertRouteToCoordinates(n,0),i=this.mergeCoordinatesToWaypoints([e,t,...s],o),r=i.findIndex(d=>l.roundPrecision(e.lng,8)===l.roundPrecision(d.lng,8)&&l.roundPrecision(e.lat,8)===l.roundPrecision(d.lat,8)),c=i.findIndex(d=>l.roundPrecision(t.lng,8)===l.roundPrecision(d.lng,8)&&l.roundPrecision(t.lat,8)===l.roundPrecision(d.lat,8));return i.filter((d,a)=>a>=r&&a<=c)}static calculateMinDistanceToRoute(e,t){let n=Number.MAX_VALUE,s=0,o=0;return t.forEach((i,r)=>{for(let c=0;c<i.length-1;c++){const u={lng:i[c][0],lat:i[c][1]},d={lng:i[c+1][0],lat:i[c+1][1]},a=this.calculatePointToLineDistance(e,u,d);n>a&&(n=a,s=c,o=r)}}),{minDist:n,segIndex:o,minIndex:s}}static calculateSubRoute(e,t){const{segIndex:n,minIndex:s}=this.calculateMinDistanceToRoute({...e},t);e.lng=l.convertToStdLng(e.lng);const o=[];let i=!0;for(let r=n;r<t.length;r++)if(i){const c=[];c.push([e.lng,e.lat]);for(let u=s+1;u<t[r].length;u++)e.lng===t[r][u][0]&&e.lat===t[r][u][1]||c.push(t[r][u]);o.push(c),i=!1}else o.push([...t[r]]);return o}static calculateSubWaypoints(e,t){let n=Number.MAX_VALUE,s=0;for(let i=0;i<t.length-1;i++){const r=t[i],c=t[i+1];if(this.calculateDistance(e,r)===0)return t;if(this.calculateDistance(e,c)===0)return t.filter((d,a)=>a>0);const u=this.calculatePointToLineDistance(e,r,c);n>u&&(n=u,s=i)}e.lng=l.convertToStdLng(e.lng);const o=[e];for(let i=s+1;i<t.length;i++)o.push(t[i]);return o}static calculatePointToLineDistance(e,t,n,s={units:"nauticalmiles",method:"geodesic"}){e.lng=l.convertToStdLng(e.lng),t={...t},n={...n},t.lng=l.convertToStdLng(t.lng,8),n.lng=l.convertToStdLng(n.lng,8);const o=l.convertToMonotonicLng([t,n]);t=o[0],n=o[1];const i=g.lineString([[t.lng,t.lat],[n.lng,n.lat]]),r=g.pointToLineDistance(g.point([e.lng,e.lat]),i,s),c=g.pointToLineDistance(g.point([e.lng>0?e.lng-360:e.lng+360,e.lat]),i,s);return l.roundPrecision(Math.min(r,c),6)}static calculateWaypointsPropInRoute(e,t){t=this.mergeWaypointsToRoute(e,t);for(let n=0;n<e.length-1;n++){const s=e[n],o=e[n+1],i=this.calculateRangeRoute(s,o,t);n===0&&(s.distanceFromPrevious=0,s.distanceFromStart=0),o.distanceFromPrevious=this.calculateRouteDistance(i),o.distanceFromStart=l.roundPrecision((s.distanceFromStart||0)+o.distanceFromPrevious)}return e}static mergeCoordinatesToWaypoints(e,t,n=!0){for(const s of e)this.mergeCoordinateToWaypoints(s,t,n);return t}static mergeCoordinateToWaypoints(e,t,n=!0){e.lng=l.convertToStdLng(e.lng,8);let s=Number.MAX_VALUE,o=0,i=0,r=0;for(let c=0;c<t.length-1;c++){const 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);s>=a&&(s=a,o=c,i=this.calculateDistance(u,e,!1,6),r=this.calculateDistance(d,e,!1,6))}return i!==0&&r!==0?i<s||i===s&&o===0?t.unshift(e):r<s||r===s&&o===t.length-2?t.push(e):t.splice(o+1,0,e):i===0?n&&t.splice(o,1,e):r===0&&n&&t.splice(o+1,1,e),t.map(c=>(c.lng=l.convertToStdLng(c.lng),c))}static generateRouteAccordingToWaypoints(e){const t=[];for(let n=1;n<e.length;n++){const s=e[n-1],o=e[n];if(n===1&&t.push(s),o.gcToPrevious){const i=this.interpolateCoordinates(s,o,200,!1,!0,"nauticalmiles");t.push(...i)}else t.push(o)}return this.divideAccordingToLng(t,!0)}static nearestCoordinateInRoute(e,t){const n=g.point([e.lng,e.lat]),s=[];for(const c of t){const u=c.map(d=>g.point(d));s.push(...u)}const o=g.featureCollection(s),i=g.nearestPoint(n,o),r=g.getCoord(i);return{lng:r[0],lat:r[1]}}static calculatePrevWaypoint(e,t){let n=0;this.mergeCoordinateToWaypoints(e,t);for(let s=0;s<t.length-1;s++){const o=t[s],i=t[s+1];if(this.calculateDistance(e,o)===0){n=s;break}if(this.calculateDistance(e,i)===0){n=s+1;break}}return t[n===0?0:n-1]}static calculateNextCoordinateAlongRoute(e,t,n,s="nauticalmiles"){var h;const o=e.speed||12,i=[];let r=[],c=!1,u=0,d=0,a;if(t&&n.length?(i.push(e),n.forEach((p,v)=>{if(c)r.push(p);else{const T=[];let P;for(let m=0;m<p.length;m++)if(a)T.push(p[m]);else{P={lng:p[m][0],lat:p[m][1]};const f=this.calculateDistance(e,P,!0,8,s);if(u+=f,u<t)d+=f,i.push(P),e=P;else{if(d=t,u===t)a=P,T.push([a.lng,a.lat]);else{const S=u-t,C=this.calculateBearing(P,e);a=this.calculateCoordinate(P,C,S,s),T.push([a.lng,a.lat]),T.push([P.lng,P.lat])}c=!0}}T.length&&r.push(T),v===n.length-1&&!a&&(a=P)}})):(r=n,a={...e}),a)if(i.push(a),a.distanceFromPrevious=d,a.hourFromPrevious=Math.round(d/o*1e4)/1e4,((h=r[0])==null?void 0:h.length)>1){const p={lng:r[0][1][0],lat:r[0][1][1]};a.bearing=this.calculateBearing(a,p)}else a.bearing=0;return{coordinate:a,nextRoute:r,prevRoute:i}}static nearestCoordinateInLine(e,t,n){const s=l.convertToStdLng(e.lng,6),o=g.point([s,e.lat]),i=l.convertToStdLng(t.lng,6),r=l.convertToStdLng(n.lng,6),c=g.lineString([[i,t.lat],[r,n.lat]]),u=g.nearestPointOnLine(c,o),d=g.getCoord(u),a=l.roundPrecision(d[0],6),h=l.roundPrecision(d[1],6);return{lng:a,lat:h,inline:!(a===i&&h===t.lat)&&!(a===r&&h===n.lat)}}static convertRouteToCoordinates(e,t=0){const n=[];let s,o;return e.forEach(i=>{i.forEach(r=>{const c={lng:r[0],lat:r[1]};if(!o)n.push(c),o=c;else if(o.bearing===void 0)o.bearing=this.calculateBearing(o,c,!0);else{const u=this.calculateDistance(s,c,!0);u&&u>=t&&(s.bearing=this.calculateBearing(s,c,!0),n.push(s),o=s)}s=c})}),s&&n.push(s),n}static simplifyRouteToCoordinates(e,t,n=1){let s=this.convertRouteToCoordinates(e,n);return s=this.simplifyGCCoordinates(s,t),s}static simplifyGCCoordinates(e,t){t.forEach(s=>{this.mergeCoordinateToWaypoints(s,e)});for(let s=1;s<t.length;s++){const o=t[s-1],i=t[s];if(i.gcToPrevious){const r=e.findIndex(u=>u.lng===o.lng&&u.lat===o.lat),c=e.findIndex(u=>u.lng===i.lng&&u.lat===i.lat);for(let u=c-1;u>r;u--)e.splice(u,1)}}let n=0;for(let s=1;s<e.length;s++){const o=e[s-1],i=e[s];i.gcToPrevious?(o.bearing=this.calculateBearing(o,i,!1),i.distanceFromPrevious=this.calculateDistance(o,i,!1)):(o.bearing=this.calculateBearing(o,i,!0),i.distanceFromPrevious=this.calculateDistance(o,i,!0)),n=l.roundPrecision(n+i.distanceFromPrevious),i.distanceFromStart=n}return e.map(s=>(s.lng=l.convertToStdLng(s.lng),s))}}b.LaneHelper=$,b.LngLatHelper=l,b.TropicalHelper=x,Object.defineProperty(b,Symbol.toStringTag,{value:"Module"})});
@@ -0,0 +1,263 @@
1
+ /**
2
+ * 坐标
3
+ */
4
+ export interface Coordinate {
5
+ lng: number;
6
+ lat: number;
7
+ distanceFromPrevious?: number;
8
+ distanceFromStart?: number;
9
+ gcToPrevious?: boolean;
10
+ speed?: number;
11
+ sog?: number;
12
+ hourFromPrevious?: number;
13
+ bearing?: number;
14
+ important?: boolean;
15
+ suspend?: number;
16
+ velocity?: number;
17
+ }
18
+ export declare class LaneHelper {
19
+ /**
20
+ * 计算方位角
21
+ * @param from 坐标 {lng, lat}
22
+ * @param to 坐标 {lng, lat}
23
+ * @param rhumb true 横向方位角,false 大圆方位角
24
+ * @param precision
25
+ * @returns {number} 单位度
26
+ */
27
+ static calculateBearing(from: Coordinate, to: Coordinate, rhumb?: boolean, precision?: number): number;
28
+ /**
29
+ * 计算两点间距离
30
+ * @param from 坐标 {lng, lat}
31
+ * @param to 坐标 {lng, lat}
32
+ * @param rhumb true 横向距离,false 大圆距离
33
+ * @param precision
34
+ * @param units 单位,默认 nm(海里)
35
+ * @returns {number}
36
+ */
37
+ static calculateDistance(from: Coordinate, to: Coordinate, rhumb?: boolean, precision?: number, units?: string): number;
38
+ /**
39
+ * 计算航线距离
40
+ * @param route [[[lng, lat],[lng, lat]]]
41
+ * @param precision
42
+ * @param units
43
+ */
44
+ static calculateRouteDistance(route: number[][][], precision?: number, units?: string): number;
45
+ /**
46
+ * 计算坐标(基于方位角和距离)
47
+ * @param from 坐标 {lng, lat}
48
+ * @param bearing 方位角,单位度
49
+ * @param distance 距离
50
+ * @param units 单位,默认 nm(海里)
51
+ * @param rhumb
52
+ */
53
+ static calculateCoordinate(from: Coordinate, bearing: number, distance: number, units?: any, rhumb?: boolean): {
54
+ lng: number;
55
+ lat: number;
56
+ };
57
+ /**
58
+ * 插值大圆坐标(基于两点方位角和间距)
59
+ * @param from 坐标 {lng, lat}
60
+ * @param to 坐标 {lng, lat}
61
+ * @param spacing 间距
62
+ * @param includeHead true 包含起点 from
63
+ * @param includeTail true 包含终点 to
64
+ * @param units 单位,默认 nm(海里)
65
+ */
66
+ static interpolateCoordinates(from: Coordinate, to: Coordinate, spacing: number, includeHead?: boolean, includeTail?: boolean, units?: string): {
67
+ lng: number;
68
+ lat: number;
69
+ }[];
70
+ /**
71
+ * 分组坐标(如相邻两个坐标经度差超180度,需以180为界将坐标分为两组)
72
+ * @param coordinates [{lng, lat}]
73
+ * @param rhumb
74
+ * @example
75
+ * coordinates: [{lng: 160,lat: 30}, {lng: 170, lat: 40},{lng: -170, lat: 40},{lng: -160, lat: 30}]
76
+ * @return [
77
+ * [[160, 30],[170,40]],
78
+ * [[-170,40],[-160,30]]
79
+ * ]
80
+ */
81
+ static divideAccordingToLng(coordinates: Array<Coordinate>, rhumb?: boolean): number[][][];
82
+ /**
83
+ * 去除重复坐标
84
+ * @param route
85
+ */
86
+ static deduplicateRoute(route: number[][][]): any;
87
+ /**
88
+ * 去除重新坐标
89
+ * @param coordinates
90
+ */
91
+ static deduplicateCoordinates(coordinates: Array<Coordinate>): Array<Coordinate>;
92
+ /**
93
+ * 移出坐标
94
+ * @param coordinate {lng, lat}
95
+ * @param route 航线[[[lng, lat],[lng, lat]]]
96
+ */
97
+ static removeCoordinateFromRoute(coordinate: Coordinate, route: number[][][]): number[][][];
98
+ /**
99
+ * 移出坐标
100
+ * @param coordinate {lng, lat}
101
+ * @param waypoints [{lat, lng}, {lat, lng}]
102
+ */
103
+ static removeCoordinateFromWaypoints(coordinate: Coordinate, waypoints: Coordinate[]): Coordinate[];
104
+ /**
105
+ * 合并坐标进航线(基于坐标到线段最短距离边合并)
106
+ * @param coordinate 待合并的坐标 {lng, lat}
107
+ * @param route 航线[[[lng, lat],[lng, lat]]]
108
+ * @example
109
+ * coordinate {lng: 122, lat: 35}
110
+ *
111
+ * route: [[[120, 30], [125,40], [130, 37]], [[-150, 40], [-130, 30]]]
112
+ * @return
113
+ * [[[120, 30], [120, 35], [125,40], [130, 37]], [[-150, 40], [-130, 30]]]
114
+ */
115
+ static mergeCoordinateToRoute(coordinate: Coordinate, route: number[][][]): number[][][];
116
+ /**
117
+ * 合并多个waypoints进航线
118
+ * @param waypoints [{lat, lng}, {lat, lng}]
119
+ * @param route 航线 [[[lng, lat],[lng, lat]]]
120
+ */
121
+ static mergeWaypointsToRoute(waypoints: Coordinate[], route: number[][][]): number[][][];
122
+ /**
123
+ * 计算区间航线
124
+ * @param from {lng, lat}
125
+ * @param to {lng, lat}
126
+ * @param route [[[lng, lat]]]
127
+ * @return [[[lng, lat]]]
128
+ */
129
+ static calculateRangeRoute(from: Coordinate, to: Coordinate, route: number[][][]): number[][][];
130
+ /**
131
+ * 计算from到to之间的航线
132
+ * @param from {lng, lat}
133
+ * @param to {lng, lat}
134
+ * @param route [[[lng, lat]]]
135
+ * @param waypoints
136
+ * @return [{lng, lat}]
137
+ */
138
+ static calculateRangeWaypoints(from: Coordinate, to: Coordinate, route: number[][][], waypoints?: Coordinate[]): any[];
139
+ /**
140
+ * 计算坐标到航路上的最短距离
141
+ * @param from
142
+ * @param route
143
+ */
144
+ static calculateMinDistanceToRoute(from: Coordinate, route: number[][][]): {
145
+ minDist: number;
146
+ segIndex: number;
147
+ minIndex: number;
148
+ };
149
+ /**
150
+ * 计算子航线
151
+ * @param from {lng, lat} 起始位置
152
+ * @param route [[[lng, lat]]] 剩余航线
153
+ * @return [[[lng, lat]]]
154
+ */
155
+ static calculateSubRoute(from: Coordinate, route: number[][][]): number[][][];
156
+ /**
157
+ * 计算子途经点
158
+ * @param from {lng, lat} 起始位置
159
+ * @param waypoints [{lng, lat}]
160
+ * @return [{lng, lat}]
161
+ */
162
+ static calculateSubWaypoints(from: Coordinate, waypoints: Coordinate[]): Coordinate[];
163
+ /**
164
+ * 计算坐标到以(from, to)横向线上的距离
165
+ * @param coordinate { lng, lat }
166
+ * @param from { lng, lat }
167
+ * @param to { lng, lat }
168
+ * @param options
169
+ */
170
+ static calculatePointToLineDistance(coordinate: Coordinate, from: Coordinate, to: Coordinate, options?: {
171
+ units: any;
172
+ method: any;
173
+ }): number;
174
+ /**
175
+ * 计算途经点的COG, Distance等属性
176
+ * @param waypoints
177
+ * @param route
178
+ */
179
+ static calculateWaypointsPropInRoute(waypoints: Coordinate[], route: number[][][]): Coordinate[];
180
+ /**
181
+ * @param coordinates [{lng, lat}]
182
+ * @param waypoints [{lng, lat}]
183
+ * @param replace true replace the same waypoint with coordinate
184
+ */
185
+ static mergeCoordinatesToWaypoints(coordinates: Coordinate[], waypoints: Coordinate[], replace?: boolean): Coordinate[];
186
+ /**
187
+ * 合并坐标进航路途经点
188
+ * @param coordinate 坐标 {lng, lat}
189
+ * @param waypoints 途经点 [{lng, lat}, {lng, lat}]
190
+ *
191
+ * @example
192
+ * coordinate: { lng: 179, lat: 50 }
193
+ * waypoints: [{ lng: 160, lat: 30}, { lng: 170, lat: 40}, {lng: -170, lat: 40}, {lng: -160, lat: 30}]
194
+ * @param replace true replace the same waypoint with coordinate
195
+ * @return
196
+ * [{ lng: 160, lat: 30}, { lng: 170, lat: 40}, {lng: 179, lat: 50}, {lng: -170, lat: 40}, {lng: -160, lat: 30}]
197
+ */
198
+ static mergeCoordinateToWaypoints(coordinate: Coordinate, waypoints: Coordinate[], replace?: boolean): Coordinate[];
199
+ /**
200
+ * 生成航线(基于途经点生成大圆/横向航线,并根据是否跨180度分组)
201
+ * @param waypoints [{lng, lat}, {lng: lat, gcToPrevious: true}]
202
+ * @return [[[lng, lat], [lng, lat]]]
203
+ */
204
+ static generateRouteAccordingToWaypoints(waypoints: Coordinate[]): number[][][];
205
+ /**
206
+ * 最近点(从route中找出距离目标点最近的点)
207
+ * @param coordinate 目标点 {lng, lat}
208
+ * @param route [[[lng, lat]]]
209
+ */
210
+ static nearestCoordinateInRoute(coordinate: Coordinate, route: number[][][]): {
211
+ lng: number;
212
+ lat: number;
213
+ };
214
+ /**
215
+ * 计算经过方向上的最后一个waypoint
216
+ * @param from
217
+ * @param waypoints
218
+ */
219
+ static calculatePrevWaypoint(from: Coordinate, waypoints: Coordinate[]): Coordinate;
220
+ /**
221
+ * 计算下一个距离单位的坐标及其子航线
222
+ * @param from 起点坐标 {lng, lat}
223
+ * @param distance 航行距离
224
+ * @param route [[[lng, lat]]]
225
+ * @param units
226
+ * @return { coordinate: {lng, lat}, route: [[[lng, lat]]]}
227
+ */
228
+ static calculateNextCoordinateAlongRoute(from: Coordinate, distance: number, route: number[][][], units?: string): {
229
+ coordinate: Coordinate | undefined;
230
+ nextRoute: number[][][];
231
+ prevRoute: Coordinate[];
232
+ };
233
+ /**
234
+ * 返回最近点及其是否为垂足(最近点不是起点或终点)
235
+ * @param coordinate { lng, lat }
236
+ * @param from {lng, lat}
237
+ * @param to {lng, lat}
238
+ */
239
+ static nearestCoordinateInLine(coordinate: Coordinate, from: Coordinate, to: Coordinate): {
240
+ lng: number;
241
+ lat: number;
242
+ inline: boolean;
243
+ };
244
+ /**
245
+ * 将route转coordinate
246
+ * @param route
247
+ * @param distance 临近点过虑
248
+ */
249
+ static convertRouteToCoordinates(route: number[][][], distance?: number): Coordinate[];
250
+ /**
251
+ * 抽稀(基于转向点)
252
+ * @param route [[lng, lat]]
253
+ * @param waypoints [{ lng, lat, gcToPrevious }]
254
+ * @param distance
255
+ */
256
+ static simplifyRouteToCoordinates(route: number[][][], waypoints: Coordinate[], distance?: number): Coordinate[];
257
+ /**
258
+ * 基于大圆标识抽稀
259
+ * @param coordinates
260
+ * @param waypoints
261
+ */
262
+ static simplifyGCCoordinates(coordinates: Coordinate[], waypoints: Coordinate[]): Coordinate[];
263
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@idm-plugin/geo",
3
3
  "private": false,
4
- "version": "1.0.4",
4
+ "version": "1.0.6",
5
5
  "description": "idm plugin for geo",
6
6
  "type": "module",
7
7
  "keywords": [