geo-coordinates-parser 1.3.0 → 1.4.1

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Geo Coordinates Parser
2
2
 
3
- A Javascript function for reading a variety of coordinate formats and converting to decimal latitude and longitude. Builds on other efforts for convenience by returning the verbatim coordinates and the decimal coordinates all in one object. Also includes a function to test existing decimal coordinates against those from the converter.
3
+ A Javascript function for reading a variety of coordinate formats and converting to decimal latitude and longitude. Builds on previous efforts and returns the verbatim coordinates and the decimal coordinates together in one object for convenience. Can be used to extract coordinates from longer strings. Also includes a function to test existing decimal coordinates against those from the converter.
4
4
 
5
- ##If you like this package please [star it on GitHub](https://github.com/ianengelbrecht/geo-coordinates-parser)
5
+ ##If you like this tool please [star it on GitHub](https://github.com/ianengelbrecht/geo-coordinates-parser)
6
6
 
7
7
  ### Installation
8
8
  ```
@@ -15,18 +15,31 @@ const convert = require('geo-coordinates-parser');
15
15
  ```
16
16
  OR
17
17
  ```js
18
- import convert from 'geo-coordinates-parser' //ES6
18
+ import convert from 'geo-coordinates-parser' //ES6, if you're using a bundler
19
19
  ```
20
20
  THEN
21
21
  ```js
22
- let converted = convert('40° 26.7717, -79° 56.93172');
22
+ let converted;
23
+ try {
24
+ converted = convert('40° 26.7717, -79° 56.93172');
25
+ }
26
+ catch {
27
+ /*we get here if the string is not valid coordinates or format is inconsistent between lat and long*/
28
+ }
29
+
23
30
  ```
24
31
  OR add the number of decimal places you want (but be reasonable, [see Coordinate Precision here](https://en.wikipedia.org/wiki/Decimal_degrees)) -- default is 5
25
32
 
26
33
  ```js
27
- let converted = convert(coordinatesString, integerDecimalPlaces)
34
+ try{
35
+ let converted = convert(coordinatesString, integerDecimalPlaces)
36
+ //do stuff with coordinates...
37
+ }
38
+ catch{
39
+ //coordinates not valid
40
+ }
28
41
  ```
29
- THEN
42
+ ALSO
30
43
  ```js
31
44
  converted.decimalLatitude; // 40.446195 ✓
32
45
  converted.decimalLongitude; // -79.948862 ✓
@@ -35,14 +48,14 @@ converted.verbatimLongitude; // '-79° 56.93172' ✓
35
48
  ```
36
49
  The returned object includes properties verbatimCoordinates, verbatimLatitude, verbatimLongitude, decimalLatitude, decimalLatitude, and decimalCoordinates.
37
50
 
38
- 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 the same up to six decimal places).
51
+ ### Validating other conversions
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).
39
53
 
40
54
  ```js
41
- converted.closeEnough(yourDecimalCoordinatesToTest) //must be a string separated by ,
55
+ converted.closeEnough(yourDecimalCoordinatesToValidate) //must be a numbers separated by ,
42
56
  ```
43
57
 
44
58
  ### Supported formats
45
-
46
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:
47
60
  - -23.3245° S / 28.2344° E
48
61
  - 27deg 15min 45.2sec S 18deg 32min 53.7sec E
@@ -55,17 +68,22 @@ All formats (except the 'exotic formats') covered by [npm coordinate-parser](htt
55
68
  Formats used for testing can be be accessed with:
56
69
 
57
70
  ```
58
- covert.formats
71
+ convert.formats
59
72
  ```
60
73
 
61
- **Please add coordinate formats that throw an error in the Github Issues.**
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>**
62
77
 
63
78
  ### Want to use it in the browser?
64
79
  A ready bundled script is available in the source code, in the bundle directory, named geocoordsparser.js. [Download](https://stackoverflow.com/a/13593430/3210158), include it in a script tag in your html, and you'll have a function called `convert()` available in your environment.
65
80
 
66
- ### Other implementations
67
- There is an [MS Excel plugin here](http://bit.ly/convertcoords). See the README for instructions.
68
- More to come...
81
+ ### Convert back to standard formats
82
+ 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.
83
+
84
+ ```js
85
+ converted.toCoordinateFormat(convert.to.DMS) /// '40° 26.771" N, 79° 56.932" W' ✓
86
+ ```
69
87
 
70
88
  ### License
71
89
  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){var e=t.filter(function(t){return!(!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,s=0;s<a;s++)if(r.test(e[s])!=r.test(e[s+a])||i.test(e[s])!=i.test(e[s+a])){n=!1;break}return n}function e(t,e){var r=Math.abs(t-e);return diff=Number(r.toFixed(6)),diff<=1e-5}function r(t){if(t.includes(",")){var r=t.split(",");if(NaN==Number(r[0])||NaN==Number(r[1]))throw new Error("coords are not valid decimals");return e(this.decimalLatitude,Number(r[0]))&&e(this.decimalLongitude,r[1])}throw new Error("coords being tested must be separated by a comma")}var i=/(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,a=/(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,n=/(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,s=/(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])?(?:[\ \t]*[,/][\ \t]*|[\ \t]*)(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;return function(e,o){o||(o=5),e=e.replace(/\s\s+/g," ").trim();var d=null,u=null,f="",l="",E=[],S=!1;if(i.test(e)){if(!(S=t(E=i.exec(e))))throw new Error("invalid decimal coordinate format");d=E[2],u=E[6],d.includes(",")&&d.replace(",","."),u.includes(",")&&u.replace(",","."),E[1]?(f=E[1],l=E[5]):E[4]&&(f=E[4],l=E[8])}else if(a.test(e)){if(!(S=t(E=a.exec(e))))throw new Error("invalid DMS coordinates format");d=Math.abs(parseInt(E[2])),E[4]&&(d+=E[4]/60),E[6]&&(d+=E[6]/3600),parseInt(E[2])<0&&(d*=-1),u=Math.abs(parseInt(E[9])),E[11]&&(u+=E[11]/60),E[13]&&(u+=E[13]/3600),parseInt(E[9])<0&&(u*=-1),E[1]?(f=E[1],l=E[8]):E[7]&&(f=E[7],l=E[14])}else if(n.test(e)){if(!(S=t(E=n.exec(e))))throw new Error("invalid DMS coordinates format");d=Math.abs(parseInt(E[2])),E[4]&&(d+=E[4]/60,E[3]||(E[3]=" ")),E[6]&&(d+=E[6]/3600,E[5]||(E[5]=" ")),parseInt(E[2])<0&&(d*=-1),u=Math.abs(parseInt(E[10])),E[12]&&(u+=E[12]/60,E[11]||(E[11]=" ")),E[14]&&(u+=E[14]/3600,E[13]||(E[13]=" ")),parseInt(E[10])<0&&(u*=-1),E[1]?(f=E[1],l=E[9]):E[8]&&(f=E[8],l=E[16])}else if(s.test(e)){if(!(S=t(E=s.exec(e))))throw new Error("invalid coordinates format");d=Math.abs(parseInt(E[2])),E[4]&&(d+=E[4]/60,E[3]||(E[3]=" ")),E[6]&&(d+=E[6]/3600,E[5]||(E[5]=" ")),parseInt(E[2])<0&&(d*=-1),u=Math.abs(parseInt(E[10])),E[12]&&(u+=E[12]/60,E[11]||(E[11]=" ")),E[14]&&(u+=E[14]/3600,E[13]||(E[13]=" ")),parseInt(E[10])<0&&(u*=-1),E[1]?(f=E[1],l=E[9]):E[8]&&(f=E[8],l=E[16])}if(Math.abs(u)>=180)throw new Error("invalid longitude value");if(S){var b,c,N=/S|SOUTH/i;N.test(f)&&d>0&&(d*=-1),(N=/W|WEST/i).test(l)&&u>0&&(u*=-1);var T=e.match(/[,/\u0020]/g);if(null==T){var m=Math.floor(e.length/2);b=e.substring(0,m).trim(),c=e.substring(m).trim()}else{var h=0;if(0==(m=T.length%2==1?Math.floor(T.length/2):T.length/2-1))h=e.indexOf(T[0]),b=e.substring(0,h).trim(),c=e.substring(h+1).trim();else{for(var p=0,x=0;p<=m;)x=(h=e.indexOf(T[p],x))+1,p++;b=e.substring(0,h).trim(),c=e.substring(h+1).trim()}}return isNaN(d)&&d.includes(",")&&(d=d.replace(",",".")),d=Number(Number(d).toFixed(o)),isNaN(u)&&u.includes(",")&&(u=u.replace(",",".")),{verbatimCoordinates:e,verbatimLatitude:b,verbatimLongitude:c,decimalLatitude:d,decimalLongitude:u=Number(Number(u).toFixed(o)),decimalCoordinates:`${d},${u}`,closeEnough:r}}throw new Error("coordinates pattern match failed")}});
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.replace(",","."),l.includes(",")&&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/converter.js CHANGED
@@ -1,5 +1,8 @@
1
1
  //function for converting coordinates from a string to decimal and verbatim
2
- //TODO, add number of decimal places to return
2
+
3
+ const toCoordinateFormat = require('./toCoordinateFormat.js')
4
+
5
+
3
6
  function converter(coordsString, decimalPlaces) {
4
7
 
5
8
  if(!decimalPlaces) {
@@ -189,17 +192,18 @@ function converter(coordsString, decimalPlaces) {
189
192
  //we need to get the verbatim coords from the string
190
193
  //we can't split down the middle because if there are decimals they may have different numbers on each side
191
194
  //so we need to find the separating character, or if none, use the match values to split down the middle
195
+ var verbatimCoordinates = match[0].trim()
192
196
  var verbatimLat
193
197
  var verbatimLng
194
198
 
195
- var sepChars = /[,/\u0020]/g //comma, forward slash and spacebar
196
- var seps = coordsString.match(sepChars)
199
+ var sepChars = /[,/;\u0020]/g //comma, forward slash and spacebar
200
+ var seps = verbatimCoordinates.match(sepChars)
197
201
 
198
202
  if (seps == null) {
199
203
  //split down the middle
200
204
  var middle = Math.floor(coordsString.length/2)
201
- verbatimLat = coordsString.substring(0, middle).trim()
202
- verbatimLng = coordsString.substring(middle).trim()
205
+ verbatimLat = verbatimCoordinates.substring(0, middle).trim()
206
+ verbatimLng = verbatimCoordinates.substring(middle).trim()
203
207
  }
204
208
  else { //if length is odd then find the index of the middle value
205
209
 
@@ -219,21 +223,21 @@ function converter(coordsString, decimalPlaces) {
219
223
 
220
224
  //it might be only one value
221
225
  if (middle == 0){
222
- splitIndex = coordsString.indexOf(seps[0])
223
- verbatimLat = coordsString.substring(0, splitIndex).trim()
224
- verbatimLng = coordsString.substring(splitIndex + 1).trim()
226
+ splitIndex = verbatimCoordinates.indexOf(seps[0])
227
+ verbatimLat = verbatimCoordinates.substring(0, splitIndex).trim()
228
+ verbatimLng = verbatimCoordinates.substring(splitIndex + 1).trim()
225
229
  }
226
230
  else {
227
231
  var currSepIndex = 0
228
232
  var startSearchIndex = 0
229
233
  while (currSepIndex <= middle){
230
- splitIndex = coordsString.indexOf(seps[currSepIndex], startSearchIndex)
234
+ splitIndex = verbatimCoordinates.indexOf(seps[currSepIndex], startSearchIndex)
231
235
  startSearchIndex = splitIndex + 1
232
236
  currSepIndex++
233
237
  }
234
238
 
235
- verbatimLat = coordsString.substring(0, splitIndex).trim()
236
- verbatimLng = coordsString.substring(splitIndex + 1).trim()
239
+ verbatimLat = verbatimCoordinates.substring(0, splitIndex).trim()
240
+ verbatimLng = verbatimCoordinates.substring(splitIndex + 1).trim()
237
241
 
238
242
  }
239
243
 
@@ -253,15 +257,16 @@ function converter(coordsString, decimalPlaces) {
253
257
 
254
258
  ddLng = Number(Number(ddLng).toFixed(decimalPlaces))
255
259
 
256
- return {
257
- verbatimCoordinates: coordsString,
260
+ return Object.freeze({
261
+ verbatimCoordinates,
258
262
  verbatimLatitude: verbatimLat,
259
263
  verbatimLongitude: verbatimLng,
260
264
  decimalLatitude: ddLat,
261
265
  decimalLongitude: ddLng,
262
266
  decimalCoordinates: `${ddLat},${ddLng}`,
263
- closeEnough: coordsCloseEnough
264
- }
267
+ closeEnough: coordsCloseEnough,
268
+ toCoordinateFormat
269
+ })
265
270
  }
266
271
  else {
267
272
  throw new Error("coordinates pattern match failed")
@@ -339,12 +344,19 @@ function coordsCloseEnough(coordsToTest) {
339
344
  }
340
345
 
341
346
  //Coordinates pattern matching regex
342
- var dd_re = /(NORTH|SOUTH|[NS])?[\s]*([+-]?[0-8]?[0-9](?:[\.,]\d{3,}))([•º°]?)[\s]*(NORTH|SOUTH|[NS])?[\s]*[,/]?[\s]*(EAST|WEST|[EW])?[\s]*([+-]?[0-1]?[0-9]?[0-9](?:[\.,]\d{3,}))([•º°]?)[\s]*(EAST|WEST|[EW])?/i;
347
+ var dd_re = /(NORTH|SOUTH|[NS])?[\s]*([+-]?[0-8]?[0-9](?:[\.,]\d{3,}))([•º°]?)[\s]*(NORTH|SOUTH|[NS])?[\s]*[,/;]?[\s]*(EAST|WEST|[EW])?[\s]*([+-]?[0-1]?[0-9]?[0-9](?:[\.,]\d{3,}))([•º°]?)[\s]*(EAST|WEST|[EW])?/i;
343
348
  //degrees minutes seconds with '.' as separator - gives array with 15 values
344
- var dms_periods = /(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;
349
+ var dms_periods = /(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;
345
350
  //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
346
- var dms_abbr = /(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;
351
+ var dms_abbr = /(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;
347
352
  //everything else - gives array of 17 values
348
- 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;
353
+ 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;
354
+
355
+ const to = Object.freeze({
356
+ DMS: 'DMS',
357
+ DM: 'DM'
358
+ })
359
+
360
+ converter.to = to
349
361
 
350
362
  module.exports = converter
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "geo-coordinates-parser",
3
- "version": "1.3.0",
3
+ "version": "1.4.1",
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/test.js CHANGED
@@ -25,9 +25,9 @@ testFormats.some(t => { //.some so we can break
25
25
  //check the verbatim coords are correct
26
26
  if(converted.verbatimLatitude != t.verbatimLatitude || converted.verbatimLongitude != t.verbatimLongitude) {
27
27
  console.log("Error in verbatim extraction")
28
- console.log(t.verbatimCoordinates)
29
- console.log(t.verbatimLatitude)
30
- console.log(t.verbatimLongitude)
28
+ console.log('For', t.verbatimCoordinates)
29
+ console.log('got', converted.verbatimLatitude, 'should be ', t.verbatimLatitude)
30
+ console.log('got', converted.verbatimLongitude, 'should be', t.verbatimLongitude)
31
31
  allPassed = false;
32
32
  return true
33
33
  }
@@ -0,0 +1,8 @@
1
+ const toCoordinateFormat = require('./toCoordinateFormat.js')
2
+
3
+ let test = {
4
+ decimalCoordinates: '-234.3456, 28.92435',
5
+ toCoordinateFormat
6
+ }
7
+
8
+ console.log(test.toCoordinateFormat('DMS'))
package/testIndividual.js CHANGED
@@ -1,8 +1,14 @@
1
1
  const convert = require('./converter')
2
- const test = '± 1 km on Schweizer rd (R504) from Schweizer Reinecke to Ipelegeng.'
2
+ const test = '42:12:4S 27:17:18E'
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
+ converted.decimalLatitude = 24
11
+ console.log(converted)
6
12
  }
7
13
  catch(err){
8
14
  console.log(err.message)
package/testformats.js CHANGED
@@ -131,6 +131,11 @@ var coordsParserFormats = [
131
131
  verbatimCoordinates: '40° 7.38, -74° 7.38',
132
132
  verbatimLatitude: '40° 7.38',
133
133
  verbatimLongitude: '-74° 7.38'
134
+ },
135
+ {
136
+ verbatimCoordinates: '40 7 22.8; -74 7 22.8', //semicolon separator
137
+ verbatimLatitude: '40 7 22.8',
138
+ verbatimLongitude: '-74 7 22.8'
134
139
  }
135
140
  ]
136
141
 
@@ -213,6 +218,13 @@ var coordsRegexFormats = [
213
218
  verbatimLongitude: '-79.948862',
214
219
  decimalLatitude: 40.446195,
215
220
  decimalLongitude: -79.948862
221
+ },
222
+ {
223
+ verbatimCoordinates: '40.123256; -74.123256', //testing semicolon
224
+ verbatimLatitude: '40.123256',
225
+ verbatimLongitude: '-74.123256',
226
+ decimalLatitude: 40.123256,
227
+ decimalLongitude: -74.123256
216
228
  }
217
229
  ]
218
230
 
@@ -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