Created
December 13, 2017 12:49
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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