Skip to content

Instantly share code, notes, and snippets.

@Hirosaji
Last active February 19, 2020 02:30
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 Hirosaji/788653f2ce96f46c18d3ed5ca3daf82d to your computer and use it in GitHub Desktop.
Save Hirosaji/788653f2ce96f46c18d3ed5ca3daf82d to your computer and use it in GitHub Desktop.
Mapbox GL JS × Turf - How big is the Tokyo Dome? (Satellite ver.)
# Mapbox GL JS × Turf - How big is the Tokyo Dome? (Satellite ver.)
license: mit

▶︎ What's this?: Tokyo Dome Polygon generator on you are here area Satellite Map (Satellite ver.)

▶︎ How to get current place: using Geolocation API

▶︎ Reference: https://bl.ocks.org/andrewharvey/c1fdbebafe3fc46d743ba9514e4d64b2


▷ Why made this?: Japanese TV often expresses a large area compared with Tokyo Dome. However, many people can not imagine how big Tokyo Dome is. So I made this content. With this content, everyone can compare the you are here area with Tokyo Dome.

▷ Another version: 3D building ver. - https://bl.ocks.org/Hirosaji/ed4443946608237eaddcf1207b3776cb


[Gist] https://gist.github.com/Hirosaji/788653f2ce96f46c18d3ed5ca3daf82d


Built with blockbuilder.org

(function () {
'use strict';
var successCallBackFunction, errorCallBackFunction;
/**
* Callback func at successful getting position
*/
successCallBackFunction = function (position) {
var lng = position.coords.longitude;
var lat = position.coords.latitude;
// revert button element
document.getElementById('input').innerHTML = "<button id='button'>Draw Map</button>";
// remove dummy img
var imgTag = document.getElementById('dummy');
if(imgTag != null){
imgTag.parentNode.removeChild(imgTag);
}
latlng2domePolygon(lng, lat);
};
/**
* Callback func at faild getting position
*/
errorCallBackFunction = function (positionError) {
alert(positionError.code + ': ' + positionError.message);
};
var option = {
enableHighAccuracy: true, // Whether to use GPS to improve accuracy
maximumAge: 0, // to hold cache ms
timeout: 30000 // Timeout ms
};
/**
* Processing at the end of HTML loading
*/
window.addEventListener('load', function () {
// Check whether Geolocation API is enabled/disabled
if (!navigator.geolocation) {
alert('Geolocation API is disabled');
return;
}
document.getElementById('button').addEventListener('click', function () {
document.getElementById('input').innerHTML = "<img id='loading' src='loading.gif'>";
navigator.geolocation.getCurrentPosition(successCallBackFunction, errorCallBackFunction, option);
}, false);
}, false);
// Generate domed polygons from [lng lat]
function latlng2domePolygon(lng, lat) {
mapboxgl.accessToken = 'pk.eyJ1IjoiaGlyb3NhamkiLCJhIjoiY2szOWljb210MDJxcjNjcXRwZGF6bmJnMiJ9.gin_FUY4wc61PoNKnUWL5Q';
var center = [lng, lat];
var radius = 0.122;
var precision = 0.001525;
var epsilon = 0.0001;
var satelliteStyle = {
"version": 8,
"sources": {
"satellite": {
"type": "raster",
"url": "mapbox://mapbox.satellite",
"tileSize": 256
}
},
"layers": [{
"id": "background",
"type": "background",
"paint": {
"background-color": "rgb(4,7,14)"
}
}, {
"id": "satellite",
"type": "raster",
"source": "satellite"
}]
};
var map = new mapboxgl.Map({
container: 'map',
style: satelliteStyle,
center: center,
zoom: 16,
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; }
// 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));
var normHeight = 56.190 / 122; // to normalize height
z = isNaN(z) ? 0 : z * normHeight;
return turf.feature(feature.geometry, {
base_height: z * 1000, // adopt z / m from z / km
height: (z * 1000) + (distance * 1000 + epsilon) * 0.1,
roof_base_height: (z * 1000) + (distance * 950 + epsilon) * 0.1,
roof_height: (z * 1000) + (distance * 1000 + epsilon) * 0.1
});
}).filter(function (feature) { return feature; }));
map.on('load', function () {
map.addSource('dome', {
type: 'geojson',
data: dome
});
map.addLayer({
id: 'dome',
type: 'fill-extrusion',
source: 'dome',
paint: {
'fill-extrusion-color': 'pink',
'fill-extrusion-base': {
type: 'identity',
property: 'base_height'
},
'fill-extrusion-height': {
type: 'identity',
property: 'height'
},
'fill-extrusion-opacity': 0.5
}
});
map.addSource('dome_roof', {
type: 'geojson',
data: dome
});
map.addLayer({
id: 'dome_roof',
type: 'fill-extrusion',
source: 'dome_roof',
paint: {
'fill-extrusion-color': 'red',
'fill-extrusion-base': {
type: 'identity',
property: 'roof_base_height'
},
'fill-extrusion-height': {
type: 'identity',
property: 'roof_height'
},
'fill-extrusion-opacity': 0.5
}
});
});
};
}());
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title>How big is the Tokyo Dome?</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v1.5.0/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v1.5.0/mapbox-gl.css' rel='stylesheet' />
<script src='https://npmcdn.com/@turf/turf/turf.min.js'></script>
<script src='./generateDomefromLatLng.js'></script>
<style>
#map {
height: 600px;
width: 600px;
}
#button {
font-size: 1.4em;
font-weight: bold;
padding: 10px 30px;
background-color: #DC143C;
color: #fff;
border-style: none;
margin-bottom: 10px;
}
#button:hover {
background-color: pink;
}
#loading {
height: 50px;
}
</style>
</head>
<body>
<div id='input'>
<button id='button'>Draw Map</button>
</div>
<img id='dummy' src='./dummy.png'>
<div id='map'></div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment