geo-coordinates-parser 1.5.8 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +5 -4
- package/dist/cjs/converter.d.ts +15 -0
- package/dist/cjs/converter.js +363 -0
- package/dist/cjs/merge.d.ts +2 -0
- package/dist/cjs/merge.js +12 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/regex.d.ts +4 -0
- package/dist/cjs/regex.js +16 -0
- package/dist/cjs/tests/failFormats.d.ts +2 -0
- package/dist/cjs/tests/failFormats.js +26 -0
- package/dist/cjs/tests/makeTestFormatsJSON.d.ts +1 -0
- package/dist/cjs/tests/makeTestFormatsJSON.js +14 -0
- package/dist/cjs/tests/test.d.ts +1 -0
- package/dist/cjs/tests/test.js +56 -0
- package/dist/cjs/tests/testFormatConverter.d.ts +1 -0
- package/dist/cjs/tests/testFormatConverter.js +11 -0
- package/dist/cjs/tests/testIndividual.d.ts +1 -0
- package/dist/cjs/tests/testIndividual.js +26 -0
- package/dist/cjs/tests/testformats.d.ts +2 -0
- package/dist/cjs/tests/testformats.js +359 -0
- package/dist/cjs/toCoordinateFormat.d.ts +6 -0
- package/dist/cjs/toCoordinateFormat.js +42 -0
- package/dist/mjs/converter.d.ts +15 -0
- package/dist/mjs/converter.js +358 -0
- package/dist/mjs/merge.d.ts +2 -0
- package/dist/mjs/merge.js +6 -0
- package/dist/mjs/package.json +3 -0
- package/dist/mjs/regex.d.ts +4 -0
- package/dist/mjs/regex.js +10 -0
- package/dist/mjs/tests/failFormats.d.ts +2 -0
- package/dist/mjs/tests/failFormats.js +24 -0
- package/dist/mjs/tests/makeTestFormatsJSON.d.ts +1 -0
- package/dist/mjs/tests/makeTestFormatsJSON.js +9 -0
- package/dist/mjs/tests/test.d.ts +1 -0
- package/dist/mjs/tests/test.js +51 -0
- package/dist/mjs/tests/testFormatConverter.d.ts +1 -0
- package/dist/mjs/tests/testFormatConverter.js +6 -0
- package/dist/mjs/tests/testIndividual.d.ts +1 -0
- package/dist/mjs/tests/testIndividual.js +21 -0
- package/dist/mjs/tests/testformats.d.ts +2 -0
- package/dist/mjs/tests/testformats.js +357 -0
- package/dist/mjs/toCoordinateFormat.d.ts +6 -0
- package/dist/mjs/toCoordinateFormat.js +40 -0
- package/package.json +50 -42
- package/bundle/demo.html +0 -39
- package/bundle/geocoordsparser.js +0 -1
- package/bundle/workflow.txt +0 -8
- package/conf.py +0 -3
- package/converter.js +0 -443
- package/failFormats.js +0 -24
- package/formatsOnly.json +0 -41
- package/geocoordsparser.js +0 -0
- package/makeTestFormatsJSON.js +0 -11
- package/merge.js +0 -9
- package/regex.js +0 -20
- package/test.js +0 -66
- package/testFormatConverter.js +0 -8
- package/testFormats.json +0 -352
- package/testIndividual.js +0 -22
- package/testformats.js +0 -372
- package/toCoordinateFormat.js +0 -52
@@ -0,0 +1,358 @@
|
|
1
|
+
//function for converting coordinates from a string to decimal and verbatim
|
2
|
+
//this is just a comment
|
3
|
+
import { dd_re, dms_periods, dms_abbr, coords_other } from './regex.js';
|
4
|
+
import toCoordinateFormat from './toCoordinateFormat.js';
|
5
|
+
/**
|
6
|
+
* Function for converting coordinates in a variety of formats to decimal coordinates
|
7
|
+
* @param {string} coordsString The coordinates string to convert
|
8
|
+
* @param {number} decimalPlaces The number of decimal places for converted coordinates; default is 5
|
9
|
+
* @returns {object} { verbatimCoordinates, decimalCoordinates, decimalLatitude, decimalLongitude }
|
10
|
+
*/
|
11
|
+
function converter(coordsString, decimalPlaces) {
|
12
|
+
//TODO add exact match to entered string, so that it can be used to filter out superflous text around it
|
13
|
+
if (!decimalPlaces) {
|
14
|
+
decimalPlaces = 5;
|
15
|
+
}
|
16
|
+
coordsString = coordsString.replace(/\s+/g, ' ').trim(); //just to tidy up whitespaces
|
17
|
+
let ddLat = null;
|
18
|
+
let ddLng = null;
|
19
|
+
let latdir = "";
|
20
|
+
let lngdir = "";
|
21
|
+
let match = [];
|
22
|
+
let matchSuccess = false;
|
23
|
+
if (dd_re.test(coordsString)) {
|
24
|
+
match = dd_re.exec(coordsString);
|
25
|
+
matchSuccess = checkMatch(match);
|
26
|
+
if (matchSuccess) {
|
27
|
+
ddLat = match[2];
|
28
|
+
ddLng = match[6];
|
29
|
+
//need to fix if there are ','s instead of '.'
|
30
|
+
if (ddLat.includes(',')) {
|
31
|
+
ddLat = ddLat.replace(',', '.');
|
32
|
+
}
|
33
|
+
if (ddLng.includes(',')) {
|
34
|
+
ddLng = ddLng.replace(',', '.');
|
35
|
+
}
|
36
|
+
//validation, we don't want things like 23.00000
|
37
|
+
//some more validation: no zero coords or degrees only
|
38
|
+
if (Number(Math.round(ddLat)) == Number(ddLat)) {
|
39
|
+
throw new Error('integer only coordinate provided');
|
40
|
+
}
|
41
|
+
if (Number(Math.round(ddLng)) == Number(ddLng)) {
|
42
|
+
throw new Error('integer only coordinate provided');
|
43
|
+
}
|
44
|
+
//get directions
|
45
|
+
if (match[1]) {
|
46
|
+
latdir = match[1];
|
47
|
+
lngdir = match[5];
|
48
|
+
}
|
49
|
+
else if (match[4]) {
|
50
|
+
latdir = match[4];
|
51
|
+
lngdir = match[8];
|
52
|
+
}
|
53
|
+
}
|
54
|
+
else {
|
55
|
+
throw new Error("invalid decimal coordinate format");
|
56
|
+
}
|
57
|
+
}
|
58
|
+
else if (dms_periods.test(coordsString)) {
|
59
|
+
match = dms_periods.exec(coordsString);
|
60
|
+
matchSuccess = checkMatch(match);
|
61
|
+
if (matchSuccess) {
|
62
|
+
ddLat = Math.abs(parseInt(match[2]));
|
63
|
+
if (match[4]) {
|
64
|
+
ddLat += match[4] / 60;
|
65
|
+
}
|
66
|
+
if (match[6]) {
|
67
|
+
ddLat += match[6].replace(',', '.') / 3600;
|
68
|
+
}
|
69
|
+
if (parseInt(match[2]) < 0) {
|
70
|
+
ddLat = -1 * ddLat;
|
71
|
+
}
|
72
|
+
ddLng = Math.abs(parseInt(match[9]));
|
73
|
+
if (match[11]) {
|
74
|
+
ddLng += match[11] / 60;
|
75
|
+
}
|
76
|
+
if (match[13]) {
|
77
|
+
ddLng += match[13].replace(',', '.') / 3600;
|
78
|
+
}
|
79
|
+
if (parseInt(match[9]) < 0) {
|
80
|
+
ddLng = -1 * ddLng;
|
81
|
+
}
|
82
|
+
//the compass directions
|
83
|
+
if (match[1]) {
|
84
|
+
latdir = match[1];
|
85
|
+
lngdir = match[8];
|
86
|
+
}
|
87
|
+
else if (match[7]) {
|
88
|
+
latdir = match[7];
|
89
|
+
lngdir = match[14];
|
90
|
+
}
|
91
|
+
}
|
92
|
+
else {
|
93
|
+
throw new Error("invalid DMS coordinates format");
|
94
|
+
}
|
95
|
+
}
|
96
|
+
else if (dms_abbr.test(coordsString)) {
|
97
|
+
match = dms_abbr.exec(coordsString);
|
98
|
+
matchSuccess = checkMatch(match);
|
99
|
+
if (matchSuccess) {
|
100
|
+
ddLat = Math.abs(parseInt(match[2]));
|
101
|
+
if (match[4]) {
|
102
|
+
ddLat += match[4] / 60;
|
103
|
+
}
|
104
|
+
if (match[6]) {
|
105
|
+
ddLat += match[6] / 3600;
|
106
|
+
}
|
107
|
+
if (parseInt(match[2]) < 0) {
|
108
|
+
ddLat = -1 * ddLat;
|
109
|
+
}
|
110
|
+
ddLng = Math.abs(parseInt(match[10]));
|
111
|
+
if (match[12]) {
|
112
|
+
ddLng += match[12] / 60;
|
113
|
+
}
|
114
|
+
if (match[14]) {
|
115
|
+
ddLng += match[14] / 3600;
|
116
|
+
}
|
117
|
+
if (parseInt(match[10]) < 0) {
|
118
|
+
ddLng = -1 * ddLng;
|
119
|
+
}
|
120
|
+
if (match[1]) {
|
121
|
+
latdir = match[1];
|
122
|
+
lngdir = match[9];
|
123
|
+
}
|
124
|
+
else if (match[8]) {
|
125
|
+
latdir = match[8];
|
126
|
+
lngdir = match[16];
|
127
|
+
}
|
128
|
+
}
|
129
|
+
else {
|
130
|
+
throw new Error("invalid DMS coordinates format");
|
131
|
+
}
|
132
|
+
}
|
133
|
+
else if (coords_other.test(coordsString)) {
|
134
|
+
match = coords_other.exec(coordsString);
|
135
|
+
matchSuccess = checkMatch(match);
|
136
|
+
if (matchSuccess) {
|
137
|
+
ddLat = Math.abs(parseInt(match[2]));
|
138
|
+
if (match[4]) {
|
139
|
+
ddLat += match[4] / 60;
|
140
|
+
}
|
141
|
+
if (match[6]) {
|
142
|
+
ddLat += match[6] / 3600;
|
143
|
+
}
|
144
|
+
if (parseInt(match[2]) < 0) {
|
145
|
+
ddLat = -1 * ddLat;
|
146
|
+
}
|
147
|
+
ddLng = Math.abs(parseInt(match[10]));
|
148
|
+
if (match[12]) {
|
149
|
+
ddLng += match[12] / 60;
|
150
|
+
}
|
151
|
+
if (match[14]) {
|
152
|
+
ddLng += match[14] / 3600;
|
153
|
+
}
|
154
|
+
if (parseInt(match[10]) < 0) {
|
155
|
+
ddLng = -1 * ddLng;
|
156
|
+
}
|
157
|
+
if (match[1]) {
|
158
|
+
latdir = match[1];
|
159
|
+
lngdir = match[9];
|
160
|
+
}
|
161
|
+
else if (match[8]) {
|
162
|
+
latdir = match[8];
|
163
|
+
lngdir = match[16];
|
164
|
+
}
|
165
|
+
}
|
166
|
+
else {
|
167
|
+
throw new Error("invalid coordinates format");
|
168
|
+
}
|
169
|
+
}
|
170
|
+
if (matchSuccess) {
|
171
|
+
//more validation....
|
172
|
+
//check longitude value - it can be wrong!
|
173
|
+
if (Math.abs(ddLng) >= 180) {
|
174
|
+
throw new Error("invalid longitude value");
|
175
|
+
}
|
176
|
+
//just to be safe check latitude also...
|
177
|
+
if (Math.abs(ddLat) >= 90) {
|
178
|
+
throw new Error("invalid latitude value");
|
179
|
+
}
|
180
|
+
//if we have one direction we must have the other
|
181
|
+
if ((latdir || lngdir) && (!latdir || !lngdir)) {
|
182
|
+
throw new Error("invalid coordinates format");
|
183
|
+
}
|
184
|
+
//the directions can't be the same
|
185
|
+
if (latdir && latdir == lngdir) {
|
186
|
+
throw new Error("invalid coordinates format");
|
187
|
+
}
|
188
|
+
//make sure the signs and cardinal directions match
|
189
|
+
let patt = /S|SOUTH/i;
|
190
|
+
if (patt.test(latdir)) {
|
191
|
+
if (ddLat > 0) {
|
192
|
+
ddLat = -1 * ddLat;
|
193
|
+
}
|
194
|
+
}
|
195
|
+
patt = /W|WEST/i;
|
196
|
+
if (patt.test(lngdir)) {
|
197
|
+
if (ddLng > 0) {
|
198
|
+
ddLng = -1 * ddLng;
|
199
|
+
}
|
200
|
+
}
|
201
|
+
//we need to get the verbatim coords from the string
|
202
|
+
//we can't split down the middle because if there are decimals they may have different numbers on each side
|
203
|
+
//so we need to find the separating character, or if none, use the match values to split down the middle
|
204
|
+
const verbatimCoordinates = match[0].trim();
|
205
|
+
let verbatimLat;
|
206
|
+
let verbatimLng;
|
207
|
+
const sepChars = /[,/;\u0020]/g; //comma, forward slash and spacebar
|
208
|
+
const seps = verbatimCoordinates.match(sepChars);
|
209
|
+
if (seps == null) {
|
210
|
+
//split down the middle
|
211
|
+
const middle = Math.floor(coordsString.length / 2);
|
212
|
+
verbatimLat = verbatimCoordinates.substring(0, middle).trim();
|
213
|
+
verbatimLng = verbatimCoordinates.substring(middle).trim();
|
214
|
+
}
|
215
|
+
else { //if length is odd then find the index of the middle value
|
216
|
+
//get the middle index
|
217
|
+
let middle;
|
218
|
+
//easy for odd numbers
|
219
|
+
if (seps.length % 2 == 1) {
|
220
|
+
middle = Math.floor(seps.length / 2);
|
221
|
+
}
|
222
|
+
else {
|
223
|
+
middle = (seps.length / 2) - 1;
|
224
|
+
}
|
225
|
+
//walk through seps until we get to the middle
|
226
|
+
let splitIndex = 0;
|
227
|
+
//it might be only one value
|
228
|
+
if (middle == 0) {
|
229
|
+
splitIndex = verbatimCoordinates.indexOf(seps[0]);
|
230
|
+
verbatimLat = verbatimCoordinates.substring(0, splitIndex).trim();
|
231
|
+
verbatimLng = verbatimCoordinates.substring(splitIndex + 1).trim();
|
232
|
+
}
|
233
|
+
else {
|
234
|
+
let currSepIndex = 0;
|
235
|
+
let startSearchIndex = 0;
|
236
|
+
while (currSepIndex <= middle) {
|
237
|
+
splitIndex = verbatimCoordinates.indexOf(seps[currSepIndex], startSearchIndex);
|
238
|
+
startSearchIndex = splitIndex + 1;
|
239
|
+
currSepIndex++;
|
240
|
+
}
|
241
|
+
verbatimLat = verbatimCoordinates.substring(0, splitIndex).trim();
|
242
|
+
verbatimLng = verbatimCoordinates.substring(splitIndex + 1).trim();
|
243
|
+
}
|
244
|
+
}
|
245
|
+
//validation again...
|
246
|
+
//we only allow zeros after the period if its DM
|
247
|
+
const splitLat = verbatimLat.split('.');
|
248
|
+
if (splitLat.length == 2) {
|
249
|
+
if (splitLat[1] == 0 && splitLat[1].length != 2) {
|
250
|
+
throw new Error('invalid coordinates format');
|
251
|
+
}
|
252
|
+
}
|
253
|
+
const splitLon = verbatimLng.split('.');
|
254
|
+
if (splitLon.length == 2) {
|
255
|
+
if (splitLon[1] == 0 && splitLon[1].length != 2) {
|
256
|
+
throw new Error('invalid coordinates format');
|
257
|
+
}
|
258
|
+
}
|
259
|
+
//no integer coords allowed
|
260
|
+
//validation -- no integer coords
|
261
|
+
if (/^\d+$/.test(verbatimLat) || /^\d+$/.test(verbatimLng)) {
|
262
|
+
throw new Error('degree only coordinate/s provided');
|
263
|
+
}
|
264
|
+
//some tidying up...
|
265
|
+
if (isNaN(ddLat) && ddLat.includes(',')) {
|
266
|
+
ddLat = ddLat.replace(',', '.');
|
267
|
+
}
|
268
|
+
//all done!!
|
269
|
+
//just truncate the decimals appropriately
|
270
|
+
ddLat = Number(Number(ddLat).toFixed(decimalPlaces));
|
271
|
+
if (isNaN(ddLng) && ddLng.includes(',')) {
|
272
|
+
ddLng = ddLng.replace(',', '.');
|
273
|
+
}
|
274
|
+
ddLng = Number(Number(ddLng).toFixed(decimalPlaces));
|
275
|
+
return Object.freeze({
|
276
|
+
verbatimCoordinates,
|
277
|
+
verbatimLatitude: verbatimLat,
|
278
|
+
verbatimLongitude: verbatimLng,
|
279
|
+
decimalLatitude: ddLat,
|
280
|
+
decimalLongitude: ddLng,
|
281
|
+
decimalCoordinates: `${ddLat},${ddLng}`,
|
282
|
+
closeEnough: coordsCloseEnough,
|
283
|
+
toCoordinateFormat
|
284
|
+
});
|
285
|
+
}
|
286
|
+
else {
|
287
|
+
throw new Error("coordinates pattern match failed");
|
288
|
+
}
|
289
|
+
}
|
290
|
+
function checkMatch(match) {
|
291
|
+
if (!isNaN(match[0])) { //we've matched a number, not what we want....
|
292
|
+
return false;
|
293
|
+
}
|
294
|
+
//first remove the empty values from the array
|
295
|
+
const filteredMatch = [...match];
|
296
|
+
//we need to shift the array because it contains the whole coordinates string in the first item
|
297
|
+
filteredMatch.shift();
|
298
|
+
//check the array length is an even number else exit
|
299
|
+
if (filteredMatch.length % 2 > 0) {
|
300
|
+
return false;
|
301
|
+
}
|
302
|
+
//regex for testing corresponding values match
|
303
|
+
const numerictest = /^[-+]?\d+([\.,]\d+)?$/; //for testing numeric values
|
304
|
+
const stringtest = /[eastsouthnorthwest]+/i; //for testing string values (north, south, etc)
|
305
|
+
const halflen = filteredMatch.length / 2;
|
306
|
+
for (let i = 0; i < halflen; i++) {
|
307
|
+
const leftside = filteredMatch[i];
|
308
|
+
const rightside = filteredMatch[i + halflen];
|
309
|
+
const bothAreNumbers = numerictest.test(leftside) && numerictest.test(rightside);
|
310
|
+
const bothAreStrings = stringtest.test(leftside) && stringtest.test(rightside);
|
311
|
+
const valuesAreEqual = leftside == rightside;
|
312
|
+
if (leftside == undefined && rightside == undefined) { //we have to handle undefined because regex converts it to string 'undefined'!!
|
313
|
+
continue;
|
314
|
+
}
|
315
|
+
else if (leftside == undefined || rightside == undefined) { //no we need to handle the case where one is and the other not...
|
316
|
+
return false;
|
317
|
+
}
|
318
|
+
else if (bothAreNumbers || bothAreStrings || valuesAreEqual) {
|
319
|
+
continue;
|
320
|
+
}
|
321
|
+
else {
|
322
|
+
return false;
|
323
|
+
}
|
324
|
+
}
|
325
|
+
return true;
|
326
|
+
}
|
327
|
+
//functions for coordinate validation
|
328
|
+
//as decimal arithmetic is not straightforward, we approximate
|
329
|
+
function decimalsCloseEnough(dec1, dec2) {
|
330
|
+
const originaldiff = Math.abs(dec1 - dec2);
|
331
|
+
const diff = Number(originaldiff.toFixed(6));
|
332
|
+
if (diff <= 0.00001) {
|
333
|
+
return true;
|
334
|
+
}
|
335
|
+
else {
|
336
|
+
return false;
|
337
|
+
}
|
338
|
+
}
|
339
|
+
function coordsCloseEnough(coordsToTest) {
|
340
|
+
if (coordsToTest.includes(',')) {
|
341
|
+
const coords = coordsToTest.split(',');
|
342
|
+
if (Number(coords[0]) == NaN || Number(coords[1]) == NaN) {
|
343
|
+
throw new Error("coords are not valid decimals");
|
344
|
+
}
|
345
|
+
else {
|
346
|
+
return decimalsCloseEnough(this.decimalLatitude, Number(coords[0])) && decimalsCloseEnough(this.decimalLongitude, coords[1]); //this here will be the converted coordinates object
|
347
|
+
}
|
348
|
+
}
|
349
|
+
else {
|
350
|
+
throw new Error("coords being tested must be separated by a comma");
|
351
|
+
}
|
352
|
+
}
|
353
|
+
const to = Object.freeze({
|
354
|
+
DMS: 'DMS',
|
355
|
+
DM: 'DM'
|
356
|
+
});
|
357
|
+
converter.to = to;
|
358
|
+
export default converter;
|
@@ -0,0 +1,6 @@
|
|
1
|
+
//adds the formats to the convert object
|
2
|
+
//we need to use this as the source for the npm package so that the formats are not included in the bundle
|
3
|
+
import converter from './converter.js';
|
4
|
+
import testFormats from './tests/testformats.js';
|
5
|
+
converter.formats = testFormats.map(format => format.verbatimCoordinates);
|
6
|
+
export const convert = converter;
|
@@ -0,0 +1,10 @@
|
|
1
|
+
//Coordinates pattern matching regex
|
2
|
+
//decimal degrees
|
3
|
+
const dd_re = /(NORTH|SOUTH|[NS])?[\s]*([+-]?[0-8]?[0-9](?:[\.,]\d{3,}))[\s]*([•º°]?)[\s]*(NORTH|SOUTH|[NS])?[\s]*[,/;]?[\s]*(EAST|WEST|[EW])?[\s]*([+-]?[0-1]?[0-9]?[0-9](?:[\.,]\d{3,}))[\s]*([•º°]?)[\s]*(EAST|WEST|[EW])?/i;
|
4
|
+
//degrees minutes seconds with '.' as separator - gives array with 15 values
|
5
|
+
const dms_periods = /(NORTH|SOUTH|[NS])?\s*([+-]?[0-8]?[0-9])\s*(\.)\s*([0-5]?[0-9])\s*(\.)\s*((?:[0-5]?[0-9])(?:[\.,]\d{1,3})?)?\s*(NORTH|SOUTH|[NS])?(?:\s*[,/;]\s*|\s*)(EAST|WEST|[EW])?\s*([+-]?[0-1]?[0-9]?[0-9])\s*(\.)\s*([0-5]?[0-9])\s*(\.)\s*((?:[0-5]?[0-9])(?:[\.,]\d{1,3})?)?\s*(EAST|WEST|[EW])?/i;
|
6
|
+
//degrees minutes seconds with words 'degrees, minutes, seconds' as separators (needed because the s of seconds messes with the S of SOUTH) - gives array of 17 values
|
7
|
+
const dms_abbr = /(NORTH|SOUTH|[NS])?\s*([+-]?[0-8]?[0-9])\s*(D(?:EG)?(?:REES)?)\s*([0-5]?[0-9])\s*(M(?:IN)?(?:UTES)?)\s*((?:[0-5]?[0-9])(?:[\.,]\d{1,3})?)?\s*(S(?:EC)?(?:ONDS)?)?\s*(NORTH|SOUTH|[NS])?(?:\s*[,/;]\s*|\s*)(EAST|WEST|[EW])?\s*([+-]?[0-1]?[0-9]?[0-9])\s*(D(?:EG)?(?:REES)?)\s*([0-5]?[0-9])\s*(M(?:IN)?(?:UTES)?)\s*((?:[0-5]?[0-9])(?:[\.,]\d{1,3})?)?\s*(S(?:EC)?(?:ONDS)?)\s*(EAST|WEST|[EW])?/i;
|
8
|
+
//everything else - gives array of 17 values
|
9
|
+
const coords_other = /(NORTH|SOUTH|[NS])?\s*([+-]?[0-8]?[0-9])\s*([•º°\.:]|D(?:EG)?(?:REES)?)?\s*,?([0-5]?[0-9](?:[\.,]\d{1,})?)?\s*(['′´’\.:]|M(?:IN)?(?:UTES)?)?\s*,?((?:[0-5]?[0-9])(?:[\.,]\d{1,3})?)?\s*(''|′′|’’|´´|["″”\.])?\s*(NORTH|SOUTH|[NS])?(?:\s*[,/;]\s*|\s*)(EAST|WEST|[EW])?\s*([+-]?[0-1]?[0-9]?[0-9])\s*([•º°\.:]|D(?:EG)?(?:REES)?)?\s*,?([0-5]?[0-9](?:[\.,]\d{1,})?)?\s*(['′´’\.:]|M(?:IN)?(?:UTES)?)?\s*,?((?:[0-5]?[0-9])(?:[\.,]\d{1,3})?)?\s*(''|′′|´´|’’|["″”\.])?\s*(EAST|WEST|[EW])?/i;
|
10
|
+
export { dd_re, dms_periods, dms_abbr, coords_other };
|
@@ -0,0 +1,24 @@
|
|
1
|
+
//TODO These formats should throw...
|
2
|
+
const failingFormats = [
|
3
|
+
'10,10',
|
4
|
+
'46,8',
|
5
|
+
'12.12323, 123',
|
6
|
+
'24.0, 26.0',
|
7
|
+
'33.25°S 18.25°E',
|
8
|
+
'27.0 23.0',
|
9
|
+
'10.00000S 10.000000E',
|
10
|
+
'00.00 01.00',
|
11
|
+
'50°4\'17.698"south, 24.34532',
|
12
|
+
'90°4\'17.698"south, 23°4\'17.698"east',
|
13
|
+
'89°4\'17.698"south, 183°4\'17.698"east',
|
14
|
+
'50°4\'17.698"east, 23°4\'17.698"south',
|
15
|
+
'E23.34355,S25.324234',
|
16
|
+
'23°45\'12.2\'\'S 18.33\'56.7\'\'E',
|
17
|
+
'S 27.45.34 23.23.23',
|
18
|
+
'S 27.45.34 S 23.23.23',
|
19
|
+
'S 90°4\'17.698" S 23°4\'17.698"',
|
20
|
+
'27.45.34 S S 23.23.23',
|
21
|
+
'27.45.34 23.23.23 E',
|
22
|
+
'8°83S 35°67E '
|
23
|
+
];
|
24
|
+
export default failingFormats;
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import fs from 'fs';
|
2
|
+
import testFormats from './testformats.js';
|
3
|
+
fs.writeFile("testFormats.json", JSON.stringify(testFormats, null, 2), 'utf8', function (err) {
|
4
|
+
if (err) {
|
5
|
+
console.log("An error occured while writing JSON Object to File.");
|
6
|
+
return console.log(err);
|
7
|
+
}
|
8
|
+
console.log("JSON file has been saved.");
|
9
|
+
});
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1,51 @@
|
|
1
|
+
import convert from '../converter.js';
|
2
|
+
import testFormats from '../testformats.js';
|
3
|
+
import failingFormats from './failFormats.js';
|
4
|
+
let allPassed = true;
|
5
|
+
//FORMATS THAT SHOULD BE CONVERTED
|
6
|
+
for (const t of testFormats) {
|
7
|
+
try {
|
8
|
+
const converted = convert(t.verbatimCoordinates, 8);
|
9
|
+
const testDecimalCoordsString = `${t.decimalLatitude},${t.decimalLongitude}`;
|
10
|
+
//check the calculation is correct
|
11
|
+
if (!converted.closeEnough(testDecimalCoordsString)) {
|
12
|
+
console.log("Error in decimal conversion");
|
13
|
+
console.log(t.verbatimCoordinates);
|
14
|
+
console.log(t.decimalLatitude);
|
15
|
+
console.log(t.decimalLongitude);
|
16
|
+
allPassed = false;
|
17
|
+
}
|
18
|
+
//check the verbatim coords are correct
|
19
|
+
if (converted.verbatimLatitude != t.verbatimLatitude || converted.verbatimLongitude != t.verbatimLongitude) {
|
20
|
+
console.log("Error in verbatim extraction");
|
21
|
+
console.log('For', t.verbatimCoordinates);
|
22
|
+
console.log('got', converted.verbatimLatitude, 'should be ', t.verbatimLatitude);
|
23
|
+
console.log('got', converted.verbatimLongitude, 'should be', t.verbatimLongitude);
|
24
|
+
allPassed = false;
|
25
|
+
}
|
26
|
+
}
|
27
|
+
catch (err) {
|
28
|
+
console.log("Failed to convert the following format");
|
29
|
+
console.log(t.verbatimCoordinates);
|
30
|
+
console.log(err.message);
|
31
|
+
allPassed = false;
|
32
|
+
}
|
33
|
+
}
|
34
|
+
//FORMATS THAT SHOULD NOT BE CONVERTED
|
35
|
+
const converting = [];
|
36
|
+
for (let f of failingFormats) {
|
37
|
+
try {
|
38
|
+
const converted = convert(f);
|
39
|
+
converting.push(f);
|
40
|
+
allPassed = false;
|
41
|
+
}
|
42
|
+
catch {
|
43
|
+
//nothing here
|
44
|
+
}
|
45
|
+
}
|
46
|
+
if (converting.length) {
|
47
|
+
console.log("The following coordinates should NOT have converted successfully: " + converting.join(' | '));
|
48
|
+
}
|
49
|
+
if (allPassed) {
|
50
|
+
console.log("all formats successfully converted");
|
51
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import convert from '../converter.js';
|
2
|
+
//const test = '26°44S 29°46E'
|
3
|
+
//const test = '00.00, 01.00'
|
4
|
+
const test = `8°83S 35°67E`;
|
5
|
+
try {
|
6
|
+
let converted = convert(test);
|
7
|
+
console.log(converted);
|
8
|
+
console.log(converted.toCoordinateFormat(convert.to.DM));
|
9
|
+
//and just to make sure it's frozen
|
10
|
+
let previous = converted.decimalLatitude;
|
11
|
+
converted.decimalLatitude = 24;
|
12
|
+
if (converted.decimalLatitude === previous) {
|
13
|
+
console.log('the result is frozen');
|
14
|
+
}
|
15
|
+
else {
|
16
|
+
console.error('!!!The result is not frozen!!!!');
|
17
|
+
}
|
18
|
+
}
|
19
|
+
catch (err) {
|
20
|
+
console.log(err.message);
|
21
|
+
}
|