From 4f69a443d99c4c32df8d40998b4e9629a9d9c883 Mon Sep 17 00:00:00 2001 From: David Manthey Date: Mon, 6 Jun 2016 11:20:51 -0400 Subject: [PATCH 1/3] Create layers based on a list of features. --- examples/choropleth/main.js | 10 ++-- examples/contour/main.js | 12 ++-- examples/deepzoom/main.js | 3 +- examples/dynamicData/main.js | 4 +- examples/geoJSON/main.js | 5 +- examples/heatmap/main.js | 2 +- examples/hurricanes/main.js | 4 +- examples/quads/main.js | 3 +- examples/reprojection/main.js | 2 +- examples/tiles/index.jade | 3 +- examples/tiles/main.js | 6 +- examples/transitions/main.js | 2 +- examples/vectors/main.js | 2 +- src/canvas/quadFeature.js | 2 +- src/d3/lineFeature.js | 2 +- src/d3/quadFeature.js | 2 +- src/gl/lineFeature.js | 2 +- src/gl/quadFeature.js | 2 +- src/layer.js | 7 ++- src/mapInteractor.js | 10 ++++ src/osmLayer.js | 4 +- src/registry.js | 103 +++++++++++++++++++++++++++++----- tests/cases/registry.js | 29 ++++++++++ tests/test-utils.js | 2 +- 24 files changed, 174 insertions(+), 49 deletions(-) create mode 100644 tests/cases/registry.js diff --git a/examples/choropleth/main.js b/examples/choropleth/main.js index 329afccd91..9eb60c939f 100644 --- a/examples/choropleth/main.js +++ b/examples/choropleth/main.js @@ -31,11 +31,13 @@ $(function () { 'osm' ); - // Create a gl feature layer - var vglLayer = map.createLayer( + // Create a feature layer. We could either ask for a layer via a specific + // render {renderer: 'vgl'} or for a layer that supports our feature + // {features: ['choropleth']}. + var choroplethLayer = map.createLayer( 'feature', { - renderer: 'vgl' + features: ['choropleth'] } ); @@ -57,7 +59,7 @@ $(function () { }); var choropleth = - makeChoropleth(geoData.features, mockScalarData, vglLayer); + makeChoropleth(geoData.features, mockScalarData, choroplethLayer); setTimeout(function () { var mockScalarData2 = geoData diff --git a/examples/contour/main.js b/examples/contour/main.js index 147eaab1d9..aa93d81ff4 100644 --- a/examples/contour/main.js +++ b/examples/contour/main.js @@ -66,11 +66,11 @@ $(function () { 'osm' ); - // Create a gl feature layer - var vglLayer = map.createLayer( + // Create a feature layer that supports contours + var contourLayer = map.createLayer( 'feature', { - renderer: 'vgl' + features: ['contour'] } ); @@ -78,15 +78,15 @@ $(function () { $.ajax({ url: '../../data/oahu.json', success: function (data) { - var contour = makeContour(data, vglLayer); + var contour = makeContour(data, contourLayer); contour.draw(); /* After 10 second, load a denser data set */ window.setTimeout(function () { $.ajax({ url: '../../data/oahu-dense.json', success: function (data) { - vglLayer.deleteFeature(contour); - contour = makeContour(data, vglLayer, contour); + contourLayer.deleteFeature(contour); + contour = makeContour(data, contourLayer, contour); contour.draw(); } }); diff --git a/examples/deepzoom/main.js b/examples/deepzoom/main.js index f34149f636..3ff947f9f6 100644 --- a/examples/deepzoom/main.js +++ b/examples/deepzoom/main.js @@ -45,7 +45,6 @@ $(function () { // Add the osm layer with a custom tile url map.createLayer( - 'tiledFish', - {renderer: 'vgl'} + 'tiledFish' ); }); diff --git a/examples/dynamicData/main.js b/examples/dynamicData/main.js index d69e9d8f29..56943cd096 100644 --- a/examples/dynamicData/main.js +++ b/examples/dynamicData/main.js @@ -19,7 +19,9 @@ $(function () { baseUrl: 'http://otile1.mqcdn.com/tiles/1.0.0/sat' }); - // Add a feature layer with a D3 renderer + // Add a feature layer with a D3 renderer. We could, instead, ask for any + // renderer that supports point features, like so: + // var features = map.createLayer('feature', {features: ['point']}); var features = map.createLayer('feature', {renderer: 'd3'}); var numberOfFeatures = 200; diff --git a/examples/geoJSON/main.js b/examples/geoJSON/main.js index 161514e110..489199aa4b 100644 --- a/examples/geoJSON/main.js +++ b/examples/geoJSON/main.js @@ -20,8 +20,9 @@ $(function () { } ); - // Create a gl layer to put the features in - var layer = map.createLayer('feature'); + // Create a layer to put the features in. We could need point, line, and + // polygon features, so ask for a layer that supports all of them. + var layer = map.createLayer('feature', {features: ['point', 'line', 'polygon']}); map.draw(); // Initialize the json reader. diff --git a/examples/heatmap/main.js b/examples/heatmap/main.js index 5bc06e74ff..417654186e 100644 --- a/examples/heatmap/main.js +++ b/examples/heatmap/main.js @@ -13,7 +13,7 @@ $(function () { var layer, heatmap, points, datapoints; var layerOptions = { - renderer: 'canvas', + features: ['heatmap'], opacity: 0.75 }; var heatmapOptions = { diff --git a/examples/hurricanes/main.js b/examples/hurricanes/main.js index 8f47eef559..252e1c589d 100644 --- a/examples/hurricanes/main.js +++ b/examples/hurricanes/main.js @@ -369,8 +369,8 @@ $(function () { } ); - // Create a feature layer to draw on - layer = map.createLayer('feature'); + // Create a feature layer to draw on. + layer = map.createLayer('feature', {features: ['line.multicolor']}); // Create a line feature feature = layer.createFeature('line', {selectionAPI: true}); diff --git a/examples/quads/main.js b/examples/quads/main.js index 0172c8fe0d..c796b1d937 100644 --- a/examples/quads/main.js +++ b/examples/quads/main.js @@ -16,7 +16,8 @@ $(function () { zoom: 4 }); var layer = map.createLayer('feature', { - renderer: query.renderer ? (query.renderer === 'html' ? null : query.renderer) : 'vgl' + renderer: query.renderer ? (query.renderer === 'html' ? null : query.renderer) : undefined, + features: query.renderer ? undefined : ['quad'] }); var quads = layer.createFeature('quad', {selectionAPI: true}); var previewImage = new Image(); diff --git a/examples/reprojection/main.js b/examples/reprojection/main.js index f9e574c5d7..e18dc4ea6a 100644 --- a/examples/reprojection/main.js +++ b/examples/reprojection/main.js @@ -126,7 +126,7 @@ $(function () { } // Set the tile layer defaults to use the specified renderer and opacity var layerParams = { - renderer: 'vgl', + features: ['quad.img-full'], zIndex: 0, gcs: 'EPSG:3857', attribution: $('#url-list [value="' + $('#layer-url').val() + '"]').attr( diff --git a/examples/tiles/index.jade b/examples/tiles/index.jade index 5f150c1448..c67e57e5bd 100644 --- a/examples/tiles/index.jade +++ b/examples/tiles/index.jade @@ -4,7 +4,8 @@ block append mainContent div#controls .form-group(title="Tiles can be drawn using WebGL, Canvas, HTML, or SVG. WebGL is generally the fastest and HTML the most compatible.") label(for="map-renderer") Renderer - select#map-renderer.mapparam(param-name="renderer", placeholder="vgl") + select#map-renderer.mapparam(param-name="renderer", placeholder="default") + option(value="default") Default option(value="vgl") VGL (WebGL) option(value="canvas") Canvas option(value="d3") SVG (d3) diff --git a/examples/tiles/main.js b/examples/tiles/main.js index 9785a2d1f1..ac7449839e 100644 --- a/examples/tiles/main.js +++ b/examples/tiles/main.js @@ -29,6 +29,7 @@ * projection: 'parallel' or 'projection' for the camera projection. * renderer: 'vgl' (default), 'canvas', 'd3', 'null', or 'html'. This picks * the renderer for map tiles. null or html uses the html renderer. + * 'default' uses the default renderer for the user's platform. * round: 'round' (default), 'floor', 'ceil'. * subdomains: a comma-separated string of subdomains to use in the {s} part * of the url parameter. If there are no commas in the string, each letter @@ -104,7 +105,7 @@ $(function () { }; // Set the tile layer defaults to use the specified renderer and opacity var layerParams = { - renderer: query.renderer || 'vgl', + renderer: query.renderer && query.renderer !== 'default' ? query.renderer : undefined, opacity: query.opacity || '1', /* Always use a larger cache so if keepLower is changed, we still have a * big enough cache. */ @@ -340,6 +341,9 @@ $(function () { if (layerParams.renderer === 'html') { layerParams.renderer = null; } + if (layerParams.renderer === 'default') { + layerParams.renderer = undefined; + } map.deleteLayer(osmLayer); osmLayer = map.createLayer('osm', layerParams); tileDebug.osmLayer = osmLayer; diff --git a/examples/transitions/main.js b/examples/transitions/main.js index 3762a1efbf..39e3c0be1d 100644 --- a/examples/transitions/main.js +++ b/examples/transitions/main.js @@ -20,7 +20,7 @@ $(function () { // Add an OSM layer map.createLayer('osm', { baseUrl: 'http://otile1.mqcdn.com/tiles/1.0.0/map', - renderer: query.renderer ? (query.renderer === 'html' ? null : query.renderer) : 'vgl' + renderer: query.renderer ? (query.renderer === 'html' ? null : query.renderer) : undefined }); // Bind button clicks to map transitions diff --git a/examples/vectors/main.js b/examples/vectors/main.js index 534dcca8fd..c799b872c5 100644 --- a/examples/vectors/main.js +++ b/examples/vectors/main.js @@ -18,7 +18,7 @@ $(function () { // Create a gl feature layer var layer = map.createLayer( - 'feature', { renderer: 'd3' } + 'feature', {features: ['vector']} ); var routes = [ diff --git a/src/canvas/quadFeature.js b/src/canvas/quadFeature.js index a595e306f4..3b312b55e4 100644 --- a/src/canvas/quadFeature.js +++ b/src/canvas/quadFeature.js @@ -143,5 +143,5 @@ var canvas_quadFeature = function (arg) { inherit(canvas_quadFeature, quadFeature); // Now register it -registerFeature('canvas', 'quad', canvas_quadFeature); +registerFeature('canvas', 'quad', canvas_quadFeature, {clr: false, img: true, 'img-full': false}); module.exports = canvas_quadFeature; diff --git a/src/d3/lineFeature.js b/src/d3/lineFeature.js index d6c1e8d0f5..bd1aa4e030 100644 --- a/src/d3/lineFeature.js +++ b/src/d3/lineFeature.js @@ -130,6 +130,6 @@ var d3_lineFeature = function (arg) { inherit(d3_lineFeature, lineFeature); -registerFeature('d3', 'line', d3_lineFeature); +registerFeature('d3', 'line', d3_lineFeature, {basic: true, multicolor: false}); module.exports = d3_lineFeature; diff --git a/src/d3/quadFeature.js b/src/d3/quadFeature.js index 9ec227e1f8..1c6713bcd0 100644 --- a/src/d3/quadFeature.js +++ b/src/d3/quadFeature.js @@ -228,5 +228,5 @@ var d3_quadFeature = function (arg) { inherit(d3_quadFeature, quadFeature); // Now register it -registerFeature('d3', 'quad', d3_quadFeature); +registerFeature('d3', 'quad', d3_quadFeature, {clr: true, img: true, 'img-full': false}); module.exports = d3_quadFeature; diff --git a/src/gl/lineFeature.js b/src/gl/lineFeature.js index 9a5ddde53f..6746e7784a 100644 --- a/src/gl/lineFeature.js +++ b/src/gl/lineFeature.js @@ -398,6 +398,6 @@ var gl_lineFeature = function (arg) { inherit(gl_lineFeature, lineFeature); // Now register it -registerFeature('vgl', 'line', gl_lineFeature); +registerFeature('vgl', 'line', gl_lineFeature, {basic: true, multicolor: true}); module.exports = gl_lineFeature; diff --git a/src/gl/quadFeature.js b/src/gl/quadFeature.js index 726e6792c4..6fdf5ab54f 100644 --- a/src/gl/quadFeature.js +++ b/src/gl/quadFeature.js @@ -392,5 +392,5 @@ var gl_quadFeature = function (arg) { inherit(gl_quadFeature, quadFeature); // Now register it -registerFeature('vgl', 'quad', gl_quadFeature); +registerFeature('vgl', 'quad', gl_quadFeature, {clr: true, img: true, 'img-full': true}); module.exports = gl_quadFeature; diff --git a/src/layer.js b/src/layer.js index 2135bd52d0..4f0d962114 100644 --- a/src/layer.js +++ b/src/layer.js @@ -2,6 +2,7 @@ var inherit = require('./inherit'); var sceneObject = require('./sceneObject'); var feature = require('./feature'); var checkRenderer = require('./registry').checkRenderer; +var rendererForFeatures = require('./registry').rendererForFeatures; ////////////////////////////////////////////////////////////////////////////// /** @@ -30,11 +31,11 @@ var layer = function (arg) { var geo_event = require('./event'); var camera = require('./camera'); - ////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////// /** * @private */ - ////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////// var m_this = this, s_exit = this._exit, m_id = arg.id === undefined ? layer.newLayerId() : arg.id, @@ -44,7 +45,7 @@ var layer = function (arg) { m_canvas = null, m_renderer = null, m_initialized = false, - m_rendererName = arg.renderer === undefined ? 'vgl' : arg.renderer, + m_rendererName = arg.renderer === undefined ? rendererForFeatures(arg.features) : arg.renderer, m_dataTime = timestamp(), m_updateTime = timestamp(), m_sticky = arg.sticky === undefined ? true : arg.sticky, diff --git a/src/mapInteractor.js b/src/mapInteractor.js index 58612d9c78..530b5039c1 100644 --- a/src/mapInteractor.js +++ b/src/mapInteractor.js @@ -684,6 +684,7 @@ var mapInteractor = function (args) { m_this.map().deleteLayer(m_selectionLayer); m_selectionLayer = null; } + /* This can be removed once selection quads are implemented */ // Create a feature layer and plane feature to show the selection bounds m_selectionLayer = m_this.map().createLayer('feature', {renderer: 'd3'}); m_selectionPlane = m_selectionLayer.createFeature('plane'); @@ -691,6 +692,15 @@ var mapInteractor = function (args) { screenCoordinates: true, fillOpacity: function () { return 0.25; } }); + /* Use this once selection quads are implemented + m_selectionLayer = m_this.map().createLayer( + 'feature', {features: ['quad.clr']}); + m_selectionQuad = m_selectionLayer.createFeature('quad'); + m_selectionQuad.style({ + opacity: 0.25, + color: {r: 0.3, g: 0.3, b: 0.3} + }); + */ m_this.map().geoTrigger(geo_event.brushstart, m_this._getSelection()); } diff --git a/src/osmLayer.js b/src/osmLayer.js index e7b8e6291c..b94d35084f 100644 --- a/src/osmLayer.js +++ b/src/osmLayer.js @@ -80,6 +80,8 @@ module.exports = (function () { }); inherit(osmLayer, tileLayer); - registry.registerLayer('osm', osmLayer); + /* By default, ask to support image quads. If the user needs full + * reprojection, they will need to require the quad.img-full feature */ + registry.registerLayer('osm', osmLayer, ['quad.img']); return osmLayer; })(); diff --git a/src/registry.js b/src/registry.js index 977397c276..4e15158f09 100644 --- a/src/registry.js +++ b/src/registry.js @@ -3,8 +3,10 @@ var widgets = { dom: {} }; var layers = {}; +var layerDefaultFeatures = {}; var renderers = {}; var features = {}; +var featureCapabilities = {}; var fileReaders = {}; var rendererLayerAdjustments = {}; var util = {}; @@ -65,7 +67,7 @@ util.createRenderer = function (name, layer, canvas, options) { * @params {string|null} name name of the desired renderer * @params {boolean} noFallack if true, don't recommend a fallback * @return {string|null|false} the name of the renderer that should be used - * of false if no valid renderer can be determined. + * or false if no valid renderer can be determined. */ ////////////////////////////////////////////////////////////////////////////// util.checkRenderer = function (name, noFallback) { @@ -92,25 +94,94 @@ util.checkRenderer = function (name, noFallback) { ////////////////////////////////////////////////////////////////////////////// /** - * Register a new feature type + * Check if there is a renderer that is supported and supports a list of + * features. If not, display a warning. This picks the first renderer that + * supports all of the listed features. + * + * @param {array|undefined} featureList A list of features that will be used + * with this renderer. Features are the basic feature names (e.g., + * 'quad'), or the feature name followed by a required capability (e.g., + * 'quad.img'). If more than one feature or more than one capability of a + * feature is required, include each feature and capability combination in + * the list (e.g., ['quad.img', 'plane']). If no capability is specified + * for a feature (or that feature was registered without a capability + * object), then the feature will match regardless of capabilities. + * @return {string|null|false} the name of the renderer that should be used + * or false if no valid renderer can be determined. */ ////////////////////////////////////////////////////////////////////////////// -util.registerFeature = function (category, name, func) { - if (features === undefined) { - features = {}; +util.rendererForFeatures = function (featureList) { + var preferredRenderers = ['vgl', 'canvas', 'd3', null]; + + var renderer, ridx, feature, fidx, capability, available; + for (ridx = 0; ridx < preferredRenderers.length; ridx += 1) { + renderer = preferredRenderers[ridx]; + if (util.checkRenderer(renderer, true) === false) { + continue; + } + if (!featureList) { + return renderer; + } + if (!features[renderer]) { + continue; + } + available = true; + for (fidx = 0; fidx < featureList.length; fidx += 1) { + feature = featureList[fidx]; + capability = null; + if (feature.indexOf('.') >= 0) { + capability = feature.substr(feature.indexOf('.') + 1); + feature = feature.substr(0, feature.indexOf('.')); + } + if (features[renderer][feature] === undefined) { + available = false; + break; + } + if (capability && featureCapabilities[renderer][feature] && + !featureCapabilities[renderer][feature][capability]) { + available = false; + break; + } + } + if (available) { + return renderer; + } } + console.warn('There is no renderer available for the feature list "' + + (featureList || []).join(', ') + '".'); + return false; +}; +////////////////////////////////////////////////////////////////////////////// +/** + * Register a new feature type + * + * @param {string} category The feature category -- this is the renderer name. + * @param {string} name The feature name + * @param {function} func A function to call to create the feature. + * @param {object|undefined} capabilities A map of capabilities that this + * feature supports. If the feature is implemented with different + * capabilities in multiple categories (renderers), then the feature + * should expose a simple dictionary of supported and unsupported + * features. For instance, the quad feature has color quads, image quads, + * and image quads that support full transformations. The capabailities + * might be {clr: true, img: true: 'img-full': false}. + */ +////////////////////////////////////////////////////////////////////////////// +util.registerFeature = function (category, name, func, capabilities) { if (!(category in features)) { features[category] = {}; + featureCapabilities[category] = {}; } // TODO Add warning if the name already exists features[category][name] = func; + featureCapabilities[category][name] = capabilities; }; ////////////////////////////////////////////////////////////////////////////// /** - * Create new instance of the renderer + * Create new instance of a feature */ ////////////////////////////////////////////////////////////////////////////// util.createFeature = function (name, layer, renderer, arg) { @@ -121,9 +192,11 @@ util.createFeature = function (name, layer, renderer, arg) { $.extend(true, options, arg); } var feature = features[category][name](options); - layer.gcs = function () { - return layer.map().gcs(); - }; + if (layer.gcs === undefined) { + layer.gcs = function () { + return layer.map().gcs(); + }; + } return feature; } return null; @@ -135,10 +208,6 @@ util.createFeature = function (name, layer, renderer, arg) { */ ////////////////////////////////////////////////////////////////////////////// util.registerLayerAdjustment = function (category, name, func) { - if (rendererLayerAdjustments === undefined) { - rendererLayerAdjustments = {}; - } - if (!(category in rendererLayerAdjustments)) { rendererLayerAdjustments[category] = {}; } @@ -172,8 +241,9 @@ util.adjustLayerForRenderer = function (name, layer) { * Register a new layer type */ ////////////////////////////////////////////////////////////////////////////// -util.registerLayer = function (name, func) { +util.registerLayer = function (name, func, defaultFeatures) { layers[name] = func; + layerDefaultFeatures[name] = defaultFeatures; }; ////////////////////////////////////////////////////////////////////////////// @@ -183,10 +253,13 @@ util.registerLayer = function (name, func) { ////////////////////////////////////////////////////////////////////////////// util.createLayer = function (name, map, arg) { /// Default renderer is vgl - var options = {'map': map, 'renderer': 'vgl'}, + var options = {map: map}, layer = null; if (name in layers) { + if (!arg.renderer && !arg.features && layerDefaultFeatures) { + options.features = layerDefaultFeatures[name]; + } if (arg !== undefined) { $.extend(true, options, arg); } diff --git a/tests/cases/registry.js b/tests/cases/registry.js new file mode 100644 index 0000000000..7a149e91d7 --- /dev/null +++ b/tests/cases/registry.js @@ -0,0 +1,29 @@ +describe('geo.registry', function () { + 'use strict'; + + var geo = require('../test-utils').geo; + var mockVGLRenderer = require('../test-utils').mockVGLRenderer; + var restoreVGLRenderer = require('../test-utils').restoreVGLRenderer; + + describe('Check rendererForFeatures', function () { + it('specific features', function () { + mockVGLRenderer(); + expect(geo.rendererForFeatures()).toBe('vgl'); + expect(geo.rendererForFeatures(['point'])).toBe('vgl'); + expect(geo.rendererForFeatures(['heatmap'])).toBe('canvas'); + expect(geo.rendererForFeatures(['point', 'graph'])).toBe('d3'); + expect(geo.rendererForFeatures(['contour'])).toBe('vgl'); + expect(geo.rendererForFeatures(['contour', 'graph'])).toBe(false); + expect(geo.rendererForFeatures(['quad', 'graph'])).toBe('d3'); + expect(geo.rendererForFeatures(['quad.img-full', 'graph'])).toBe(false); + expect(geo.rendererForFeatures(['quad.img', 'graph'])).toBe('d3'); + restoreVGLRenderer(); + }); + it('unsupported vgl renderer', function () { + mockVGLRenderer(false); + expect(geo.rendererForFeatures()).toBe('canvas'); + expect(geo.rendererForFeatures(['point'])).toBe('d3'); + restoreVGLRenderer(); + }); + }); +}); diff --git a/tests/test-utils.js b/tests/test-utils.js index c48d031ab6..15ab2e9933 100644 --- a/tests/test-utils.js +++ b/tests/test-utils.js @@ -101,7 +101,7 @@ module.exports.closeToEqual = function closeToEqual(o1, o2, precision) { * default state. * * @param {boolean} [supported=true] If false, then the vgl renderer - * will indicate that this is an unsupported browser environement. + * will indicate that this is an unsupported browser environment. */ module.exports.mockVGLRenderer = function mockVGLRenderer(supported) { 'use strict'; From eb81d5e4b2e4f136886ee4c390944be0a859fa9b Mon Sep 17 00:00:00 2001 From: David Manthey Date: Tue, 14 Jun 2016 12:16:03 -0400 Subject: [PATCH 2/3] Switch to using quad features in the selection now that that branch has been merged. --- src/mapInteractor.js | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/mapInteractor.js b/src/mapInteractor.js index 5cd2ca2243..b53eb2fc4c 100644 --- a/src/mapInteractor.js +++ b/src/mapInteractor.js @@ -685,17 +685,6 @@ var mapInteractor = function (args) { m_this.map().deleteLayer(m_selectionLayer); m_selectionLayer = null; } - /* This can be removed once selection quads are implemented */ - // Create a feature layer and plane feature to show the selection bounds - m_selectionLayer = m_this.map().createLayer('feature', {renderer: 'd3'}); - - m_selectionQuad = m_selectionLayer.createFeature( - 'quad', {gcs: m_this.map().gcs()}); - m_selectionQuad.style({ - opacity: 0.25, - color: {r: 0.3, g: 0.3, b: 0.3} - }); - /* Use this once selection quads are implemented m_selectionLayer = m_this.map().createLayer( 'feature', {features: ['quad.clr']}); m_selectionQuad = m_selectionLayer.createFeature('quad'); @@ -703,7 +692,6 @@ var mapInteractor = function (args) { opacity: 0.25, color: {r: 0.3, g: 0.3, b: 0.3} }); - */ m_this.map().geoTrigger(geo_event.brushstart, m_this._getSelection()); } From 5f41066f95d17b5f06c187972eea07dc0a9f3c10 Mon Sep 17 00:00:00 2001 From: David Manthey Date: Fri, 17 Jun 2016 11:49:31 -0400 Subject: [PATCH 3/3] Use defined values for the capabilities of features so that they are more clearly documented. --- examples/hurricanes/main.js | 2 +- examples/reprojection/main.js | 2 +- src/canvas/quadFeature.js | 7 ++++++- src/d3/lineFeature.js | 7 ++++++- src/d3/quadFeature.js | 7 ++++++- src/gl/lineFeature.js | 7 ++++++- src/gl/quadFeature.js | 7 ++++++- src/lineFeature.js | 7 +++++++ src/mapInteractor.js | 6 ++++-- src/osmLayer.js | 6 ++++-- src/quadFeature.js | 9 +++++++++ src/registry.js | 16 +++++++++------- tests/cases/registry.js | 4 ++-- 13 files changed, 67 insertions(+), 20 deletions(-) diff --git a/examples/hurricanes/main.js b/examples/hurricanes/main.js index 252e1c589d..1cbb7acf09 100644 --- a/examples/hurricanes/main.js +++ b/examples/hurricanes/main.js @@ -370,7 +370,7 @@ $(function () { ); // Create a feature layer to draw on. - layer = map.createLayer('feature', {features: ['line.multicolor']}); + layer = map.createLayer('feature', {features: [geo.lineFeature.capabilities.multicolor]}); // Create a line feature feature = layer.createFeature('line', {selectionAPI: true}); diff --git a/examples/reprojection/main.js b/examples/reprojection/main.js index e18dc4ea6a..da5c18ec91 100644 --- a/examples/reprojection/main.js +++ b/examples/reprojection/main.js @@ -126,7 +126,7 @@ $(function () { } // Set the tile layer defaults to use the specified renderer and opacity var layerParams = { - features: ['quad.img-full'], + features: [geo.quadFeature.capabilities.imageFull], zIndex: 0, gcs: 'EPSG:3857', attribution: $('#url-list [value="' + $('#layer-url').val() + '"]').attr( diff --git a/src/canvas/quadFeature.js b/src/canvas/quadFeature.js index 3b312b55e4..2fd6cae8eb 100644 --- a/src/canvas/quadFeature.js +++ b/src/canvas/quadFeature.js @@ -143,5 +143,10 @@ var canvas_quadFeature = function (arg) { inherit(canvas_quadFeature, quadFeature); // Now register it -registerFeature('canvas', 'quad', canvas_quadFeature, {clr: false, img: true, 'img-full': false}); +var capabilities = {}; +capabilities[quadFeature.capabilities.color] = false; +capabilities[quadFeature.capabilities.image] = true; +capabilities[quadFeature.capabilities.imageFull] = false; + +registerFeature('canvas', 'quad', canvas_quadFeature, capabilities); module.exports = canvas_quadFeature; diff --git a/src/d3/lineFeature.js b/src/d3/lineFeature.js index bd1aa4e030..8eb5dd9dc1 100644 --- a/src/d3/lineFeature.js +++ b/src/d3/lineFeature.js @@ -130,6 +130,11 @@ var d3_lineFeature = function (arg) { inherit(d3_lineFeature, lineFeature); -registerFeature('d3', 'line', d3_lineFeature, {basic: true, multicolor: false}); +// Now register it +var capabilities = {}; +capabilities[lineFeature.capabilities.basic] = true; +capabilities[lineFeature.capabilities.multicolor] = false; + +registerFeature('d3', 'line', d3_lineFeature, capabilities); module.exports = d3_lineFeature; diff --git a/src/d3/quadFeature.js b/src/d3/quadFeature.js index 1c6713bcd0..a82181bec3 100644 --- a/src/d3/quadFeature.js +++ b/src/d3/quadFeature.js @@ -228,5 +228,10 @@ var d3_quadFeature = function (arg) { inherit(d3_quadFeature, quadFeature); // Now register it -registerFeature('d3', 'quad', d3_quadFeature, {clr: true, img: true, 'img-full': false}); +var capabilities = {}; +capabilities[quadFeature.capabilities.color] = true; +capabilities[quadFeature.capabilities.image] = true; +capabilities[quadFeature.capabilities.imageFull] = false; + +registerFeature('d3', 'quad', d3_quadFeature, capabilities); module.exports = d3_quadFeature; diff --git a/src/gl/lineFeature.js b/src/gl/lineFeature.js index 6746e7784a..b9d1872f7f 100644 --- a/src/gl/lineFeature.js +++ b/src/gl/lineFeature.js @@ -398,6 +398,11 @@ var gl_lineFeature = function (arg) { inherit(gl_lineFeature, lineFeature); // Now register it -registerFeature('vgl', 'line', gl_lineFeature, {basic: true, multicolor: true}); +var capabilities = {}; +capabilities[lineFeature.capabilities.basic] = true; +capabilities[lineFeature.capabilities.multicolor] = true; + +// Now register it +registerFeature('vgl', 'line', gl_lineFeature, capabilities); module.exports = gl_lineFeature; diff --git a/src/gl/quadFeature.js b/src/gl/quadFeature.js index 6fdf5ab54f..1d61bf655f 100644 --- a/src/gl/quadFeature.js +++ b/src/gl/quadFeature.js @@ -392,5 +392,10 @@ var gl_quadFeature = function (arg) { inherit(gl_quadFeature, quadFeature); // Now register it -registerFeature('vgl', 'quad', gl_quadFeature, {clr: true, img: true, 'img-full': true}); +var capabilities = {}; +capabilities[quadFeature.capabilities.color] = true; +capabilities[quadFeature.capabilities.image] = true; +capabilities[quadFeature.capabilities.imageFull] = true; + +registerFeature('vgl', 'quad', gl_quadFeature, capabilities); module.exports = gl_quadFeature; diff --git a/src/lineFeature.js b/src/lineFeature.js index ece37e003e..1ca4df8ceb 100644 --- a/src/lineFeature.js +++ b/src/lineFeature.js @@ -244,5 +244,12 @@ lineFeature.create = function (layer, spec) { return feature.create(layer, spec); }; +lineFeature.capabilities = { + /* support for solid-colored, constant-width lines */ + basic: 'line.basic', + /* support for lines that very in width and color */ + multicolor: 'line.multicolor' +}; + inherit(lineFeature, feature); module.exports = lineFeature; diff --git a/src/mapInteractor.js b/src/mapInteractor.js index b53eb2fc4c..ff602466de 100644 --- a/src/mapInteractor.js +++ b/src/mapInteractor.js @@ -24,6 +24,7 @@ var mapInteractor = function (args) { var geo_event = require('./event'); var throttle = require('./util').throttle; var debounce = require('./util').debounce; + var quadFeature = require('./quadFeature'); var m_options = args || {}, m_this = this, @@ -686,8 +687,9 @@ var mapInteractor = function (args) { m_selectionLayer = null; } m_selectionLayer = m_this.map().createLayer( - 'feature', {features: ['quad.clr']}); - m_selectionQuad = m_selectionLayer.createFeature('quad'); + 'feature', {features: [quadFeature.capabilities.color]}); + m_selectionQuad = m_selectionLayer.createFeature( + 'quad', {gcs: m_this.map().gcs()}); m_selectionQuad.style({ opacity: 0.25, color: {r: 0.3, g: 0.3, b: 0.3} diff --git a/src/osmLayer.js b/src/osmLayer.js index b94d35084f..d146986cfa 100644 --- a/src/osmLayer.js +++ b/src/osmLayer.js @@ -5,6 +5,7 @@ module.exports = (function () { var inherit = require('./inherit'); var tileLayer = require('./tileLayer'); var registry = require('./registry'); + var quadFeature = require('./quadFeature'); ////////////////////////////////////////////////////////////////////////////// /** @@ -81,7 +82,8 @@ module.exports = (function () { inherit(osmLayer, tileLayer); /* By default, ask to support image quads. If the user needs full - * reprojection, they will need to require the quad.img-full feature */ - registry.registerLayer('osm', osmLayer, ['quad.img']); + * reprojection, they will need to require the + * quadFeature.capabilities.imageFull feature */ + registry.registerLayer('osm', osmLayer, [quadFeature.capabilities.image]); return osmLayer; })(); diff --git a/src/quadFeature.js b/src/quadFeature.js index fddb10d4d2..05519c8258 100644 --- a/src/quadFeature.js +++ b/src/quadFeature.js @@ -465,5 +465,14 @@ quadFeature.create = function (layer, spec) { return feature.create(layer, spec); }; +quadFeature.capabilities = { + /* support for solid-colored quads */ + color: 'quad.color', + /* support for parallelogram images */ + image: 'quad.image', + /* support for arbitrary quad images */ + imageFull: 'quad.imageFull' +}; + inherit(quadFeature, feature); module.exports = quadFeature; diff --git a/src/registry.js b/src/registry.js index 4e15158f09..0310552f10 100644 --- a/src/registry.js +++ b/src/registry.js @@ -101,11 +101,12 @@ util.checkRenderer = function (name, noFallback) { * @param {array|undefined} featureList A list of features that will be used * with this renderer. Features are the basic feature names (e.g., * 'quad'), or the feature name followed by a required capability (e.g., - * 'quad.img'). If more than one feature or more than one capability of a - * feature is required, include each feature and capability combination in - * the list (e.g., ['quad.img', 'plane']). If no capability is specified - * for a feature (or that feature was registered without a capability - * object), then the feature will match regardless of capabilities. + * 'quad.image'). If more than one feature or more than one capability of + * a feature is required, include each feature and capability combination + * in the list (e.g., ['quad.image', 'plane']). If no capability is + * specified for a feature (or that feature was registered without a + * capability object), then the feature will match regardless of + * capabilities. * @return {string|null|false} the name of the renderer that should be used * or false if no valid renderer can be determined. */ @@ -130,7 +131,7 @@ util.rendererForFeatures = function (featureList) { feature = featureList[fidx]; capability = null; if (feature.indexOf('.') >= 0) { - capability = feature.substr(feature.indexOf('.') + 1); + capability = feature; feature = feature.substr(0, feature.indexOf('.')); } if (features[renderer][feature] === undefined) { @@ -165,7 +166,8 @@ util.rendererForFeatures = function (featureList) { * should expose a simple dictionary of supported and unsupported * features. For instance, the quad feature has color quads, image quads, * and image quads that support full transformations. The capabailities - * might be {clr: true, img: true: 'img-full': false}. + * should be defined in the base feature in a capabilities object so that + * they can be referenced by that rather than an explicit string. */ ////////////////////////////////////////////////////////////////////////////// util.registerFeature = function (category, name, func, capabilities) { diff --git a/tests/cases/registry.js b/tests/cases/registry.js index 7a149e91d7..0f14ab54da 100644 --- a/tests/cases/registry.js +++ b/tests/cases/registry.js @@ -15,8 +15,8 @@ describe('geo.registry', function () { expect(geo.rendererForFeatures(['contour'])).toBe('vgl'); expect(geo.rendererForFeatures(['contour', 'graph'])).toBe(false); expect(geo.rendererForFeatures(['quad', 'graph'])).toBe('d3'); - expect(geo.rendererForFeatures(['quad.img-full', 'graph'])).toBe(false); - expect(geo.rendererForFeatures(['quad.img', 'graph'])).toBe('d3'); + expect(geo.rendererForFeatures([geo.quadFeature.capabilities.imageFull, 'graph'])).toBe(false); + expect(geo.rendererForFeatures([geo.quadFeature.capabilities.image, 'graph'])).toBe('d3'); restoreVGLRenderer(); }); it('unsupported vgl renderer', function () {