From 3a4e1cae6afc75b34b9bf6ab551a6221fc8cc142 Mon Sep 17 00:00:00 2001 From: Evan Siroky Date: Tue, 20 Dec 2016 14:44:07 -0800 Subject: [PATCH 1/7] test(normalization): add test for coordinates with 0, 0 --- package.json | 3 +- test.js | 92 ++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 74 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index 87985f1..ac7a8b6 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "Lon/lat normalization", "main": "index.js", "scripts": { - "test": "mastarm lint && node test.js", + "test": "mastarm lint && mocha test.js", "semantic-release": "semantic-release pre && npm publish && semantic-release post" }, "repository": { @@ -25,6 +25,7 @@ "homepage": "https://github.com/conveyal/lonlat", "devDependencies": { "mastarm": "^1.3.0", + "mocha": "^3.2.0", "semantic-release": "^4.3.5" } } diff --git a/test.js b/test.js index 69d6e3e..37d5a59 100644 --- a/test.js +++ b/test.js @@ -1,3 +1,5 @@ +/* globals describe, it */ + const assert = require('assert') const ll = require('./') @@ -9,23 +11,73 @@ const coordinates = [lon, lat] const str = `${lon},${lat}` const latlng = {lat, lng: lon} -const pairs = [ - // normalization - [lonlat, ll(lonlat)], - [lonlat, ll(point)], - [lonlat, ll(coordinates)], - [lonlat, ll(str)], - - // convert to type, normalizes to `latlng` first in each function - [ll.toCoordinates(lonlat), coordinates], - [ll.toPoint(lonlat), point], - [ll.toString(lonlat), str], - - // if the type is known, use the specific convert function directly - [lonlat, ll.fromLatlng(latlng)], - [lonlat, ll.fromCoordinates(coordinates)], - [lonlat, ll.fromPoint(point)], - [lonlat, ll.fromString(str)] -] - -pairs.forEach((pair) => assert.deepEqual(pair[0], pair[1])) +describe('lonlat', () => { + describe('normalization', () => { + const testCases = [{ + calculated: ll(lonlat), + description: 'Object with lon and lat keys' + }, { + calculated: ll(point), + description: 'Object with x and y keys' + }, { + calculated: ll(coordinates), + description: 'Array of lon and lat' + }, { + calculated: ll(str), + description: 'String with comma separating lon and lat' + }] + + testCases.forEach((test) => { + it(`should normalize from ${test.description}`, () => { + assert.deepEqual(test.calculated, lonlat) + }) + }) + }) + + describe('translations', () => { + const testCases = [{ + expected: coordinates, + method: 'toCoordinates' + }, { + expected: point, + method: 'toPoint' + }, { + expected: str, + method: 'toString' + }] + + testCases.forEach((test) => { + it(`should translate using ${test.method}`, () => { + assert.deepEqual(ll[test.method](lonlat), test.expected) + }) + }) + }) + + describe('known type parsing', () => { + const testCases = [{ + calculated: ll.fromLatlng(latlng), + description: 'Object with lon and lat keys' + }, { + calculated: ll.fromCoordinates(coordinates), + description: 'Array of lon and lat' + }, { + calculated: ll.fromPoint(point), + description: 'Object with x and y keys' + }, { + calculated: ll.fromString(str), + description: 'String with comma separating lon and lat' + }] + + testCases.forEach((test) => { + it(`should normalize from ${test.description}`, () => { + assert.deepEqual(test.calculated, lonlat) + }) + }) + }) + + describe('issues', () => { + it('#3 - Does not parse coordinates with 0 for lat or lon', () => { + assert.deepEqual(ll({ lat: 0, lng: 0 }), { lat: 0, lon: 0 }) + }) + }) +}) From 691c3a694909766012edbf277bf8e73386f5a78c Mon Sep 17 00:00:00 2001 From: Evan Siroky Date: Tue, 20 Dec 2016 15:37:58 -0800 Subject: [PATCH 2/7] chore(testing): replace mocha w/ Jest and add coverage --- .gitignore | 1 + .travis.yml | 6 ++++++ test.js => index.test.js | 4 ++-- package.json | 9 +++++---- 4 files changed, 14 insertions(+), 6 deletions(-) rename test.js => index.test.js (94%) diff --git a/.gitignore b/.gitignore index e920c16..40b0523 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ lib-cov # Coverage directory used by tools like istanbul coverage +tmp # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) .grunt diff --git a/.travis.yml b/.travis.yml index 40c649c..3940d3b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,12 @@ notifications: email: false node_js: - '6' +before_install: + - npm i -g codecov +script: + - npm run lint + - npm run cover + - codecov after_success: - npm run semantic-release branches: diff --git a/test.js b/index.test.js similarity index 94% rename from test.js rename to index.test.js index 37d5a59..393ee1b 100644 --- a/test.js +++ b/index.test.js @@ -56,7 +56,7 @@ describe('lonlat', () => { describe('known type parsing', () => { const testCases = [{ calculated: ll.fromLatlng(latlng), - description: 'Object with lon and lat keys' + description: 'Object with lng and lat keys' }, { calculated: ll.fromCoordinates(coordinates), description: 'Array of lon and lat' @@ -69,7 +69,7 @@ describe('lonlat', () => { }] testCases.forEach((test) => { - it(`should normalize from ${test.description}`, () => { + it(`should specifically parse from ${test.description}`, () => { assert.deepEqual(test.calculated, lonlat) }) }) diff --git a/package.json b/package.json index ac7a8b6..e11617a 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,10 @@ "description": "Lon/lat normalization", "main": "index.js", "scripts": { - "test": "mastarm lint && mocha test.js", - "semantic-release": "semantic-release pre && npm publish && semantic-release post" + "cover": "npm test --coverage", + "lint": "mastarm lint", + "semantic-release": "semantic-release pre && npm publish && semantic-release post", + "test": "mastarm test" }, "repository": { "type": "git", @@ -24,8 +26,7 @@ }, "homepage": "https://github.com/conveyal/lonlat", "devDependencies": { - "mastarm": "^1.3.0", - "mocha": "^3.2.0", + "mastarm": "^3.2.1", "semantic-release": "^4.3.5" } } From 9c44c00f702f40fcce3390cefea25ee40be7a6a2 Mon Sep 17 00:00:00 2001 From: Evan Siroky Date: Tue, 20 Dec 2016 15:39:27 -0800 Subject: [PATCH 3/7] fix(floatize): allow for correct parsing of coordinates at 0, 0 --- index.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index e6c63e7..0967b59 100644 --- a/index.js +++ b/index.js @@ -56,8 +56,20 @@ function fromString (str) { } function floatize (lonlat) { - const lon = parseFloat(lonlat.lon || lonlat.lng || lonlat.longitude) - return {lon: lon, lat: parseFloat(lonlat.lat || lonlat.latitude)} + const lon = parseFloatWithAlternates([lonlat.lon, lonlat.lng, lonlat.longitude]) + const lat = parseFloatWithAlternates([lonlat.lat, lonlat.latitude]) + return {lon: lon, lat: lat} +} + +function parseFloatWithAlternates (alternates) { + if (alternates.length > 0) { + const num = parseFloat(alternates[0]) + if (isNaN(num)) { + return parseFloatWithAlternates(alternates.slice(1)) + } else { + return num + } + } } function normalize (unknown) { From 09cfac09a1a330e52dd74af2ba6ebab6957a6c1e Mon Sep 17 00:00:00 2001 From: Evan Siroky Date: Tue, 20 Dec 2016 16:06:21 -0800 Subject: [PATCH 4/7] feat(coordinates): throw error upon identifying invalid coordinates --- __snapshots__/index.test.js.snap | 3 +++ index.js | 6 ++++++ index.test.js | 24 ++++++++++++++++++------ package.json | 2 +- 4 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 __snapshots__/index.test.js.snap diff --git a/__snapshots__/index.test.js.snap b/__snapshots__/index.test.js.snap new file mode 100644 index 0000000..759a27a --- /dev/null +++ b/__snapshots__/index.test.js.snap @@ -0,0 +1,3 @@ +exports[`lonlat invalid coordinates should throw error when parsing: "-999,999" 1`] = `"Invalid longitude value: -999"`; + +exports[`lonlat invalid coordinates should throw error when parsing: "0,999" 1`] = `"Invalid longitude value: 999"`; diff --git a/index.js b/index.js index 0967b59..8f0749e 100644 --- a/index.js +++ b/index.js @@ -58,6 +58,12 @@ function fromString (str) { function floatize (lonlat) { const lon = parseFloatWithAlternates([lonlat.lon, lonlat.lng, lonlat.longitude]) const lat = parseFloatWithAlternates([lonlat.lat, lonlat.latitude]) + if ((!lon || lon > 180 || lon < -180) && lon !== 0) { + throw new Error(`Invalid longitude value: ${lonlat.lon || lonlat.lng || lonlat.longitude}`) + } + if ((!lat || lat > 90 || lat < -90) && lat !== 0) { + throw new Error(`Invalid longitude value: ${lonlat.lat || lonlat.latitude}`) + } return {lon: lon, lat: lat} } diff --git a/index.test.js b/index.test.js index 393ee1b..60084d7 100644 --- a/index.test.js +++ b/index.test.js @@ -1,6 +1,5 @@ -/* globals describe, it */ +/* globals describe, expect, it */ -const assert = require('assert') const ll = require('./') const lat = 38.13234 @@ -29,7 +28,7 @@ describe('lonlat', () => { testCases.forEach((test) => { it(`should normalize from ${test.description}`, () => { - assert.deepEqual(test.calculated, lonlat) + expect(test.calculated).toEqual(lonlat) }) }) }) @@ -48,7 +47,7 @@ describe('lonlat', () => { testCases.forEach((test) => { it(`should translate using ${test.method}`, () => { - assert.deepEqual(ll[test.method](lonlat), test.expected) + expect(ll[test.method](lonlat)).toEqual(test.expected) }) }) }) @@ -70,14 +69,27 @@ describe('lonlat', () => { testCases.forEach((test) => { it(`should specifically parse from ${test.description}`, () => { - assert.deepEqual(test.calculated, lonlat) + expect(test.calculated).toEqual(lonlat) + }) + }) + }) + + describe('invalid coordinates', () => { + const badCoords = [ + '-999,999', + '0,999' + ] + + badCoords.forEach((data) => { + it(`should throw error when parsing: ${JSON.stringify(data)}`, () => { + expect(() => ll(data)).toThrowErrorMatchingSnapshot() }) }) }) describe('issues', () => { it('#3 - Does not parse coordinates with 0 for lat or lon', () => { - assert.deepEqual(ll({ lat: 0, lng: 0 }), { lat: 0, lon: 0 }) + expect(ll({ lat: 0, lng: 0 })).toEqual({ lat: 0, lon: 0 }) }) }) }) diff --git a/package.json b/package.json index e11617a..23a4f4f 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "Lon/lat normalization", "main": "index.js", "scripts": { - "cover": "npm test --coverage", + "cover": "npm test -- --coverage --coverage-paths index.js", "lint": "mastarm lint", "semantic-release": "semantic-release pre && npm publish && semantic-release post", "test": "mastarm test" From 3d38053df6330b16de9f8ac33150b572ab3abb42 Mon Sep 17 00:00:00 2001 From: Evan Siroky Date: Wed, 21 Dec 2016 15:30:16 -0800 Subject: [PATCH 5/7] test(all): add tests to get to 100% coverage --- __snapshots__/index.test.js.snap | 12 +++++-- index.js | 8 ++--- index.test.js | 55 ++++++++++++++++++++++++++------ 3 files changed, 60 insertions(+), 15 deletions(-) diff --git a/__snapshots__/index.test.js.snap b/__snapshots__/index.test.js.snap index 759a27a..fd2d2d2 100644 --- a/__snapshots__/index.test.js.snap +++ b/__snapshots__/index.test.js.snap @@ -1,3 +1,11 @@ -exports[`lonlat invalid coordinates should throw error when parsing: "-999,999" 1`] = `"Invalid longitude value: -999"`; +exports[`lonlat errors invalid coordinates should throw error when parsing: "-999,999" 1`] = `"Invalid longitude value: -999"`; -exports[`lonlat invalid coordinates should throw error when parsing: "0,999" 1`] = `"Invalid longitude value: 999"`; +exports[`lonlat errors invalid coordinates should throw error when parsing: "0,999" 1`] = `"Invalid longitude value: 999"`; + +exports[`lonlat errors invalid coordinates should throw error when parsing: {"lng":1,"latitude":1234} 1`] = `"Invalid longitude value: 1234"`; + +exports[`lonlat errors invalid coordinates should throw error when parsing: {} 1`] = `"Invalid longitude value: undefined"`; + +exports[`lonlat errors invalid coordinates should throw error when parsing: undefined 1`] = `"Value must not be null or undefined."`; + +exports[`lonlat errors toLeaflet should throw error if leaflet is not loaded 1`] = `"Leaflet not found."`; diff --git a/index.js b/index.js index 8f0749e..66c8d16 100644 --- a/index.js +++ b/index.js @@ -51,13 +51,13 @@ function fromPoint (point) { } function fromString (str) { - const arr = str.split(',') + var arr = str.split(',') return floatize({lon: arr[0], lat: arr[1]}) } function floatize (lonlat) { - const lon = parseFloatWithAlternates([lonlat.lon, lonlat.lng, lonlat.longitude]) - const lat = parseFloatWithAlternates([lonlat.lat, lonlat.latitude]) + var lon = parseFloatWithAlternates([lonlat.lon, lonlat.lng, lonlat.longitude]) + var lat = parseFloatWithAlternates([lonlat.lat, lonlat.latitude]) if ((!lon || lon > 180 || lon < -180) && lon !== 0) { throw new Error(`Invalid longitude value: ${lonlat.lon || lonlat.lng || lonlat.longitude}`) } @@ -69,7 +69,7 @@ function floatize (lonlat) { function parseFloatWithAlternates (alternates) { if (alternates.length > 0) { - const num = parseFloat(alternates[0]) + var num = parseFloat(alternates[0]) if (isNaN(num)) { return parseFloatWithAlternates(alternates.slice(1)) } else { diff --git a/index.test.js b/index.test.js index 60084d7..f233ff6 100644 --- a/index.test.js +++ b/index.test.js @@ -1,4 +1,4 @@ -/* globals describe, expect, it */ +/* globals describe, expect, jest, it */ const ll = require('./') @@ -11,6 +11,34 @@ const str = `${lon},${lat}` const latlng = {lat, lng: lon} describe('lonlat', () => { + describe('print', () => { + it('should print basic input', () => { + expect(ll.print(str)).toEqual('70.01232, 38.13234') + }) + }) + + describe('isEqual', () => { + it('should not be equal for different coordinates', () => { + expect(ll.isEqual('123.456,78.9', '123.4567,78.9')).toEqual(false) + }) + + it('should be equal for different coordinates with allowable epsilon', () => { + expect(ll.isEqual('123.456,78.9', '123.4567,78.9', 0.001)).toEqual(true) + }) + }) + + describe('toLeaflet', () => { + it('should create leaflet latLng', () => { + window.L = { + latLng: jest.fn((lat, lng) => { return { leaflet_lat: lat, leaflet_lng: lng } }) + } + + expect(ll.toLeaflet('0,0')).toEqual({ leaflet_lat: 0, leaflet_lng: 0 }) + + window.L = undefined + }) + }) + describe('normalization', () => { const testCases = [{ calculated: ll(lonlat), @@ -74,15 +102,24 @@ describe('lonlat', () => { }) }) - describe('invalid coordinates', () => { - const badCoords = [ - '-999,999', - '0,999' - ] + describe('errors', () => { + it('toLeaflet should throw error if leaflet is not loaded', () => { + expect(() => ll.toLeaflet('0,0')).toThrowErrorMatchingSnapshot() + }) + + describe('invalid coordinates', () => { + const badCoords = [ + '-999,999', + '0,999', + {}, + undefined, + { lng: 1, latitude: 1234 } + ] - badCoords.forEach((data) => { - it(`should throw error when parsing: ${JSON.stringify(data)}`, () => { - expect(() => ll(data)).toThrowErrorMatchingSnapshot() + badCoords.forEach((data) => { + it(`should throw error when parsing: ${JSON.stringify(data)}`, () => { + expect(() => ll(data)).toThrowErrorMatchingSnapshot() + }) }) }) }) From 05641483a817096d7902032cc21a0ecc716b39ed Mon Sep 17 00:00:00 2001 From: Evan Siroky Date: Thu, 22 Dec 2016 00:29:39 -0800 Subject: [PATCH 6/7] fix(parsing): allow parsing coordinate at 0,0 with x,y object input --- index.js | 2 +- index.test.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 66c8d16..287c5a6 100644 --- a/index.js +++ b/index.js @@ -82,6 +82,6 @@ function normalize (unknown) { if (!unknown) throw new Error('Value must not be null or undefined.') if (Array.isArray(unknown)) return fromCoordinates(unknown) else if (typeof unknown === 'string') return fromString(unknown) - else if (unknown.x && unknown.y) return fromPoint(unknown) + else if ((unknown.x || unknown.x === 0) && (unknown.y || unknown.y === 0)) return fromPoint(unknown) return floatize(unknown) } diff --git a/index.test.js b/index.test.js index f233ff6..52428fc 100644 --- a/index.test.js +++ b/index.test.js @@ -127,6 +127,7 @@ describe('lonlat', () => { describe('issues', () => { it('#3 - Does not parse coordinates with 0 for lat or lon', () => { expect(ll({ lat: 0, lng: 0 })).toEqual({ lat: 0, lon: 0 }) + expect(ll({ x: 0, y: 0 })).toEqual({ lat: 0, lon: 0 }) }) }) }) From 457eb5d31ef6d58d83d1be5e8bf503d2d9d0eb21 Mon Sep 17 00:00:00 2001 From: Evan Siroky Date: Thu, 22 Dec 2016 00:30:22 -0800 Subject: [PATCH 7/7] docs(README): make comprehensive documentation --- README.md | 271 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 237 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index ac868d8..8df20ba 100644 --- a/README.md +++ b/README.md @@ -7,54 +7,257 @@ Lon/lat normalization cause...**sigh**. No one has agreed on a standard way of representing lon/lat. This is a small normalization library. Use this to convert all outside input before processing internally and convert to an external format right when it's being output. -## Just use the `{lon: ${longitude}, lat: ${latitude}}` representation +## API -Utilizing this won't always be possible/easiest, so please at least adopt the following conventions. Any variables or functions that contain the following names should be represented by the accompanying structure: +### lonlat(input) -* `lonlat`: `{lon: ${longitude}, lat: ${latitude}}` -* `coordinates`: `[${longitude}, ${latitude}]` -* `point`: `{x: ${longitude}, y: ${latitude}}` +Tries parse input and transform to an output of normalized coordinates. Will throw an error upon finding invalid coordinates. -If you must convert it to a string, put it in the following format: +#### Arguments -* `'${longitude},${latitude}'` +`input (*)`: Can be any of the following: +- an array in the format: [longitude, latitude] +- a string in the format: '{longitude},{latitude}' +- an object with a `x` attribute representing `longitude` and a `y` attribute representing `latitude` +- an object with a `lon`, `lng` or `longitude` attribute and a `lat` or `latitude` attribute -## API +#### Returns + +`(Object)`: An object with `lon` and `lat` attributes. + +#### Example + +```js +var lonlat = require('@conveyal/lonlat') + +// Object with lon/lat-ish attributes +var position = lonlat({ lon: 12, lat: 34 }) // { lon: 12, lat: 34 } +position = lonlat({ lng: 12, lat: 34 }) // { lon: 12, lat: 34 } +position = lonlat({ longitude: 12, latitude: 34 }) // { lon: 12, lat: 34 } +position = lonlat({ lng: 12, latitude: 34 }) // { lon: 12, lat: 34 } + +// coordinate array +position = lonlat([12, 34]) // { lon: 12, lat: 34 } + +// string +position = lonlat('12,34') // { lon: 12, lat: 34 } + +// object with x and y attributes +position = lonlat({ x: 12, y: 34 }) // { lon: 12, lat: 34 } + +// the following will throw errors +position = lonlat({ lon: 999, lat: 34 }) // Error: Invalid longitude value: 999 +position = lonlat({ lon: 12, lat: 999 }) // Error: Invalid latitude value: 999 +position = lonlat({}) // Error: Invalid latitude value: undefined +position = lonlat(null) // Error: Value must not be null or undefined +``` + +### lonlat.fromCoordinates(arr) or lonlat.fromGeoJSON(arr) + +Tries to parse from an array of coordinates. Will throw an error upon finding invalid coordinates. + +#### Arguments + +`arr (Array)`: An array in the format: [longitude, latitude] + +#### Returns + +`(Object)`: An object with `lon` and `lat` attributes. + +#### Example + +```js +var lonlat = require('@conveyal/lonlat') + +var position = lonlat.fromCoordinates([12, 34]) // { lon: 12, lat: 34 } +position = lonlat.fromGeoJSON([12, 34]) // { lon: 12, lat: 34 } +``` + +### lonlat.fromLatlng(obj) or lonlat.fromLeaflet(obj) + +Tries to parse from an object. Will throw an error upon finding invalid coordinates. + +#### Arguments + +`obj (Object)`: An object with a `lon`, `lng` or `longitude` attribute and a `lat` or `latitude` attribute + +#### Returns + +`(Object)`: An object with `lon` and `lat` attributes. + +#### Example ```js -const assert = require('assert') -const ll = require('@conveyal/lonlat') +var lonlat = require('@conveyal/lonlat') + +var position = lonlat.fromLatlng({ longitude: 12, latitude: 34 }) // { lon: 12, lat: 34 } +position = lonlat.fromLeaflet({ lng: 12, lat: 34 }) // { lon: 12, lat: 34 } +``` + +### lonlat.fromPoint(obj) -const lat = 38.13234 -const lon = 70.01232 -const lonlat = {lon, lat} -const point = {x: lon, y: lat} -const coordinates = [lon, lat] -const str = `${lon},${lat}` -const latlng = {lat, lng: lon} +Tries to parse from an object. Will throw an error upon finding invalid coordinates. -const pairs = [ - // normalization - [lonlat, ll(lonlat)], - [lonlat, ll(point)], - [lonlat, ll(coordinates)], - [lonlat, ll(str)], +#### Arguments - // convert to type, normalizes to `latlng` first in each function - [ll.toCoordinates(lonlat), coordinates], - [ll.toPoint(lonlat), point], - [ll.toString(lonlat), str], +`obj (Object)`: An object with a `x` attribute representing `longitude` and a `y` attribute representing `latitude` - // if the type is known, use the specific convert function directly - [lonlat, ll.fromLatlng(latlng)], - [lonlat, ll.fromCoordinates(coordinates)], - [lonlat, ll.fromPoint(point)], - [lonlat, ll.fromString(str)] -] +#### Returns + +`(Object)`: An object with `lon` and `lat` attributes. + +#### Example + +```js +var lonlat = require('@conveyal/lonlat') -pairs.forEach((pair) => assert.deepEqual(pair[0], pair[1])) +var position = lonlat.fromPoint({ x: 12, y: 34 }) // { lon: 12, lat: 34 } ``` +### lonlat.fromString(str) + +Tries to parse from a string. Will throw an error upon finding invalid coordinates. + +#### Arguments + +`str (string)`: A string in the format: '{longitude},{latitude}' + +#### Returns + +`(Object)`: An object with `lon` and `lat` attributes. + +#### Example + +```js +var lonlat = require('@conveyal/lonlat') + +var position = lonlat.fromString('12,34') // { lon: 12, lat: 34 } +``` + +### lonlat.print(input, [fixed=5]) + +Returns a pretty string + +#### Arguments + +- `input (*)`: Any format mentioned in [lonlat(input)](#lonlatinput) +- `[fixed=5] (Number)`: The number of digits to round to + +#### Returns + +`(string)`: A string with the latitude and longitude rounded to the number of decimal places as specified by `fixed` + +#### Example + +```js +var lonlat = require('@conveyal/lonlat') + +var pretty = lonlat.print('12.345678,34') // '12.34568, 34.00000' +``` + +### lonlat.isEqual(lonlat1, lonlat2, [epsilon=0]) + +Checks equality of two inputs within an allowable difference. + +#### Arguments + +- `lonlat1 (*)`: Any format mentioned in [lonlat(input)](#lonlatinput) +- `lonlat2 (*)`: Any format mentioned in [lonlat(input)](#lonlatinput) +- `[epsilon=0] (Number)`: The maximum allowable difference of between each latitude and longitude + +#### Returns + +`(boolean)`: Returns `true` if the inputs are equal or `false` if they are not + +#### Example + +```js +var lonlat = require('@conveyal/lonlat') + +var isEqual = lonlat.isEqual('12,34', [12, 34]) // true +``` + +### lonlat.toCoordinates(input) + +Translates to a coordinate array. + +#### Arguments + +`input (*)`: Any format mentioned in [lonlat(input)](#lonlatinput) + +#### Returns + +`(Array)`: An array in the format: [longitude, latitude] + +#### Example + +```js +var lonlat = require('@conveyal/lonlat') + +var coords = lonlat.toCoordinates('12,34') // [12, 34] +``` + +### lonlat.toPoint(input) + +Translates to point Object. + +#### Arguments + +`input (*)`: Any format mentioned in [lonlat(input)](#lonlatinput) + +#### Returns + +`(Object)`: An object with `x` and `y` attributes representing latitude and longitude respectively + +#### Example + +```js +var lonlat = require('@conveyal/lonlat') + +var point = lonlat.toPoint('12,34') // { x: 12, y: 34 } +``` + +### lonlat.toString(input) + +Translates to coordinate string. + +#### Arguments + +`input (*)`: Any format mentioned in [lonlat(input)](#lonlatinput) + +#### Returns + +`(string)`: A string in the format 'latitude,longitude' + +#### Example + +```js +var lonlat = require('@conveyal/lonlat') + +var str = lonlat.toString({ lat: 12, long: 34 }) // '12,34' +``` + +### lonlat.toLeaflet(input) + +Translates to [Leaflet LatLng](http://leafletjs.com/reference.html#latlng) object. This function requires Leaflet to be installed as a global variable `L` in the window environment. + +#### Arguments + +`input (*)`: Any format mentioned in [lonlat(input)](#lonlatinput) + +#### Returns + +`(Object)`: A [Leaflet LatLng](http://leafletjs.com/reference.html#latlng) object + +#### Example + +```js +var lonlat = require('@conveyal/lonlat') + +var position = lonlat.toLeaflet({ lat: 12, long: 34 }) // Leaflet LatLng object +``` + + [npm-image]: https://img.shields.io/npm/v/@conveyal/lonlat.svg?maxAge=2592000&style=flat-square [npm-url]: https://www.npmjs.com/package/@conveyal/lonlat [travis-image]: https://img.shields.io/travis/conveyal/lonlat.svg?style=flat-square