Skip to content

Instantly share code, notes, and snippets.

@pianosnake
pianosnake / width-of-degree.js
Last active August 29, 2023 15:33
Calculate the width of one degree in meters at a given latitude on Earth
const EARTH_CIR_METERS = 40075016.686;
function toRadians(degrees) {
return degrees * Math.PI / 180;
};
function degreeWidth(lat){
return EARTH_CIR_METERS / 360 * Math.cos(toRadians(lat));
}
@pianosnake
pianosnake / meters-to-pixels.js
Created June 19, 2020 19:02
Convert meters to pixels when given a map zoom level and a latitude
const EARTH_CIR_METERS = 40075016.686;
function toRadians(degrees) {
return degrees * Math.PI / 180;
};
const metersToPixels = (meters, latitude, zoom) => {
const metersPerPixel = EARTH_CIR_METERS / Math.pow(2, zoom + 8) * Math.cos(toRadians(latitude));
return meters / metersPerPixel
}
@pianosnake
pianosnake / GoogleSheetCell.js
Last active August 8, 2019 21:54
Web component to inline a value from a Google Sheet into your HTML page. Use the component by giving it a value of the cell you'd like to display <g-cell value='a2'></g-cell> or if you need a cell from a different page of the sheet provide that number first followed by an exclamation mark <g-cell value='2!a2'></g-cell>
// define window.sheetId sometime before loading this script. the sheet id is in the URL of the Google Sheet when you're editing it.
if(!window.sheetId) throw Error('window.sheetId required');
class DataProvider {
constructor(sheetId) {
this.sheetId = sheetId;
this.dataPromises = {};
}
@pianosnake
pianosnake / most-recent-file.js
Created July 30, 2018 19:11
Get the name of the most recently created file in a given directory using Node.js
const fs = require('fs');
const path = require('path');
function getMostRecentFile(dir) {
const files = fs.readdirSync(dir);
let earliestCreate = 0;
let mostRecentFile = files[0];
files.forEach(file => {
if (fs.statSync(path.join(dir, file)).ctime > earliestCreate) {
@pianosnake
pianosnake / bounding-box-from-lat-lng-zoom-img-size.js
Last active July 17, 2024 14:19
Get a bounding box from latitude, longitude, zoom level and image size. Useful for getting the bounding box of a static map generated with only those variables.
const EARTH_CIR_METERS = 40075016.686;
const degreesPerMeter = 360 / EARTH_CIR_METERS;
function toRadians(degrees) {
return degrees * Math.PI / 180;
};
function latLngToBounds(lat, lng, zoom, width, height){
const metersPerPixelEW = EARTH_CIR_METERS / Math.pow(2, zoom + 8);
const metersPerPixelNS = EARTH_CIR_METERS / Math.pow(2, zoom + 8) * Math.cos(toRadians(lat));
@pianosnake
pianosnake / bounding-box-area.js
Last active July 16, 2018 22:38
Computes the area of a geographic bounding box assuming spherical Earth
// adapted from http://mathforum.org/library/drmath/view/63767.html
const r = 6371.0072; //earth radius in KM
function toRadians(degrees) {
return degrees * Math.PI / 180;
};
function computeArea(bbox){
const [minLng, minLat, maxLng, maxLat] = bbox;
@pianosnake
pianosnake / cardinalDirection.js
Last active April 18, 2018 16:00
Convert bearing (0-360 degrees) to cardinal direction (N, NW, etc...)
//divide 360 into 16 equal slices
const degrees = (new Array(16)).fill(null).map((x, i) => 360/16 * i + 11.25);
const directions = ['N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE', 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW'];
function cardinalDirection(bearing) {
for (let i = 0, l = degrees.length; i < l; i++) {
if (bearing < degrees[i]) return directions[i];
if (i == l - 1) return directions[0];
}
}
@pianosnake
pianosnake / insistent request using generators.js
Last active September 21, 2017 19:47
retry a Request repeatedly until it succeeds or the try limit is reached
function insistentRequest(request, tryLimit){
if(!tryLimit) return Promise.reject('tryLimit must be above 0');
let tries = 0;
return new Promise(function(resolve, reject){
//create a generator object that repeatedly 'yields' the same promise until it succeeds or the try limit is reached
const genObj = function* gen(){
while(1){
yield request()
.then(resolve)
@pianosnake
pianosnake / throttle-promises.js
Created August 22, 2017 21:13
Promise throttling using a generator
function throttlePromises(elements, asyncForEach, groupSize){
return new Promise(function(resolve, reject){
//create a generator object that 'yields' for every group
const genObj = function* gen(){
while(elements.length > 0){
yield Promise.all(elements.splice(0, groupSize).map(asyncForEach))
.then(() => genObj.next());
}
return resolve(true);
}();
@pianosnake
pianosnake / gist:af8b04f9db7987f55832ca2394b74ae0
Created June 2, 2017 22:54
Find out who wrote the bad JavaScript!! Use `git blame` on each line output by ESLINT
eslint "**/**.js" -f unix | perl -n -l -e '/(.*\.js):(\d*):/ && print "$1 $2"' | xargs -n 2 sh -c 'git blame $0 -L$1,$1'