Comparing version 0.1.5 to 1.0.0
@@ -0,1 +1,15 @@ | ||
## 1.0.0 (2020-06-21) | ||
##### New Features | ||
* **validateHash:** add geohash validation ([0bb5cd47](https://github.com/MichaelSolati/geokit/commit/0bb5cd47d8c39cdc48846e4fb5fe64631c5f7e73)) | ||
##### Bug Fixes | ||
* fix docs build and deploy ([97b77f14](https://github.com/MichaelSolati/geokit/commit/97b77f146de164c3e898ea0dc82b0305c2b781db)) | ||
##### Refactors | ||
* break out class into functions ([3f662fe0](https://github.com/MichaelSolati/geokit/commit/3f662fe0efc03ce292a1ab40121e1e50bfba49a1)) | ||
#### 0.1.5 (2020-06-11) | ||
@@ -2,0 +16,0 @@ |
@@ -1,1 +0,1 @@ | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t=t||self).window=t.window||{})}(this,(function(t){"use strict";function e(t,e){return(e[0]+e[1])/2>t?0:1}function n(t){return t*Math.PI/180}function o(t){const e=[];if(t.lat>90&&e.push("Your latitude is greater than 90°"),t.lat<-90&&e.push("Your latitude is less than -90°"),t.lng>180&&e.push("Your longitude is greater than 180°"),t.lng<-180&&e.push("Your longitude is less than -180°"),0!==e.length)return new Error(e.join(" "))}t.Geokit=class{static distance(t,e,r="km"){const s=o(t);if(s instanceof Error)throw new Error("Start coordinates: "+s.message);const a=o(e);if(a instanceof Error)throw new Error("End coordinates: "+a.message);const i="miles"===r.toLowerCase()?3963:6371,l=n(e.lat-t.lat),c=n(e.lng-t.lng),h=n(t.lat),u=n(e.lat),f=Math.sin(l/2)*Math.sin(l/2)+Math.sin(c/2)*Math.sin(c/2)*Math.cos(h)*Math.cos(u);return i*(2*Math.atan2(Math.sqrt(f),Math.sqrt(1-f)))}static hash(t,n=10){const r=o(t);if(r instanceof Error)throw r;let s="";const a=[-90,90],i=[-180,180];for(;s.length<n;){let n=0;for(let o=0;o<5;o++){const r=(5*s.length+o)%2==0,l=r?t.lng:t.lat,c=r?i:a,h=(c[0]+c[1])/2;n=(n<<1)+e(l,c),l>h?c[0]=h:c[1]=h}s+="0123456789bcdefghjkmnpqrstuvwxyz".charAt(n)}return s}static decodeHash(t){let e=!0;const n=[-90,90],o=[-180,180],r=t.split("");for(;r.length;){const t=(s=r.shift(),"0123456789bcdefghjkmnpqrstuvwxyz".indexOf(s.toLowerCase()));for(let r=0;r<5;r++){const s=[16,8,4,2,1][r],a=e?o:n,i=(a[0]+a[1])/2;a[t&s?0:1]=i,e=!e}}var s;return{lat:(n[0]+n[1])/2,lng:(o[0]+o[1])/2}}},Object.defineProperty(t,"__esModule",{value:!0})})); | ||
!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((t=t||self).Geokit={})}(this,(function(t){"use strict";const n="0123456789bcdefghjkmnpqrstuvwxyz";function e(t,n){return(n[0]+n[1])/2>t?0:1}function o(t){return t*Math.PI/180}function r(t){const n=[];if(t.lat>90&&n.push("Your latitude is greater than 90°"),t.lat<-90&&n.push("Your latitude is less than -90°"),t.lng>180&&n.push("Your longitude is greater than 180°"),t.lng<-180&&n.push("Your longitude is less than -180°"),0!==n.length)return new Error(n.join(" "))}function s(t,e=!1){let o;if("string"!=typeof t)o="geohash must be a string";else if(0===t.length)o="geohash cannot be the empty string";else for(const e of t)-1===n.indexOf(e)&&(o="geohash cannot contain '"+e+"'");if(void 0===o||e)return!o;throw new Error("Invalid geohash '"+t+"': "+o)}t.decodeHash=function(t){s(t);let n=!0;const e=[-90,90],o=[-180,180],r=t.split("");for(;r.length;){const t=(a=r.shift(),"0123456789bcdefghjkmnpqrstuvwxyz".indexOf(a.toLowerCase()));for(let r=0;r<5;r++){const s=[16,8,4,2,1][r],a=n?o:e,i=(a[0]+a[1])/2;a[t&s?0:1]=i,n=!n}}var a;return{lat:(e[0]+e[1])/2,lng:(o[0]+o[1])/2}},t.distance=function(t,n,e="km"){const s=r(t);if(s instanceof Error)throw new Error("Start coordinates: "+s.message);const a=r(n);if(a instanceof Error)throw new Error("End coordinates: "+a.message);const i="miles"===e.toLowerCase()?3963:6371,h=o(n.lat-t.lat),f=o(n.lng-t.lng),l=o(t.lat),c=o(n.lat),u=Math.sin(h/2)*Math.sin(h/2)+Math.sin(f/2)*Math.sin(f/2)*Math.cos(l)*Math.cos(c);return i*(2*Math.atan2(Math.sqrt(u),Math.sqrt(1-u)))},t.hash=function(t,o=10){const s=r(t);if(s instanceof Error)throw s;let a="";const i=[-90,90],h=[-180,180];for(;a.length<o;){let o=0;for(let n=0;n<5;n++){const r=(5*a.length+n)%2==0,s=r?t.lng:t.lat,f=r?h:i,l=(f[0]+f[1])/2;o=(o<<1)+e(s,f),s>l?f[0]=l:f[1]=l}a+=n.charAt(o)}return a},t.validateHash=s,Object.defineProperty(t,"__esModule",{value:!0})})); |
@@ -5,4 +5,5 @@ 'use strict'; | ||
const BASE32 = '0123456789bcdefghjkmnpqrstuvwxyz'; | ||
function base32(value) { | ||
return '0123456789bcdefghjkmnpqrstuvwxyz'.charAt(value); | ||
return BASE32.charAt(value); | ||
} | ||
@@ -38,63 +39,90 @@ function decimalChunk(value) { | ||
class Geokit { | ||
static distance(start, end, unit = 'km') { | ||
const startValid = validateCoordinates(start); | ||
if (startValid instanceof Error) { | ||
throw new Error('Start coordinates: ' + startValid.message); | ||
} | ||
const endValid = validateCoordinates(end); | ||
if (endValid instanceof Error) { | ||
throw new Error('End coordinates: ' + endValid.message); | ||
} | ||
const radius = unit.toLowerCase() === 'miles' ? 3963 : 6371; | ||
const dLat = toRad(end.lat - start.lat); | ||
const dLon = toRad(end.lng - start.lng); | ||
const lat1 = toRad(start.lat); | ||
const lat2 = toRad(end.lat); | ||
const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + | ||
Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2); | ||
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); | ||
return radius * c; | ||
function validateHash(geohash, flag = false) { | ||
let error; | ||
if (typeof geohash !== 'string') { | ||
error = 'geohash must be a string'; | ||
} | ||
static hash(coordinates, precision = 10) { | ||
const valid = validateCoordinates(coordinates); | ||
if (valid instanceof Error) { | ||
throw valid; | ||
} | ||
let hash = ''; | ||
const latRng = [-90, 90]; | ||
const lngRng = [-180, 180]; | ||
while (hash.length < precision) { | ||
let temp = 0; | ||
for (let i = 0; i < 5; i++) { | ||
const even = (hash.length * 5 + i) % 2 === 0; | ||
const coord = even ? coordinates.lng : coordinates.lat; | ||
const range = even ? lngRng : latRng; | ||
const middle = (range[0] + range[1]) / 2; | ||
temp = (temp << 1) + getBit(coord, range); | ||
coord > middle ? (range[0] = middle) : (range[1] = middle); | ||
else if (geohash.length === 0) { | ||
error = 'geohash cannot be the empty string'; | ||
} | ||
else { | ||
for (const letter of geohash) { | ||
if (BASE32.indexOf(letter) === -1) { | ||
error = "geohash cannot contain '" + letter + "'"; | ||
} | ||
hash += base32(temp); | ||
} | ||
return hash; | ||
} | ||
static decodeHash(hash) { | ||
let even = true; | ||
const latRng = [-90, 90]; | ||
const lngRng = [-180, 180]; | ||
const hashChars = hash.split(''); | ||
while (hashChars.length) { | ||
const chunk = decimalChunk(hashChars.shift()); | ||
for (let i = 0; i < 5; i++) { | ||
const mask = [16, 8, 4, 2, 1][i]; | ||
const range = even ? lngRng : latRng; | ||
const middle = (range[0] + range[1]) / 2; | ||
range[chunk & mask ? 0 : 1] = middle; | ||
even = !even; | ||
} | ||
if (typeof error !== 'undefined' && !flag) { | ||
throw new Error("Invalid geohash '" + geohash + "': " + error); | ||
} | ||
else { | ||
return !error; | ||
} | ||
} | ||
function decodeHash(hash) { | ||
validateHash(hash); | ||
let even = true; | ||
const latRng = [-90, 90]; | ||
const lngRng = [-180, 180]; | ||
const hashChars = hash.split(''); | ||
while (hashChars.length) { | ||
const chunk = decimalChunk(hashChars.shift()); | ||
for (let i = 0; i < 5; i++) { | ||
const mask = [16, 8, 4, 2, 1][i]; | ||
const range = even ? lngRng : latRng; | ||
const middle = (range[0] + range[1]) / 2; | ||
range[chunk & mask ? 0 : 1] = middle; | ||
even = !even; | ||
} | ||
return { lat: (latRng[0] + latRng[1]) / 2, lng: (lngRng[0] + lngRng[1]) / 2 }; | ||
} | ||
return { lat: (latRng[0] + latRng[1]) / 2, lng: (lngRng[0] + lngRng[1]) / 2 }; | ||
} | ||
exports.Geokit = Geokit; | ||
function distance(start, end, unit = 'km') { | ||
const startValid = validateCoordinates(start); | ||
if (startValid instanceof Error) { | ||
throw new Error('Start coordinates: ' + startValid.message); | ||
} | ||
const endValid = validateCoordinates(end); | ||
if (endValid instanceof Error) { | ||
throw new Error('End coordinates: ' + endValid.message); | ||
} | ||
const radius = unit.toLowerCase() === 'miles' ? 3963 : 6371; | ||
const dLat = toRad(end.lat - start.lat); | ||
const dLon = toRad(end.lng - start.lng); | ||
const lat1 = toRad(start.lat); | ||
const lat2 = toRad(end.lat); | ||
const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + | ||
Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2); | ||
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); | ||
return radius * c; | ||
} | ||
function hash(coordinates, precision = 10) { | ||
const valid = validateCoordinates(coordinates); | ||
if (valid instanceof Error) { | ||
throw valid; | ||
} | ||
let hash = ''; | ||
const latRng = [-90, 90]; | ||
const lngRng = [-180, 180]; | ||
while (hash.length < precision) { | ||
let temp = 0; | ||
for (let i = 0; i < 5; i++) { | ||
const even = (hash.length * 5 + i) % 2 === 0; | ||
const coord = even ? coordinates.lng : coordinates.lat; | ||
const range = even ? lngRng : latRng; | ||
const middle = (range[0] + range[1]) / 2; | ||
temp = (temp << 1) + getBit(coord, range); | ||
coord > middle ? (range[0] = middle) : (range[1] = middle); | ||
} | ||
hash += base32(temp); | ||
} | ||
return hash; | ||
} | ||
exports.decodeHash = decodeHash; | ||
exports.distance = distance; | ||
exports.hash = hash; | ||
exports.validateHash = validateHash; |
@@ -1,2 +0,5 @@ | ||
export { Geokit } from './geokit'; | ||
export * from './definitions'; | ||
export * from './functions/decode-hash'; | ||
export * from './functions/distance'; | ||
export * from './functions/hash'; | ||
export * from './functions/validate-hash'; |
@@ -0,3 +1,4 @@ | ||
const BASE32 = '0123456789bcdefghjkmnpqrstuvwxyz'; | ||
function base32(value) { | ||
return '0123456789bcdefghjkmnpqrstuvwxyz'.charAt(value); | ||
return BASE32.charAt(value); | ||
} | ||
@@ -33,63 +34,87 @@ function decimalChunk(value) { | ||
class Geokit { | ||
static distance(start, end, unit = 'km') { | ||
const startValid = validateCoordinates(start); | ||
if (startValid instanceof Error) { | ||
throw new Error('Start coordinates: ' + startValid.message); | ||
} | ||
const endValid = validateCoordinates(end); | ||
if (endValid instanceof Error) { | ||
throw new Error('End coordinates: ' + endValid.message); | ||
} | ||
const radius = unit.toLowerCase() === 'miles' ? 3963 : 6371; | ||
const dLat = toRad(end.lat - start.lat); | ||
const dLon = toRad(end.lng - start.lng); | ||
const lat1 = toRad(start.lat); | ||
const lat2 = toRad(end.lat); | ||
const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + | ||
Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2); | ||
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); | ||
return radius * c; | ||
function validateHash(geohash, flag = false) { | ||
let error; | ||
if (typeof geohash !== 'string') { | ||
error = 'geohash must be a string'; | ||
} | ||
static hash(coordinates, precision = 10) { | ||
const valid = validateCoordinates(coordinates); | ||
if (valid instanceof Error) { | ||
throw valid; | ||
} | ||
let hash = ''; | ||
const latRng = [-90, 90]; | ||
const lngRng = [-180, 180]; | ||
while (hash.length < precision) { | ||
let temp = 0; | ||
for (let i = 0; i < 5; i++) { | ||
const even = (hash.length * 5 + i) % 2 === 0; | ||
const coord = even ? coordinates.lng : coordinates.lat; | ||
const range = even ? lngRng : latRng; | ||
const middle = (range[0] + range[1]) / 2; | ||
temp = (temp << 1) + getBit(coord, range); | ||
coord > middle ? (range[0] = middle) : (range[1] = middle); | ||
else if (geohash.length === 0) { | ||
error = 'geohash cannot be the empty string'; | ||
} | ||
else { | ||
for (const letter of geohash) { | ||
if (BASE32.indexOf(letter) === -1) { | ||
error = "geohash cannot contain '" + letter + "'"; | ||
} | ||
hash += base32(temp); | ||
} | ||
return hash; | ||
} | ||
static decodeHash(hash) { | ||
let even = true; | ||
const latRng = [-90, 90]; | ||
const lngRng = [-180, 180]; | ||
const hashChars = hash.split(''); | ||
while (hashChars.length) { | ||
const chunk = decimalChunk(hashChars.shift()); | ||
for (let i = 0; i < 5; i++) { | ||
const mask = [16, 8, 4, 2, 1][i]; | ||
const range = even ? lngRng : latRng; | ||
const middle = (range[0] + range[1]) / 2; | ||
range[chunk & mask ? 0 : 1] = middle; | ||
even = !even; | ||
} | ||
if (typeof error !== 'undefined' && !flag) { | ||
throw new Error("Invalid geohash '" + geohash + "': " + error); | ||
} | ||
else { | ||
return !error; | ||
} | ||
} | ||
function decodeHash(hash) { | ||
validateHash(hash); | ||
let even = true; | ||
const latRng = [-90, 90]; | ||
const lngRng = [-180, 180]; | ||
const hashChars = hash.split(''); | ||
while (hashChars.length) { | ||
const chunk = decimalChunk(hashChars.shift()); | ||
for (let i = 0; i < 5; i++) { | ||
const mask = [16, 8, 4, 2, 1][i]; | ||
const range = even ? lngRng : latRng; | ||
const middle = (range[0] + range[1]) / 2; | ||
range[chunk & mask ? 0 : 1] = middle; | ||
even = !even; | ||
} | ||
return { lat: (latRng[0] + latRng[1]) / 2, lng: (lngRng[0] + lngRng[1]) / 2 }; | ||
} | ||
return { lat: (latRng[0] + latRng[1]) / 2, lng: (lngRng[0] + lngRng[1]) / 2 }; | ||
} | ||
export { Geokit }; | ||
function distance(start, end, unit = 'km') { | ||
const startValid = validateCoordinates(start); | ||
if (startValid instanceof Error) { | ||
throw new Error('Start coordinates: ' + startValid.message); | ||
} | ||
const endValid = validateCoordinates(end); | ||
if (endValid instanceof Error) { | ||
throw new Error('End coordinates: ' + endValid.message); | ||
} | ||
const radius = unit.toLowerCase() === 'miles' ? 3963 : 6371; | ||
const dLat = toRad(end.lat - start.lat); | ||
const dLon = toRad(end.lng - start.lng); | ||
const lat1 = toRad(start.lat); | ||
const lat2 = toRad(end.lat); | ||
const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + | ||
Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2); | ||
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); | ||
return radius * c; | ||
} | ||
function hash(coordinates, precision = 10) { | ||
const valid = validateCoordinates(coordinates); | ||
if (valid instanceof Error) { | ||
throw valid; | ||
} | ||
let hash = ''; | ||
const latRng = [-90, 90]; | ||
const lngRng = [-180, 180]; | ||
while (hash.length < precision) { | ||
let temp = 0; | ||
for (let i = 0; i < 5; i++) { | ||
const even = (hash.length * 5 + i) % 2 === 0; | ||
const coord = even ? coordinates.lng : coordinates.lat; | ||
const range = even ? lngRng : latRng; | ||
const middle = (range[0] + range[1]) / 2; | ||
temp = (temp << 1) + getBit(coord, range); | ||
coord > middle ? (range[0] = middle) : (range[1] = middle); | ||
} | ||
hash += base32(temp); | ||
} | ||
return hash; | ||
} | ||
export { decodeHash, distance, hash, validateHash }; |
{ | ||
"name": "geokit", | ||
"version": "0.1.5", | ||
"version": "1.0.0", | ||
"description": "An assortment of geolocation related tools, all packaged in one easy to use kit.", | ||
"scripts": { | ||
"build": "rm -rf ./dist && rollup -c", | ||
"docs": "typedoc --module node --target es5 --out docs/ src/", | ||
"docs": "typedoc --out docs/ src/", | ||
"coverage": "nyc report --reporter=text-lcov | coveralls", | ||
@@ -9,0 +9,0 @@ "test": "nyc --reporter=html --reporter=text mocha --package package.json --exit", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
24190
14
264
0
0