diff --git a/index.html b/index.html index 1f87ae2..23ce8f5 100644 --- a/index.html +++ b/index.html @@ -126,7 +126,7 @@ const cities = await response.json(); await state_shape_data_request; // We can't draw until this is in const state_shape = state_shape_data.features.find(f => f.properties.NAME.toLowerCase() == stateName.toLowerCase()); - const state_bounds = find_bounds(state_shape.geometry.coordinates[0]); + const state_mercator_adjusted_bounds = find_bounds(state_shape.geometry.coordinates[0].map(mercator)); if (!state_shape) { console.error("Unable to find state in shapes"); } @@ -169,14 +169,21 @@ const ctx = canvas.getContext("2d"); ctx.clearRect(0, 0, canvas.width, canvas.height); + const [minx, maxx, miny, maxy] = state_mercator_adjusted_bounds; + const height_scale = (canvas.height - 8) / (maxy - miny); + const width_scale = (canvas.width - 8) / (maxx - minx); + const scale = Math.min(height_scale, width_scale); + + const y_offset = miny - (canvas.height / scale - (maxy - miny)) / 2; + const x_offset = minx - (canvas.width / scale - (maxx - minx)) / 2; + function transform(pt) { - // TODO: this just works for MN, and not very well at that - return [(pt[0]+98)*80, 600-(pt[1]-42)*80]; + pt = mercator(pt) + return [scale * (pt[0] - x_offset), canvas.height - (scale * (pt[1] - y_offset))]; } ctx.beginPath(); ctx.moveTo(...transform(state_shape.geometry.coordinates[0][0])) - console.log(transform(state_shape.geometry.coordinates[0][0])) for (let coord of state_shape.geometry.coordinates[0].slice(1)) { ctx.lineTo(...transform(coord)); } @@ -194,6 +201,14 @@ }).mount(); } + function mercator(pt) { + const radians_from_eq = Math.abs(Math.PI/180 * pt[1]); + // https://en.wikipedia.org/wiki/Mercator_projection#Derivation + const y_radians = Math.log(Math.tan(Math.PI/4 + radians_from_eq/2)); + const y_degrees = 180/Math.PI * y_radians; + return [pt[0], y_degrees]; + } + // returns minx, maxx, miny, maxy function find_bounds(coords) { return [