diff --git a/public_html/config.js b/public_html/config.js index b513b26..52b2b13 100644 --- a/public_html/config.js +++ b/public_html/config.js @@ -113,5 +113,11 @@ ShowFlags = true; // Path to country flags (can be a relative or absolute URL; include a trailing /) FlagPath = "flags-tiny/"; +// Set to true to enable the ChartBundle base layers (US coverage only) +ChartBundleLayers = true; + // Provide a Bing Maps API key here to enable the Bing imagery layer. BingMapsAPIKey = null; + +// Provide a Mapzen API key here to enable the Mapzen vector tile layer. +MapzenAPIKey = null; diff --git a/public_html/gmap.html b/public_html/gmap.html index 4a053fb..ffbab32 100644 --- a/public_html/gmap.html +++ b/public_html/gmap.html @@ -19,6 +19,7 @@ + diff --git a/public_html/layers.js b/public_html/layers.js new file mode 100644 index 0000000..329cd6d --- /dev/null +++ b/public_html/layers.js @@ -0,0 +1,173 @@ +// -*- mode: javascript; indent-tabs-mode: nil; c-basic-offset: 8 -*- +"use strict"; + +// Base layers configuration + +function createBaseLayers() { + var layers = []; + + var world = []; + var us = []; + + world.push(new ol.layer.Tile({ + source: new ol.source.OSM(), + name: 'osm', + title: 'OpenStreetMap', + type: 'base', + })); + + if (BingMapsAPIKey) { + world.push(new ol.layer.Tile({ + source: new ol.source.BingMaps({ + key: BingMapsAPIKey, + imagerySet: 'Aerial' + }), + name: 'bing_aerial', + title: 'Bing Aerial', + type: 'base', + })); + } + + if (MapzenAPIKey) { + world.push(createMapzenLayer()); + } + + if (ChartBundleLayers) { + var chartbundleTypes = { + sec: "Sectional Charts", + tac: "Terminal Area Charts", + wac: "World Aeronautical Charts", + enrl: "IFR Enroute Low Charts", + enra: "IFR Area Charts", + enrh: "IFR Enroute High Charts" + }; + + for (var type in chartbundleTypes) { + us.push(new ol.layer.Tile({ + source: new ol.source.TileWMS({ + url: 'http://wms.chartbundle.com/wms', + params: {LAYERS: type}, + projection: 'EPSG:3857', + attributions: 'Tiles courtesy of ChartBundle' + }), + name: 'chartbundle_' + type, + title: chartbundleTypes[type], + type: 'base', + group: 'chartbundle'})); + } + } + + if (world.length > 0) { + layers.push(new ol.layer.Group({ + name: 'world', + title: 'Worldwide', + layers: world + })); + } + + if (us.length > 0) { + layers.push(new ol.layer.Group({ + name: 'us', + title: 'US', + layers: us + })); + } + + return layers; +} + +function createMapzenLayer() { + // draw earth with a fat stroke; + // force water above earth + + var earthStyle = new ol.style.Style({ + fill: new ol.style.Fill({ + color: '#a06000' + }), + stroke: new ol.style.Stroke({ + color: '#a06000', + width: 5.0 + }), + zIndex: 0 + }); + + var waterStyle = new ol.style.Style({ + fill: new ol.style.Fill({ + color: '#0040a0' + }), + stroke: new ol.style.Stroke({ + color: '#0040a0', + width: 1.0 + }), + zIndex: 1 + }); + + var boundaryStyle = new ol.style.Style({ + stroke: new ol.style.Stroke({ + color: '#804000', + width: 2.0 + }), + zIndex: 2 + }); + + var dashedBoundaryStyle = new ol.style.Style({ + stroke: new ol.style.Stroke({ + color: '#804000', + width: 1.0, + lineDash: [4, 4], + }), + zIndex: 2 + }); + + var styleMap = { + earth: earthStyle, + + water: waterStyle, + basin: waterStyle, + dock: waterStyle, + lake: waterStyle, + ocean: waterStyle, + riverbank: waterStyle, + river: waterStyle, + + country: boundaryStyle, + disputed: dashedBoundaryStyle, + indefinite: dashedBoundaryStyle, + indeterminate: dashedBoundaryStyle, + line_of_control: dashedBoundaryStyle + }; + + return new ol.layer.VectorTile({ + name: 'mapzen_vector', + title: 'Mapzen coastlines and water', + type: 'base', + renderMode: 'image', + renderOrder: function(a,b) { + return a.get('sort_key') - b.get('sort_key'); + }, + source: new ol.source.VectorTile({ + url: '//vector.mapzen.com/osm/earth,water,boundaries/{z}/{x}/{y}.topojson?api_key=' + MapzenAPIKey, + format: new ol.format.TopoJSON(), + attributions: [ + new ol.Attribution({ + html: 'Tiles courtesy of Mapzen' + }), + new ol.Attribution({ + html: '© OpenStreetMap contributors' + }) + ], + + tileGrid: ol.tilegrid.createXYZ({ + preload: 3, + maxZoom: 14, + tileSize: [512, 512] + }), + + wrapX: true + }), + + style: function (feature) { + return (styleMap[feature.get('kind')]); + } + }); +} diff --git a/public_html/script.js b/public_html/script.js index 5819386..2977d7a 100644 --- a/public_html/script.js +++ b/public_html/script.js @@ -316,10 +316,6 @@ function end_load_history() { } -function generic_gettile(template, coord, zoom) { - return template.replace('{x}', coord.x).replace('{y}', coord.y).replace('{z}', zoom) -} - // Initalizes the map and starts up our timers to call various functions function initialize_map() { // Load stored map settings if present @@ -348,122 +344,58 @@ function initialize_map() { // Initialize OL3 - var baseLayerGroups = { - 'world': new ol.layer.Group({ - title: 'Worldwide' - }), + var layers = createBaseLayers(); + var foundType = false; - 'chartbundle': new ol.layer.Group({ - title: 'ChartBundle (US)' - }) - }; + ol.control.LayerSwitcher.forEachRecursive(layers, function(lyr) { + if (lyr.get('type') !== 'base') + return; - var baseLayers = [] - - baseLayers.push(new ol.layer.Tile({ - source: new ol.source.OSM(), - name: 'osm', - title: 'OpenStreetMap', - type: 'base', - group: 'world' - })); - - if (BingMapsAPIKey) { - baseLayers.push(new ol.layer.Tile({ - source: new ol.source.BingMaps({ - key: BingMapsAPIKey, - imagerySet: 'Aerial' - }), - name: 'bing_aerial', - title: 'Bing Aerial', - type: 'base', - group: 'world' - })); - } - - var chartbundleTypes = { - sec: "Sectional Charts", - tac: "Terminal Area Charts", - wac: "World Aeronautical Charts", - enrl: "IFR Enroute Low Charts", - enra: "IFR Area Charts", - enrh: "IFR Enroute High Charts" - }; - - for (var type in chartbundleTypes) { - baseLayers.push(new ol.layer.Tile({ - source: new ol.source.TileWMS({ - url: 'http://wms.chartbundle.com/wms', - params: {LAYERS: type}, - projection: 'EPSG:3857', - attributions: 'Tiles courtesy of ChartBundle' - }), - name: 'chartbundle_' + type, - title: chartbundleTypes[type], - type: 'base', - group: 'chartbundle'})); - } - - var layers = []; - var found = false; - for (var i = 0; i < baseLayers.length; ++i) { - var layer = baseLayers[i]; - if (MapType === layer.get('name')) { - found = true; - layer.setVisible(true); + if (MapType === lyr.get('name')) { + foundType = true; + lyr.setVisible(true); } else { - layer.setVisible(false); + lyr.setVisible(false); } - layer.on('change:visible', function(evt) { + lyr.on('change:visible', function(evt) { if (evt.target.getVisible()) { MapType = localStorage['MapType'] = evt.target.get('name'); } }); + }) - // The layer selector displays in reverse order for some reason, unreverse it - if (layer.get('group')) { - // hurf - baseLayerGroups[layer.get('group')].getLayers().insertAt(0, layer); - } else { - layers.unshift(layer); - } + if (!foundType) { + layers[0].setVisible(true); } - if (!found) { - baseLayers[0].setVisible(true); - } - - for (var key in baseLayerGroups) { - if (baseLayerGroups[key].getLayers().getLength() > 0) { - layers.unshift(baseLayerGroups[key]); - } - } - - layers.push(new ol.layer.Vector({ - source: new ol.source.Vector({ - features: StaticFeatures, - updateWhileInteracting: true, - updateWhileAnimating: true - }) - })); - - layers.push(new ol.layer.Vector({ - source: new ol.source.Vector({ - features: PlaneTrailFeatures, - updateWhileInteracting: true, - updateWhileAnimating: true - }) - })); - var iconsLayer = new ol.layer.Vector({ + title: 'Aircraft positions', source: new ol.source.Vector({ features: PlaneIconFeatures, - updateWhileInteracting: true, - updateWhileAnimating: true }) }); - layers.push(iconsLayer); + + layers.push(new ol.layer.Group({ + title: 'Overlays', + layers: [ + iconsLayer, + + new ol.layer.Vector({ + title: 'Site position and range rings', + source: new ol.source.Vector({ + features: StaticFeatures, + }) + }), + + new ol.layer.Vector({ + title: 'Selected aircraft trail', + source: new ol.source.Vector({ + features: PlaneTrailFeatures, + }) + }), + ] + })); OLMap = new ol.Map({ target: 'map_canvas',