Skip to content

Instantly share code, notes, and snippets.

@wboykinm
Last active January 12, 2020 02:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save wboykinm/4448865 to your computer and use it in GitHub Desktop.
Save wboykinm/4448865 to your computer and use it in GitHub Desktop.
Census Dotmap + Reference
<!DOCTYPE html>
<html>
<head>
<title>Census Dotmap</title>
<link rel="image_src" href="/dotmap/sample.png" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta name="description" content="This is a map of every person counted by the 2010 US and 2011 Canadian censuses. The map has 341,817,095 dots - one for each person." />
<meta name="og:description" content="This is a map of every person counted by the 2010 US and 2011 Canadian censuses. The map has 341,817,095 dots - one for each person." />
<meta name="og:image" content="/dotmap/sample.png" />
<meta name="og:url" content="http://bmander.com/dotmap/index.html" />
<meta name="og:title" content="Census Dotmap" />
<style type="text/css">
html { height: 100% }
body { height: 100%; margin: 0; padding: 0 }
#map_canvas { height: 100% }
</style>
<link type="text/css" rel="stylesheet" href="main.css" />
<script type="text/javascript"
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDM5hCtSjwpVyntcUPCOP1dzheF6JXcx5k&sensor=false">
</script>
<script type="text/javascript"
src="http://dev.geosprocket.com/hon/js/wax.g.js">
</script>
<script type="text/javascript">
var dotTypeOptions = {
getTileUrl: function(coord, zoom) {
//var ret = "tiles/"+zoom+"/"+coord.x+"/"+coord.y+".png";
if( zoom <= 7 ){
var ret = "https://s3.amazonaws.com/dotmap_tiles/"+zoom+"/"+coord.x+"/"+coord.y+".png";
} else {
var ret = "https://s3.amazonaws.com/dotmap_tiles/"+zoom+"/"+coord.x+"/"+coord.y+".png";
var ret = "http://mt"+((coord.x+coord.y)%4)+".bmander.com/tiles/"+zoom+"/"+coord.x+"/"+coord.y+".png";
}
return ret;
},
tileSize: new google.maps.Size(256, 256),
maxZoom: 14,
minZoom: 4,
name: "Census dots"
};
var lat = 39.0;
var lon = -96.341308;
var zoom = 4;
function setViewportFromArgs(){
var urlhash = window.location.hash;
if( urlhash != "" ){
urlhash = urlhash.substring(1); //remove the hash
var parts = urlhash.split("&");
var coord = {};
for(var i=0; i<parts.length; i++){
var keyval = parts[i].split("=");
if(keyval[0]==="lat" || keyval[0]==="lon") {
coord[keyval[0]] = parseFloat(keyval[1])
} else if(keyval[0]==="z"){
coord.z = parseInt(keyval[1]);
}
}
if( coord.lat && coord.lon ){
lat = coord.lat;
lon = coord.lon;
}
if( coord.z ){
zoom = coord.z;
}
}
}
var dotMapType = new google.maps.ImageMapType(dotTypeOptions);
var map;
function initialize() {
setViewportFromArgs();
wax.tilejson('http://api.tiles.mapbox.com/v3/landplanner.map-73h9vsq0.jsonp', function(tilejson) {
var myLatlng = new google.maps.LatLng(lat, lon);
var mapOptions = {
center: myLatlng,
zoom: zoom,
streetViewControl: false,
backgroundColor:"ffffff",
mapTypeControlOptions: {
mapTypeIds: ["dot", google.maps.MapTypeId.ROADMAP],
style: google.maps.MapTypeControlStyle.DEFAULT
}
};
map = new google.maps.Map(document.getElementById("map_canvas"),
mapOptions);
map.mapTypes.set('dot', dotMapType);
map.setMapTypeId('dot');
map.overlayMapTypes.insertAt(0, new wax.g.connector(tilejson));
}
function roundToPlace(x,places){
return Math.round(x*Math.pow(10,places))/Math.pow(10,places);
}
</script>
</head>
<body onload="initialize()">
<div id="map_canvas" style="width:80%; height:100%; float:left"></div>
<div style="float:left;width:20%">
<div style="padding:5px">
<h1>Census Dotmap</h1>
<h3>What's all this?</h3>
<p>This is a map of every person counted by the 2010 US and 2011 Canadian censuses. The map has <b>341,817,095</b> dots - one for each person.</p>
<h3>Why?</h3>
<p>I wanted an image of human settlement patterns unmediated by proxies like city boundaries, arterial roads, state lines, &amp;c. Also, it was an interesting challenge.</p>
<h3>Who is responsible for this?</h3>
<p>The US and Canadian censuses, mostly. I made the map. I'm <a href="https://twitter.com/ewedistrict">Brandon Martin-Anderson.</a> <a href="https://twitter.com/kieran">Kieran Huggins</a> came to the rescue with spare server capacity and technical advice once this took off.</p>
<h3>How?</h3>
<p>I wrote a Python script to generate points from US Census block-level counts, and then generated the tiles with Processing. Here's <a href="methods.html">more detail for the interested</a>.</p>
<h3>I don't see dots. I see smudges.</h3>
<p>The dots are very small. Try zooming in.</p>
<h3>Nobody lives in Central Park/Pier 12/County Lockup/Abandoned Themepark.</h3>
<p>The census reported that someone lived there.</p>
<h3>This says someone lives in the middle of a lake.</h3>
<p>The census reported that someone lives in a block which includes a lake, and that's where their dot was randomly placed. Also, some people live in the middle of lakes.</p>
<a href="#" onclick="window.location.hash='lat='+roundToPlace(map.getCenter().lat(),6)+'&lon='+roundToPlace(map.getCenter().lng(),6)+'&z='+map.getZoom();return false;" style="margin-top:10px;background-color:#ffeeee">link to this map</a>
</div>
</div>
</body>
</html>
div#container {
width:960px;
padding:0 10px;
margin-left:auto;
margin-right:auto;
border-left:1px solid #b3b3a4;
}
div#portfolio {
width:960px;
padding:0 10px;
margin-left:auto;
margin-right:auto;
border-left:1px solid #b3b3a4;
}
span#red {
color:#FF0000;
}
div#title {
font-size: 400%;
font-weight: bold;
}
h1 {
font-size: 400%;
font-weight: bold;
margin-bottom: 0px;
margin-top: 0px;
}
body {
font-family: Verdana, Helvetica, sans-serif;
background-color: #FFFFFF;
font-size: 90%;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment