Skip to content

Instantly share code, notes, and snippets.

View missinglink's full-sized avatar

Peter Johnson missinglink

View GitHub Profile
@missinglink
missinglink / duckdb.sql
Last active October 15, 2024 19:45
Indian postcode polygons as convex hull
INSTALL spatial;
LOAD spatial;
.mode tabs
SELECT
postcode,
ST_AsGeoJSON(CASE WHEN ST_Area(hull) > 0 THEN hull ELSE ST_Centroid(hull) END) AS geometry
FROM (
SELECT
@missinglink
missinglink / scraper.ts
Last active September 13, 2024 20:37
Scrape a list of Europa data portal catalogues & datasets
import got from 'got'
import fs from 'node:fs'
import path from 'node:path'
const API_BASE = 'https://data.europa.eu/api/hub/search'
await fs.promises.mkdir('data', { recursive: true })
const catalogues: string[] = await got.get(`${API_BASE}/catalogues`).json()
for (const catalogue of catalogues) {
@missinglink
missinglink / wof-finding-aid.ts
Created July 25, 2024 12:39
Find the corresponding repo for a WhosOnFirst ID
/**
* download the ccmap file (updated every time the data updates):
*
* curl -OL https://data.geocode.earth/wof/dist/meta/whosonfirst-data-admin.ccmap.gz
*
*
* convert ccmap file to typescript (save stdout to `whosonfirst-data-admin.ccmap.ts`):
*
* import fs from 'node:fs'
* const data = fs.readFileSync('whosonfirst-data-admin.ccmap.gz', 'base64')
@missinglink
missinglink / remainder.ts
Created July 24, 2024 09:18
Javascript IEEE 754 floating-point remainder of x / y
/** Computes the IEEE 754 floating-point remainder of x / y. */
export const remainder = (x: number, y: number): number => {
if (isNaN(x) || isNaN(y) || !isFinite(x) || y === 0) return NaN
const quotient = x / y
let n = Math.round(quotient)
// When quotient is exactly halfway between two integers, round to the nearest even integer
if (Math.abs(quotient - n) === 0.5) n = 2 * Math.round(quotient / 2)
@missinglink
missinglink / random.ts
Created July 23, 2024 22:44
Generate random BigInt values in the browser of variable bit length
/** Returns a random hex string of length chars. */
const randomHexString = (length: number): string => {
return Array.from({ length }, () => Math.round(Math.random() * 0xf).toString(16)).join('')
}
/** Returns a random BigInt of n bits in length. */
export const randomBigIntN = (n: number): bigint => {
return BigInt.asUintN(n, BigInt(`0x${randomHexString(Math.ceil(n / 4))}`))
}
@missinglink
missinglink / geojson-custom-replacer.js
Last active April 22, 2024 23:54
Custom `JSON.stringify` replacer which provides the object path and depth
// decorator
function replacerWithPath (fn) {
let paths = new Map()
return function (key, value) {
let path = paths.get(this) || '$'
if (key) path += Array.isArray(this) ? `[${key}]` : `.${key}`
let v = fn(key, value, path)
if (v === Object(v)) paths.set(v, path)
return v
}
@missinglink
missinglink / canonicalize.js
Last active April 22, 2024 23:35
Output a canonical normalised GeoJSON string which will hash deterministically
const geojson = {
'id': -99,
'type': -6,
'properties': -5,
'geometry': -4,
'coordinates': -3,
'bbox': -2
}
// GeoJSON Feature/Geometry
@missinglink
missinglink / formula-one.js
Last active February 28, 2024 15:21
compute the cartesian product of formula one team/player scores
// copy->paste into the browser console and wait
// note: sorted with the highest points last
const csv = (text) =>
text
.trim()
.split('\n')
.map((r) => {
const c = r.split(',').map((c) => c.trim())
return {
@missinglink
missinglink / conversions.go
Created January 20, 2024 21:51
Convert golang S2 geometries to Simple Features
package spatial
import (
"fmt"
"strconv"
"github.com/golang/geo/s2"
"github.com/peterstace/simplefeatures/geom"
)
@missinglink
missinglink / tcpdump.sh
Last active October 13, 2023 13:22
log all UDP packets starting with a byte sequence
sudo tcpdump -X -v 'udp[8:4] = 0x03050b11'