Skip to content

Instantly share code, notes, and snippets.

@bmcminn
Created March 26, 2019 22:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bmcminn/80da4da313f48c906a8388ccbf01a433 to your computer and use it in GitHub Desktop.
Save bmcminn/80da4da313f48c906a8388ccbf01a433 to your computer and use it in GitHub Desktop.
Playing around with zip code distance algorithms and radius search
const ZIPCODES = require('./zipcodes.js')
const sqlite = require('sqlite')
const Promise = require('bluebird')
// http://www.zipcodeapi.com/API
/**
* Calculates distance between two ZIPCODES
* @sauce: https://www.movable-type.co.uk/scripts/latlong.html
* @param {object} zip1 Object containing zip, lat, lng
* @param {object} zip2 Object containing zip, lat, lng
* @param {integer} PRECISION Flag to return the result in kilometers or miles
* @return {double} A double representing the distance between the two points
*/
function zipDistance(zip1, zip2, PRECISION=3) {
const R = 6371
// const R = 6371e3 // meters
// const M = R / 1.609
const φ1 = degressToRadians(zip1.lat)
const φ2 = degressToRadians(zip2.lat)
const Δφ = degressToRadians((zip2.lat-zip1.lat))
const Δλ = degressToRadians((zip2.lng-zip1.lng))
let a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
Math.cos(φ1) * Math.cos(φ2) *
Math.sin(Δλ/2) * Math.sin(Δλ/2)
let c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a))
return (R * c).toFixed(PRECISION)
}
/**
* Calculate the lat and lng ranges for a given "radius"
* @param {[type]} zip1 [description]
* @param {[type]} radius [description]
* @return {[type]} [description]
*/
function getZipRadius(zip1, radius) {
let DIST = 0.01035 * radius
return {
latMin: zip1.lat - DIST,
latMax: zip1.lat + DIST,
lngMin: zip1.lng - DIST,
lngMax: zip1.lng + DIST,
}
}
/**
* [degressToRadians description]
* @param {[type]} degrees [description]
* @return {[type]} [description]
*/
function degressToRadians(degrees) {
return degrees * (Math.PI/180)
}
/**
* Converts Km to miles
* @param {float} km distance in kilometers
* @return {double} miles distance in miles
*/
function kmToMiles(km, PRECISION=3) {
return (km / 1.609).toFixed(PRECISION)
}
/**
* [getZipsInRadius description]
* @param {[type]} zip [description]
* @param {[type]} zips [description]
* @param {[type]} radius [description]
* @return {[type]} [description]
*/
function getZipsInRadius(zip, zips, radius) {
const RADIUS = getZipRadius(zip, radius)
return zips.filter(el => {
if (RADIUS.latMin <= el.lat && el.lat <= RADIUS.latMax
&& RADIUS.lngMin <= el.lng && el.lng <= RADIUS.lngMax
) {
let distance = zipDistance(zip, el)
if (distance <= radius) {
return el
}
}
})
}
// const TARGET = ZIPCODES[0]
const RADIUS = 100
const TARGET = {
lat: 30.3,
lng: -97.6,
zip_code: '???',
}
// let res = getZipsInRadius(TARGET, ZIPCODES, RADIUS)
// res.map(el => {
// console.log(`distance from ${TARGET.zip_code} to ${el.zip_code} is`, kmToMiles(zipDistance(TARGET, el)), 'miles')
// })
getZipsInRadius(TARGET, ZIPCODES, RADIUS)
.map(el => {
console.log(`distance from ${TARGET.zip_code} to ${el.zip_code} is`, kmToMiles(zipDistance(TARGET, el)), 'miles')
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment