opened by  (2017-08-11 01:32:45+00:00): <!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
    <meta name="ICBM" content="42.67417, 23.36806">
    <meta name="description" content="Bulgaria TOPO">
    <meta name="keywords" content="Bulgaria, topo, map, vector, garmin, free, BGMountains, BGtopoVJ">
    <meta name="robots" content="index,follow">
    <meta name="GOOGLEBOT" content="index,FOLLOW">
    <meta name="author" content="Vedrin Jeliazkov">
    <meta name="revisit-after" content="7">
    <script src="ol3-20150621/jquery.min.js"></script>
    <link rel="stylesheet" href="ol3-20150621/bootstrap.min.css">
    <script src="ol3-20150621/bootstrap.min.js"></script>
    <link rel="stylesheet" href="ol3-20150621/ol.css" type="text/css">
    <script src="ol3-20150621/ol.js"></script>
    <link rel="stylesheet" href="ol3-20150621/ol3-layerswitcher.css" />
    <script src="ol3-20150621/ol3-layerswitcher.js"></script>
    <script src="ol3-20150621/FileSaver.min.js"></script>
    <style>
      .alert {
        position: fixed;
        top: 24px;
        right: 8px;
        float: right;
        opacity: 0.8;
        background: #ffffff;
        background: rgba(255,255,255,0.8);
        padding: 2px;
        border-radius: 4px;
        font-size: 10px;
        color: #00000;
        text-align: right;
        margin: 0px;
      }
      .map {
        position: fixed;
        height: 100%;
        width: 100%;
        left: 0;
        top: 0;
        overflow: hidden;
        -ms-touch-action: none;
        touch-action: none;
      }
      .links {
        position: absolute;
        margin: auto;
        top: 8px;
        left: 46px;
        text-align: center;
        opacity: 0.8;
        background: #ffffff;
        background: rgba(255,255,255,0.8);
        padding: 4px;
        border-radius: 4px;
        font-size: 10px;
        color: #00000;
      }
      .location {
        position: fixed;
        bottom: 8px;
        left: 46%;
        opacity: 0.8;
        background: #ffffff;
        background: rgba(255,255,255,0.8);
        border-radius: 4px;
        font-size: 11px;
        color: #00000;
        margin: 0px;
        padding: 0px;
      }
      .ol-mouse-position {
        font-size: 11px;
        font-weight: bold;
      }
    </style>
    <title>BGMountains&nbsp;&bull;&nbsp;BGtopoVJ</title>
  </head>
  <body>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
      ga('create', 'UA-5778466-3', 'auto');
      ga('send', 'pageview');
    </script>
    <div id="map" class="map" tabindex="0"></div>
    <div id="info" class="alert"></div>
    <div id="links" class="links">
      <a id="browse" href="/">Browse</a>
      &bull;
      <a id="area" href="area.html">Area</a>
      &bull; 
      <a id="distance" href="distance.html">Distance</a>
      &bull;
      <a id="route" href="route.html">Route</a>
      &bull;
      <a id="save-link" href="#">Save</a>
    </div>
    <div id="location" class="location">
      <label for="track">&nbsp;<input id="track" type="checkbox"/>
      &nbsp;Position&nbsp;<br>
      &nbsp;H [<i>m</i>]:<code id="altitude"></code><br>
      &nbsp;V [<i>km/h</i>]:<code id="speed"></code>&nbsp;</label>
    </div>
    <script type="text/javascript">
    var zoom = 8;
    var center = [2810000, 5250000];
    var rotation = 0;    
    if (window.location.hash !== '') {
      var hash = window.location.hash.replace('#map=', '');
      var parts = hash.split('/');
      if (parts.length === 4) {
        zoom = parseInt(parts[0], 10);
        center = [
          parseFloat(parts[1]),
          parseFloat(parts[2])
        ];
        rotation = parseFloat(parts[3]);
      }
    }
    var defaultStyle = {
      'Point': [new ol.style.Style({
        image: new ol.style.Circle({
          fill: new ol.style.Fill({
            color: 'rgba(204,42,0,0.5)'
          }),
          radius: 5,
          stroke: new ol.style.Stroke({
            color: '#cc6600',
            width: 1
          })
        })
      })],
      'LineString': [new ol.style.Style({
        stroke: new ol.style.Stroke({
          color: '#f00',
          width: 3
        })
      })],
      'Polygon': [new ol.style.Style({
        fill: new ol.style.Fill({
          color: 'rgba(0,255,255,0.5)'
        }),
        stroke: new ol.style.Stroke({
          color: '#0ff',
          width: 1
        })
      })],
      'MultiPoint': [new ol.style.Style({
        image: new ol.style.Circle({
          fill: new ol.style.Fill({
            color: 'rgba(255,0,255,0.5)'
          }),
          radius: 5,
          stroke: new ol.style.Stroke({
            color: '#f0f',
            width: 1
          })
        })
      })],
      'MultiLineString': [new ol.style.Style({
        stroke: new ol.style.Stroke({
          color: 'rgba(153,0,153,0.6)',
          width: 3
        })
      })],
      'MultiPolygon': [new ol.style.Style({
        fill: new ol.style.Fill({
          color: 'rgba(0,0,255,0.5)'
        }),
        stroke: new ol.style.Stroke({
          color: '#00f',
          width: 1
        })
      })]
    };
    var styleFunction = function(feature, resolution) {
      var featureStyleFunction = feature.getStyleFunction();
      if (featureStyleFunction) {
        return featureStyleFunction.call(feature, resolution);
      } else {
        return defaultStyle[feature.getGeometry().getType()];
      }
    };
    var dragAndDropInteraction = new ol.interaction.DragAndDrop({
      formatConstructors: [
        ol.format.GPX,
        ol.format.GeoJSON,
        ol.format.IGC,
        ol.format.KML,
        ol.format.TopoJSON
      ]
    });
    var map = new ol.Map({
      logo: false,
      loadTilesWhileInteracting: true,
      interactions: ol.interaction.defaults().extend([dragAndDropInteraction]),
      controls: ol.control.defaults().extend([
        new ol.control.ScaleLine({
        units: 'metric'
        }),
        new ol.control.MousePosition({
          projection: 'EPSG:4326',
          coordinateFormat: ol.coordinate.createStringXY(6)
        })
      ]),
      layers: [
            new ol.layer.Tile({
              title: 'Bing Maps',
              type: 'base',
              visible: false,
              preload: Infinity,
              source: new ol.source.BingMaps({
                key: 'ArWfnxvEPy_H9zkO0YJm1_5qwSZYCfWSwGQoVxFi5TLiOmUf1jUUSvSPv9uGyu8A',
                imagerySet: 'AerialWithLabels'
              })
            }),
            new ol.layer.Tile({
              title: 'Sentinel-2',
              type: 'base',
              visible: false,
              preload: Infinity,
              source: new ol.source.TileWMS(/** @type {olx.source.TileWMSOptions} */ ({
                attributions: [
                  new ol.Attribution({
                    html: '<a href="https://sentinel.esa.int/documents/247904/690755/Sentinel_Data_Legal_Notice" target="_blank">Contains modified Copernicus Sentinel data [2015-2016]</a>' +
                          ' / ' +
                          '<a href="http://cart.uni-plovdiv.net/" target="_blank">CART Lab</a>' +
                          ' / ' +
                          '<a href="https://plus.google.com/117738982997877636232?rel=author" target="_blank">Vedrin Jeliazkov</a>'
                  })
                ],
                url: 'https://kade.si/cgi-bin/mapserv?',
                params: {'LAYERS': 'Sentinel-2', 'TILED': true, 'format': 'image/png'}
              }))
            }),
            new ol.layer.Tile({
              title: 'Landsat-8',
              type: 'base',
              visible: false,
              preload: Infinity,
              source: new ol.source.TileWMS(/** @type {olx.source.TileWMSOptions} */ ({
                attributions: [
                  new ol.Attribution({
                    html: '<a href="http://landsat.gsfc.nasa.gov/?page_id=4071" target="_blank">Landsat 8</a>' +
                          ' / ' +
                          '<a href="http://cart.uni-plovdiv.net/" target="_blank">CART Lab</a>' +
                          ' / ' +
                          '<a href="https://plus.google.com/117738982997877636232?rel=author" target="_blank">Vedrin Jeliazkov</a>'
                  })
                ],
                url: 'https://kade.si/cgi-bin/mapserv?',
                params: {'LAYERS': 'Landsat-8', 'TILED': true, 'format': 'image/png'}
              }))
            }),
            new ol.layer.Tile({
              title: 'OpenTopoMap',
              type: 'base',
              visible: false,
              preload: Infinity,
              source: new ol.source.OSM({
                attributions: [
                  new ol.Attribution({
                    html: '&copy; <a href="http://www.openstreetmap.org/copyright" target="_blank">OpenStreetMap</a> contributors' +
                          ' / ' +
                          '<a href="https://opentopomap.org" target="_blank">OpenTopoMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/" target="_blank">CC-BY-SA</a>)'
                  })
                ],
                url: 'https://opentopomap.org/{z}/{x}/{y}.png',
                crossOrigin: null
              })
            }),
            new ol.layer.Tile({
              title: 'OSMap',
              type: 'base',
              visible: false,
              preload: Infinity,
              source: new ol.source.OSM({
                attributions: [
                  new ol.Attribution({
                    html: '&copy; <a href="http://www.openstreetmap.org/copyright" target="_blank">OpenStreetMap</a> contributors' +
                          ' / ' +
                          '<a href="http://osmap.org/" target="_blank">OSMap</a>' +
                          ' / ' +
                          '<a href="http://maps.igurbev.net/" target="_blank">Garmin version</a>' +
                          ' / ' +
                          '<a href="http://blog.igurbev.net/" target="_blank">Blog</a>'
                  })
                ],
                url: 'http://osmap.org/tile/{z}/{x}/{y}.png',
                crossOrigin: null
              })
            }),
            new ol.layer.Tile({
              title: 'OpenStreetMap',
              type: 'base',
              visible: false,
              preload: Infinity,
              source: new ol.source.OSM()
            }),
            new ol.layer.Tile({
              title: 'Tourist Map',
              type: 'base',
              visible: false,
              preload: Infinity,
              source: new ol.source.OSM({
                attributions: [
                  new ol.Attribution({
                    html: '&copy; <a href="https://www.seznam.cz/" target="_blank">Seznam.cz a.s.</a>' +
                          ' / ' +
                          '&copy;<a href="http://www.openstreetmap.org/copyright" target="_blank">OpenStreetMap</a>'
                  })
                ],
                url: 'https://m3.mapserver.mapy.cz/wturist-m/{z}-{x}-{y}.png',
                crossOrigin: null
              })
            }),
            new ol.layer.Tile({
              title: 'BGtopo-126k',
              type: 'base',
              visible: false,
              preload: Infinity,
              source: new ol.source.TileWMS(/** @type {olx.source.TileWMSOptions} */ ({
                attributions: [
                  new ol.Attribution({
                    html: '<a href="http://cart.uni-plovdiv.net/" target="_blank">CART Lab</a>' +
                          ' / ' +
                          '<a href="https://plus.google.com/117738982997877636232?rel=author" target="_blank">Vedrin Jeliazkov</a>'
                  })
                ],
                url: 'https://kade.si/cgi-bin/mapserv?',
                params: {'LAYERS': 'BGtopo-126k', 'TILED': true, 'format': 'image/png'}
              }))
            }),
            new ol.layer.Tile({
              title: 'BGtopo-1933',
              type: 'base',
              visible: false,
              preload: Infinity,
              source: new ol.source.TileWMS(/** @type {olx.source.TileWMSOptions} */ ({
                attributions: [
                  new ol.Attribution({
                    html: '<a href="http://cart.uni-plovdiv.net/" target="_blank">CART Lab</a>' +
                          ' / ' +
                          '<a href="https://plus.google.com/117738982997877636232?rel=author" target="_blank">Vedrin Jeliazkov</a>'
                  })
                ],
                url: 'https://kade.si/cgi-bin/mapserv?',
                params: {'LAYERS': 'BGtopo-1933', 'TILED': true, 'format': 'image/png'}
              }))
            }),
            new ol.layer.Tile({
              title: 'BGtopoVJ-v3.00',
              type: 'base',
              visible: false,
              preload: Infinity,
              source: new ol.source.TileWMS(/** @type {olx.source.TileWMSOptions} */ ({
                attributions: [
                  new ol.Attribution({
                    html: '<a href="http://cart.uni-plovdiv.net/" target="_blank">CART Lab</a>' +
                          ' / ' +
                          '<a href="https://plus.google.com/117738982997877636232?rel=author" target="_blank">Vedrin Jeliazkov</a>'
                  })
                ],
                url: 'https://kade.si/cgi-bin/mapserv?',
                params: {'LAYERS': 'BGtopoVJ-raster-v3.00', 'TILED': true, 'format': 'image/png'}
              }))
            }),
            new ol.layer.Tile({
              title: 'BGMountains',
              type: 'base',
              visible: true,
              preload: Infinity,
              source: new ol.source.OSM ({
                attributions: [
                  new ol.Attribution({
                    html: '<a href="http://cart.uni-plovdiv.net/" target="_blank">CART Lab</a>' +
                          ' / ' +
                          '<a href="http://www.bgmountains.org/" target="_blank">BGM team</a>' +
                          ' / ' +
                          '<a href="http://bgmountains.org/en/maps/garmin-maps/category/9-bgmountains/" target="_blank">Garmin version</a>'
                  })
                ],
                url: 'https://bgmtile.kade.si/{z}/{x}/{y}.png',
                crossOrigin: null
              })
            })
      ],
      renderer: 'canvas',
      target: 'map',
      view: new ol.View({
        minZoom: 4,
        maxZoom: 19,
        center: center,
        zoom: zoom,
        rotation: rotation
      })
    });    
    var shouldUpdate = true;
    var view = map.getView();
    var updatePermalink = function() {
      if (!shouldUpdate) {
        shouldUpdate = true;
        return;
      }
      var center = view.getCenter();
      var hash = '#map=' +
          view.getZoom() + '/' +
          Math.round(center[0] * 100) / 100 + '/' +
          Math.round(center[1] * 100) / 100 + '/' +
          view.getRotation();
      document.getElementById("browse").href = '/' + hash
      document.getElementById("area").href = 'area.html' + hash
      document.getElementById("distance").href = 'distance.html' + hash
      document.getElementById("route").href = 'route.html' + hash
      var state = {
        zoom: view.getZoom(),
        center: view.getCenter(),
        rotation: view.getRotation()
      };
      window.history.pushState(state, 'map', hash);
    };
    map.on('moveend', updatePermalink);
    window.addEventListener('popstate', function(event) {
      if (event.state === null) {
        return;
      }
      map.getView().setCenter(event.state.center);
      map.getView().setZoom(event.state.zoom);
      map.getView().setRotation(event.state.rotation);
      shouldUpdate = false;
    });
    var layerSwitcher = new ol.control.LayerSwitcher({
    });
    map.addControl(layerSwitcher);
    dragAndDropInteraction.on('addfeatures', function(event) {
      var vectorSource = new ol.source.Vector({
        features: event.features
      });
      map.addLayer(new ol.layer.Image({
        source: new ol.source.ImageVector({
          source: vectorSource,
          style: styleFunction
        })
      }));
      map.getView().fitExtent(
          vectorSource.getExtent(), /** @type {ol.Size} */ (map.getSize()));
    });
    var displayFeatureInfo = function(pixel) {
      var features = [];
      map.forEachFeatureAtPixel(pixel, function(feature, layer) {
        features.push(feature);
      });
      if (features.length > 0) {
        var info = [];
        var i, ii;
        for (i = 0, ii = features.length; i < ii; ++i) {
          info.push(features[i].get('name'));
        }
        document.getElementById('info').innerHTML = info.join(', ') || '&nbsp';
      } else {
        document.getElementById('info').innerHTML = '&nbsp;';
      }
    };
    map.on('pointermove', function(evt) {
      if (evt.dragging) {
        return;
      }
      var pixel = map.getEventPixel(evt.originalEvent);
      displayFeatureInfo(pixel);
    });    
    map.on('click', function(evt) {
      displayFeatureInfo(evt.pixel);
    });
    var geolocation = new ol.Geolocation({
      projection: view.getProjection(),
      trackingOptions: {
        maximumAge: 1000,
        enableHighAccuracy: true,
        timeout: 300000
      }
    });
    function el(id) {
      return document.getElementById(id);
    }
    el('track').addEventListener('change', function() {
      geolocation.setTracking(this.checked);
    });
    geolocation.on('change', function() {
      el('altitude').innerText = geolocation.getAltitude() || 0;
      el('speed').innerText = (((geolocation.getSpeed()) || 0) * 3.6).toFixed(1);
      map.getView().setCenter(geolocation.getPosition());
    });
    geolocation.on('error', function(error) {
      var info = document.getElementById('info');
      info.innerHTML = error.message;
      info.style.display = '';
    });
    var accuracyFeature = new ol.Feature();
    geolocation.on('change:accuracyGeometry', function() {
      accuracyFeature.setGeometry(geolocation.getAccuracyGeometry());
    });
    var positionFeature = new ol.Feature();
    positionFeature.setStyle(new ol.style.Style({
      image: new ol.style.Circle({
        radius: 6,
        fill: new ol.style.Fill({
          color: '#3399CC'
        }),
        stroke: new ol.style.Stroke({
          color: '#fff',
          width: 2
        })
      })
    }));
    geolocation.on('change:position', function() {
      var coordinates = geolocation.getPosition();
      positionFeature.setGeometry(coordinates ?
          new ol.geom.Point(coordinates) : null);
    });
    var featuresOverlay = new ol.FeatureOverlay({
      map: map,
      features: [accuracyFeature, positionFeature]
    });    
    var featureOverlay = new ol.FeatureOverlay({
      style: new ol.style.Style({
        fill: new ol.style.Fill({
          color: 'rgba(255, 255, 255, 0.2)'
        }),
        stroke: new ol.style.Stroke({
          color: '#ffcc33',
          width: 2
        }),
        image: new ol.style.Circle({
          radius: 7,
          fill: new ol.style.Fill({
            color: '#ffcc33'
          })
        })
      })
    });
    featureOverlay.setMap(map);
    var modify = new ol.interaction.Modify({
      features: featureOverlay.getFeatures(),
      deleteCondition: function(event) {
        return ol.events.condition.shiftKeyOnly(event) &&
            ol.events.condition.singleClick(event);
      }
    });
    map.addInteraction(modify);
    var draw;
    function addInteraction() {
      draw = new ol.interaction.Draw({
        features: featureOverlay.getFeatures(),
        type: /** @type {ol.geom.GeometryType} */ 'Point'
      });
      map.addInteraction(draw);
    }
    addInteraction();
    var today = new Date();
    var myFileName = "route-" + today.getFullYear() + "-" + today.getMonth() + "-" + today.getDate() + ".kml";
    $('#save-link').click(function() {
        var features = featureOverlay.getFeatures().getArray();
        var format = new ol.format.GPX();
        var result = format.writeFeatures(features, {featureProjection: 'EPSG:3857'});
        result = result.replace('<gpx xmlns="http://www.topografix.com/GPX/1/1">','<?xml version="1.0" encoding="UTF-8"?><gpx version="1.0" creator="BGMountains - https://kade.si/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.topografix.com/GPX/1/0" xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd">');
        var blob = new Blob([result], {type: "text/plain;charset=utf-8;"});
        datetime = new Date().toISOString();        
        var myFileName = 'wpt-' + datetime + '.gpx';
        saveAs(blob, myFileName);
    });
    document.getElementById('map').focus();
    </script>
  </body>
</html>