Skip to content

Instantly share code, notes, and snippets.

@andrewharvey
Created December 13, 2017 12:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andrewharvey/c1fdbebafe3fc46d743ba9514e4d64b2 to your computer and use it in GitHub Desktop.
Save andrewharvey/c1fdbebafe3fc46d743ba9514e4d64b2 to your computer and use it in GitHub Desktop.
Add dome in Mapbox GL JS using a hex grid and polygon extrusions
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title>Add dome in Mapbox GL JS using a hex grid and polygon extrusions</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.42.2/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.42.2/mapbox-gl.css' rel='stylesheet' />
<script src='https://npmcdn.com/@turf/turf/turf.min.js'></script>
<style>
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<div id='map'></div>
<script>
mapboxgl.accessToken = 'pk.eyJ1IjoiYWxhbnRnZW8tcHJlc2FsZXMiLCJhIjoiNkRKcXdVdyJ9.XVLiu2tRo5f2P__oBfdqsw';
var center = [151.1745, -33.9411];
var radius = 20;
var precision = 0.25;
var epsilon = 0.0001; // small number so that grid cells have some non zero height
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v9',
center: center,
zoom: 9,
pitch: 60
});
var grid = turf.hexGrid(turf.bbox(turf.circle(center, radius)), precision);
var dome = turf.featureCollection(grid.features.map(function (feature) {
var point = turf.centroid(feature);
var distance = turf.distance(center, point);
if (distance > radius) {
return; // will be filtered out later
}
// sphere r^2 = x^2 + y^2 + z^2
// therefore z = Math.sqrt(r^2 - x^2 - y^2)
// = Math.sqrt(r^2 - (x^2 + y^2))
// but distance^2 = x^2 + y^2
// so z = Math.sqrt(r^2 - distance^2)
var z = Math.sqrt(Math.pow(radius, 2) - Math.pow(distance, 2));
z = isNaN(z) ? 0 : z;
return turf.feature(feature.geometry, {
base_height: z * 1000, // z is km so times 1000 to get meters
height: (z * 1000) + (distance * 1000 + epsilon) * 0.1 // TODO with a bit of maths you could work out exactly how much extrusion to use based on the distance and precision variables
});
}).filter(function (feature) {
// filter out null features, which resulted where the grid point was outside the circle
return feature;
}));
map.on('load', function () {
map.addSource('dome', {
type: 'geojson',
data: dome
});
map.addLayer({
id: 'dome',
type: 'fill-extrusion',
source: 'dome',
layout: {},
paint: {
'fill-extrusion-color': 'red',
'fill-extrusion-base': {
type: 'identity',
property: 'base_height'
},
'fill-extrusion-height': {
type: 'identity',
property: 'height'
},
'fill-extrusion-opacity': 0.5
}
});
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment