geo-coordinates-parser 1.3.2 → 1.4.3
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +13 -7
- package/bundle/geocoordsparser.js +1 -1
- package/bundle/workflow.txt +2 -0
- package/converter.js +23 -6
- package/package.json +1 -1
- package/testFormatConverter.js +8 -0
- package/testIndividual.js +13 -1
- package/testformats.js +7 -0
- package/toCoordinateFormat.js +52 -0
package/README.md
CHANGED
@@ -48,14 +48,14 @@ converted.verbatimLongitude; // '-79° 56.93172' ✓
|
|
48
48
|
```
|
49
49
|
The returned object includes properties verbatimCoordinates, verbatimLatitude, verbatimLongitude, decimalLatitude, decimalLatitude, and decimalCoordinates.
|
50
50
|
|
51
|
+
### Validating other conversions
|
51
52
|
Sometimes we may want to validate existing decimal coordinates against those returned from the converter to find errors. Because we're working with decimal numbers we must settle for values that are close enough (in this case equal up to six decimal places).
|
52
53
|
|
53
54
|
```js
|
54
|
-
converted.closeEnough(
|
55
|
+
converted.closeEnough(yourDecimalCoordinatesToValidate) //must be a numbers separated by ,
|
55
56
|
```
|
56
57
|
|
57
58
|
### Supported formats
|
58
|
-
|
59
59
|
All formats (except the 'exotic formats') covered by [npm coordinate-parser](https://www.npmjs.com/package/coordinate-parser) and the [coordinate regex in this GitHub Gist](https://gist.github.com/moole/3707127/337bd31d813a10abcf55084381803e5bbb0b20dc), including the following:
|
60
60
|
- -23.3245° S / 28.2344° E
|
61
61
|
- 27deg 15min 45.2sec S 18deg 32min 53.7sec E
|
@@ -71,14 +71,20 @@ Formats used for testing can be be accessed with:
|
|
71
71
|
convert.formats
|
72
72
|
```
|
73
73
|
|
74
|
-
|
74
|
+
**<span style="color:red">Please add coordinate formats that throw an error in the Github Issues.</span>**
|
75
|
+
|
76
|
+
**<span style="color:red">Note that formats like 24.56S 26.48E are treated as degrees and minutes! And 24.0, 26.0 is treated as an error. If you don't want this behaviour you need to catch these cases with your own code before you use convert.</span>**
|
75
77
|
|
76
78
|
### Want to use it in the browser?
|
77
|
-
|
79
|
+
Add ```<script src="https://cdn.jsdelivr.net/npm/geo-coordinates-parser/bundle/geocoordsparser.js"></script>```
|
80
|
+
to your html head and you'll have the ```convert``` function available globally. You won't have .formats, .closeEnough or .toCoordinateFormat though, only the coordinates conversion function.
|
81
|
+
|
82
|
+
### Convert back to standard formats
|
83
|
+
Sometimes we might want to convert back to more traditional formats for representing coordinates, such as DMS or DM. This can be useful for standardizing coordinates. The convert function has an enum to help.
|
78
84
|
|
79
|
-
|
80
|
-
|
81
|
-
|
85
|
+
```js
|
86
|
+
converted.toCoordinateFormat(convert.to.DMS) /// '40° 26.771" N, 79° 56.932" W' ✓
|
87
|
+
```
|
82
88
|
|
83
89
|
### License
|
84
90
|
MIT Licence
|
@@ -1 +1 @@
|
|
1
|
-
!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).convert=t()}}(function(){function t(t){if(!isNaN(t[0]))return!1;var e=t.filter(t=>t);if(e.shift(),e.length%2>0)return!1;for(var r=/^[-+]?(\d+|\d+\.\d*|\d*\.\d+)$/,i=/[A-Za-z]+/,a=e.length/2,n=!0,
|
1
|
+
!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).convert=t()}}(function(){function t(t,e,r){const i=Number(t);let a;a=r?i>=0?"N":"S":i>=0?"E":"W";const n=Math.abs(i),o=Math.floor(n),s=60*(n-o);if("DM"==e)return`${o}\xb0 ${s.toFixed(3).replace(/\.0+$/,"")}' ${a}`;const d=Math.floor(s);return`${o}\xb0 ${d}' ${(60*(s-d)).toFixed(1).replace(/\.0$/,"")}" ${a}`}var e=function(e){if(!["DMS","DM"].includes(e))throw new Error("invalid format specified");if(this.decimalCoordinates&&this.decimalCoordinates.trim()){const r=this.decimalCoordinates.split(",").map(t=>t.trim());return`${t(r[0],e,!0)}, ${t(r[1],e,!1)}`}throw new Error("no decimal coordinates to convert")};function r(t,r){r||(r=5),t=t.replace(/\s\s+/g," ").trim();var a=null,l=null,f="",c="",E=[],S=!1;if(o.test(t)){if(!(S=i(E=o.exec(t))))throw new Error("invalid decimal coordinate format");a=E[2],l=E[6],a.includes(",")&&(a=a.replace(",",".")),l.includes(",")&&(l=l.replace(",",".")),E[1]?(f=E[1],c=E[5]):E[4]&&(f=E[4],c=E[8])}else if(s.test(t)){if(!(S=i(E=s.exec(t))))throw new Error("invalid DMS coordinates format");a=Math.abs(parseInt(E[2])),E[4]&&(a+=E[4]/60),E[6]&&(a+=E[6]/3600),parseInt(E[2])<0&&(a*=-1),l=Math.abs(parseInt(E[9])),E[11]&&(l+=E[11]/60),E[13]&&(l+=E[13]/3600),parseInt(E[9])<0&&(l*=-1),E[1]?(f=E[1],c=E[8]):E[7]&&(f=E[7],c=E[14])}else if(d.test(t)){if(!(S=i(E=d.exec(t))))throw new Error("invalid DMS coordinates format");a=Math.abs(parseInt(E[2])),E[4]&&(a+=E[4]/60,E[3]||(E[3]=" ")),E[6]&&(a+=E[6]/3600,E[5]||(E[5]=" ")),parseInt(E[2])<0&&(a*=-1),l=Math.abs(parseInt(E[10])),E[12]&&(l+=E[12]/60,E[11]||(E[11]=" ")),E[14]&&(l+=E[14]/3600,E[13]||(E[13]=" ")),parseInt(E[10])<0&&(l*=-1),E[1]?(f=E[1],c=E[9]):E[8]&&(f=E[8],c=E[16])}else if(u.test(t)){if(!(S=i(E=u.exec(t))))throw new Error("invalid coordinates format");a=Math.abs(parseInt(E[2])),E[4]&&(a+=E[4]/60,E[3]||(E[3]=" ")),E[6]&&(a+=E[6]/3600,E[5]||(E[5]=" ")),parseInt(E[2])<0&&(a*=-1),l=Math.abs(parseInt(E[10])),E[12]&&(l+=E[12]/60,E[11]||(E[11]=" ")),E[14]&&(l+=E[14]/3600,E[13]||(E[13]=" ")),parseInt(E[10])<0&&(l*=-1),E[1]?(f=E[1],c=E[9]):E[8]&&(f=E[8],c=E[16])}if(Math.abs(l)>=180)throw new Error("invalid longitude value");if(S){var b=/S|SOUTH/i;b.test(f)&&a>0&&(a*=-1),(b=/W|WEST/i).test(c)&&l>0&&(l*=-1);var m,N,h=E[0].trim(),T=h.match(/[,/;\u0020]/g);if(null==T){var p=Math.floor(t.length/2);m=h.substring(0,p).trim(),N=h.substring(p).trim()}else{var x=0;if(0==(p=T.length%2==1?Math.floor(T.length/2):T.length/2-1))x=h.indexOf(T[0]),m=h.substring(0,x).trim(),N=h.substring(x+1).trim();else{for(var M=0,v=0;M<=p;)v=(x=h.indexOf(T[M],v))+1,M++;m=h.substring(0,x).trim(),N=h.substring(x+1).trim()}}return isNaN(a)&&a.includes(",")&&(a=a.replace(",",".")),a=Number(Number(a).toFixed(r)),isNaN(l)&&l.includes(",")&&(l=l.replace(",",".")),l=Number(Number(l).toFixed(r)),Object.freeze({verbatimCoordinates:h,verbatimLatitude:m,verbatimLongitude:N,decimalLatitude:a,decimalLongitude:l,decimalCoordinates:`${a},${l}`,closeEnough:n,toCoordinateFormat:e})}throw new Error("coordinates pattern match failed")}function i(t){if(!isNaN(t[0]))return!1;var e=t.filter(t=>t);if(e.shift(),e.length%2>0)return!1;for(var r=/^[-+]?(\d+|\d+\.\d*|\d*\.\d+)$/,i=/[A-Za-z]+/,a=e.length/2,n=!0,o=0;o<a;o++)if(r.test(e[o])!=r.test(e[o+a])||i.test(e[o])!=i.test(e[o+a])){n=!1;break}return n}function a(t,e){var r=Math.abs(t-e);return diff=Number(r.toFixed(6)),diff<=1e-5}function n(t){if(t.includes(",")){var e=t.split(",");if(NaN==Number(e[0])||NaN==Number(e[1]))throw new Error("coords are not valid decimals");return a(this.decimalLatitude,Number(e[0]))&&a(this.decimalLongitude,e[1])}throw new Error("coords being tested must be separated by a comma")}var o=/(NORTH|SOUTH|[NS])?[\s]*([+-]?[0-8]?[0-9](?:[\.,]\d{3,}))([\u2022\xba\xb0]?)[\s]*(NORTH|SOUTH|[NS])?[\s]*[,/;]?[\s]*(EAST|WEST|[EW])?[\s]*([+-]?[0-1]?[0-9]?[0-9](?:[\.,]\d{3,}))([\u2022\xba\xb0]?)[\s]*(EAST|WEST|[EW])?/i,s=/(NORTH|SOUTH|[NS])?[\ \t]*([+-]?[0-8]?[0-9])[\ \t]*(\.)[\ \t]*([0-5]?[0-9])[\ \t]*(\.)?[\ \t]*((?:[0-5]?[0-9])(?:\.\d{1,3})?)?(NORTH|SOUTH|[NS])?(?:[\ \t]*[,/;][\ \t]*|[\ \t]*)(EAST|WEST|[EW])?[\ \t]*([+-]?[0-1]?[0-9]?[0-9])[\ \t]*(\.)[\ \t]*([0-5]?[0-9])[\ \t]*(\.)?[\ \t]*((?:[0-5]?[0-9])(?:\.\d{1,3})?)?(EAST|WEST|[EW])?/i,d=/(NORTH|SOUTH|[NS])?[\ \t]*([+-]?[0-8]?[0-9])[\ \t]*(D(?:EG)?(?:REES)?)[\ \t]*([0-5]?[0-9])[\ \t]*(M(?:IN)?(?:UTES)?)[\ \t]*((?:[0-5]?[0-9])(?:\.\d{1,3})?)?(S(?:EC)?(?:ONDS)?)?[\ \t]*(NORTH|SOUTH|[NS])?(?:[\ \t]*[,/;][\ \t]*|[\ \t]*)(EAST|WEST|[EW])?[\ \t]*([+-]?[0-1]?[0-9]?[0-9])[\ \t]*(D(?:EG)?(?:REES)?)[\ \t]*([0-5]?[0-9])[\ \t]*(M(?:IN)?(?:UTES)?)[\ \t]*((?:[0-5]?[0-9])(?:\.\d{1,3})?)?(S(?:EC)?(?:ONDS)?)[\ \t]*(EAST|WEST|[EW])?/i,u=/(NORTH|SOUTH|[NS])?[\ \t]*([+-]?[0-8]?[0-9])[\ \t]*([\u2022\xba\xb0\.:]|D(?:EG)?(?:REES)?)?[\ \t]*,?([0-5]?[0-9](?:\.\d{1,})?)?[\ \t]*(['\u2032\xb4\u2019\.:]|M(?:IN)?(?:UTES)?)?[\ \t]*,?((?:[0-5]?[0-9])(?:\.\d{1,3})?)?[\ \t]*(''|\u2032\u2032|\u2019\u2019|\xb4\xb4|["\u2033\u201d\.])?[\ \t]*(NORTH|SOUTH|[NS])?(?:\s*[,/;]\s*|\s*)(EAST|WEST|[EW])?[\ \t]*([+-]?[0-1]?[0-9]?[0-9])[\ \t]*([\u2022\xba\xb0\.:]|D(?:EG)?(?:REES)?)?[\ \t]*,?([0-5]?[0-9](?:\.\d{1,})?)?[\ \t]*(['\u2032\xb4\u2019\.:]|M(?:IN)?(?:UTES)?)?[\ \t]*,?((?:[0-5]?[0-9])(?:\.\d{1,3})?)?[\ \t]*(''|\u2032\u2032|\xb4\xb4|\u2019\u2019|["\u2033\u201d\.])?[\ \t]*(EAST|WEST|[EW])?/i;const l=Object.freeze({DMS:"DMS",DM:"DM"});return r.to=l,r});
|
package/bundle/workflow.txt
CHANGED
package/converter.js
CHANGED
@@ -1,7 +1,16 @@
|
|
1
1
|
//function for converting coordinates from a string to decimal and verbatim
|
2
|
-
|
2
|
+
|
3
|
+
const toCoordinateFormat = require('./toCoordinateFormat.js')
|
4
|
+
|
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
|
+
*/
|
3
11
|
function converter(coordsString, decimalPlaces) {
|
4
12
|
|
13
|
+
//TODO add exact match to entered string, so that it can be used to filter out superflous text around it
|
5
14
|
if(!decimalPlaces) {
|
6
15
|
decimalPlaces = 5
|
7
16
|
}
|
@@ -24,10 +33,10 @@ function converter(coordsString, decimalPlaces) {
|
|
24
33
|
|
25
34
|
//need to fix if there are ','s instead of '.'
|
26
35
|
if(ddLat.includes(',')) {
|
27
|
-
ddLat.replace(',','.');
|
36
|
+
ddLat = ddLat.replace(',','.');
|
28
37
|
}
|
29
38
|
if(ddLng.includes(',')) {
|
30
|
-
ddLng.replace(',', '.');
|
39
|
+
ddLng = ddLng.replace(',', '.');
|
31
40
|
}
|
32
41
|
|
33
42
|
//get directions
|
@@ -254,15 +263,16 @@ function converter(coordsString, decimalPlaces) {
|
|
254
263
|
|
255
264
|
ddLng = Number(Number(ddLng).toFixed(decimalPlaces))
|
256
265
|
|
257
|
-
return {
|
266
|
+
return Object.freeze({
|
258
267
|
verbatimCoordinates,
|
259
268
|
verbatimLatitude: verbatimLat,
|
260
269
|
verbatimLongitude: verbatimLng,
|
261
270
|
decimalLatitude: ddLat,
|
262
271
|
decimalLongitude: ddLng,
|
263
272
|
decimalCoordinates: `${ddLat},${ddLng}`,
|
264
|
-
closeEnough: coordsCloseEnough
|
265
|
-
|
273
|
+
closeEnough: coordsCloseEnough,
|
274
|
+
toCoordinateFormat
|
275
|
+
})
|
266
276
|
}
|
267
277
|
else {
|
268
278
|
throw new Error("coordinates pattern match failed")
|
@@ -348,4 +358,11 @@ var dms_abbr = /(NORTH|SOUTH|[NS])?[\ \t]*([+-]?[0-8]?[0-9])[\ \t]*(D(?:EG)?(?:R
|
|
348
358
|
//everything else - gives array of 17 values
|
349
359
|
var coords_other = /(NORTH|SOUTH|[NS])?[\ \t]*([+-]?[0-8]?[0-9])[\ \t]*([•º°\.:]|D(?:EG)?(?:REES)?)?[\ \t]*,?([0-5]?[0-9](?:\.\d{1,})?)?[\ \t]*(['′´’\.:]|M(?:IN)?(?:UTES)?)?[\ \t]*,?((?:[0-5]?[0-9])(?:\.\d{1,3})?)?[\ \t]*(''|′′|’’|´´|["″”\.])?[\ \t]*(NORTH|SOUTH|[NS])?(?:\s*[,/;]\s*|\s*)(EAST|WEST|[EW])?[\ \t]*([+-]?[0-1]?[0-9]?[0-9])[\ \t]*([•º°\.:]|D(?:EG)?(?:REES)?)?[\ \t]*,?([0-5]?[0-9](?:\.\d{1,})?)?[\ \t]*(['′´’\.:]|M(?:IN)?(?:UTES)?)?[\ \t]*,?((?:[0-5]?[0-9])(?:\.\d{1,3})?)?[\ \t]*(''|′′|´´|’’|["″”\.])?[\ \t]*(EAST|WEST|[EW])?/i;
|
350
360
|
|
361
|
+
const to = Object.freeze({
|
362
|
+
DMS: 'DMS',
|
363
|
+
DM: 'DM'
|
364
|
+
})
|
365
|
+
|
366
|
+
converter.to = to
|
367
|
+
|
351
368
|
module.exports = converter
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "geo-coordinates-parser",
|
3
|
-
"version": "1.3
|
3
|
+
"version": "1.4.3",
|
4
4
|
"description": "A Javascript function for reading a variety of coordinate formats and converting to decimal numbers. Builds on other efforts by returning the verbatim coordinates and the decimal coordinates all in one object.",
|
5
5
|
"main": "merge.js",
|
6
6
|
"scripts": {
|
package/testIndividual.js
CHANGED
@@ -1,8 +1,20 @@
|
|
1
1
|
const convert = require('./converter')
|
2
|
-
const test = '
|
2
|
+
const test = '27,71372° S 23,07771° E'
|
3
|
+
|
3
4
|
try{
|
4
5
|
let converted = convert(test)
|
5
6
|
console.log(converted)
|
7
|
+
console.log(converted.toCoordinateFormat(convert.to.DM))
|
8
|
+
|
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
|
+
}
|
6
18
|
}
|
7
19
|
catch(err){
|
8
20
|
console.log(err.message)
|
package/testformats.js
CHANGED
@@ -265,6 +265,13 @@ var otherFormats = [
|
|
265
265
|
verbatimLongitude: '18.32.53E',
|
266
266
|
decimalLatitude: -27.2625,
|
267
267
|
decimalLongitude: 18.548055
|
268
|
+
},
|
269
|
+
{
|
270
|
+
verbatimCoordinates: '27,71372° S 23,07771° E', //decimals with commas
|
271
|
+
verbatimLatitude: '27,71372° S',
|
272
|
+
verbatimLongitude: '23,07771° E',
|
273
|
+
decimalLatitude: -27.71372,
|
274
|
+
decimalLongitude: 23.07771
|
268
275
|
}
|
269
276
|
]
|
270
277
|
|
@@ -0,0 +1,52 @@
|
|
1
|
+
|
2
|
+
//borrowed from https://www.codegrepper.com/code-examples/javascript/javascript+converting+latitude+longitude+to+gps+coordinates
|
3
|
+
|
4
|
+
/**
|
5
|
+
* Converts decimalCoordinates to other formats commonly used
|
6
|
+
* @param {*} format Either DMS or DM
|
7
|
+
*/
|
8
|
+
function toCoordinateFormat(format) {
|
9
|
+
|
10
|
+
if(!['DMS', 'DM'].includes(format)) throw new Error('invalid format specified')
|
11
|
+
|
12
|
+
if(this.decimalCoordinates && this.decimalCoordinates.trim()) {
|
13
|
+
const parts = this.decimalCoordinates.split(',').map(x => x.trim())
|
14
|
+
const convertedLat = convert(parts[0], format, true)
|
15
|
+
const convertedLong = convert(parts[1], format, false)
|
16
|
+
return `${convertedLat}, ${convertedLong}`
|
17
|
+
}
|
18
|
+
else {
|
19
|
+
throw new Error('no decimal coordinates to convert')
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
//assumes everything is valid...
|
24
|
+
function convert(coordString, format, isLatitude) {
|
25
|
+
|
26
|
+
const coord = Number(coordString)
|
27
|
+
|
28
|
+
let direction
|
29
|
+
if (isLatitude) {
|
30
|
+
direction = coord >= 0 ? "N" : "S";
|
31
|
+
}
|
32
|
+
else {
|
33
|
+
direction = coord >= 0 ? "E" : "W";
|
34
|
+
}
|
35
|
+
|
36
|
+
const absolute = Math.abs(coord);
|
37
|
+
|
38
|
+
const degrees = Math.floor(absolute);
|
39
|
+
const minutesNotTruncated = (absolute - degrees) * 60;
|
40
|
+
|
41
|
+
if(format == 'DM') {
|
42
|
+
return `${degrees}° ${minutesNotTruncated.toFixed(3).replace(/\.0+$/, '')}' ${direction}`;
|
43
|
+
}
|
44
|
+
|
45
|
+
//else
|
46
|
+
const minutes = Math.floor(minutesNotTruncated);
|
47
|
+
const seconds = ((minutesNotTruncated - minutes) * 60).toFixed(1).replace(/\.0$/, '');
|
48
|
+
|
49
|
+
return `${degrees}° ${minutes}' ${seconds}" ${direction}`;
|
50
|
+
}
|
51
|
+
|
52
|
+
module.exports = toCoordinateFormat
|