[guadec-web: 8/10] merged map



commit 2f647ce5961b07a3e7ed3c3b51c6da346be4aaa0
Merge: 34be52f b31ba67
Author: Jorge Sanz <xurxosanz gmail com>
Date:   Wed Jun 27 10:25:30 2018 +0200

    merged map

 content/documents/schedule.xml    |   2 +-
 content/pages/map.md              | 263 +++++++++++++++++++++++++++++++++++++-
 content/pages/schedule.md         |   2 +-
 content/pages/social-events.md    |   4 +
 content/pages/sponsors.md         |   1 +
 content/pages/talks-and-events.md |   2 +-
 content/pages/venue.md            |   2 +-
 7 files changed, 267 insertions(+), 9 deletions(-)
---
diff --cc content/pages/map.md
index c2d404a,7b2a900..ba13d62
--- a/content/pages/map.md
+++ b/content/pages/map.md
@@@ -84,26 -82,21 +84,29 @@@ Date: 2018061
              { osm_id: 509640566, name: 'Patio de los naranjos'}, // Patio de los naranjos
              187403583, // terraza del mar
              { osm_id: 27155530, name: 'Alcazaba meeting point'},
 -            { osm_id: 27018547, name: 'Alcazaba de Almería'},
 +            { osm_id: 27018547, name: 'Alcazaba de Almería', icon: 'gnome-guadec-yellow'},
+             { osm_id: 37639082, name: 'Auditorium'},
+             { osm_id: 37639116, name: 'Conference Room'},
 -            { osm_id: 37639300, name: 'University cafeteria'},                   
++            { osm_id: 37639300, name: 'University cafeteria'},
          ],
          /* List of nodes to include in the map */
 -        osm_nodes = [
 -            4414057566, // la mala
 -            { osm_id: 2870058034, name: 'Intermodal bus stop'}, // 292
 -            974730957, // 144
 -            469474242, // 71
 -            469474241,  //56
 -            { osm_id: 1304074112, name: 'Airport bus stop'}, // 188
 +        osm_nodes : [
-             4414057566, // la mala
-             { osm_id: 2870058034, name: 'Intermodal bus stop',icon: 'bus-15'}, // 292
++            { osm_id: 2870058034, name: 'Intermodal bus stop',icon: 'bus-45'}, // 292
 +            { osm_id: 974730957, icon: 'bus-45'}, // 144
 +            { osm_id: 469474242, icon: 'bus-45'}, // 71
 +            { osm_id: 469474241, icon: 'bus-45'},  //56
-             { osm_id: 1304074112, name: 'Airport bus stop',icon: 'airport-45'}, // 188
++            { osm_id: 1304074112, name: 'Airport bus stop',icon: 'bus-45'}, // 188
+             { osm_id: 999522025, name: 'ATM'}, // ATM machine
          ],
 +        /* list of routes to render */
 +        routes : [
 +            {
 +                from: 2870058034,
 +                to: 469474241,
 +                title: 'Sample route',
 +                color: '#f00'
 +            }
 +        ],
          /* Basemap Styles
          OpenMapTiles https://openmaptiles.github.io/positron-gl-style/style-cdn.json
          CARTO https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json
@@@ -122,48 -115,313 +125,298 @@@
              'description',
              'shop','amenity','wheelchair',
              'highway', 'network', 'bench', 'shelter', 'ref',
-             'adr:street',
+             'adr:street', 'picture',
              'website','wikidata','wikipedia'
          ]
++<<<<<<< HEAD
++=======
+         ;
+ </script>
+ 
+ <script>
+     /* Functions and helpers */
+     var overpass_url = 'https://overpass-api.de/api/interpreter',
+         /* from https://www.npmjs.com/package/geojson-polygon-center */
+         polygon_center = function (polygon) {
+             var minx = miny = 1000,
+                 maxx = maxy = -1000
+             polygon = polygon[0]
+             for (var i = 0; i < polygon.length; i++) {
+                 var point = polygon[i]
+                 var x = point[0]
+                 var y = point[1]
+ 
+                 if (x < minx) minx = x
+                 else if (x > maxx) maxx = x
+                 if (y < miny) miny = y
+                 else if (y > maxy) maxy = y
+             }
+ 
+             return {
+                 type: 'Point',
+                 coordinates: [
+                 minx + ((maxx - minx) / 2),
+                 miny + ((maxy - miny) / 2)
+                 ]
+             }
+         },
+         /* helper to get the list of ids */
+         get_ids = function(el){
+             return typeof el == "number" ? el : el['osm_id'];
+         },
+         /* takes a feature, and augment it with any custom properties 
+            passed on thi list of nodes and ways */
+         get_props = function(feature){
+             var /* filter checker */
+                 filter_node = function(node){
+                     return typeof node != "number" && node['osm_id'] == feat_id;
+                 },
+                 properties = feature['properties'],
+                 /* feature id */
+                 feat_id = properties['id'],
+                 /* candidates */
+                 candidate = osm_nodes.filter(filter_node)
+                                 .concat(osm_ways.filter(filter_node));
+ 
+             if (candidate.length == 1){
+                 properties = Object.assign(properties,candidate[0]);
+             };
+ 
+             return feature;
+         },
+         /* Generate a valid OSM Overpass API request */
+         get_osm_query = function(){
+             var ways = osm_ways.map(get_ids).join(',');
+             var nodes = osm_nodes.map(get_ids).join(',');
+ 
+             return `[out:xml][timeout:300];
+                     (
+                         way(id:${ways});
+                         node(id:${nodes});
+                     )->.a;
+                     (.a; .a >;);out qt;`
+         }
+         /* moves tags up to the main properties function */
+         tags_to_props = function(feature){
+             properties = feature['properties']
+             tags = properties['tags'];
+             Object.assign(properties, tags);
+             delete properties['tags'];
+ 
+             if (properties['id'] == undefined){
+                 properties['id'] = String(feature['id'])
+             } else {
+                 properties['id'] = String(properties['id'])
+             };
+ 
+             // Override the name in Engish, if it exists
+             if (properties['name:en'] != undefined){
+                 properties['name'] = properties['name:en']
+             };
+ 
+             return feature
+         },
+         /* transforms OSM data into geojson and adds that as
+            points and labels to the map */
+         load_osm_data = function(data){
+             console.log('loading data...');
+             var  // Convert to GeoJSON
+                 geojson_data = osmtogeojson(data),
+                 // Filter ways
+                 polys_geojson = geojson_data.features.filter(function(feature){
+                     return feature.properties.type == "way"
+                 }),
+                 // Filter points
+                 points_geojson = geojson_data.features.filter(function(feature){
+                     return feature.properties.type == "node"
+                 }),
+                 // Generate centroids for points
+                 polys_geojson_points = polys_geojson.map(function(poly){
+                     copy = JSON.parse(JSON.stringify(poly));
+                     copy['geometry'] = polygon_center(copy.geometry.coordinates);
+                     return copy
+                 }),
+                 // Get together both set of points
+                 all_features = points_geojson.concat(polys_geojson_points),
+                 // Get all properties out from the tags
+                 points_geojson_props = all_features.map(tags_to_props),
+                 // Override any custom properties
+                 final_points = points_geojson_props.map(get_props);
+ 
+             // Build final geojson collection
+             return {
+                         'type': 'FeatureCollection',
+                         'features': final_points
+             };           
+         },
+         /* Loads the data retrieved into a mapboxgl map */
+         add_layers = function(map, data){
+             map.loadImage(icon, function(error, image) {
+                 if (error) throw error;
+                 map.addImage('gnome', image);
+ 
+                 /* Icon layer */
+                 map.addLayer({
+                     'id': 'guadec_icon',
+                     'type': 'symbol',
+                     'source': {
+                         'type': 'geojson',
+                         'data': geojson_data
+                     },
+                     'layout': {
+                         "symbol-placement": "point",
+                         "text-field": '{name}' ,
+                         "icon-image": "gnome",
+                         "text-font": ["Open Sans Regular"],
+                         "icon-allow-overlap": true,
+                         "text-offset": [.3,.3],
+                         "text-anchor": "top-left",
+                         "text-max-width": 5,
+                         "text-justify": "left",
+                         "text-allow-overlap": false,
+                         "text-optional": true,
+                         "icon-size": {
+                             "stops": [
+                                 [0, 0.10],
+                                 [12, 0.12],
+                                 [14, 0.15],
+                                 [18, 0.25]
+                             ]
+                         },
+                         "text-size": {
+                             "stops": [
+                                 [0, 0],
+                                 [9,0],
+                                 [12, 15],
+                                 [16, 20]
+                             ]
+                         }
+                     },
+                     'paint': {
+                         "text-color": main_color,
+                         "icon-opacity": 1,
+                         "text-opacity": {
+                             "stops": [
+                                 [0, 0],
+                                 [9,0],
+                                 [12, 1]
+                             ]
+                         },
+                         "text-halo-color": "white",
+                         "text-halo-width": 1.5,
+                         "text-halo-blur": 1
+                     }
+                 },'place_hamlet');
+             }); 
+         };
+ </script>
+ 
+ <script>
+     /* SCRIPT */
+     var geojson_data = {},
+         map = new mapboxgl.Map({
+             container: 'map',
+             style: basemap_style,
+             center: center,
+             zoom: zoom,
+             attributionControl: true
+         });
+     
+     /*Once map is loaded, get data from OSM to add as a new layer */
+     map.on('load', function() {
+         console.log('fetching osm data...')
+         fetch(overpass_url,{
+             method: "POST",
+             body:  get_osm_query()})
+             .then(response => response.text())
+             .then(str => (new window.DOMParser()).parseFromString(str, "text/xml"))
+             .then(function(data){
+                 // Get the geojson to work
+                 geojson_data = load_osm_data(data);
+                 console.log(geojson_data);
+                 // Add it as a layer
+                 add_layers(map,geojson_data);
+             })
+             .catch(error => console.log("Error:", error));
+     });
+ 
+     /* Navigation control */
+     map.addControl(new mapboxgl.NavigationControl());
+ 
+     /* Popup up singleton */
+     var tooltip = new mapboxgl.Popup({   
+         closeButton: false,
+         closeOnClick: true,
+         anchor: "top",
+         offset: [0, 8]
+         });
+     
+     // helper to render the properties
+     var get_properties_list = function(properties){
+         return popup_properties.filter(function(key){
+                 return (Object.keys(properties).findIndex(x => x == key) > -1)
+             })
+             .map(function(key){
+                 if (key == 'website'){
+                     return `<li><a href="${properties[key]}">${key}</a></li>`
+                 } else if (key == 'wikidata'){
+                     return `<li><a href="https://www.wikidata.org/wiki/${properties[key]}";>${key}</a></li>`
+                 } else if (key == 'wikipedia'){
+                     return `<li><a href="https://en.wikipedia.org/wiki/${properties[key]}";>${key}</a></li>`
+                 } else if (key == 'picture'){
+                     return `<li><a href="${properties[key]}">${key}</a></li>`
+                 } else {
+                     return `<li><strong>${key}</strong>: ${properties[key]}</li>`
+                 }
+             }).join('')
++>>>>>>> master
      };
  
 -    var interactivity_handler = function(location,is_tooltip){
 -        var features = map.queryRenderedFeatures(location.point, {
 -            layers: ['guadec_icon']
 -        });
 -        tooltip.remove();
 +    (async function() {
  
 -        if (features != ''){
 -            popup = null;
 -            var feature = features[0];
 +        var guadec_map = new GuadecMap(options);
 +        var map = null;
  
 -            if (is_tooltip){
 -                tooltip.setHTML(`<span>${feature.properties.name}</span>`)
 -                        .setLngLat(location.lngLat) 
 -                        .addTo(map);
 -            } else {
 -                popup = new mapboxgl.Popup({anchor:'bottom'})
 -                        .setHTML(`
 -                            <h3>${feature.properties.name}</h3>
 -                            <ul>
 -                            ${get_properties_list(feature.properties)}
 -                            </ul>
 -                            <p class="osm-source"><a 
href="https://www.openstreetmap.org/${feature.properties.type}/${feature.properties.id}";>Source</a></p>
 -                            `
 -                        )
 -                        .setLngLat(location.lngLat) 
 -                        .addTo(map);
 -            }                
 +        // Promise to load the map
 +        async function get_map(){
 +            return new Promise((resolve,reject)=>{
 +                map = guadec_map.init_map();
 +                map.on('load',function(){
 +                    resolve();
 +                })
 +            });
          }
 -    }
  
 -    /* Popup interactivity */
 -    map.on('click',function(location){
 -        interactivity_handler(location,false);
 -    });
 -
 -    /* Popup interactivity */
 -    map.on('mousemove',function(location){
 -        interactivity_handler(location,true);
 -    });
 +        // Promise to load the data from OSM
 +        async function get_data(){
 +            var osm_data = await guadec_map.fetch_data();
 +            return new Promise((resolve,reject)=>{
 +                var geojson_data = guadec_map.process_osm_data(osm_data);
 +                guadec_map.set_geojson_data(geojson_data);
 +                resolve();
 +            });
 +        }
  
 -    /* Filter control */
 -    document
 -        .getElementById('filter-input')
 -        .addEventListener('keyup', function(e) {
 -            function normalize(string) {
 -                return string.trim().toLowerCase();
 -            };
 +        // When map and OSM data is retrieved, we can load POIS and Routes
 +        Promise.all([
 +            get_map(),
 +            get_data()
 +        ]).then(function(){
 +            // Load the POIS
 +            guadec_map.load_pois();
 +            // Load the Routes
 +            guadec_map.load_routes();
 +        })
  
 -            // Get the value of the input
 -            var value = normalize(e.target.value);
 -            
 -            if (value == ""){
 -                // If it's empty remove the filter
 -                map.setFilter('guadec_icon', null);
 +    })();
  
 -            } else {
 -                // Filter the geojson features and get their ids
 -                ids = geojson_data.features
 -                    .filter( x =>  normalize( x['properties']['name']).match(new RegExp(value,"g")) != null)
 -                    .map(x => x['properties']['id'])
  
- </script>
++<<<<<<< HEAD
++</script>
++=======
+                 // Set the filter of the layer to match those ids
+                 map.setFilter('guadec_icon', ['match', ['get', 'id'], ids, true, false]);
+             }
+         });
+ </script>
++>>>>>>> master


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]