Experience results from numerical simulations by the CEREMA in 2 locations in France. Build on OpenStreetMap, IGN data and AFrame for WebXR support.
https://bric-vr.com/cerema/portail/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
99 lines
3.7 KiB
99 lines
3.7 KiB
<html>
|
|
<head>
|
|
<script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script>
|
|
</head>
|
|
<body>
|
|
<script>
|
|
var currentGeoPose = null; // https://developer.mozilla.org/en-US/docs/Web/API/Geolocation/getCurrentPosition
|
|
navigator.geolocation.getCurrentPosition( geolocalized ) // should handle error, including being ignored
|
|
// otherwise have 2 fallbacks via menu
|
|
var positionsCurated = [
|
|
[50.8440239,4.3952614], // brussels for tests
|
|
[1,1]
|
|
]
|
|
|
|
// should get in turn nwr(50.844,4.395,50.845,4.396); as example of scale
|
|
|
|
// default position fallback to faciliate tests
|
|
var position = positionsCurated[0]
|
|
|
|
// initially done as a different page at first with query parameter
|
|
var forcePosition = AFRAME.utils.getUrlParameter('position');
|
|
if ( forcePosition ) position = positionsCurated[forcePosition]
|
|
|
|
// generate 3D model from the target location from OSM data
|
|
var bbox = "" + position[0]
|
|
+ "," + position[1]
|
|
+ "," + (position[0]+0.001)
|
|
+ "," + (position[1]+0.001)
|
|
var queryOSM = `https://overpass-api.de/api/interpreter?data=[out:json];nwr(${bbox});out;`
|
|
console.log( bbox )
|
|
// format https://overpass-api.de/output_formats.html#json
|
|
// bounding box https://dev.overpass-api.de/overpass-doc/en/full_data/bbox.html
|
|
// testing https://overpass-turbo.eu
|
|
fetch(queryOSM).then(response => response.json()).then(data => fromOSMTo3DElements(data) )
|
|
|
|
// fetch flood data of target location (should be only 2 available) as timeseries
|
|
var queryCEREMA = "https://cerema.fr/api/"+position
|
|
fetch(queryCEREMA).then(response => response.json()).then(data => console.log(data) )
|
|
|
|
// animate water based on flood data
|
|
|
|
// allow viewer to control the animation e.g restart, pause, change time
|
|
|
|
// modify environment to reflect time of day
|
|
|
|
AFRAME.registerComponent('osm', { // currently only 1 hand, the right one
|
|
init: function () {
|
|
}
|
|
});
|
|
|
|
var globaljosm
|
|
|
|
function fromOSMTo3DElements( josm ){
|
|
globaljosm = josm
|
|
var ways = josm.elements.filter( e => (e.type == "way") )
|
|
var houses = josm.elements.filter( e => (e.type == "node" && e.tags && e.tags["addr:housenumber"]))
|
|
// does not give a polygon, might need further requests. Might also not be the right way.
|
|
addHouses( houses )
|
|
console.log( ways.length, houses.length )
|
|
}
|
|
|
|
function addHouses( houses ){
|
|
houses.map( h => {
|
|
var el = document.createElement("a-box")
|
|
el.setAttribute("position",
|
|
(((h.lat*1000)-(Math.round(h.lat*1000)))*10).toFixed(3)
|
|
+ " 0 "
|
|
+ (((h.lon*1000)-(Math.round(h.lon*1000)))*10).toFixed(3)
|
|
)
|
|
AFRAME.scenes[0].appendChild( el )
|
|
})
|
|
}
|
|
|
|
function geolocalized( pos ){
|
|
console.log( pos.coords )
|
|
}
|
|
|
|
</script>
|
|
<a-scene osm>
|
|
<!-- Quest available only during event, otherwise cardboard -->
|
|
<a-entity id="leftHand" hand-tracking-controls="hand: left;"></a-entity>
|
|
<a-entity id="rightHand" hand-tracking-controls="hand: right;"></a-entity>
|
|
<!-- for cardboard consider instead https://aframe.io/docs/1.3.0/components/cursor.html -->
|
|
|
|
<!-- Default lighting injected by A-Frame. -->
|
|
<a-entity light="type: ambient; color: #BBB"></a-entity>
|
|
<a-entity animation="property: position; to: 5 1 1; dur: 20000; easing: linear; loop: true"
|
|
light="type: directional; color: #FFF; intensity: 0.6" position="-5 1 1"></a-entity>
|
|
<!-- to animate but also consider the background color -->
|
|
<a-sky color="#ECECEC"></a-sky>
|
|
|
|
<a-sound src="src: url(birds.mp3)" autoplay="true" position="0 2 5"></a-sound>
|
|
<a-sound src="src: url(river.mp3)" autoplay="true" position="0 2 5"></a-sound>
|
|
|
|
<a-plane animation="property: position; to: 0 0.4 0; dur: 20000; easing: linear; loop: true"
|
|
position="0 -0.5 0" rotation="-90 0 0" width="100" height="100" color="lightblue"></a-plane>
|
|
</a-scene>
|
|
</body>
|
|
</html>
|
|
|