|
(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.eyJ1IjoiaGlyb3NhamkiLCJhIjoiY2szOWlqZWNzMDJueTNjcWhyNjhqdXBnOSJ9._6mJT202QqpnMuK-jvMr3g'; |
|
var center = [lng, lat]; |
|
var radius = 0.122; |
|
var precision = 0.001525; |
|
var epsilon = 0.0001; |
|
|
|
var map = new mapboxgl.Map({ |
|
container: 'map', |
|
style: 'mapbox://styles/hirosaji/ck39jbjve00bc1dohszauaski', |
|
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 |
|
} |
|
}); |
|
|
|
// Insert the layer beneath any symbol layer |
|
var layers = map.getStyle().layers; |
|
|
|
var labelLayerId; |
|
for (var i = 0; i < layers.length; i++) { |
|
if (layers[i].type === 'symbol' && layers[i].layout['text-field']) { |
|
labelLayerId = layers[i].id; |
|
break; |
|
} |
|
} |
|
|
|
map.addLayer({ |
|
'id': '3d-buildings', |
|
'source': 'composite', |
|
'source-layer': 'building', |
|
'filter': ['==', 'extrude', 'true'], |
|
'type': 'fill-extrusion', |
|
'minzoom': 15, |
|
'paint': { |
|
'fill-extrusion-color': '#aaa', |
|
|
|
// add a smooth transition effect to the buildings as the user zooms in |
|
'fill-extrusion-height': [ |
|
"interpolate", ["linear"], ["zoom"], |
|
15, 0, |
|
15.05, ["get", "height"] |
|
], |
|
'fill-extrusion-base': [ |
|
"interpolate", ["linear"], ["zoom"], |
|
15, 0, |
|
15.05, ["get", "min_height"] |
|
], |
|
'fill-extrusion-opacity': .6 |
|
} |
|
}, labelLayerId); |
|
}); |
|
}; |
|
|
|
}()); |