|
(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 |
|
} |
|
}); |
|
}); |
|
}; |
|
|
|
}()); |