Skip to content

Instantly share code, notes, and snippets.

@mindrones
Last active November 5, 2017 22:34
Show Gist options
  • Save mindrones/0cd290cadc0e7cc3992eef8565962076 to your computer and use it in GitHub Desktop.
Save mindrones/0cd290cadc0e7cc3992eef8565962076 to your computer and use it in GitHub Desktop.
The world population crowd
license: gpl-3.0
height: 700

See https://medium.com/@mindrones/how-big-is-the-world-population-crowd-b8c9a5f2b4e0.

The red square (87187 meters wide) represents the human population as of October 2017, 1 person per square meter. The black circle represents the distance from the center of this crowd to the horizon at an altitude of 300 meters, from where you can see the whole crowd.

Drag/zoom the map to see how this super crowd would compare to various places in the world.

html,
svg,
body {
width: 100%;
height: 100%;
}
body {
overflow: hidden;
}
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
#app {
width: 100%;
height: 100%;
}
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<title>The world population crowd</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<script src="https://d3js.org/d3-geo.v1.min.js"></script>
<script src="https://api.mapbox.com/mapbox-gl-js/v0.41.0/mapbox-gl.js"></script>
<link href="https://api.mapbox.com/mapbox-gl-js/v0.41.0/mapbox-gl.css" rel="stylesheet" />
<link href="index.css" rel="stylesheet">
</head>
<body>
<div id="app"></div>
<script src="index.js"></script>
</body>
mapboxgl.accessToken = "pk.eyJ1IjoibWluZHJvbmVzIiwiYSI6ImNqOWNxb2libzF5OXgycXQ0Y2tvOGhrbGMifQ.BhUb7T8FceWj45x-ikQmHg";
const earthRadius = 6371; // km
const people = 7.6e9;
const viewHeight = 300; // meters
const horizonRatio = Math.acos(1 / (1 + viewHeight / (1000 * earthRadius))); // horizonRadius / earthRadius
const POICenter = new mapboxgl.LngLat(2.2945, 48.858222); // eiffel tower
const toDeg = radians => radians * 180 / Math.PI;
const toRad = degrees => Math.PI * degrees / 180;
const dLng = (dlat, lat) => Math.acos(
(Math.cos(dlat) - Math.pow(Math.sin(lat), 2))
/ Math.pow(Math.cos(lat), 2)
);
const makeGeojson = coordinates => ({
type: "FeatureCollection",
features: [{
type: "Feature",
geometry: {
type: "LineString",
coordinates
}
}]
});
const mapsStyles = {
"light_v9": "mapbox://styles/mapbox/light-v9",
"satellite_streets_v10": "mapbox://styles/mapbox/satellite-streets-v10",
"streets_v10": "mapbox://styles/mapbox/streets-v10",
}
const map = new mapboxgl.Map({
container: "app",
style: mapsStyles.streets_v10,
center: POICenter.toArray(),
zoom: 7,
renderWorldCopies: false
});
map.on("load", function() {
map.addLayer({
"id": "humans",
"type": "line",
"source": {
"type": "geojson",
"data": makeSquare(POICenter)
},
"layout": {
"line-cap": "round",
"line-join": "round"
},
"paint": {
"line-color": "red",
"line-width": 2,
"line-opacity": 1
}
});
map.addLayer({
"id": "horizon",
"type": "line",
"source": {
"type": "geojson",
"data": makeHorizon(POICenter)
},
"layout": {
"line-cap": "round",
"line-join": "round"
},
"paint": {
"line-color": "black",
"line-width": 1,
"line-opacity": 1
}
});
["move", "resize",
"dragstart", "drag", "dragend",
"zoomstart", "zoom", "zoomend"
].forEach(eventName => {
map.on(eventName, () => {
const center = map.getBounds().getCenter();
updateHumans(center)
updateHorizon(center)
});
});
});
function updateHumans(center) {
map.getSource("humans").setData(makeSquare(center));
}
function updateHorizon(center) {
map.getSource("horizon").setData(makeHorizon(center));
}
function makeSquare (center) {
const peoplePerSide = Math.sqrt(people);
const dLat = peoplePerSide / (2 * 1000 * earthRadius);
const northLat = toRad(center.lat) + dLat;
const southLat = toRad(center.lat) - dLat;
const N = 10;
const yStep = (northLat - southLat) / N;
const coordinates = []
const sides = {west: [], east: []}
for (let lat = southLat; lat <= northLat; lat += yStep) {
const y = toDeg(lat);
const dx = toDeg(dLng(dLat, lat));
sides.west.push([center.lng + dx, y])
sides.east.push([center.lng - dx, y])
}
return geojsonLineString([
...sides.west,
...sides.east.reverse(),
sides.west[0]
]);
}
function makeHorizon (center) {
return d3.geoCircle()
.center(center.toArray())
.radius(toDeg(horizonRatio))();
}
function geojsonLineString (coordinates) {
return {
type: "FeatureCollection",
features: [{
type: "Feature",
geometry: {
type: "LineString",
coordinates
}
}]
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment