Compare commits
No commits in common. "4c9ef7aa441f74dd81967338c31fd7dd06d12445" and "bf11f90a3429c27b895ec91320addde40b59225f" have entirely different histories.
4c9ef7aa44
...
bf11f90a34
|
@ -34,8 +34,8 @@ for state in states[:51]: # Just the 50 and DC, not Guam/American Samoa/PR/etc
|
||||||
for feature in data['features']:
|
for feature in data['features']:
|
||||||
# {"type": "Feature", "properties": {"STATEFP": "01", "PLACEFP": "02260", "PLACENS": "02405163", "GEOID": "0102260", "NAME": "Ardmore", "NAMELSAD": "Ardmore town", "LSAD": "43", "CLASSFP": "C1", "PCICBSA": "N", "PCINECTA": "N", "MTFCC": "G4110", "FUNCSTAT": "A", "ALAND": 5289895, "AWATER": 21830, "INTPTLAT": "+34.9878376", "INTPTLON": "-086.8290225"}, "geometry": {"type": "Polygon", "coordinates": [[[-86.856689, 34.992046], [-86.855354, 34.992044], [-86.855101, 34.99204]
|
# {"type": "Feature", "properties": {"STATEFP": "01", "PLACEFP": "02260", "PLACENS": "02405163", "GEOID": "0102260", "NAME": "Ardmore", "NAMELSAD": "Ardmore town", "LSAD": "43", "CLASSFP": "C1", "PCICBSA": "N", "PCINECTA": "N", "MTFCC": "G4110", "FUNCSTAT": "A", "ALAND": 5289895, "AWATER": 21830, "INTPTLAT": "+34.9878376", "INTPTLON": "-086.8290225"}, "geometry": {"type": "Polygon", "coordinates": [[[-86.856689, 34.992046], [-86.855354, 34.992044], [-86.855101, 34.99204]
|
||||||
state_place = (feature['properties']['STATEFP'], feature['properties']['PLACEFP'])
|
state_place = (feature['properties']['STATEFP'], feature['properties']['PLACEFP'])
|
||||||
lon_lat = (float(feature['properties']['INTPTLON']), float(feature['properties']['INTPTLAT']))
|
lat_lon = (float(feature['properties']['INTPTLAT']), float(feature['properties']['INTPTLON']))
|
||||||
place_locations[state_place] = lon_lat
|
place_locations[state_place] = lat_lon
|
||||||
print("done")
|
print("done")
|
||||||
|
|
||||||
print("Fetching population data for all states…", flush=True, end="")
|
print("Fetching population data for all states…", flush=True, end="")
|
||||||
|
|
38
index.html
38
index.html
|
@ -61,9 +61,6 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="col-8 h-100">
|
<div class="col-8 h-100">
|
||||||
<canvas id="canvas" class="mx-3 my-auto" @vue:mounted="draw" width="800" height="600"></canvas>
|
<canvas id="canvas" class="mx-3 my-auto" @vue:mounted="draw" width="800" height="600"></canvas>
|
||||||
<div>
|
|
||||||
<input type="checkbox" v-model="show_unguessed_cities" @change="draw"> Show unguessed cities
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -129,7 +126,7 @@
|
||||||
const cities = await response.json();
|
const cities = await response.json();
|
||||||
await state_shape_data_request; // We can't draw until this is in
|
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_shape = state_shape_data.features.find(f => f.properties.NAME.toLowerCase() == stateName.toLowerCase());
|
||||||
const state_mercator_adjusted_bounds = find_bounds(state_shape.geometry.coordinates[0].map(mercator));
|
const state_bounds = find_bounds(state_shape.geometry.coordinates[0]);
|
||||||
if (!state_shape) {
|
if (!state_shape) {
|
||||||
console.error("Unable to find state in shapes");
|
console.error("Unable to find state in shapes");
|
||||||
}
|
}
|
||||||
|
@ -140,7 +137,6 @@
|
||||||
simplified_cities: cities.map(city => simplify(city.name)),
|
simplified_cities: cities.map(city => simplify(city.name)),
|
||||||
city_guess: "",
|
city_guess: "",
|
||||||
message: "",
|
message: "",
|
||||||
show_unguessed_cities: true,
|
|
||||||
achievements: {
|
achievements: {
|
||||||
"Top Five": cities => cities.slice(0, 5),
|
"Top Five": cities => cities.slice(0, 5),
|
||||||
"Top Ten": cities => cities.slice(0, 10),
|
"Top Ten": cities => cities.slice(0, 10),
|
||||||
|
@ -173,21 +169,14 @@
|
||||||
const ctx = canvas.getContext("2d");
|
const ctx = canvas.getContext("2d");
|
||||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
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) {
|
function transform(pt) {
|
||||||
pt = mercator(pt)
|
// TODO: this just works for MN, and not very well at that
|
||||||
return [scale * (pt[0] - x_offset), canvas.height - (scale * (pt[1] - y_offset))];
|
return [(pt[0]+98)*80, 600-(pt[1]-42)*80];
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.moveTo(...transform(state_shape.geometry.coordinates[0][0]))
|
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)) {
|
for (let coord of state_shape.geometry.coordinates[0].slice(1)) {
|
||||||
ctx.lineTo(...transform(coord));
|
ctx.lineTo(...transform(coord));
|
||||||
}
|
}
|
||||||
|
@ -195,29 +184,16 @@
|
||||||
for (let city of cities) {
|
for (let city of cities) {
|
||||||
if (city.guessed) {
|
if (city.guessed) {
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
const c = transform(city.location)
|
const c = transform([city.location[1], city.location[0]])
|
||||||
ctx.fillStyle = "black";
|
console.log(city.location, c)
|
||||||
ctx.arc(c[0], c[1], 2, 0, 2*Math.PI, true);
|
|
||||||
} else if (this.show_unguessed_cities) {
|
|
||||||
ctx.beginPath();
|
|
||||||
const c = transform(city.location)
|
|
||||||
ctx.fillStyle = "lightgray";
|
|
||||||
ctx.arc(c[0], c[1], 2, 0, 2*Math.PI, true);
|
ctx.arc(c[0], c[1], 2, 0, 2*Math.PI, true);
|
||||||
|
ctx.fill();
|
||||||
}
|
}
|
||||||
ctx.fill();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}).mount();
|
}).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
|
// returns minx, maxx, miny, maxy
|
||||||
function find_bounds(coords) {
|
function find_bounds(coords) {
|
||||||
return [
|
return [
|
||||||
|
|
Loading…
Reference in a new issue