@hybridcore/ui 1.6.13 → 1.6.16
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/AccordionSummary-DUtr16g6.js +781 -0
- package/dist/Add-Bk8R160M.js +403 -0
- package/dist/Button-Cem3nbwc.js +357 -0
- package/dist/ButtonBase-DObmf4Q_.js +886 -0
- package/dist/Delete-CVJ6FeDn.js +203 -0
- package/dist/FormGroup-BRj1o7-E.js +89 -0
- package/dist/InputLabel-CjD30ZHz.js +341 -0
- package/dist/MenuItem-BKvRGLvM.js +233 -0
- package/dist/Modal-BVYydOr5.js +1156 -0
- package/dist/Paper-B1HV8GyO.js +582 -0
- package/dist/Select-Bfhvigsx.js +3914 -0
- package/dist/Source-BSZST_GH.js +4410 -0
- package/dist/SwitchBase-BEK49kdS.js +235 -0
- package/dist/Text-ChJRuaD8.js +2197 -0
- package/dist/TextField-Ca9ykixI.js +696 -0
- package/dist/TransitionGroupContext-Ja2CgIob.js +96 -0
- package/dist/Typography-D3X-Y5fh.js +178 -0
- package/dist/Vector-BmuhQO4p.js +3606 -0
- package/dist/Vector-DfTqQEln.js +1735 -0
- package/dist/WKT-2wsDT-nq.js +2310 -0
- package/dist/{_commonjsHelpers-BVfed4GL.js → _commonjsHelpers-BkfeUUK-.js} +2 -2
- package/dist/assertThisInitialized-C1dAyb4j.js +7 -0
- package/dist/assets/index.css +1 -1
- package/dist/assets/index2.css +1 -1
- package/dist/assets/index3.css +1 -0
- package/dist/assets/index4.css +1 -0
- package/dist/clsx-OuTLNxxd.js +16 -0
- package/dist/components/button/styled.js +1 -1
- package/dist/components/charts/_common/format.js +126 -82
- package/dist/components/charts/_common/tooltip.js +44 -35
- package/dist/components/charts/chart-wrapper/index.js +44 -43
- package/dist/components/charts/donut-chart/logic.js +53 -40
- package/dist/components/charts/drill-down-voronoi-treemap/logic.js +1 -1
- package/dist/components/charts/xy-chart/logic.js +135 -134
- package/dist/components/collapsible-card/index.js +30 -21
- package/dist/components/collapsible-card/styled.js +14 -16
- package/dist/components/color-picker/index.js +3358 -2228
- package/dist/components/color-picker/styled.js +7 -87
- package/dist/components/confirm/dialog.js +7 -89
- package/dist/components/confirm/index.js +1 -1
- package/dist/components/data-map/index.js +1 -1
- package/dist/components/data-map/logic.js +20 -20
- package/dist/components/data-security-selectors/dissemination-list/index.js +3117 -32
- package/dist/components/date-range-picker/index.js +454 -466
- package/dist/components/document-viewer/components/viewer/index.js +1 -1
- package/dist/components/duration-select/index.js +10 -10
- package/dist/components/duration-select/styled.js +1 -1
- package/dist/components/geometry-picker/coordinate/index.js +14 -14
- package/dist/components/geometry-picker/edit/index.js +1 -1
- package/dist/components/geometry-picker/geometry/index.js +1 -1
- package/dist/components/geometry-picker/kml/index.js +11 -11
- package/dist/components/geometry-picker/map/logic.js +3656 -145
- package/dist/components/geometry-picker/map/style.js +17 -18
- package/dist/components/geometry-picker/parser/coordinate-input/logic.js +1255 -43
- package/dist/components/heat-map/index.js +1 -1
- package/dist/components/heat-map/logic.js +1924 -77
- package/dist/components/instance-form/components/composite-matrix/components/json-editor/index.js +8737 -8722
- package/dist/components/instance-hierarchy-table/styled.js +16 -18
- package/dist/components/map/helpers/mapbox.js +15 -17
- package/dist/components/map/helpers/ol.js +27 -386
- package/dist/components/map/index.js +10 -11
- package/dist/components/map/logic.js +22 -22
- package/dist/components/map/styled.js +27 -31
- package/dist/components/phone-input/index.js +9 -10
- package/dist/components/property-mapping/index.js +1 -1
- package/dist/components/prr-map/index.js +1 -1
- package/dist/components/prr-map/logic.js +26 -27
- package/dist/components/raster-grid-map/index.js +1 -1
- package/dist/components/raster-grid-map/logic.js +57 -60
- package/dist/components/sortable-list/index.js +1264 -1091
- package/dist/components/template-form/components/property-list/index.js +32 -36
- package/dist/components/template-form/components/property-list/property-list-columns.js +17 -19
- package/dist/components/template-form/components/property-list/property-list-form.js +600 -137
- package/dist/components/template-form/components/recognition-property-list/index.js +36 -40
- package/dist/components/template-form/components/recognition-property-list/recognition-property-list-columns.js +9 -11
- package/dist/components/template-form/components/recognition-property-list/recognition-property-list-form.js +64 -57
- package/dist/components/tree-select/index.js +16 -16
- package/dist/createChainedFunction-C0nujS3O.js +9 -0
- package/dist/createSvgIcon-BghzB2Y9.js +93 -0
- package/dist/createSvgIcon-D7U1nd99.js +185 -0
- package/dist/debounce-46wSf_lW.js +15 -0
- package/dist/dialog-BtJhjyF5.js +664 -0
- package/dist/extends-C3382pL0.js +22 -0
- package/dist/formControlState-vgaj2ksH.js +10 -0
- package/dist/generateUtilityClasses-Cc-owZ4J.js +2971 -0
- package/dist/{index-C__OZmYy.js → index-CblbdqjE.js} +1 -1
- package/dist/index-DH6qsPBn.js +153 -0
- package/dist/index.esm-DAf19hyR.js +318 -0
- package/dist/main.d.ts +9 -1
- package/dist/math-Bvt2Ubuz.js +704 -0
- package/dist/ol-yOE-NV0X.js +7465 -0
- package/dist/ownerWindow-wg6foiOE.js +10 -0
- package/dist/setPrototypeOf-NPgp4cYc.js +8 -0
- package/dist/styled-DD4BkuVf.js +350 -0
- package/dist/useControlled-BYdyS7Pn.js +31 -0
- package/dist/useFormControl-CatNKXAi.js +10 -0
- package/dist/useId-BW-oWmul.js +19 -0
- package/dist/useSlot-u4t0X96G.js +42 -0
- package/package.json +1 -1
- package/dist/index.esm-UfGMjYOL.js +0 -197
|
@@ -1,38 +1,1250 @@
|
|
|
1
|
-
import { useState as
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { useState as ht, useEffect as ct } from "react";
|
|
2
|
+
let ut = " ";
|
|
3
|
+
class h {
|
|
4
|
+
// note Unicode Degree = U+00B0. Prime = U+2032, Double prime = U+2033
|
|
5
|
+
/**
|
|
6
|
+
* Separator character to be used to separate degrees, minutes, seconds, and cardinal directions.
|
|
7
|
+
*
|
|
8
|
+
* Default separator is U+202F ‘narrow no-break space’.
|
|
9
|
+
*
|
|
10
|
+
* To change this (e.g. to empty string or full space), set Dms.separator prior to invoking
|
|
11
|
+
* formatting.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* import LatLon, { Dms } from '/js/geodesy/latlon-spherical.js';
|
|
15
|
+
* const p = new LatLon(51.2, 0.33).toString('dms'); // 51° 12′ 00″ N, 000° 19′ 48″ E
|
|
16
|
+
* Dms.separator = ''; // no separator
|
|
17
|
+
* const pʹ = new LatLon(51.2, 0.33).toString('dms'); // 51°12′00″N, 000°19′48″E
|
|
18
|
+
*/
|
|
19
|
+
static get separator() {
|
|
20
|
+
return ut;
|
|
21
|
+
}
|
|
22
|
+
static set separator(t) {
|
|
23
|
+
ut = t;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Parses string representing degrees/minutes/seconds into numeric degrees.
|
|
27
|
+
*
|
|
28
|
+
* This is very flexible on formats, allowing signed decimal degrees, or deg-min-sec optionally
|
|
29
|
+
* suffixed by compass direction (NSEW); a variety of separators are accepted. Examples -3.62,
|
|
30
|
+
* '3 37 12W', '3°37′12″W'.
|
|
31
|
+
*
|
|
32
|
+
* Thousands/decimal separators must be comma/dot; use Dms.fromLocale to convert locale-specific
|
|
33
|
+
* thousands/decimal separators.
|
|
34
|
+
*
|
|
35
|
+
* @param {string|number} dms - Degrees or deg/min/sec in variety of formats.
|
|
36
|
+
* @returns {number} Degrees as decimal number.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* const lat = Dms.parse('51° 28′ 40.37″ N');
|
|
40
|
+
* const lon = Dms.parse('000° 00′ 05.29″ W');
|
|
41
|
+
* const p1 = new LatLon(lat, lon); // 51.4779°N, 000.0015°W
|
|
42
|
+
*/
|
|
43
|
+
static parse(t) {
|
|
44
|
+
if (!isNaN(parseFloat(t)) && isFinite(t)) return Number(t);
|
|
45
|
+
const n = String(t).trim().replace(/^-/, "").replace(/[NSEW]$/i, "").split(/[^0-9.,]+/);
|
|
46
|
+
if (n[n.length - 1] == "" && n.splice(n.length - 1), n == "") return NaN;
|
|
47
|
+
let s = null;
|
|
48
|
+
switch (n.length) {
|
|
49
|
+
case 3:
|
|
50
|
+
s = n[0] / 1 + n[1] / 60 + n[2] / 3600;
|
|
51
|
+
break;
|
|
52
|
+
case 2:
|
|
53
|
+
s = n[0] / 1 + n[1] / 60;
|
|
54
|
+
break;
|
|
55
|
+
case 1:
|
|
56
|
+
s = n[0];
|
|
57
|
+
break;
|
|
58
|
+
default:
|
|
59
|
+
return NaN;
|
|
60
|
+
}
|
|
61
|
+
return /^-|[WS]$/i.test(t.trim()) && (s = -s), Number(s);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Converts decimal degrees to deg/min/sec format
|
|
65
|
+
* - degree, prime, double-prime symbols are added, but sign is discarded, though no compass
|
|
66
|
+
* direction is added.
|
|
67
|
+
* - degrees are zero-padded to 3 digits; for degrees latitude, use .slice(1) to remove leading
|
|
68
|
+
* zero.
|
|
69
|
+
*
|
|
70
|
+
* @private
|
|
71
|
+
* @param {number} deg - Degrees to be formatted as specified.
|
|
72
|
+
* @param {string} [format=d] - Return value as 'd', 'dm', 'dms' for deg, deg+min, deg+min+sec.
|
|
73
|
+
* @param {number} [dp=4|2|0] - Number of decimal places to use – default 4 for d, 2 for dm, 0 for dms.
|
|
74
|
+
* @returns {string} Degrees formatted as deg/min/secs according to specified format.
|
|
75
|
+
*/
|
|
76
|
+
static toDms(t, n = "d", s = void 0) {
|
|
77
|
+
if (isNaN(t) || typeof t == "string" && t.trim() == "" || typeof t == "boolean" || t == 1 / 0 || t == null) return null;
|
|
78
|
+
if (s === void 0)
|
|
79
|
+
switch (n) {
|
|
80
|
+
case "d":
|
|
81
|
+
case "deg":
|
|
82
|
+
s = 4;
|
|
83
|
+
break;
|
|
84
|
+
case "dm":
|
|
85
|
+
case "deg+min":
|
|
86
|
+
s = 2;
|
|
87
|
+
break;
|
|
88
|
+
case "dms":
|
|
89
|
+
case "deg+min+sec":
|
|
90
|
+
s = 0;
|
|
91
|
+
break;
|
|
92
|
+
default:
|
|
93
|
+
n = "d", s = 4;
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
t = Math.abs(t);
|
|
97
|
+
let e = null, i = null, r = null, a = null;
|
|
98
|
+
switch (n) {
|
|
99
|
+
default:
|
|
100
|
+
case "d":
|
|
101
|
+
case "deg":
|
|
102
|
+
i = t.toFixed(s), i < 100 && (i = "0" + i), i < 10 && (i = "0" + i), e = i + "°";
|
|
103
|
+
break;
|
|
104
|
+
case "dm":
|
|
105
|
+
case "deg+min":
|
|
106
|
+
i = Math.floor(t), r = (t * 60 % 60).toFixed(s), r == 60 && (r = 0 .toFixed(s), i++), i = ("000" + i).slice(-3), r < 10 && (r = "0" + r), e = i + "°" + h.separator + r + "′";
|
|
107
|
+
break;
|
|
108
|
+
case "dms":
|
|
109
|
+
case "deg+min+sec":
|
|
110
|
+
i = Math.floor(t), r = Math.floor(t * 3600 / 60) % 60, a = (t * 3600 % 60).toFixed(s), a == 60 && (a = 0 .toFixed(s), r++), r == 60 && (r = 0, i++), i = ("000" + i).slice(-3), r = ("00" + r).slice(-2), a < 10 && (a = "0" + a), e = i + "°" + h.separator + r + "′" + h.separator + a + "″";
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
return e;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Converts numeric degrees to deg/min/sec latitude (2-digit degrees, suffixed with N/S).
|
|
117
|
+
*
|
|
118
|
+
* @param {number} deg - Degrees to be formatted as specified.
|
|
119
|
+
* @param {string} [format=d] - Return value as 'd', 'dm', 'dms' for deg, deg+min, deg+min+sec.
|
|
120
|
+
* @param {number} [dp=4|2|0] - Number of decimal places to use – default 4 for d, 2 for dm, 0 for dms.
|
|
121
|
+
* @returns {string} Degrees formatted as deg/min/secs according to specified format.
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* const lat = Dms.toLat(-3.62, 'dms'); // 3°37′12″S
|
|
125
|
+
*/
|
|
126
|
+
static toLat(t, n, s) {
|
|
127
|
+
const e = h.toDms(h.wrap90(t), n, s);
|
|
128
|
+
return e === null ? "–" : e.slice(1) + h.separator + (t < 0 ? "S" : "N");
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Convert numeric degrees to deg/min/sec longitude (3-digit degrees, suffixed with E/W).
|
|
132
|
+
*
|
|
133
|
+
* @param {number} deg - Degrees to be formatted as specified.
|
|
134
|
+
* @param {string} [format=d] - Return value as 'd', 'dm', 'dms' for deg, deg+min, deg+min+sec.
|
|
135
|
+
* @param {number} [dp=4|2|0] - Number of decimal places to use – default 4 for d, 2 for dm, 0 for dms.
|
|
136
|
+
* @returns {string} Degrees formatted as deg/min/secs according to specified format.
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* const lon = Dms.toLon(-3.62, 'dms'); // 3°37′12″W
|
|
140
|
+
*/
|
|
141
|
+
static toLon(t, n, s) {
|
|
142
|
+
const e = h.toDms(h.wrap180(t), n, s);
|
|
143
|
+
return e === null ? "–" : e + h.separator + (t < 0 ? "W" : "E");
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Converts numeric degrees to deg/min/sec as a bearing (0°..360°).
|
|
147
|
+
*
|
|
148
|
+
* @param {number} deg - Degrees to be formatted as specified.
|
|
149
|
+
* @param {string} [format=d] - Return value as 'd', 'dm', 'dms' for deg, deg+min, deg+min+sec.
|
|
150
|
+
* @param {number} [dp=4|2|0] - Number of decimal places to use – default 4 for d, 2 for dm, 0 for dms.
|
|
151
|
+
* @returns {string} Degrees formatted as deg/min/secs according to specified format.
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* const lon = Dms.toBrng(-3.62, 'dms'); // 356°22′48″
|
|
155
|
+
*/
|
|
156
|
+
static toBrng(t, n, s) {
|
|
157
|
+
const e = h.toDms(h.wrap360(t), n, s);
|
|
158
|
+
return e === null ? "–" : e.replace("360", "0");
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Converts DMS string from locale thousands/decimal separators to JavaScript comma/dot separators
|
|
162
|
+
* for subsequent parsing.
|
|
163
|
+
*
|
|
164
|
+
* Both thousands and decimal separators must be followed by a numeric character, to facilitate
|
|
165
|
+
* parsing of single lat/long string (in which whitespace must be left after the comma separator).
|
|
166
|
+
*
|
|
167
|
+
* @param {string} str - Degrees/minutes/seconds formatted with locale separators.
|
|
168
|
+
* @returns {string} Degrees/minutes/seconds formatted with standard Javascript separators.
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* const lat = Dms.fromLocale('51°28′40,12″N'); // '51°28′40.12″N' in France
|
|
172
|
+
* const p = new LatLon(Dms.fromLocale('51°28′40,37″N, 000°00′05,29″W'); // '51.4779°N, 000.0015°W' in France
|
|
173
|
+
*/
|
|
174
|
+
static fromLocale(t) {
|
|
175
|
+
const n = 123456.789.toLocaleString(), s = { thousands: n.slice(3, 4), decimal: n.slice(7, 8) };
|
|
176
|
+
return t.replace(s.thousands, "⁜").replace(s.decimal, ".").replace("⁜", ",");
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Converts DMS string from JavaScript comma/dot thousands/decimal separators to locale separators.
|
|
180
|
+
*
|
|
181
|
+
* Can also be used to format standard numbers such as distances.
|
|
182
|
+
*
|
|
183
|
+
* @param {string} str - Degrees/minutes/seconds formatted with standard Javascript separators.
|
|
184
|
+
* @returns {string} Degrees/minutes/seconds formatted with locale separators.
|
|
185
|
+
*
|
|
186
|
+
* @example
|
|
187
|
+
* const Dms.toLocale('123,456.789'); // '123.456,789' in France
|
|
188
|
+
* const Dms.toLocale('51°28′40.12″N, 000°00′05.31″W'); // '51°28′40,12″N, 000°00′05,31″W' in France
|
|
189
|
+
*/
|
|
190
|
+
static toLocale(t) {
|
|
191
|
+
const n = 123456.789.toLocaleString(), s = { thousands: n.slice(3, 4), decimal: n.slice(7, 8) };
|
|
192
|
+
return t.replace(/,([0-9])/, "⁜$1").replace(".", s.decimal).replace("⁜", s.thousands);
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Returns compass point (to given precision) for supplied bearing.
|
|
196
|
+
*
|
|
197
|
+
* @param {number} bearing - Bearing in degrees from north.
|
|
198
|
+
* @param {number} [precision=3] - Precision (1:cardinal / 2:intercardinal / 3:secondary-intercardinal).
|
|
199
|
+
* @returns {string} Compass point for supplied bearing.
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
* const point = Dms.compassPoint(24); // point = 'NNE'
|
|
203
|
+
* const point = Dms.compassPoint(24, 1); // point = 'N'
|
|
204
|
+
*/
|
|
205
|
+
static compassPoint(t, n = 3) {
|
|
206
|
+
if (![1, 2, 3].includes(Number(n))) throw new RangeError(`invalid precision ‘${n}’`);
|
|
207
|
+
t = h.wrap360(t);
|
|
208
|
+
const s = [
|
|
209
|
+
"N",
|
|
210
|
+
"NNE",
|
|
211
|
+
"NE",
|
|
212
|
+
"ENE",
|
|
213
|
+
"E",
|
|
214
|
+
"ESE",
|
|
215
|
+
"SE",
|
|
216
|
+
"SSE",
|
|
217
|
+
"S",
|
|
218
|
+
"SSW",
|
|
219
|
+
"SW",
|
|
220
|
+
"WSW",
|
|
221
|
+
"W",
|
|
222
|
+
"WNW",
|
|
223
|
+
"NW",
|
|
224
|
+
"NNW"
|
|
225
|
+
], e = 4 * 2 ** (n - 1);
|
|
226
|
+
return s[Math.round(t * e / 360) % e * 16 / e];
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Constrain degrees to range -90..+90 (for latitude); e.g. -91 => -89, 91 => 89.
|
|
230
|
+
*
|
|
231
|
+
* @private
|
|
232
|
+
* @param {number} degrees
|
|
233
|
+
* @returns degrees within range -90..+90.
|
|
234
|
+
*/
|
|
235
|
+
static wrap90(t) {
|
|
236
|
+
if (-90 <= t && t <= 90) return t;
|
|
237
|
+
const n = t, s = 90, e = 360;
|
|
238
|
+
return 4 * s / e * Math.abs(((n - e / 4) % e + e) % e - e / 2) - s;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Constrain degrees to range -180..+180 (for longitude); e.g. -181 => 179, 181 => -179.
|
|
242
|
+
*
|
|
243
|
+
* @private
|
|
244
|
+
* @param {number} degrees
|
|
245
|
+
* @returns degrees within range -180..+180.
|
|
246
|
+
*/
|
|
247
|
+
static wrap180(t) {
|
|
248
|
+
if (-180 <= t && t <= 180) return t;
|
|
249
|
+
const n = t, s = 180, e = 360;
|
|
250
|
+
return ((2 * s * n / e - e / 2) % e + e) % e - s;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Constrain degrees to range 0..360 (for bearings); e.g. -1 => 359, 361 => 1.
|
|
254
|
+
*
|
|
255
|
+
* @private
|
|
256
|
+
* @param {number} degrees
|
|
257
|
+
* @returns degrees within range 0..360.
|
|
258
|
+
*/
|
|
259
|
+
static wrap360(t) {
|
|
260
|
+
if (0 <= t && t < 360) return t;
|
|
261
|
+
const n = t, s = 180, e = 360;
|
|
262
|
+
return (2 * s * n / e % e + e) % e;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
Number.prototype.toRadians = function() {
|
|
266
|
+
return this * Math.PI / 180;
|
|
267
|
+
};
|
|
268
|
+
Number.prototype.toDegrees = function() {
|
|
269
|
+
return this * 180 / Math.PI;
|
|
270
|
+
};
|
|
271
|
+
class b {
|
|
272
|
+
/**
|
|
273
|
+
* Creates a 3-d vector.
|
|
274
|
+
*
|
|
275
|
+
* @param {number} x - X component of vector.
|
|
276
|
+
* @param {number} y - Y component of vector.
|
|
277
|
+
* @param {number} z - Z component of vector.
|
|
278
|
+
*
|
|
279
|
+
* @example
|
|
280
|
+
* import Vector3d from '/js/geodesy/vector3d.js';
|
|
281
|
+
* const v = new Vector3d(0.267, 0.535, 0.802);
|
|
282
|
+
*/
|
|
283
|
+
constructor(t, n, s) {
|
|
284
|
+
if (isNaN(t) || isNaN(n) || isNaN(s)) throw new TypeError(`invalid vector [${t},${n},${s}]`);
|
|
285
|
+
this.x = Number(t), this.y = Number(n), this.z = Number(s);
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Length (magnitude or norm) of ‘this’ vector.
|
|
289
|
+
*
|
|
290
|
+
* @returns {number} Magnitude of this vector.
|
|
291
|
+
*/
|
|
292
|
+
get length() {
|
|
293
|
+
return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Adds supplied vector to ‘this’ vector.
|
|
297
|
+
*
|
|
298
|
+
* @param {Vector3d} v - Vector to be added to this vector.
|
|
299
|
+
* @returns {Vector3d} Vector representing sum of this and v.
|
|
300
|
+
*/
|
|
301
|
+
plus(t) {
|
|
302
|
+
if (!(t instanceof b)) throw new TypeError("v is not Vector3d object");
|
|
303
|
+
return new b(this.x + t.x, this.y + t.y, this.z + t.z);
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Subtracts supplied vector from ‘this’ vector.
|
|
307
|
+
*
|
|
308
|
+
* @param {Vector3d} v - Vector to be subtracted from this vector.
|
|
309
|
+
* @returns {Vector3d} Vector representing difference between this and v.
|
|
310
|
+
*/
|
|
311
|
+
minus(t) {
|
|
312
|
+
if (!(t instanceof b)) throw new TypeError("v is not Vector3d object");
|
|
313
|
+
return new b(this.x - t.x, this.y - t.y, this.z - t.z);
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Multiplies ‘this’ vector by a scalar value.
|
|
317
|
+
*
|
|
318
|
+
* @param {number} x - Factor to multiply this vector by.
|
|
319
|
+
* @returns {Vector3d} Vector scaled by x.
|
|
320
|
+
*/
|
|
321
|
+
times(t) {
|
|
322
|
+
if (isNaN(t)) throw new TypeError(`invalid scalar value ‘${t}’`);
|
|
323
|
+
return new b(this.x * t, this.y * t, this.z * t);
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Divides ‘this’ vector by a scalar value.
|
|
327
|
+
*
|
|
328
|
+
* @param {number} x - Factor to divide this vector by.
|
|
329
|
+
* @returns {Vector3d} Vector divided by x.
|
|
330
|
+
*/
|
|
331
|
+
dividedBy(t) {
|
|
332
|
+
if (isNaN(t)) throw new TypeError(`invalid scalar value ‘${t}’`);
|
|
333
|
+
return new b(this.x / t, this.y / t, this.z / t);
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Multiplies ‘this’ vector by the supplied vector using dot (scalar) product.
|
|
337
|
+
*
|
|
338
|
+
* @param {Vector3d} v - Vector to be dotted with this vector.
|
|
339
|
+
* @returns {number} Dot product of ‘this’ and v.
|
|
340
|
+
*/
|
|
341
|
+
dot(t) {
|
|
342
|
+
if (!(t instanceof b)) throw new TypeError("v is not Vector3d object");
|
|
343
|
+
return this.x * t.x + this.y * t.y + this.z * t.z;
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Multiplies ‘this’ vector by the supplied vector using cross (vector) product.
|
|
347
|
+
*
|
|
348
|
+
* @param {Vector3d} v - Vector to be crossed with this vector.
|
|
349
|
+
* @returns {Vector3d} Cross product of ‘this’ and v.
|
|
350
|
+
*/
|
|
351
|
+
cross(t) {
|
|
352
|
+
if (!(t instanceof b)) throw new TypeError("v is not Vector3d object");
|
|
353
|
+
const n = this.y * t.z - this.z * t.y, s = this.z * t.x - this.x * t.z, e = this.x * t.y - this.y * t.x;
|
|
354
|
+
return new b(n, s, e);
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Negates a vector to point in the opposite direction.
|
|
358
|
+
*
|
|
359
|
+
* @returns {Vector3d} Negated vector.
|
|
360
|
+
*/
|
|
361
|
+
negate() {
|
|
362
|
+
return new b(-this.x, -this.y, -this.z);
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Normalizes a vector to its unit vector
|
|
366
|
+
* – if the vector is already unit or is zero magnitude, this is a no-op.
|
|
367
|
+
*
|
|
368
|
+
* @returns {Vector3d} Normalised version of this vector.
|
|
369
|
+
*/
|
|
370
|
+
unit() {
|
|
371
|
+
const t = this.length;
|
|
372
|
+
if (t == 1) return this;
|
|
373
|
+
if (t == 0) return this;
|
|
374
|
+
const n = this.x / t, s = this.y / t, e = this.z / t;
|
|
375
|
+
return new b(n, s, e);
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Calculates the angle between ‘this’ vector and supplied vector atan2(|p₁×p₂|, p₁·p₂) (or if
|
|
379
|
+
* (extra-planar) ‘n’ supplied then atan2(n·p₁×p₂, p₁·p₂).
|
|
380
|
+
*
|
|
381
|
+
* @param {Vector3d} v - Vector whose angle is to be determined from ‘this’ vector.
|
|
382
|
+
* @param {Vector3d} [n] - Plane normal: if supplied, angle is signed +ve if this->v is
|
|
383
|
+
* clockwise looking along n, -ve in opposite direction.
|
|
384
|
+
* @returns {number} Angle (in radians) between this vector and supplied vector (in range 0..π
|
|
385
|
+
* if n not supplied, range -π..+π if n supplied).
|
|
386
|
+
*/
|
|
387
|
+
angleTo(t, n = void 0) {
|
|
388
|
+
if (!(t instanceof b)) throw new TypeError("v is not Vector3d object");
|
|
389
|
+
if (!(n instanceof b || n == null)) throw new TypeError("n is not Vector3d object");
|
|
390
|
+
const s = n == null || this.cross(t).dot(n) >= 0 ? 1 : -1, e = this.cross(t).length * s, i = this.dot(t);
|
|
391
|
+
return Math.atan2(e, i);
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Rotates ‘this’ point around an axis by a specified angle.
|
|
395
|
+
*
|
|
396
|
+
* @param {Vector3d} axis - The axis being rotated around.
|
|
397
|
+
* @param {number} angle - The angle of rotation (in degrees).
|
|
398
|
+
* @returns {Vector3d} The rotated point.
|
|
399
|
+
*/
|
|
400
|
+
rotateAround(t, n) {
|
|
401
|
+
if (!(t instanceof b)) throw new TypeError("axis is not Vector3d object");
|
|
402
|
+
const s = n.toRadians(), e = this.unit(), i = t.unit(), r = Math.sin(s), a = Math.cos(s), l = 1 - a, p = i.x, c = i.y, d = i.z, m = [
|
|
403
|
+
// rotation matrix for rotation about supplied axis
|
|
404
|
+
[l * p * p + a, l * p * c - r * d, l * p * d + r * c],
|
|
405
|
+
[l * p * c + r * d, l * c * c + a, l * c * d - r * p],
|
|
406
|
+
[l * p * d - r * c, l * c * d + r * p, l * d * d + a]
|
|
407
|
+
], f = [
|
|
408
|
+
m[0][0] * e.x + m[0][1] * e.y + m[0][2] * e.z,
|
|
409
|
+
m[1][0] * e.x + m[1][1] * e.y + m[1][2] * e.z,
|
|
410
|
+
m[2][0] * e.x + m[2][1] * e.y + m[2][2] * e.z
|
|
411
|
+
];
|
|
412
|
+
return new b(f[0], f[1], f[2]);
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* String representation of vector.
|
|
416
|
+
*
|
|
417
|
+
* @param {number} [dp=3] - Number of decimal places to be used.
|
|
418
|
+
* @returns {string} Vector represented as [x,y,z].
|
|
419
|
+
*/
|
|
420
|
+
toString(t = 3) {
|
|
421
|
+
return `[${this.x.toFixed(t)},${this.y.toFixed(t)},${this.z.toFixed(t)}]`;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
Number.prototype.toRadians = function() {
|
|
425
|
+
return this * Math.PI / 180;
|
|
426
|
+
};
|
|
427
|
+
Number.prototype.toDegrees = function() {
|
|
428
|
+
return this * 180 / Math.PI;
|
|
429
|
+
};
|
|
430
|
+
const B = {
|
|
431
|
+
WGS84: { a: 6378137, b: 6356752314245e-6, f: 1 / 298.257223563 }
|
|
432
|
+
}, dt = {
|
|
433
|
+
WGS84: { ellipsoid: B.WGS84 }
|
|
434
|
+
};
|
|
435
|
+
Object.freeze(B.WGS84);
|
|
436
|
+
Object.freeze(dt.WGS84);
|
|
437
|
+
class Q {
|
|
438
|
+
/**
|
|
439
|
+
* Creates a geodetic latitude/longitude point on a (WGS84) ellipsoidal model earth.
|
|
440
|
+
*
|
|
441
|
+
* @param {number} lat - Latitude (in degrees).
|
|
442
|
+
* @param {number} lon - Longitude (in degrees).
|
|
443
|
+
* @param {number} [height=0] - Height above ellipsoid in metres.
|
|
444
|
+
* @throws {TypeError} Invalid lat/lon/height.
|
|
445
|
+
*
|
|
446
|
+
* @example
|
|
447
|
+
* import LatLon from '/js/geodesy/latlon-ellipsoidal.js';
|
|
448
|
+
* const p = new LatLon(51.47788, -0.00147, 17);
|
|
449
|
+
*/
|
|
450
|
+
constructor(t, n, s = 0) {
|
|
451
|
+
if (isNaN(t) || t == null) throw new TypeError(`invalid lat ‘${t}’`);
|
|
452
|
+
if (isNaN(n) || n == null) throw new TypeError(`invalid lon ‘${n}’`);
|
|
453
|
+
if (isNaN(s) || s == null) throw new TypeError(`invalid height ‘${s}’`);
|
|
454
|
+
this._lat = h.wrap90(Number(t)), this._lon = h.wrap180(Number(n)), this._height = Number(s);
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Latitude in degrees north from equator (including aliases lat, latitude): can be set as
|
|
458
|
+
* numeric or hexagesimal (deg-min-sec); returned as numeric.
|
|
459
|
+
*/
|
|
460
|
+
get lat() {
|
|
461
|
+
return this._lat;
|
|
462
|
+
}
|
|
463
|
+
get latitude() {
|
|
464
|
+
return this._lat;
|
|
465
|
+
}
|
|
466
|
+
set lat(t) {
|
|
467
|
+
if (this._lat = isNaN(t) ? h.wrap90(h.parse(t)) : h.wrap90(Number(t)), isNaN(this._lat)) throw new TypeError(`invalid lat ‘${t}’`);
|
|
468
|
+
}
|
|
469
|
+
set latitude(t) {
|
|
470
|
+
if (this._lat = isNaN(t) ? h.wrap90(h.parse(t)) : h.wrap90(Number(t)), isNaN(this._lat)) throw new TypeError(`invalid latitude ‘${t}’`);
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Longitude in degrees east from international reference meridian (including aliases lon, lng,
|
|
474
|
+
* longitude): can be set as numeric or hexagesimal (deg-min-sec); returned as numeric.
|
|
475
|
+
*/
|
|
476
|
+
get lon() {
|
|
477
|
+
return this._lon;
|
|
478
|
+
}
|
|
479
|
+
get lng() {
|
|
480
|
+
return this._lon;
|
|
481
|
+
}
|
|
482
|
+
get longitude() {
|
|
483
|
+
return this._lon;
|
|
484
|
+
}
|
|
485
|
+
set lon(t) {
|
|
486
|
+
if (this._lon = isNaN(t) ? h.wrap180(h.parse(t)) : h.wrap180(Number(t)), isNaN(this._lon)) throw new TypeError(`invalid lon ‘${t}’`);
|
|
487
|
+
}
|
|
488
|
+
set lng(t) {
|
|
489
|
+
if (this._lon = isNaN(t) ? h.wrap180(h.parse(t)) : h.wrap180(Number(t)), isNaN(this._lon)) throw new TypeError(`invalid lng ‘${t}’`);
|
|
490
|
+
}
|
|
491
|
+
set longitude(t) {
|
|
492
|
+
if (this._lon = isNaN(t) ? h.wrap180(h.parse(t)) : h.wrap180(Number(t)), isNaN(this._lon)) throw new TypeError(`invalid longitude ‘${t}’`);
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* Height in metres above ellipsoid.
|
|
496
|
+
*/
|
|
497
|
+
get height() {
|
|
498
|
+
return this._height;
|
|
499
|
+
}
|
|
500
|
+
set height(t) {
|
|
501
|
+
if (this._height = Number(t), isNaN(this._height)) throw new TypeError(`invalid height ‘${t}’`);
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* Datum.
|
|
505
|
+
*
|
|
506
|
+
* Note this is replicated within LatLonEllipsoidal in order that a LatLonEllipsoidal object can
|
|
507
|
+
* be monkey-patched to look like a LatLonEllipsoidal_Datum, for Vincenty calculations on
|
|
508
|
+
* different ellipsoids.
|
|
509
|
+
*
|
|
510
|
+
* @private
|
|
511
|
+
*/
|
|
512
|
+
get datum() {
|
|
513
|
+
return this._datum;
|
|
514
|
+
}
|
|
515
|
+
set datum(t) {
|
|
516
|
+
this._datum = t;
|
|
517
|
+
}
|
|
518
|
+
/**
|
|
519
|
+
* Ellipsoids with their parameters; this module only defines WGS84 parameters a = 6378137, b =
|
|
520
|
+
* 6356752.314245, f = 1/298.257223563.
|
|
521
|
+
*
|
|
522
|
+
* @example
|
|
523
|
+
* const a = LatLon.ellipsoids.WGS84.a; // 6378137
|
|
524
|
+
*/
|
|
525
|
+
static get ellipsoids() {
|
|
526
|
+
return B;
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* Datums; this module only defines WGS84 datum, hence no datum transformations.
|
|
530
|
+
*
|
|
531
|
+
* @example
|
|
532
|
+
* const a = LatLon.datums.WGS84.ellipsoid.a; // 6377563.396
|
|
533
|
+
*/
|
|
534
|
+
static get datums() {
|
|
535
|
+
return dt;
|
|
536
|
+
}
|
|
537
|
+
/**
|
|
538
|
+
* Parses a latitude/longitude point from a variety of formats.
|
|
539
|
+
*
|
|
540
|
+
* Latitude & longitude (in degrees) can be supplied as two separate parameters, as a single
|
|
541
|
+
* comma-separated lat/lon string, or as a single object with { lat, lon } or GeoJSON properties.
|
|
542
|
+
*
|
|
543
|
+
* The latitude/longitude values may be numeric or strings; they may be signed decimal or
|
|
544
|
+
* deg-min-sec (hexagesimal) suffixed by compass direction (NSEW); a variety of separators are
|
|
545
|
+
* accepted. Examples -3.62, '3 37 12W', '3°37′12″W'.
|
|
546
|
+
*
|
|
547
|
+
* Thousands/decimal separators must be comma/dot; use Dms.fromLocale to convert locale-specific
|
|
548
|
+
* thousands/decimal separators.
|
|
549
|
+
*
|
|
550
|
+
* @param {number|string|Object} lat|latlon - Latitude (in degrees), or comma-separated lat/lon, or lat/lon object.
|
|
551
|
+
* @param {number} [lon] - Longitude (in degrees).
|
|
552
|
+
* @param {number} [height=0] - Height above ellipsoid in metres.
|
|
553
|
+
* @returns {LatLon} Latitude/longitude point on WGS84 ellipsoidal model earth.
|
|
554
|
+
* @throws {TypeError} Invalid coordinate.
|
|
555
|
+
*
|
|
556
|
+
* @example
|
|
557
|
+
* const p1 = LatLon.parse(51.47788, -0.00147); // numeric pair
|
|
558
|
+
* const p2 = LatLon.parse('51°28′40″N, 000°00′05″W', 17); // dms string + height
|
|
559
|
+
* const p3 = LatLon.parse({ lat: 52.205, lon: 0.119 }, 17); // { lat, lon } object numeric + height
|
|
560
|
+
*/
|
|
561
|
+
static parse(...t) {
|
|
562
|
+
if (t.length == 0) throw new TypeError("invalid (empty) point");
|
|
563
|
+
let n, s, e;
|
|
564
|
+
if (typeof t[0] == "object" && (t.length == 1 || !isNaN(parseFloat(t[1])))) {
|
|
565
|
+
const i = t[0];
|
|
566
|
+
if (i.type == "Point" && Array.isArray(i.coordinates) ? ([s, n, e] = i.coordinates, e = e || 0) : (i.latitude != null && (n = i.latitude), i.lat != null && (n = i.lat), i.longitude != null && (s = i.longitude), i.lng != null && (s = i.lng), i.lon != null && (s = i.lon), i.height != null && (e = i.height), n = h.wrap90(h.parse(n)), s = h.wrap180(h.parse(s))), t[1] != null && (e = t[1]), isNaN(n) || isNaN(s)) throw new TypeError(`invalid point ‘${JSON.stringify(t[0])}’`);
|
|
567
|
+
}
|
|
568
|
+
if (typeof t[0] == "string" && t[0].split(",").length == 2 && ([n, s] = t[0].split(","), n = h.wrap90(h.parse(n)), s = h.wrap180(h.parse(s)), e = t[1] || 0, isNaN(n) || isNaN(s)))
|
|
569
|
+
throw new TypeError(`invalid point ‘${t[0]}’`);
|
|
570
|
+
if (n == null && s == null && ([n, s] = t, n = h.wrap90(h.parse(n)), s = h.wrap180(h.parse(s)), e = t[2] || 0, isNaN(n) || isNaN(s)))
|
|
571
|
+
throw new TypeError(`invalid point ‘${t.toString()}’`);
|
|
572
|
+
return new this(n, s, e);
|
|
573
|
+
}
|
|
574
|
+
/**
|
|
575
|
+
* Converts ‘this’ point from (geodetic) latitude/longitude coordinates to (geocentric)
|
|
576
|
+
* cartesian (x/y/z) coordinates.
|
|
577
|
+
*
|
|
578
|
+
* @returns {Cartesian} Cartesian point equivalent to lat/lon point, with x, y, z in metres from
|
|
579
|
+
* earth centre.
|
|
580
|
+
*/
|
|
581
|
+
toCartesian() {
|
|
582
|
+
const t = this.datum ? this.datum.ellipsoid : this.referenceFrame ? this.referenceFrame.ellipsoid : B.WGS84, n = this.lat.toRadians(), s = this.lon.toRadians(), e = this.height, { a: i, f: r } = t, a = Math.sin(n), l = Math.cos(n), p = Math.sin(s), c = Math.cos(s), d = 2 * r - r * r, m = i / Math.sqrt(1 - d * a * a), f = (m + e) * l * c, u = (m + e) * l * p, w = (m * (1 - d) + e) * a;
|
|
583
|
+
return new ft(f, u, w);
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
* Checks if another point is equal to ‘this’ point.
|
|
587
|
+
*
|
|
588
|
+
* @param {LatLon} point - Point to be compared against this point.
|
|
589
|
+
* @returns {bool} True if points have identical latitude, longitude, height, and datum/referenceFrame.
|
|
590
|
+
* @throws {TypeError} Invalid point.
|
|
591
|
+
*
|
|
592
|
+
* @example
|
|
593
|
+
* const p1 = new LatLon(52.205, 0.119);
|
|
594
|
+
* const p2 = new LatLon(52.205, 0.119);
|
|
595
|
+
* const equal = p1.equals(p2); // true
|
|
596
|
+
*/
|
|
597
|
+
equals(t) {
|
|
598
|
+
if (!(t instanceof Q)) throw new TypeError(`invalid point ‘${t}’`);
|
|
599
|
+
return !(Math.abs(this.lat - t.lat) > Number.EPSILON || Math.abs(this.lon - t.lon) > Number.EPSILON || Math.abs(this.height - t.height) > Number.EPSILON || this.datum != t.datum || this.referenceFrame != t.referenceFrame || this.epoch != t.epoch);
|
|
600
|
+
}
|
|
601
|
+
/**
|
|
602
|
+
* Returns a string representation of ‘this’ point, formatted as degrees, degrees+minutes, or
|
|
603
|
+
* degrees+minutes+seconds.
|
|
604
|
+
*
|
|
605
|
+
* @param {string} [format=d] - Format point as 'd', 'dm', 'dms', or 'n' for signed numeric.
|
|
606
|
+
* @param {number} [dp=4|2|0] - Number of decimal places to use: default 4 for d, 2 for dm, 0 for dms.
|
|
607
|
+
* @param {number} [dpHeight=null] - Number of decimal places to use for height; default is no height display.
|
|
608
|
+
* @returns {string} Comma-separated formatted latitude/longitude.
|
|
609
|
+
* @throws {RangeError} Invalid format.
|
|
610
|
+
*
|
|
611
|
+
* @example
|
|
612
|
+
* const greenwich = new LatLon(51.47788, -0.00147, 46);
|
|
613
|
+
* const d = greenwich.toString(); // 51.4779°N, 000.0015°W
|
|
614
|
+
* const dms = greenwich.toString('dms', 2); // 51°28′40″N, 000°00′05″W
|
|
615
|
+
* const [lat, lon] = greenwich.toString('n').split(','); // 51.4779, -0.0015
|
|
616
|
+
* const dmsh = greenwich.toString('dms', 0, 0); // 51°28′40″N, 000°00′06″W +46m
|
|
617
|
+
*/
|
|
618
|
+
toString(t = "d", n = void 0, s = null) {
|
|
619
|
+
if (!["d", "dm", "dms", "n"].includes(t)) throw new RangeError(`invalid format ‘${t}’`);
|
|
620
|
+
const e = (this.height >= 0 ? " +" : " ") + this.height.toFixed(s) + "m";
|
|
621
|
+
if (t == "n") {
|
|
622
|
+
n == null && (n = 4);
|
|
623
|
+
const a = this.lat.toFixed(n), l = this.lon.toFixed(n);
|
|
624
|
+
return `${a}, ${l}${s == null ? "" : e}`;
|
|
625
|
+
}
|
|
626
|
+
const i = h.toLat(this.lat, t, n), r = h.toLon(this.lon, t, n);
|
|
627
|
+
return `${i}, ${r}${s == null ? "" : e}`;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
class ft extends b {
|
|
631
|
+
/**
|
|
632
|
+
* Creates cartesian coordinate representing ECEF (earth-centric earth-fixed) point.
|
|
633
|
+
*
|
|
634
|
+
* @param {number} x - X coordinate in metres (=> 0°N,0°E).
|
|
635
|
+
* @param {number} y - Y coordinate in metres (=> 0°N,90°E).
|
|
636
|
+
* @param {number} z - Z coordinate in metres (=> 90°N).
|
|
637
|
+
*
|
|
638
|
+
* @example
|
|
639
|
+
* import { Cartesian } from '/js/geodesy/latlon-ellipsoidal.js';
|
|
640
|
+
* const coord = new Cartesian(3980581.210, -111.159, 4966824.522);
|
|
641
|
+
*/
|
|
642
|
+
constructor(t, n, s) {
|
|
643
|
+
super(t, n, s);
|
|
644
|
+
}
|
|
645
|
+
/**
|
|
646
|
+
* Converts ‘this’ (geocentric) cartesian (x/y/z) coordinate to (geodetic) latitude/longitude
|
|
647
|
+
* point on specified ellipsoid.
|
|
648
|
+
*
|
|
649
|
+
* Uses Bowring’s (1985) formulation for μm precision in concise form; ‘The accuracy of geodetic
|
|
650
|
+
* latitude and height equations’, B R Bowring, Survey Review vol 28, 218, Oct 1985.
|
|
651
|
+
*
|
|
652
|
+
* @param {LatLon.ellipsoids} [ellipsoid=WGS84] - Ellipsoid to use when converting point.
|
|
653
|
+
* @returns {LatLon} Latitude/longitude point defined by cartesian coordinates, on given ellipsoid.
|
|
654
|
+
* @throws {TypeError} Invalid ellipsoid.
|
|
655
|
+
*
|
|
656
|
+
* @example
|
|
657
|
+
* const c = new Cartesian(4027893.924, 307041.993, 4919474.294);
|
|
658
|
+
* const p = c.toLatLon(); // 50.7978°N, 004.3592°E
|
|
659
|
+
*/
|
|
660
|
+
toLatLon(t = B.WGS84) {
|
|
661
|
+
if (!t || !t.a) throw new TypeError(`invalid ellipsoid ‘${t}’`);
|
|
662
|
+
const { x: n, y: s, z: e } = this, { a: i, b: r, f: a } = t, l = 2 * a - a * a, p = l / (1 - l), c = Math.sqrt(n * n + s * s), d = Math.sqrt(c * c + e * e), m = r * e / (i * c) * (1 + p * r / d), f = m / Math.sqrt(1 + m * m), u = f / m, w = isNaN(u) ? 0 : Math.atan2(e + p * r * f * f * f, c - l * i * u * u * u), N = Math.atan2(s, n), S = Math.sin(w), M = Math.cos(w), E = i / Math.sqrt(1 - l * S * S), $ = c * M + e * S - i * i / E;
|
|
663
|
+
return new Q(w.toDegrees(), N.toDegrees(), $);
|
|
664
|
+
}
|
|
665
|
+
/**
|
|
666
|
+
* Returns a string representation of ‘this’ cartesian point.
|
|
667
|
+
*
|
|
668
|
+
* @param {number} [dp=0] - Number of decimal places to use.
|
|
669
|
+
* @returns {string} Comma-separated latitude/longitude.
|
|
670
|
+
*/
|
|
671
|
+
toString(t = 0) {
|
|
672
|
+
const n = this.x.toFixed(t), s = this.y.toFixed(t), e = this.z.toFixed(t);
|
|
673
|
+
return `[${n},${s},${e}]`;
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
const x = {
|
|
677
|
+
WGS84: { a: 6378137, b: 6356752314245e-6, f: 1 / 298.257223563 },
|
|
678
|
+
Airy1830: { a: 6377563396e-3, b: 6356256909e-3, f: 1 / 299.3249646 },
|
|
679
|
+
AiryModified: { a: 6377340189e-3, b: 6356034448e-3, f: 1 / 299.3249646 },
|
|
680
|
+
Bessel1841: { a: 6377397155e-3, b: 6356078962818e-6, f: 1 / 299.1528128 },
|
|
681
|
+
Clarke1866: { a: 63782064e-1, b: 63565838e-1, f: 1 / 294.978698214 },
|
|
682
|
+
Clarke1880IGN: { a: 63782492e-1, b: 6356515, f: 1 / 293.466021294 },
|
|
683
|
+
GRS80: { a: 6378137, b: 635675231414e-5, f: 1 / 298.257222101 },
|
|
684
|
+
Intl1924: { a: 6378388, b: 6356911946e-3, f: 1 / 297 },
|
|
685
|
+
// aka Hayford
|
|
686
|
+
WGS72: { a: 6378135, b: 63567505e-1, f: 1 / 298.26 }
|
|
687
|
+
}, R = {
|
|
688
|
+
// transforms: t in metres, s in ppm, r in arcseconds tx ty tz s rx ry rz
|
|
689
|
+
ED50: { ellipsoid: x.Intl1924, transform: [89.5, 93.8, 123.1, -1.2, 0, 0, 0.156] },
|
|
690
|
+
// epsg.io/1311
|
|
691
|
+
ETRS89: { ellipsoid: x.GRS80, transform: [0, 0, 0, 0, 0, 0, 0] },
|
|
692
|
+
// epsg.io/1149; @ 1-metre level
|
|
693
|
+
Irl1975: { ellipsoid: x.AiryModified, transform: [-482.53, 130.596, -564.557, -8.15, 1.042, 0.214, 0.631] },
|
|
694
|
+
// epsg.io/1954
|
|
695
|
+
NAD27: { ellipsoid: x.Clarke1866, transform: [8, -160, -176, 0, 0, 0, 0] },
|
|
696
|
+
NAD83: { ellipsoid: x.GRS80, transform: [0.9956, -1.9103, -0.5215, -62e-5, 0.025915, 9426e-6, 0.011599] },
|
|
697
|
+
NTF: { ellipsoid: x.Clarke1880IGN, transform: [168, 60, -320, 0, 0, 0, 0] },
|
|
698
|
+
OSGB36: { ellipsoid: x.Airy1830, transform: [-446.448, 125.157, -542.06, 20.4894, -0.1502, -0.247, -0.8421] },
|
|
699
|
+
// epsg.io/1314
|
|
700
|
+
Potsdam: { ellipsoid: x.Bessel1841, transform: [-582, -105, -414, -8.3, 1.04, 0.35, -3.08] },
|
|
701
|
+
TokyoJapan: { ellipsoid: x.Bessel1841, transform: [148, -507, -685, 0, 0, 0, 0] },
|
|
702
|
+
WGS72: { ellipsoid: x.WGS72, transform: [0, 0, -4.5, -0.22, 0, 0, 0.554] },
|
|
703
|
+
WGS84: { ellipsoid: x.WGS84, transform: [0, 0, 0, 0, 0, 0, 0] }
|
|
704
|
+
};
|
|
705
|
+
Object.keys(x).forEach((g) => Object.freeze(x[g]));
|
|
706
|
+
Object.keys(R).forEach((g) => {
|
|
707
|
+
Object.freeze(R[g]), Object.freeze(R[g].transform);
|
|
708
|
+
});
|
|
709
|
+
class D extends Q {
|
|
710
|
+
/**
|
|
711
|
+
* Creates a geodetic latitude/longitude point on an ellipsoidal model earth using given datum.
|
|
712
|
+
*
|
|
713
|
+
* @param {number} lat - Latitude (in degrees).
|
|
714
|
+
* @param {number} lon - Longitude (in degrees).
|
|
715
|
+
* @param {number} [height=0] - Height above ellipsoid in metres.
|
|
716
|
+
* @param {LatLon.datums} datum - Datum this point is defined within.
|
|
717
|
+
*
|
|
718
|
+
* @example
|
|
719
|
+
* import LatLon from '/js/geodesy/latlon-ellipsoidal-datum.js';
|
|
720
|
+
* const p = new LatLon(53.3444, -6.2577, 17, LatLon.datums.Irl1975);
|
|
721
|
+
*/
|
|
722
|
+
constructor(t, n, s = 0, e = R.WGS84) {
|
|
723
|
+
if (!e || e.ellipsoid == null) throw new TypeError(`unrecognised datum ‘${e}’`);
|
|
724
|
+
super(t, n, s), this._datum = e;
|
|
725
|
+
}
|
|
726
|
+
/**
|
|
727
|
+
* Datum this point is defined within.
|
|
728
|
+
*/
|
|
729
|
+
get datum() {
|
|
730
|
+
return this._datum;
|
|
731
|
+
}
|
|
732
|
+
/**
|
|
733
|
+
* Ellipsoids with their parameters; semi-major axis (a), semi-minor axis (b), and flattening (f).
|
|
734
|
+
*
|
|
735
|
+
* Flattening f = (a−b)/a; at least one of these parameters is derived from defining constants.
|
|
736
|
+
*
|
|
737
|
+
* @example
|
|
738
|
+
* const a = LatLon.ellipsoids.Airy1830.a; // 6377563.396
|
|
739
|
+
*/
|
|
740
|
+
static get ellipsoids() {
|
|
741
|
+
return x;
|
|
742
|
+
}
|
|
743
|
+
/**
|
|
744
|
+
* Datums; with associated ellipsoid, and Helmert transform parameters to convert from WGS-84
|
|
745
|
+
* into given datum.
|
|
746
|
+
*
|
|
747
|
+
* Note that precision of various datums will vary, and WGS-84 (original) is not defined to be
|
|
748
|
+
* accurate to better than ±1 metre. No transformation should be assumed to be accurate to
|
|
749
|
+
* better than a metre, for many datums somewhat less.
|
|
750
|
+
*
|
|
751
|
+
* This is a small sample of commoner datums from a large set of historical datums. I will add
|
|
752
|
+
* new datums on request.
|
|
753
|
+
*
|
|
754
|
+
* @example
|
|
755
|
+
* const a = LatLon.datums.OSGB36.ellipsoid.a; // 6377563.396
|
|
756
|
+
* const tx = LatLon.datums.OSGB36.transform; // [ tx, ty, tz, s, rx, ry, rz ]
|
|
757
|
+
* const availableDatums = Object.keys(LatLon.datums).join(', '); // ED50, Irl1975, NAD27, ...
|
|
758
|
+
*/
|
|
759
|
+
static get datums() {
|
|
760
|
+
return R;
|
|
761
|
+
}
|
|
762
|
+
// note instance datum getter/setters are in LatLonEllipsoidal
|
|
763
|
+
/**
|
|
764
|
+
* Parses a latitude/longitude point from a variety of formats.
|
|
765
|
+
*
|
|
766
|
+
* Latitude & longitude (in degrees) can be supplied as two separate parameters, as a single
|
|
767
|
+
* comma-separated lat/lon string, or as a single object with { lat, lon } or GeoJSON properties.
|
|
768
|
+
*
|
|
769
|
+
* The latitude/longitude values may be numeric or strings; they may be signed decimal or
|
|
770
|
+
* deg-min-sec (hexagesimal) suffixed by compass direction (NSEW); a variety of separators are
|
|
771
|
+
* accepted. Examples -3.62, '3 37 12W', '3°37′12″W'.
|
|
772
|
+
*
|
|
773
|
+
* Thousands/decimal separators must be comma/dot; use Dms.fromLocale to convert locale-specific
|
|
774
|
+
* thousands/decimal separators.
|
|
775
|
+
*
|
|
776
|
+
* @param {number|string|Object} lat|latlon - Geodetic Latitude (in degrees) or comma-separated lat/lon or lat/lon object.
|
|
777
|
+
* @param {number} [lon] - Longitude in degrees.
|
|
778
|
+
* @param {number} [height=0] - Height above ellipsoid in metres.
|
|
779
|
+
* @param {LatLon.datums} [datum=WGS84] - Datum this point is defined within.
|
|
780
|
+
* @returns {LatLon} Latitude/longitude point on ellipsoidal model earth using given datum.
|
|
781
|
+
* @throws {TypeError} Unrecognised datum.
|
|
782
|
+
*
|
|
783
|
+
* @example
|
|
784
|
+
* const p = LatLon.parse('51.47736, 0.0000', 0, LatLon.datums.OSGB36);
|
|
785
|
+
*/
|
|
786
|
+
static parse(...t) {
|
|
787
|
+
let n = R.WGS84;
|
|
788
|
+
if ((t.length == 4 || t.length == 3 && typeof t[2] == "object") && (n = t.pop()), !n || n.ellipsoid == null) throw new TypeError(`unrecognised datum ‘${n}’`);
|
|
789
|
+
const s = super.parse(...t);
|
|
790
|
+
return s._datum = n, s;
|
|
791
|
+
}
|
|
792
|
+
/**
|
|
793
|
+
* Converts ‘this’ lat/lon coordinate to new coordinate system.
|
|
794
|
+
*
|
|
795
|
+
* @param {LatLon.datums} toDatum - Datum this coordinate is to be converted to.
|
|
796
|
+
* @returns {LatLon} This point converted to new datum.
|
|
797
|
+
* @throws {TypeError} Unrecognised datum.
|
|
798
|
+
*
|
|
799
|
+
* @example
|
|
800
|
+
* const pWGS84 = new LatLon(51.47788, -0.00147, 0, LatLon.datums.WGS84);
|
|
801
|
+
* const pOSGB = pWGS84.convertDatum(LatLon.datums.OSGB36); // 51.4773°N, 000.0001°E
|
|
802
|
+
*/
|
|
803
|
+
convertDatum(t) {
|
|
804
|
+
if (!t || t.ellipsoid == null) throw new TypeError(`unrecognised datum ‘${t}’`);
|
|
805
|
+
return this.toCartesian().convertDatum(t).toLatLon();
|
|
806
|
+
}
|
|
807
|
+
/**
|
|
808
|
+
* Converts ‘this’ point from (geodetic) latitude/longitude coordinates to (geocentric) cartesian
|
|
809
|
+
* (x/y/z) coordinates, based on the same datum.
|
|
810
|
+
*
|
|
811
|
+
* Shadow of LatLonEllipsoidal.toCartesian(), returning Cartesian augmented with
|
|
812
|
+
* LatLonEllipsoidal_Datum methods/properties.
|
|
813
|
+
*
|
|
814
|
+
* @returns {Cartesian} Cartesian point equivalent to lat/lon point, with x, y, z in metres from
|
|
815
|
+
* earth centre, augmented with reference frame conversion methods and properties.
|
|
816
|
+
*/
|
|
817
|
+
toCartesian() {
|
|
818
|
+
const t = super.toCartesian();
|
|
819
|
+
return new at(t.x, t.y, t.z, this.datum);
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
class at extends ft {
|
|
823
|
+
/**
|
|
824
|
+
* Creates cartesian coordinate representing ECEF (earth-centric earth-fixed) point, on a given
|
|
825
|
+
* datum. The datum will identify the primary meridian (for the x-coordinate), and is also
|
|
826
|
+
* useful in transforming to/from geodetic (lat/lon) coordinates.
|
|
827
|
+
*
|
|
828
|
+
* @param {number} x - X coordinate in metres (=> 0°N,0°E).
|
|
829
|
+
* @param {number} y - Y coordinate in metres (=> 0°N,90°E).
|
|
830
|
+
* @param {number} z - Z coordinate in metres (=> 90°N).
|
|
831
|
+
* @param {LatLon.datums} [datum] - Datum this coordinate is defined within.
|
|
832
|
+
* @throws {TypeError} Unrecognised datum.
|
|
833
|
+
*
|
|
834
|
+
* @example
|
|
835
|
+
* import { Cartesian } from '/js/geodesy/latlon-ellipsoidal-datum.js';
|
|
836
|
+
* const coord = new Cartesian(3980581.210, -111.159, 4966824.522);
|
|
837
|
+
*/
|
|
838
|
+
constructor(t, n, s, e = void 0) {
|
|
839
|
+
if (e && e.ellipsoid == null) throw new TypeError(`unrecognised datum ‘${e}’`);
|
|
840
|
+
super(t, n, s), e && (this._datum = e);
|
|
841
|
+
}
|
|
842
|
+
/**
|
|
843
|
+
* Datum this point is defined within.
|
|
844
|
+
*/
|
|
845
|
+
get datum() {
|
|
846
|
+
return this._datum;
|
|
847
|
+
}
|
|
848
|
+
set datum(t) {
|
|
849
|
+
if (!t || t.ellipsoid == null) throw new TypeError(`unrecognised datum ‘${t}’`);
|
|
850
|
+
this._datum = t;
|
|
851
|
+
}
|
|
852
|
+
/**
|
|
853
|
+
* Converts ‘this’ (geocentric) cartesian (x/y/z) coordinate to (geodetic) latitude/longitude
|
|
854
|
+
* point (based on the same datum, or WGS84 if unset).
|
|
855
|
+
*
|
|
856
|
+
* Shadow of Cartesian.toLatLon(), returning LatLon augmented with LatLonEllipsoidal_Datum
|
|
857
|
+
* methods convertDatum, toCartesian, etc.
|
|
858
|
+
*
|
|
859
|
+
* @returns {LatLon} Latitude/longitude point defined by cartesian coordinates.
|
|
860
|
+
* @throws {TypeError} Unrecognised datum
|
|
861
|
+
*
|
|
862
|
+
* @example
|
|
863
|
+
* const c = new Cartesian(4027893.924, 307041.993, 4919474.294);
|
|
864
|
+
* const p = c.toLatLon(); // 50.7978°N, 004.3592°E
|
|
865
|
+
*/
|
|
866
|
+
toLatLon(t = void 0) {
|
|
867
|
+
t && (console.info("datum parameter to Cartesian_Datum.toLatLon is deprecated: set datum before calling toLatLon()"), this.datum = t);
|
|
868
|
+
const n = this.datum || R.WGS84;
|
|
869
|
+
if (!n || n.ellipsoid == null) throw new TypeError(`unrecognised datum ‘${n}’`);
|
|
870
|
+
const s = super.toLatLon(n.ellipsoid);
|
|
871
|
+
return new D(s.lat, s.lon, s.height, this.datum);
|
|
872
|
+
}
|
|
873
|
+
/**
|
|
874
|
+
* Converts ‘this’ cartesian coordinate to new datum using Helmert 7-parameter transformation.
|
|
875
|
+
*
|
|
876
|
+
* @param {LatLon.datums} toDatum - Datum this coordinate is to be converted to.
|
|
877
|
+
* @returns {Cartesian} This point converted to new datum.
|
|
878
|
+
* @throws {Error} Undefined datum.
|
|
879
|
+
*
|
|
880
|
+
* @example
|
|
881
|
+
* const c = new Cartesian(3980574.247, -102.127, 4966830.065, LatLon.datums.OSGB36);
|
|
882
|
+
* c.convertDatum(LatLon.datums.Irl1975); // [??,??,??]
|
|
883
|
+
*/
|
|
884
|
+
convertDatum(t) {
|
|
885
|
+
if (!t || t.ellipsoid == null) throw new TypeError(`unrecognised datum ‘${t}’`);
|
|
886
|
+
if (!this.datum) throw new TypeError("cartesian coordinate has no datum");
|
|
887
|
+
let n = null, s = null;
|
|
888
|
+
(this.datum == null || this.datum == R.WGS84) && (n = this, s = t.transform), t == R.WGS84 && (n = this, s = this.datum.transform.map((i) => -i)), s == null && (n = this.convertDatum(R.WGS84), s = t.transform);
|
|
889
|
+
const e = n.applyTransform(s);
|
|
890
|
+
return e.datum = t, e;
|
|
891
|
+
}
|
|
892
|
+
/**
|
|
893
|
+
* Applies Helmert 7-parameter transformation to ‘this’ coordinate using transform parameters t.
|
|
894
|
+
*
|
|
895
|
+
* This is used in converting datums (geodetic->cartesian, apply transform, cartesian->geodetic).
|
|
896
|
+
*
|
|
897
|
+
* @private
|
|
898
|
+
* @param {number[]} t - Transformation to apply to this coordinate.
|
|
899
|
+
* @returns {Cartesian} Transformed point.
|
|
900
|
+
*/
|
|
901
|
+
applyTransform(t) {
|
|
902
|
+
const { x: n, y: s, z: e } = this, i = t[0], r = t[1], a = t[2], l = t[3] / 1e6 + 1, p = (t[4] / 3600).toRadians(), c = (t[5] / 3600).toRadians(), d = (t[6] / 3600).toRadians(), m = i + n * l - s * d + e * c, f = r + n * d + s * l - e * p, u = a - n * c + s * p + e * l;
|
|
903
|
+
return new at(m, f, u);
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
class pt {
|
|
907
|
+
/**
|
|
908
|
+
* Creates a Utm coordinate object comprising zone, hemisphere, easting, northing on a given
|
|
909
|
+
* datum (normally WGS84).
|
|
910
|
+
*
|
|
911
|
+
* @param {number} zone - UTM 6° longitudinal zone (1..60 covering 180°W..180°E).
|
|
912
|
+
* @param {string} hemisphere - N for northern hemisphere, S for southern hemisphere.
|
|
913
|
+
* @param {number} easting - Easting in metres from false easting (-500km from central meridian).
|
|
914
|
+
* @param {number} northing - Northing in metres from equator (N) or from false northing -10,000km (S).
|
|
915
|
+
* @param {LatLon.datums} [datum=WGS84] - Datum UTM coordinate is based on.
|
|
916
|
+
* @param {number} [convergence=null] - Meridian convergence (bearing of grid north
|
|
917
|
+
* clockwise from true north), in degrees.
|
|
918
|
+
* @param {number} [scale=null] - Grid scale factor.
|
|
919
|
+
* @params {boolean=true} verifyEN - Check easting/northing is within 'normal' values (may be
|
|
920
|
+
* suppressed for extended coherent coordinates or alternative datums
|
|
921
|
+
* e.g. ED50 (epsg.io/23029).
|
|
922
|
+
* @throws {TypeError} Invalid UTM coordinate.
|
|
923
|
+
*
|
|
924
|
+
* @example
|
|
925
|
+
* import Utm from '/js/geodesy/utm.js';
|
|
926
|
+
* const utmCoord = new Utm(31, 'N', 448251, 5411932);
|
|
927
|
+
*/
|
|
928
|
+
constructor(t, n, s, e, i = D.datums.WGS84, r = null, a = null, l = !0) {
|
|
929
|
+
if (!(1 <= t && t <= 60)) throw new RangeError(`invalid UTM zone ‘${t}’`);
|
|
930
|
+
if (t != parseInt(t)) throw new RangeError(`invalid UTM zone ‘${t}’`);
|
|
931
|
+
if (typeof n != "string" || !n.match(/[NS]/i)) throw new RangeError(`invalid UTM hemisphere ‘${n}’`);
|
|
932
|
+
if (l) {
|
|
933
|
+
if (!(0 <= s && s <= 1e6)) throw new RangeError(`invalid UTM easting ‘${s}’`);
|
|
934
|
+
if (n.toUpperCase() == "N" && !(0 <= e && e < 9328094)) throw new RangeError(`invalid UTM northing ‘${e}’`);
|
|
935
|
+
if (n.toUpperCase() == "S" && !(1118414 < e && e <= 1e7)) throw new RangeError(`invalid UTM northing ‘${e}’`);
|
|
936
|
+
}
|
|
937
|
+
if (!i || i.ellipsoid == null) throw new TypeError(`unrecognised datum ‘${i}’`);
|
|
938
|
+
this.zone = Number(t), this.hemisphere = n.toUpperCase(), this.easting = Number(s), this.northing = Number(e), this.datum = i, this.convergence = r === null ? null : Number(r), this.scale = a === null ? null : Number(a);
|
|
939
|
+
}
|
|
940
|
+
/**
|
|
941
|
+
* Converts UTM zone/easting/northing coordinate to latitude/longitude.
|
|
942
|
+
*
|
|
943
|
+
* Implements Karney’s method, using Krüger series to order n⁶, giving results accurate to 5nm
|
|
944
|
+
* for distances up to 3900km from the central meridian.
|
|
945
|
+
*
|
|
946
|
+
* @param {Utm} utmCoord - UTM coordinate to be converted to latitude/longitude.
|
|
947
|
+
* @returns {LatLon} Latitude/longitude of supplied grid reference.
|
|
948
|
+
*
|
|
949
|
+
* @example
|
|
950
|
+
* const grid = new Utm(31, 'N', 448251.795, 5411932.678);
|
|
951
|
+
* const latlong = grid.toLatLon(); // 48°51′29.52″N, 002°17′40.20″E
|
|
952
|
+
*/
|
|
953
|
+
toLatLon() {
|
|
954
|
+
const { zone: t, hemisphere: n } = this, s = 5e5, e = 1e7, { a: i, f: r } = this.datum.ellipsoid, a = 0.9996, l = this.easting - s, p = n == "S" ? this.northing - e : this.northing, c = Math.sqrt(r * (2 - r)), d = r / (2 - r), m = d * d, f = d * m, u = d * f, w = d * u, N = d * w, S = i / (1 + d) * (1 + 1 / 4 * m + 1 / 64 * u + 1 / 256 * N), M = l / (a * S), E = p / (a * S), $ = [
|
|
955
|
+
null,
|
|
956
|
+
// note β is one-based array (6th order Krüger expressions)
|
|
957
|
+
1 / 2 * d - 2 / 3 * m + 37 / 96 * f - 1 / 360 * u - 81 / 512 * w + 96199 / 604800 * N,
|
|
958
|
+
1 / 48 * m + 1 / 15 * f - 437 / 1440 * u + 46 / 105 * w - 1118711 / 3870720 * N,
|
|
959
|
+
17 / 480 * f - 37 / 840 * u - 209 / 4480 * w + 5569 / 90720 * N,
|
|
960
|
+
4397 / 161280 * u - 11 / 504 * w - 830251 / 7257600 * N,
|
|
961
|
+
4583 / 161280 * w - 108847 / 3991680 * N,
|
|
962
|
+
20648693 / 638668800 * N
|
|
963
|
+
];
|
|
964
|
+
let L = E;
|
|
965
|
+
for (let o = 1; o <= 6; o++) L -= $[o] * Math.sin(2 * o * E) * Math.cosh(2 * o * M);
|
|
966
|
+
let P = M;
|
|
967
|
+
for (let o = 1; o <= 6; o++) P -= $[o] * Math.cos(2 * o * E) * Math.sinh(2 * o * M);
|
|
968
|
+
const G = Math.sinh(P), v = Math.sin(L), F = Math.cos(L), T = v / Math.sqrt(G * G + F * F);
|
|
969
|
+
let W = null, y = T;
|
|
970
|
+
do {
|
|
971
|
+
const o = Math.sinh(c * Math.atanh(c * y / Math.sqrt(1 + y * y))), st = y * Math.sqrt(1 + o * o) - o * Math.sqrt(1 + y * y);
|
|
972
|
+
W = (T - st) / Math.sqrt(1 + st * st) * (1 + (1 - c * c) * y * y) / ((1 - c * c) * Math.sqrt(1 + y * y)), y += W;
|
|
973
|
+
} while (Math.abs(W) > 1e-12);
|
|
974
|
+
const q = y, U = Math.atan(q);
|
|
975
|
+
let O = Math.atan2(G, F), C = 1;
|
|
976
|
+
for (let o = 1; o <= 6; o++) C -= 2 * o * $[o] * Math.cos(2 * o * E) * Math.cosh(2 * o * M);
|
|
977
|
+
let z = 0;
|
|
978
|
+
for (let o = 1; o <= 6; o++) z += 2 * o * $[o] * Math.sin(2 * o * E) * Math.sinh(2 * o * M);
|
|
979
|
+
const k = Math.atan(Math.tan(L) * Math.tanh(P)), j = Math.atan2(z, C), A = k + j, X = Math.sin(U), H = Math.sqrt(1 - c * c * X * X) * Math.sqrt(1 + q * q) * Math.sqrt(G * G + F * F), Y = S / i / Math.sqrt(C * C + z * z), J = a * H * Y, Z = ((t - 1) * 6 - 180 + 3).toRadians();
|
|
980
|
+
O += Z;
|
|
981
|
+
const V = Number(U.toDegrees().toFixed(14)), tt = Number(O.toDegrees().toFixed(14)), nt = Number(A.toDegrees().toFixed(9)), et = Number(J.toFixed(12)), I = new K(V, tt, 0, this.datum);
|
|
982
|
+
return I.convergence = nt, I.scale = et, I;
|
|
983
|
+
}
|
|
984
|
+
/**
|
|
985
|
+
* Parses string representation of UTM coordinate.
|
|
986
|
+
*
|
|
987
|
+
* A UTM coordinate comprises (space-separated)
|
|
988
|
+
* - zone
|
|
989
|
+
* - hemisphere
|
|
990
|
+
* - easting
|
|
991
|
+
* - northing.
|
|
992
|
+
*
|
|
993
|
+
* @param {string} utmCoord - UTM coordinate (WGS 84).
|
|
994
|
+
* @param {Datum} [datum=WGS84] - Datum coordinate is defined in (default WGS 84).
|
|
995
|
+
* @returns {Utm} Parsed UTM coordinate.
|
|
996
|
+
* @throws {TypeError} Invalid UTM coordinate.
|
|
997
|
+
*
|
|
998
|
+
* @example
|
|
999
|
+
* const utmCoord = Utm.parse('31 N 448251 5411932');
|
|
1000
|
+
* // utmCoord: {zone: 31, hemisphere: 'N', easting: 448251, northing: 5411932 }
|
|
1001
|
+
*/
|
|
1002
|
+
static parse(t, n = D.datums.WGS84) {
|
|
1003
|
+
if (t = t.trim().match(/\S+/g), t == null || t.length != 4) throw new Error(`invalid UTM coordinate ‘${t}’`);
|
|
1004
|
+
const s = t[0], e = t[1], i = t[2], r = t[3];
|
|
1005
|
+
return new this(s, e, i, r, n);
|
|
1006
|
+
}
|
|
1007
|
+
/**
|
|
1008
|
+
* Returns a string representation of a UTM coordinate.
|
|
1009
|
+
*
|
|
1010
|
+
* To distinguish from MGRS grid zone designators, a space is left between the zone and the
|
|
1011
|
+
* hemisphere.
|
|
1012
|
+
*
|
|
1013
|
+
* Note that UTM coordinates get rounded, not truncated (unlike MGRS grid references).
|
|
1014
|
+
*
|
|
1015
|
+
* @param {number} [digits=0] - Number of digits to appear after the decimal point (3 ≡ mm).
|
|
1016
|
+
* @returns {string} A string representation of the coordinate.
|
|
1017
|
+
*
|
|
1018
|
+
* @example
|
|
1019
|
+
* const utm = new Utm('31', 'N', 448251, 5411932).toString(4); // 31 N 448251.0000 5411932.0000
|
|
1020
|
+
*/
|
|
1021
|
+
toString(t = 0) {
|
|
1022
|
+
const n = this.zone.toString().padStart(2, "0"), s = this.hemisphere, e = this.easting.toFixed(t), i = this.northing.toFixed(t);
|
|
1023
|
+
return `${n} ${s} ${e} ${i}`;
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
class K extends D {
|
|
1027
|
+
/**
|
|
1028
|
+
* Converts latitude/longitude to UTM coordinate.
|
|
1029
|
+
*
|
|
1030
|
+
* Implements Karney’s method, using Krüger series to order n⁶, giving results accurate to 5nm
|
|
1031
|
+
* for distances up to 3900km from the central meridian.
|
|
1032
|
+
*
|
|
1033
|
+
* @param {number} [zoneOverride] - Use specified zone rather than zone within which point lies;
|
|
1034
|
+
* note overriding the UTM zone has the potential to result in negative eastings, and
|
|
1035
|
+
* perverse results within Norway/Svalbard exceptions.
|
|
1036
|
+
* @returns {Utm} UTM coordinate.
|
|
1037
|
+
* @throws {TypeError} Latitude outside UTM limits.
|
|
1038
|
+
*
|
|
1039
|
+
* @example
|
|
1040
|
+
* const latlong = new LatLon(48.8582, 2.2945);
|
|
1041
|
+
* const utmCoord = latlong.toUtm(); // 31 N 448252 5411933
|
|
1042
|
+
*/
|
|
1043
|
+
toUtm(t = void 0) {
|
|
1044
|
+
if (!(-80 <= this.lat && this.lat <= 84)) throw new RangeError(`latitude ‘${this.lat}’ outside UTM limits`);
|
|
1045
|
+
const n = 5e5, s = 1e7;
|
|
1046
|
+
let e = t || Math.floor((this.lon + 180) / 6) + 1, i = ((e - 1) * 6 - 180 + 3).toRadians();
|
|
1047
|
+
const a = "CDEFGHJKLMNPQRSTUVWXX".charAt(Math.floor(this.lat / 8 + 10));
|
|
1048
|
+
e == 31 && a == "V" && this.lon >= 3 && (e++, i += 6 .toRadians()), e == 32 && a == "X" && this.lon < 9 && (e--, i -= 6 .toRadians()), e == 32 && a == "X" && this.lon >= 9 && (e++, i += 6 .toRadians()), e == 34 && a == "X" && this.lon < 21 && (e--, i -= 6 .toRadians()), e == 34 && a == "X" && this.lon >= 21 && (e++, i += 6 .toRadians()), e == 36 && a == "X" && this.lon < 33 && (e--, i -= 6 .toRadians()), e == 36 && a == "X" && this.lon >= 33 && (e++, i += 6 .toRadians());
|
|
1049
|
+
const l = this.lat.toRadians(), p = this.lon.toRadians() - i, c = this.datum ? this.datum.ellipsoid : D.ellipsoids.WGS84, { a: d, f: m } = c, f = 0.9996, u = Math.sqrt(m * (2 - m)), w = m / (2 - m), N = w * w, S = w * N, M = w * S, E = w * M, $ = w * E, L = Math.cos(p), P = Math.sin(p), G = Math.tan(p), v = Math.tan(l), F = Math.sinh(u * Math.atanh(u * v / Math.sqrt(1 + v * v))), T = v * Math.sqrt(1 + F * F) - F * Math.sqrt(1 + v * v), W = Math.atan2(T, L), y = Math.asinh(P / Math.sqrt(T * T + L * L)), q = d / (1 + w) * (1 + 1 / 4 * N + 1 / 64 * M + 1 / 256 * $), U = [
|
|
1050
|
+
null,
|
|
1051
|
+
// note α is one-based array (6th order Krüger expressions)
|
|
1052
|
+
1 / 2 * w - 2 / 3 * N + 5 / 16 * S + 41 / 180 * M - 127 / 288 * E + 7891 / 37800 * $,
|
|
1053
|
+
13 / 48 * N - 3 / 5 * S + 557 / 1440 * M + 281 / 630 * E - 1983433 / 1935360 * $,
|
|
1054
|
+
61 / 240 * S - 103 / 140 * M + 15061 / 26880 * E + 167603 / 181440 * $,
|
|
1055
|
+
49561 / 161280 * M - 179 / 168 * E + 6601661 / 7257600 * $,
|
|
1056
|
+
34729 / 80640 * E - 3418889 / 1995840 * $,
|
|
1057
|
+
212378941 / 319334400 * $
|
|
1058
|
+
];
|
|
1059
|
+
let O = W;
|
|
1060
|
+
for (let o = 1; o <= 6; o++) O += U[o] * Math.sin(2 * o * W) * Math.cosh(2 * o * y);
|
|
1061
|
+
let C = y;
|
|
1062
|
+
for (let o = 1; o <= 6; o++) C += U[o] * Math.cos(2 * o * W) * Math.sinh(2 * o * y);
|
|
1063
|
+
let z = f * q * C, k = f * q * O, j = 1;
|
|
1064
|
+
for (let o = 1; o <= 6; o++) j += 2 * o * U[o] * Math.cos(2 * o * W) * Math.cosh(2 * o * y);
|
|
1065
|
+
let A = 0;
|
|
1066
|
+
for (let o = 1; o <= 6; o++) A += 2 * o * U[o] * Math.sin(2 * o * W) * Math.sinh(2 * o * y);
|
|
1067
|
+
const X = Math.atan(T / Math.sqrt(1 + T * T) * G), H = Math.atan2(A, j), Y = X + H, J = Math.sin(l), Z = Math.sqrt(1 - u * u * J * J) * Math.sqrt(1 + v * v) / Math.sqrt(T * T + L * L), V = q / d * Math.sqrt(j * j + A * A), tt = f * Z * V;
|
|
1068
|
+
z = z + n, k < 0 && (k = k + s), z = Number(z.toFixed(9)), k = Number(k.toFixed(9));
|
|
1069
|
+
const nt = Number(Y.toDegrees().toFixed(9)), et = Number(tt.toFixed(12)), I = this.lat >= 0 ? "N" : "S";
|
|
1070
|
+
return new pt(e, I, z, k, this.datum, nt, et, !!t);
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
const it = "CDEFGHJKLMNPQRSTUVWXX", rt = ["ABCDEFGH", "JKLMNPQR", "STUVWXYZ"], ot = ["ABCDEFGHJKLMNPQRSTUV", "FGHJKLMNPQRSTUVABCDE"];
|
|
1074
|
+
class _ {
|
|
1075
|
+
/**
|
|
1076
|
+
* Creates an Mgrs grid reference object.
|
|
1077
|
+
*
|
|
1078
|
+
* @param {number} zone - 6° longitudinal zone (1..60 covering 180°W..180°E).
|
|
1079
|
+
* @param {string} band - 8° latitudinal band (C..X covering 80°S..84°N).
|
|
1080
|
+
* @param {string} e100k - First letter (E) of 100km grid square.
|
|
1081
|
+
* @param {string} n100k - Second letter (N) of 100km grid square.
|
|
1082
|
+
* @param {number} easting - Easting in metres within 100km grid square.
|
|
1083
|
+
* @param {number} northing - Northing in metres within 100km grid square.
|
|
1084
|
+
* @param {LatLon.datums} [datum=WGS84] - Datum UTM coordinate is based on.
|
|
1085
|
+
* @throws {RangeError} Invalid MGRS grid reference.
|
|
1086
|
+
*
|
|
1087
|
+
* @example
|
|
1088
|
+
* import Mgrs from '/js/geodesy/mgrs.js';
|
|
1089
|
+
* const mgrsRef = new Mgrs(31, 'U', 'D', 'Q', 48251, 11932); // 31U DQ 48251 11932
|
|
1090
|
+
*/
|
|
1091
|
+
constructor(t, n, s, e, i, r, a = K.datums.WGS84) {
|
|
1092
|
+
if (!(1 <= t && t <= 60)) throw new RangeError(`invalid MGRS zone ‘${t}’`);
|
|
1093
|
+
if (t != parseInt(t)) throw new RangeError(`invalid MGRS zone ‘${t}’`);
|
|
1094
|
+
const l = [];
|
|
1095
|
+
if ((n.length != 1 || it.indexOf(n) == -1) && l.push(`invalid MGRS band ‘${n}’`), (s.length != 1 || rt[(t - 1) % 3].indexOf(s) == -1) && l.push(`invalid MGRS 100km grid square column ‘${s}’ for zone ${t}`), (e.length != 1 || ot[0].indexOf(e) == -1) && l.push(`invalid MGRS 100km grid square row ‘${e}’`), isNaN(Number(i)) && l.push(`invalid MGRS easting ‘${i}’`), isNaN(Number(r)) && l.push(`invalid MGRS northing ‘${r}’`), (!a || a.ellipsoid == null) && l.push(`unrecognised datum ‘${a}’`), l.length > 0) throw new RangeError(l.join(", "));
|
|
1096
|
+
this.zone = Number(t), this.band = n, this.e100k = s, this.n100k = e, this.easting = Number(i), this.northing = Number(r), this.datum = a;
|
|
1097
|
+
}
|
|
1098
|
+
/**
|
|
1099
|
+
* Converts MGRS grid reference to UTM coordinate.
|
|
1100
|
+
*
|
|
1101
|
+
* Grid references refer to squares rather than points (with the size of the square indicated
|
|
1102
|
+
* by the precision of the reference); this conversion will return the UTM coordinate of the SW
|
|
1103
|
+
* corner of the grid reference square.
|
|
1104
|
+
*
|
|
1105
|
+
* @returns {Utm} UTM coordinate of SW corner of this MGRS grid reference.
|
|
1106
|
+
*
|
|
1107
|
+
* @example
|
|
1108
|
+
* const mgrsRef = Mgrs.parse('31U DQ 48251 11932');
|
|
1109
|
+
* const utmCoord = mgrsRef.toUtm(); // 31 N 448251 5411932
|
|
1110
|
+
*/
|
|
1111
|
+
toUtm() {
|
|
1112
|
+
const t = this.band >= "N" ? "N" : "S", s = (rt[(this.zone - 1) % 3].indexOf(this.e100k) + 1) * 1e5, i = ot[(this.zone - 1) % 2].indexOf(this.n100k) * 1e5, r = (it.indexOf(this.band) - 10) * 8, a = Math.floor(new K(r, 3).toUtm().northing / 1e5) * 1e5;
|
|
1113
|
+
let l = 0;
|
|
1114
|
+
for (; l + i + this.northing < a; ) l += 2e6;
|
|
1115
|
+
return new lt(this.zone, t, s + this.easting, l + i + this.northing, this.datum);
|
|
1116
|
+
}
|
|
1117
|
+
/**
|
|
1118
|
+
* Parses string representation of MGRS grid reference.
|
|
1119
|
+
*
|
|
1120
|
+
* An MGRS grid reference comprises (space-separated)
|
|
1121
|
+
* - grid zone designator (GZD)
|
|
1122
|
+
* - 100km grid square letter-pair
|
|
1123
|
+
* - easting
|
|
1124
|
+
* - northing.
|
|
1125
|
+
*
|
|
1126
|
+
* @param {string} mgrsGridRef - String representation of MGRS grid reference.
|
|
1127
|
+
* @returns {Mgrs} Mgrs grid reference object.
|
|
1128
|
+
* @throws {Error} Invalid MGRS grid reference.
|
|
1129
|
+
*
|
|
1130
|
+
* @example
|
|
1131
|
+
* const mgrsRef = Mgrs.parse('31U DQ 48251 11932');
|
|
1132
|
+
* const mgrsRef = Mgrs.parse('31UDQ4825111932');
|
|
1133
|
+
* // mgrsRef: { zone:31, band:'U', e100k:'D', n100k:'Q', easting:48251, northing:11932 }
|
|
1134
|
+
*/
|
|
1135
|
+
static parse(t) {
|
|
1136
|
+
if (!t) throw new Error(`invalid MGRS grid reference ‘${t}’`);
|
|
1137
|
+
if (!t.trim().match(/\s/)) {
|
|
1138
|
+
if (!Number(t.slice(0, 2))) throw new Error(`invalid MGRS grid reference ‘${t}’`);
|
|
1139
|
+
let d = t.trim().slice(5);
|
|
1140
|
+
d = d.slice(0, d.length / 2) + " " + d.slice(-d.length / 2), t = t.slice(0, 3) + " " + t.slice(3, 5) + " " + d;
|
|
1141
|
+
}
|
|
1142
|
+
const n = t.match(/\S+/g);
|
|
1143
|
+
if (n == null || n.length != 4) throw new Error(`invalid MGRS grid reference ‘${t}’`);
|
|
1144
|
+
const s = n[0], e = s.slice(0, 2), i = s.slice(2, 3), r = n[1], a = r.slice(0, 1), l = r.slice(1, 2);
|
|
1145
|
+
let p = n[2], c = n[3];
|
|
1146
|
+
return p = p.length >= 5 ? p : (p + "00000").slice(0, 5), c = c.length >= 5 ? c : (c + "00000").slice(0, 5), new _(e, i, a, l, p, c);
|
|
1147
|
+
}
|
|
1148
|
+
/**
|
|
1149
|
+
* Returns a string representation of an MGRS grid reference.
|
|
1150
|
+
*
|
|
1151
|
+
* To distinguish from civilian UTM coordinate representations, no space is included within the
|
|
1152
|
+
* zone/band grid zone designator.
|
|
1153
|
+
*
|
|
1154
|
+
* Components are separated by spaces: for a military-style unseparated string, use
|
|
1155
|
+
* Mgrs.toString().replace(/ /g, '');
|
|
1156
|
+
*
|
|
1157
|
+
* Note that MGRS grid references get truncated, not rounded (unlike UTM coordinates); grid
|
|
1158
|
+
* references indicate a bounding square, rather than a point, with the size of the square
|
|
1159
|
+
* indicated by the precision - a precision of 10 indicates a 1-metre square, a precision of 4
|
|
1160
|
+
* indicates a 1,000-metre square (hence 31U DQ 48 11 indicates a 1km square with SW corner at
|
|
1161
|
+
* 31 N 448000 5411000, which would include the 1m square 31U DQ 48251 11932).
|
|
1162
|
+
*
|
|
1163
|
+
* @param {number} [digits=10] - Precision of returned grid reference (eg 4 = km, 10 = m).
|
|
1164
|
+
* @returns {string} This grid reference in standard format.
|
|
1165
|
+
* @throws {RangeError} Invalid precision.
|
|
1166
|
+
*
|
|
1167
|
+
* @example
|
|
1168
|
+
* const mgrsStr = new Mgrs(31, 'U', 'D', 'Q', 48251, 11932).toString(); // 31U DQ 48251 11932
|
|
1169
|
+
*/
|
|
1170
|
+
toString(t = 10) {
|
|
1171
|
+
if (![2, 4, 6, 8, 10].includes(Number(t))) throw new RangeError(`invalid precision ‘${t}’`);
|
|
1172
|
+
const { zone: n, band: s, e100k: e, n100k: i, easting: r, northing: a } = this, l = Math.floor(r / Math.pow(10, 5 - t / 2)), p = Math.floor(a / Math.pow(10, 5 - t / 2)), c = n.toString().padStart(2, "0"), d = l.toString().padStart(t / 2, "0"), m = p.toString().padStart(t / 2, "0");
|
|
1173
|
+
return `${c}${s} ${e}${i} ${d} ${m}`;
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
class lt extends pt {
|
|
1177
|
+
/**
|
|
1178
|
+
* Converts UTM coordinate to MGRS reference.
|
|
1179
|
+
*
|
|
1180
|
+
* @returns {Mgrs}
|
|
1181
|
+
* @throws {TypeError} Invalid UTM coordinate.
|
|
1182
|
+
*
|
|
1183
|
+
* @example
|
|
1184
|
+
* const utmCoord = new Utm(31, 'N', 448251, 5411932);
|
|
1185
|
+
* const mgrsRef = utmCoord.toMgrs(); // 31U DQ 48251 11932
|
|
1186
|
+
*/
|
|
1187
|
+
toMgrs() {
|
|
1188
|
+
const t = this.zone, n = this.toLatLon(), s = it.charAt(Math.floor(n.lat / 8 + 10)), e = Math.floor(this.easting / 1e5), i = rt[(t - 1) % 3].charAt(e - 1), r = Math.floor(this.northing / 1e5) % 20, a = ot[(t - 1) % 2].charAt(r);
|
|
1189
|
+
let l = this.easting % 1e5, p = this.northing % 1e5;
|
|
1190
|
+
return l = Number(l.toFixed(6)), p = Number(p.toFixed(6)), new _(t, s, i, a, l, p);
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
class wt extends K {
|
|
1194
|
+
/**
|
|
1195
|
+
* Converts latitude/longitude to UTM coordinate.
|
|
1196
|
+
*
|
|
1197
|
+
* Shadow of LatLon.toUtm, returning Utm augmented with toMgrs() method.
|
|
1198
|
+
*
|
|
1199
|
+
* @param {number} [zoneOverride] - Use specified zone rather than zone within which point lies;
|
|
1200
|
+
* note overriding the UTM zone has the potential to result in negative eastings, and
|
|
1201
|
+
* perverse results within Norway/Svalbard exceptions (this is unlikely to be relevant
|
|
1202
|
+
* for MGRS, but is needed as Mgrs passes through the Utm class).
|
|
1203
|
+
* @returns {Utm} UTM coordinate.
|
|
1204
|
+
* @throws {Error} If point not valid, if point outside latitude range.
|
|
1205
|
+
*
|
|
1206
|
+
* @example
|
|
1207
|
+
* const latlong = new LatLon(48.8582, 2.2945);
|
|
1208
|
+
* const utmCoord = latlong.toUtm(); // 31 N 448252 5411933
|
|
1209
|
+
*/
|
|
1210
|
+
toUtm(t = void 0) {
|
|
1211
|
+
const n = super.toUtm(t);
|
|
1212
|
+
return new lt(n.zone, n.hemisphere, n.easting, n.northing, n.datum, n.convergence, n.scale);
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
function Nt({
|
|
1216
|
+
coordinate: g,
|
|
1217
|
+
onChange: t
|
|
6
1218
|
}) {
|
|
7
|
-
const [
|
|
1219
|
+
const [n, s] = ht("LATLON"), [e, i] = ht({
|
|
8
1220
|
latLon: {
|
|
9
|
-
latitude:
|
|
10
|
-
longitude:
|
|
1221
|
+
latitude: g[1],
|
|
1222
|
+
longitude: g[0]
|
|
11
1223
|
},
|
|
12
1224
|
utm: "",
|
|
13
1225
|
mgrs: "",
|
|
14
1226
|
dms: ""
|
|
15
1227
|
});
|
|
16
|
-
|
|
17
|
-
}), [
|
|
18
|
-
const { latitude:
|
|
19
|
-
return
|
|
20
|
-
latitude:
|
|
21
|
-
longitude:
|
|
1228
|
+
ct(() => (r(g[1], g[0]), () => {
|
|
1229
|
+
}), [g]), ct(() => {
|
|
1230
|
+
const { latitude: f, longitude: u } = e.latLon;
|
|
1231
|
+
return t && (f !== g[1] || u !== g[0]) && t({
|
|
1232
|
+
latitude: f,
|
|
1233
|
+
longitude: u
|
|
22
1234
|
}), () => {
|
|
23
1235
|
};
|
|
24
|
-
}, [
|
|
25
|
-
const
|
|
1236
|
+
}, [e]);
|
|
1237
|
+
const r = (f, u) => {
|
|
26
1238
|
try {
|
|
27
|
-
const
|
|
28
|
-
|
|
1239
|
+
const w = new wt(f, u), N = w.toUtm(), S = N.toMgrs(), M = w.toString("dms");
|
|
1240
|
+
i({
|
|
29
1241
|
latLon: {
|
|
30
|
-
latitude:
|
|
31
|
-
longitude:
|
|
1242
|
+
latitude: w.latitude,
|
|
1243
|
+
longitude: w.longitude
|
|
32
1244
|
},
|
|
33
|
-
utm:
|
|
34
|
-
mgrs:
|
|
35
|
-
dms:
|
|
1245
|
+
utm: N.toString(),
|
|
1246
|
+
mgrs: S.toString(),
|
|
1247
|
+
dms: M
|
|
36
1248
|
});
|
|
37
1249
|
} catch {
|
|
38
1250
|
console.log("conv err");
|
|
@@ -40,39 +1252,39 @@ function b({
|
|
|
40
1252
|
};
|
|
41
1253
|
return {
|
|
42
1254
|
state: {
|
|
43
|
-
format:
|
|
44
|
-
data:
|
|
1255
|
+
format: n,
|
|
1256
|
+
data: e
|
|
45
1257
|
},
|
|
46
1258
|
action: {
|
|
47
|
-
onChangeFormat: (
|
|
48
|
-
|
|
1259
|
+
onChangeFormat: (f) => {
|
|
1260
|
+
s(f.target.value);
|
|
49
1261
|
},
|
|
50
|
-
onChangeLat: (
|
|
51
|
-
let
|
|
52
|
-
|
|
1262
|
+
onChangeLat: (f) => {
|
|
1263
|
+
let u = f.target.value;
|
|
1264
|
+
u = u.replace(",", "."), r(Number(u), e.latLon.longitude);
|
|
53
1265
|
},
|
|
54
|
-
onChangeLon: (
|
|
55
|
-
let
|
|
56
|
-
|
|
1266
|
+
onChangeLon: (f) => {
|
|
1267
|
+
let u = f.target.value;
|
|
1268
|
+
u = u.replace(",", "."), r(e.latLon.latitude, Number(u));
|
|
57
1269
|
},
|
|
58
|
-
onChangeDms: (
|
|
1270
|
+
onChangeDms: (f) => {
|
|
59
1271
|
try {
|
|
60
|
-
const
|
|
61
|
-
|
|
1272
|
+
const u = f.target.value.split(","), w = u[0].trim(), N = u[1].trim(), S = h.parse(w), M = h.parse(N);
|
|
1273
|
+
r(S, M);
|
|
62
1274
|
} catch {
|
|
63
1275
|
}
|
|
64
1276
|
},
|
|
65
|
-
onChangeMgrs: (
|
|
1277
|
+
onChangeMgrs: (f) => {
|
|
66
1278
|
try {
|
|
67
|
-
const
|
|
68
|
-
|
|
1279
|
+
const w = _.parse(f.target.value).toUtm().toLatLon();
|
|
1280
|
+
r(w.latitude, w.longitude);
|
|
69
1281
|
} catch {
|
|
70
1282
|
}
|
|
71
1283
|
},
|
|
72
|
-
onChangeUtm: (
|
|
1284
|
+
onChangeUtm: (f) => {
|
|
73
1285
|
try {
|
|
74
|
-
const
|
|
75
|
-
|
|
1286
|
+
const w = lt.parse(f.target.value).toLatLon();
|
|
1287
|
+
r(w.latitude, w.longitude);
|
|
76
1288
|
} catch {
|
|
77
1289
|
}
|
|
78
1290
|
}
|
|
@@ -80,5 +1292,5 @@ function b({
|
|
|
80
1292
|
};
|
|
81
1293
|
}
|
|
82
1294
|
export {
|
|
83
|
-
|
|
1295
|
+
Nt as default
|
|
84
1296
|
};
|