From 9f7cba0ac0c0ec1b459c905dcbbe194fcc9f3ccd Mon Sep 17 00:00:00 2001 From: Antoine Abt Date: Fri, 28 Feb 2014 16:06:38 +0100 Subject: [PATCH 01/13] Skipped features replaces RenderGeometryFunction --- src/ol/layer/vectorlayer.js | 95 +++++++++++-------- src/ol/render/canvas/canvasreplay.js | 76 +++++++-------- .../canvas/canvasvectorlayerrenderer.js | 52 ++-------- src/ol/source/imagevectorsource.js | 4 +- 4 files changed, 106 insertions(+), 121 deletions(-) diff --git a/src/ol/layer/vectorlayer.js b/src/ol/layer/vectorlayer.js index 9fe1f28092..e5bb858d38 100644 --- a/src/ol/layer/vectorlayer.js +++ b/src/ol/layer/vectorlayer.js @@ -1,18 +1,15 @@ goog.provide('ol.layer.Vector'); +goog.require('goog.array'); +goog.require('goog.events'); +goog.require('goog.events.EventType'); goog.require('goog.object'); +goog.require('ol.Collection'); +goog.require('ol.CollectionEventType'); goog.require('ol.feature'); goog.require('ol.layer.Layer'); -/** - * @enum {string} - */ -ol.layer.VectorProperty = { - RENDER_GEOMETRY_FUNCTIONS: 'renderGeometryFunctions' -}; - - /** * @constructor @@ -48,24 +45,29 @@ ol.layer.Vector = function(opt_options) { this.setStyle(options.style); } + /** + * Collection of Features to skip drawing. + * @type {ol.Collection} + * @private + */ + this.skippedFeatures_ = new ol.Collection(); + + /** + * Array of Feature ids to skip drawing. + * @type {Array.} + * @private + */ + this.skippedFeaturesIds_ = []; + + goog.events.listen(this.skippedFeatures_, [ + ol.CollectionEventType.REMOVE, + ol.CollectionEventType.ADD + ], this.updateSkippedFeaturesArray_, false, this); + }; goog.inherits(ol.layer.Vector, ol.layer.Layer); -/** - * @return {ol.Collection|undefined} Render geometry functions. - * @todo stability experimental - */ -ol.layer.Vector.prototype.getRenderGeometryFunctions = function() { - return /** @type {ol.Collection|undefined} */ ( - this.get(ol.layer.VectorProperty.RENDER_GEOMETRY_FUNCTIONS)); -}; -goog.exportProperty( - ol.layer.Vector.prototype, - 'getRenderGeometryFunctions', - ol.layer.Vector.prototype.getRenderGeometryFunctions); - - /** * Get the style for features. This returns whatever was passed to the `style` * option at construction or to the `setStyle` method. @@ -87,22 +89,6 @@ ol.layer.Vector.prototype.getStyleFunction = function() { }; -/** - * @param {ol.Collection|undefined} renderGeometryFunctions Render geometry - * functions. - * @todo stability experimental - */ -ol.layer.Vector.prototype.setRenderGeometryFunctions = - function(renderGeometryFunctions) { - this.set(ol.layer.VectorProperty.RENDER_GEOMETRY_FUNCTIONS, - renderGeometryFunctions); -}; -goog.exportProperty( - ol.layer.Vector.prototype, - 'setRenderGeometryFunctions', - ol.layer.Vector.prototype.setRenderGeometryFunctions); - - /** * Set the style for features. This can be a single style object, an array * of styles, or a function that takes a feature and resolution and returns @@ -116,3 +102,36 @@ ol.layer.Vector.prototype.setStyle = function(style) { this.styleFunction_ = ol.feature.createStyleFunction(style); this.dispatchChangeEvent(); }; + + +/** + * Update Features Ids internal array. + * @private + */ +ol.layer.Vector.prototype.updateSkippedFeaturesArray_ = function() { + this.skippedFeaturesIds_ = goog.array.map( + this.skippedFeatures_.getArray(), goog.getUid); + // Don’t use dispatchChangeEvent here because we don’t want the batch + // to be re-created, just replayed. + this.dispatchEvent(goog.events.EventType.CHANGE); +}; + + +/** + * Get the collection of features to be skipped. + * @return {ol.Collection} Features collection. + * @todo stability experimental + */ +ol.layer.Vector.prototype.getSkippedFeatures = function() { + return this.skippedFeatures_; +}; + + +/** + * Get the feature’s ids to be skipped. + * @return {Array.} Array of features Ids + * @todo stability experimental + */ +ol.layer.Vector.prototype.getSkippedFeaturesIds = function() { + return this.skippedFeaturesIds_; +}; diff --git a/src/ol/render/canvas/canvasreplay.js b/src/ol/render/canvas/canvasreplay.js index 257324cab1..0d2787ce55 100644 --- a/src/ol/render/canvas/canvasreplay.js +++ b/src/ol/render/canvas/canvasreplay.js @@ -134,6 +134,12 @@ ol.render.canvas.Replay = function(tolerance, maxExtent, resolution) { */ this.tmpLocalTransform_ = goog.vec.Mat4.createNumber(); + /** + * @private + * @type {Object} + */ + this.instructionIndices_ = {}; + }; @@ -197,11 +203,13 @@ ol.render.canvas.Replay.prototype.appendFlatCoordinates = /** * @protected * @param {ol.geom.Geometry} geometry Geometry. + * @param {number} uid Data uid */ -ol.render.canvas.Replay.prototype.beginGeometry = function(geometry) { +ol.render.canvas.Replay.prototype.beginGeometry = function(geometry, uid) { this.beginGeometryInstruction1_ = [ol.render.canvas.Instruction.BEGIN_GEOMETRY, geometry, 0]; this.instructions.push(this.beginGeometryInstruction1_); + this.instructionIndices_[this.instructions.length - 1] = uid; this.beginGeometryInstruction2_ = [ol.render.canvas.Instruction.BEGIN_GEOMETRY, geometry, 0]; this.hitDetectionInstructions.push(this.beginGeometryInstruction2_); @@ -214,8 +222,7 @@ ol.render.canvas.Replay.prototype.beginGeometry = function(geometry) { * @param {number} pixelRatio Pixel ratio. * @param {goog.vec.Mat4.Number} transform Transform. * @param {number} viewRotation View rotation. - * @param {function(ol.geom.Geometry): boolean} renderGeometryFunction Render - * geometry function. + * @param {Array.} skippedFeaturesIds Ids of features to skip. * @param {Array.<*>} instructions Instructions array. * @param {function(ol.geom.Geometry, Object): T|undefined} geometryCallback * Geometry callback. @@ -223,7 +230,7 @@ ol.render.canvas.Replay.prototype.beginGeometry = function(geometry) { * @template T */ ol.render.canvas.Replay.prototype.replay_ = function( - context, pixelRatio, transform, viewRotation, renderGeometryFunction, + context, pixelRatio, transform, viewRotation, skippedFeaturesIds, instructions, geometryCallback) { /** @type {Array.} */ var pixelCoordinates; @@ -247,7 +254,8 @@ ol.render.canvas.Replay.prototype.replay_ = function( switch (type) { case ol.render.canvas.Instruction.BEGIN_GEOMETRY: geometry = /** @type {ol.geom.Geometry} */ (instruction[1]); - if (renderGeometryFunction(geometry)) { + if (!goog.array.contains(skippedFeaturesIds, + this.instructionIndices_[i])) { ++i; } else { i = /** @type {number} */ (instruction[2]); @@ -453,16 +461,15 @@ ol.render.canvas.Replay.prototype.replay_ = function( * @param {number} pixelRatio Pixel ratio. * @param {goog.vec.Mat4.Number} transform Transform. * @param {number} viewRotation View rotation. - * @param {function(ol.geom.Geometry): boolean} renderGeometryFunction Render - * geometry function. + * @param {Array.} skippedFeaturesIds Ids of features to skip * @return {T|undefined} Callback result. * @template T */ ol.render.canvas.Replay.prototype.replay = function( - context, pixelRatio, transform, viewRotation, renderGeometryFunction) { + context, pixelRatio, transform, viewRotation, skippedFeaturesIds) { var instructions = this.instructions; return this.replay_(context, pixelRatio, transform, viewRotation, - renderGeometryFunction, instructions, undefined); + skippedFeaturesIds, instructions, undefined); }; @@ -470,19 +477,18 @@ ol.render.canvas.Replay.prototype.replay = function( * @param {CanvasRenderingContext2D} context Context. * @param {goog.vec.Mat4.Number} transform Transform. * @param {number} viewRotation View rotation. - * @param {function(ol.geom.Geometry): boolean} renderGeometryFunction Render - * geometry function. + * @param {Array.} skippedFeaturesIds Ids of features to skip * @param {function(ol.geom.Geometry, Object): T=} opt_geometryCallback * Geometry callback. * @return {T|undefined} Callback result. * @template T */ ol.render.canvas.Replay.prototype.replayHitDetection = function( - context, transform, viewRotation, renderGeometryFunction, + context, transform, viewRotation, skippedFeaturesIds, opt_geometryCallback) { var instructions = this.hitDetectionInstructions; return this.replay_(context, 1, transform, viewRotation, - renderGeometryFunction, instructions, opt_geometryCallback); + skippedFeaturesIds, instructions, opt_geometryCallback); }; @@ -764,7 +770,7 @@ ol.render.canvas.ImageReplay.prototype.drawPointGeometry = goog.asserts.assert(goog.isDef(this.scale_)); goog.asserts.assert(goog.isDef(this.width_)); ol.extent.extend(this.extent_, pointGeometry.getExtent()); - this.beginGeometry(pointGeometry); + this.beginGeometry(pointGeometry, goog.getUid(data)); var flatCoordinates = pointGeometry.getFlatCoordinates(); var stride = pointGeometry.getStride(); var myBegin = this.coordinates.length; @@ -806,7 +812,7 @@ ol.render.canvas.ImageReplay.prototype.drawMultiPointGeometry = goog.asserts.assert(goog.isDef(this.scale_)); goog.asserts.assert(goog.isDef(this.width_)); ol.extent.extend(this.extent_, multiPointGeometry.getExtent()); - this.beginGeometry(multiPointGeometry); + this.beginGeometry(multiPointGeometry, goog.getUid(data)); var flatCoordinates = multiPointGeometry.getFlatCoordinates(); var stride = multiPointGeometry.getStride(); var myBegin = this.coordinates.length; @@ -1018,7 +1024,7 @@ ol.render.canvas.LineStringReplay.prototype.drawLineStringGeometry = } ol.extent.extend(this.extent_, lineStringGeometry.getExtent()); this.setStrokeStyle_(); - this.beginGeometry(lineStringGeometry); + this.beginGeometry(lineStringGeometry, goog.getUid(data)); this.hitDetectionInstructions.push( [ol.render.canvas.Instruction.SET_STROKE_STYLE, state.strokeStyle, state.lineWidth, state.lineCap, state.lineJoin, @@ -1047,7 +1053,7 @@ ol.render.canvas.LineStringReplay.prototype.drawMultiLineStringGeometry = } ol.extent.extend(this.extent_, multiLineStringGeometry.getExtent()); this.setStrokeStyle_(); - this.beginGeometry(multiLineStringGeometry); + this.beginGeometry(multiLineStringGeometry, goog.getUid(data)); this.hitDetectionInstructions.push( [ol.render.canvas.Instruction.SET_STROKE_STYLE, state.strokeStyle, state.lineWidth, state.lineCap, state.lineJoin, @@ -1225,7 +1231,7 @@ ol.render.canvas.PolygonReplay.prototype.drawCircleGeometry = } ol.extent.extend(this.extent_, circleGeometry.getExtent()); this.setFillStrokeStyles_(); - this.beginGeometry(circleGeometry); + this.beginGeometry(circleGeometry, goog.getUid(data)); // always fill the circle for hit detection this.hitDetectionInstructions.push( [ol.render.canvas.Instruction.SET_FILL_STYLE, @@ -1276,7 +1282,7 @@ ol.render.canvas.PolygonReplay.prototype.drawPolygonGeometry = } ol.extent.extend(this.extent_, polygonGeometry.getExtent()); this.setFillStrokeStyles_(); - this.beginGeometry(polygonGeometry); + this.beginGeometry(polygonGeometry, goog.getUid(data)); // always fill the polygon for hit detection this.hitDetectionInstructions.push( [ol.render.canvas.Instruction.SET_FILL_STYLE, @@ -1312,7 +1318,7 @@ ol.render.canvas.PolygonReplay.prototype.drawMultiPolygonGeometry = } ol.extent.extend(this.extent_, multiPolygonGeometry.getExtent()); this.setFillStrokeStyles_(); - this.beginGeometry(multiPolygonGeometry); + this.beginGeometry(multiPolygonGeometry, goog.getUid(data)); // always fill the multi-polygon for hit detection this.hitDetectionInstructions.push( [ol.render.canvas.Instruction.SET_FILL_STYLE, @@ -1564,7 +1570,7 @@ ol.render.canvas.TextReplay.prototype.drawText = this.setReplayStrokeState_(this.textStrokeState_); } this.setReplayTextState_(this.textState_); - this.beginGeometry(geometry); + this.beginGeometry(geometry, goog.getUid(data)); var myBegin = this.coordinates.length; var myEnd = this.appendFlatCoordinates(flatCoordinates, offset, end, stride, false); @@ -1844,18 +1850,17 @@ ol.render.canvas.ReplayGroup = function(tolerance, maxExtent, resolution) { * @param {number} pixelRatio Pixel ratio. * @param {goog.vec.Mat4.Number} transform Transform. * @param {number} viewRotation View rotation. - * @param {function(ol.geom.Geometry): boolean} renderGeometryFunction Render - * geometry function. + * @param {Array.} skippedFeaturesIds Ids of features to skip * @return {T|undefined} Callback result. * @template T */ ol.render.canvas.ReplayGroup.prototype.replay = function(context, extent, - pixelRatio, transform, viewRotation, renderGeometryFunction) { + pixelRatio, transform, viewRotation, skippedFeaturesIds) { /** @type {Array.} */ var zs = goog.array.map(goog.object.getKeys(this.replaysByZIndex_), Number); goog.array.sort(zs); return this.replay_(zs, context, extent, pixelRatio, transform, - viewRotation, renderGeometryFunction); + viewRotation, skippedFeaturesIds); }; @@ -1866,15 +1871,14 @@ ol.render.canvas.ReplayGroup.prototype.replay = function(context, extent, * @param {ol.Extent} extent Extent. * @param {goog.vec.Mat4.Number} transform Transform. * @param {number} viewRotation View rotation. - * @param {function(ol.geom.Geometry): boolean} renderGeometryFunction Render - * geometry function. + * @param {Array.} skippedFeaturesIds Ids of features to skip * @param {function(ol.geom.Geometry, Object): T} geometryCallback Geometry * callback. * @return {T|undefined} Callback result. * @template T */ ol.render.canvas.ReplayGroup.prototype.replayHitDetection_ = function( - zs, context, extent, transform, viewRotation, renderGeometryFunction, + zs, context, extent, transform, viewRotation, skippedFeaturesIds, geometryCallback) { var i, ii, replays, replayType, replay, result; for (i = 0, ii = zs.length; i < ii; ++i) { @@ -1883,7 +1887,7 @@ ol.render.canvas.ReplayGroup.prototype.replayHitDetection_ = function( replay = replays[replayType]; if (ol.extent.intersects(extent, replay.getExtent())) { result = replay.replayHitDetection(context, transform, viewRotation, - renderGeometryFunction, geometryCallback); + skippedFeaturesIds, geometryCallback); if (result) { return result; } @@ -1902,14 +1906,13 @@ ol.render.canvas.ReplayGroup.prototype.replayHitDetection_ = function( * @param {number} pixelRatio Pixel ratio. * @param {goog.vec.Mat4.Number} transform Transform. * @param {number} viewRotation View rotation. - * @param {function(ol.geom.Geometry): boolean} renderGeometryFunction Render - * geometry function. + * @param {Array.} skippedFeaturesIds Ids of features to skip * @return {T|undefined} Callback result. * @template T */ ol.render.canvas.ReplayGroup.prototype.replay_ = function( zs, context, extent, pixelRatio, transform, viewRotation, - renderGeometryFunction) { + skippedFeaturesIds) { var maxExtent = this.maxExtent_; var minX = maxExtent[0]; @@ -1935,7 +1938,7 @@ ol.render.canvas.ReplayGroup.prototype.replay_ = function( if (goog.isDef(replay) && ol.extent.intersects(extent, replay.getExtent())) { result = replay.replay(context, pixelRatio, transform, viewRotation, - renderGeometryFunction); + skippedFeaturesIds); if (result) { return result; } @@ -1953,15 +1956,14 @@ ol.render.canvas.ReplayGroup.prototype.replay_ = function( * @param {number} resolution Resolution. * @param {number} rotation Rotation. * @param {ol.Coordinate} coordinate Coordinate. - * @param {function(ol.geom.Geometry): boolean} renderGeometryFunction Render - * geometry function. + * @param {Array.} skippedFeaturesIds Ids of features to skip * @param {function(ol.geom.Geometry, Object): T} callback Geometry callback. * @return {T|undefined} Callback result. * @template T */ ol.render.canvas.ReplayGroup.prototype.forEachGeometryAtPixel = function( extent, resolution, rotation, coordinate, - renderGeometryFunction, callback) { + skippedFeaturesIds, callback) { var transform = this.hitDetectionTransform_; ol.vec.Mat4.makeTransform2D(transform, 0.5, 0.5, @@ -1976,7 +1978,7 @@ ol.render.canvas.ReplayGroup.prototype.forEachGeometryAtPixel = function( context.clearRect(0, 0, 1, 1); return this.replayHitDetection_(zs, context, extent, transform, - rotation, renderGeometryFunction, + rotation, skippedFeaturesIds, /** * @param {ol.geom.Geometry} geometry Geometry. * @param {Object} data Opaque data object. diff --git a/src/ol/renderer/canvas/canvasvectorlayerrenderer.js b/src/ol/renderer/canvas/canvasvectorlayerrenderer.js index 5b0f97c226..30cb9f3130 100644 --- a/src/ol/renderer/canvas/canvasvectorlayerrenderer.js +++ b/src/ol/renderer/canvas/canvasvectorlayerrenderer.js @@ -4,7 +4,6 @@ goog.require('goog.asserts'); goog.require('goog.dom'); goog.require('goog.dom.TagName'); goog.require('goog.events'); -goog.require('goog.functions'); goog.require('ol.ViewHint'); goog.require('ol.extent'); goog.require('ol.feature'); @@ -96,12 +95,13 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame = } else { replayContext = context; } - var renderGeometryFunction = this.getRenderGeometryFunction_(); - goog.asserts.assert(goog.isFunction(renderGeometryFunction)); + goog.asserts.assertInstanceof(layer, ol.layer.Vector); + var skippedFeaturesIds = layer.getSkippedFeaturesIds(); + goog.asserts.assert(goog.isArray(skippedFeaturesIds)); replayContext.globalAlpha = layerState.opacity; replayGroup.replay( replayContext, frameState.extent, frameState.pixelRatio, transform, - frameState.view2DState.rotation, renderGeometryFunction); + frameState.view2DState.rotation, skippedFeaturesIds); if (replayContext != context) { this.dispatchRenderEvent(replayContext, frameState, transform); @@ -126,10 +126,11 @@ ol.renderer.canvas.VectorLayer.prototype.forEachFeatureAtPixel = var resolution = frameState.view2DState.resolution; var rotation = frameState.view2DState.rotation; var layer = this.getLayer(); - var renderGeometryFunction = this.getRenderGeometryFunction_(); - goog.asserts.assert(goog.isFunction(renderGeometryFunction)); + goog.asserts.assertInstanceof(layer, ol.layer.Vector); + var skippedFeaturesIds = layer.getSkippedFeaturesIds(); + goog.asserts.assert(goog.isArray(skippedFeaturesIds)); return this.replayGroup_.forEachGeometryAtPixel(extent, resolution, - rotation, coordinate, renderGeometryFunction, + rotation, coordinate, skippedFeaturesIds, /** * @param {ol.geom.Geometry} geometry Geometry. * @param {Object} data Data. @@ -144,43 +145,6 @@ ol.renderer.canvas.VectorLayer.prototype.forEachFeatureAtPixel = }; -/** - * @private - * @return {function(ol.geom.Geometry): boolean} Render geometry function. - */ -ol.renderer.canvas.VectorLayer.prototype.getRenderGeometryFunction_ = - function() { - var vectorLayer = this.getLayer(); - goog.asserts.assertInstanceof(vectorLayer, ol.layer.Vector); - var renderGeometryFunctions = vectorLayer.getRenderGeometryFunctions(); - if (!goog.isDef(renderGeometryFunctions)) { - return goog.functions.TRUE; - } - var renderGeometryFunctionsArray = renderGeometryFunctions.getArray(); - switch (renderGeometryFunctionsArray.length) { - case 0: - return goog.functions.TRUE; - case 1: - return renderGeometryFunctionsArray[0]; - default: - return ( - /** - * @param {ol.geom.Geometry} geometry Geometry. - * @return {boolean} Render geometry. - */ - function(geometry) { - var i, ii; - for (i = 0, ii = renderGeometryFunctionsArray.length; i < ii; ++i) { - if (!renderGeometryFunctionsArray[i](geometry)) { - return false; - } - } - return true; - }); - } -}; - - /** * Handle changes in image style state. * @param {goog.events.Event} event Image style change event. diff --git a/src/ol/source/imagevectorsource.js b/src/ol/source/imagevectorsource.js index 07c8196ff8..f4a436ee17 100644 --- a/src/ol/source/imagevectorsource.js +++ b/src/ol/source/imagevectorsource.js @@ -141,7 +141,7 @@ ol.source.ImageVector.prototype.canvasFunctionInternal_ = var transform = this.getTransform_(ol.extent.getCenter(extent), resolution, pixelRatio, size); replayGroup.replay(this.canvasContext_, extent, pixelRatio, transform, 0, - goog.functions.TRUE); + []); this.replayGroup_ = replayGroup; @@ -158,7 +158,7 @@ ol.source.ImageVector.prototype.forEachFeatureAtPixel = return undefined; } else { return this.replayGroup_.forEachGeometryAtPixel( - extent, resolution, 0, coordinate, goog.functions.TRUE, + extent, resolution, 0, coordinate, [], /** * @param {ol.geom.Geometry} geometry Geometry. * @param {Object} data Data. From c2c379808718b8b42dd0f9fe590bb03793c42514 Mon Sep 17 00:00:00 2001 From: Antoine Abt Date: Mon, 3 Mar 2014 18:24:29 +0100 Subject: [PATCH 02/13] Update select-features example styles --- examples/select-features.js | 41 +++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/examples/select-features.js b/examples/select-features.js index 5244b6af9f..d1c16603c9 100644 --- a/examples/select-features.js +++ b/examples/select-features.js @@ -9,6 +9,7 @@ goog.require('ol.source.MapQuest'); goog.require('ol.style.Fill'); goog.require('ol.style.Stroke'); goog.require('ol.style.Style'); +goog.require('ol.style.Text'); var raster = new ol.layer.Tile({ source: new ol.source.MapQuest({layer: 'sat'}) @@ -18,23 +19,37 @@ var vector = new ol.layer.Vector({ source: new ol.source.GeoJSON({ projection: 'EPSG:3857', url: 'data/geojson/countries.geojson' - }), - style: new ol.style.Style({ - fill: new ol.style.Fill({ - color: 'rgba(255,255,255,0.25)' - }), - stroke: new ol.style.Stroke({ - color: '#6666ff' - }) }) }); +var styleCache = {}; var select = new ol.interaction.Select({ - style: new ol.style.Style({ - fill: new ol.style.Fill({ - color: 'rgba(255,255,255,0.5)' - }) - }) + style: function(feature, resolution) { + var text = feature.get('name'); + if (!styleCache[text]) { + styleCache[text] = [new ol.style.Style({ + fill: new ol.style.Fill({ + color: 'rgba(255,0,0,0.3)' + }), + stroke: new ol.style.Stroke({ + color: 'rgba(255,0,0,1)', + size: 2 + }), + text: new ol.style.Text({ + font: '12px Calibri,sans-serif', + text: text, + fill: new ol.style.Fill({ + color: '#000' + }), + stroke: new ol.style.Stroke({ + color: '#fff', + width: 3 + }) + }) + })]; + } + return styleCache[text]; + } }); var map = new ol.Map({ From c8de4d908d4ebcbcea66e1002cfe4a2087306584 Mon Sep 17 00:00:00 2001 From: Antoine Abt Date: Tue, 4 Mar 2014 09:31:56 +0100 Subject: [PATCH 03/13] Skip features in select interaction --- examples/select-features.js | 4 +- src/ol/interaction/selectinteraction.js | 146 ++++++++++++++++-------- 2 files changed, 102 insertions(+), 48 deletions(-) diff --git a/examples/select-features.js b/examples/select-features.js index d1c16603c9..cb4cb3b3d4 100644 --- a/examples/select-features.js +++ b/examples/select-features.js @@ -32,8 +32,8 @@ var select = new ol.interaction.Select({ color: 'rgba(255,0,0,0.3)' }), stroke: new ol.style.Stroke({ - color: 'rgba(255,0,0,1)', - size: 2 + color: 'rgba(255,0,0,1)', + size: 2 }), text: new ol.style.Text({ font: '12px Calibri,sans-serif', diff --git a/src/ol/interaction/selectinteraction.js b/src/ol/interaction/selectinteraction.js index 4fd1b5e7c6..660af12e48 100644 --- a/src/ol/interaction/selectinteraction.js +++ b/src/ol/interaction/selectinteraction.js @@ -1,10 +1,13 @@ goog.provide('ol.interaction.Select'); goog.require('goog.array'); +goog.require('goog.asserts'); goog.require('goog.functions'); +goog.require('ol.Feature'); goog.require('ol.FeatureOverlay'); goog.require('ol.events.condition'); goog.require('ol.interaction.Interaction'); +goog.require('ol.layer.Vector'); @@ -87,6 +90,12 @@ ol.interaction.Select = function(options) { style: options.style }); + /** + * @private + * @type {Object} + */ + this.featuresLayerHash_ = {}; + }; goog.inherits(ol.interaction.Select, ol.interaction.Interaction); @@ -111,58 +120,103 @@ ol.interaction.Select.prototype.handleMapBrowserEvent = var add = this.addCondition_(mapBrowserEvent); var remove = this.removeCondition_(mapBrowserEvent); var toggle = this.toggleCondition_(mapBrowserEvent); - var set = !add && !remove && !toggle; var map = mapBrowserEvent.map; - var features = this.featureOverlay_.getFeatures(); - if (set) { - // Replace the currently selected feature(s) with the feature at the pixel, - // or clear the selected feature(s) if there is no feature at the pixel. - /** @type {ol.Feature|undefined} */ - var feature = map.forEachFeatureAtPixel(mapBrowserEvent.pixel, - /** - * @param {ol.Feature} feature Feature. - * @param {ol.layer.Layer} layer Layer. - */ - function(feature, layer) { - return feature; - }, undefined, this.layerFilter_); - if (goog.isDef(feature)) { - if (features.getLength() == 1) { - if (features.getAt(0) !== feature) { - features.setAt(0, feature); + var feature = map.forEachFeatureAtPixel(mapBrowserEvent.pixel, + /** + * @param {ol.Feature} feature Feature. + * @param {ol.layer.Layer} layer Layer. + */ + function(feature, layer) { + this.addFeature_(feature, layer, add, remove, toggle); + return feature; + }, this, this.layerFilter_); + if (!goog.isDef(feature) && !add && !remove) { + this.removeAllFeatures_(); + } + return false; +}; + + +/** + * @param {?ol.Feature|undefined} feature Feature. + * @param {ol.layer.Layer} layer Layer. + * @param {Boolean} add Add + * @param {Boolean} remove Remove + * @param {Boolean} toggle Toggle + * @private + * @todo stability experimental + */ +ol.interaction.Select.prototype.addFeature_ = function(feature, layer, add, + remove, toggle) { + var features = this.featureOverlay_.getFeatures(), + hash = this.featuresLayerHash_, + uid, index = -1, + i, ii; + if ((!goog.isDef(feature) || goog.isNull(feature)) && !add) { + this.removeAllFeatures_(); + return; + } + goog.asserts.assertInstanceof(feature, ol.Feature); + uid = goog.getUid(feature); + index = features.getArray().indexOf(feature); + if (index == -1) { + if (!add && !remove && (features.getLength() > 0)) { + for (ii = features.getLength() - 1, i = ii; i >= 0; i--) { + if (features.getAt(i) != feature) { + this.removeFeature_(/** @type {ol.Feature} */ (features.getAt(i))); } - } else { - if (features.getLength() != 1) { - features.clear(); - } - features.push(feature); - } - } else { - if (features.getLength() !== 0) { - features.clear(); } } } else { - // Modify the currently selected feature(s). - map.forEachFeatureAtPixel(mapBrowserEvent.pixel, - /** - * @param {ol.Feature} feature Feature. - * @param {ol.layer.Layer} layer Layer. - */ - function(feature, layer) { - var index = goog.array.indexOf(features.getArray(), feature); - if (index == -1) { - if (add || toggle) { - features.push(feature); - } - } else { - if (remove || toggle) { - features.removeAt(index); - } - } - }, undefined, this.layerFilter_); + if (toggle || remove) { + this.removeFeature_(/** @type {ol.Feature} */ (features.getAt(index))); + return; + } + } + if (remove) { + return; + } + if (index >= 0) { + goog.array.insert(hash[uid], layer); + return; + } + features.push(feature); + goog.asserts.assertInstanceof(layer, ol.layer.Vector); + layer.getSkippedFeatures().push(feature); + hash[uid] = [layer]; +}; + + +/** + * @param {ol.Feature} feature Feature. + * @private + * @todo stability experimental + */ +ol.interaction.Select.prototype.removeFeature_ = function(feature) { + var features = this.featureOverlay_.getFeatures(), + hash = this.featuresLayerHash_, + uid = goog.getUid(feature), + i, ii, layer; + features.remove(feature); + for (i = 0, ii = hash[uid].length; i < ii; i++) { + layer = hash[uid][i]; + goog.asserts.assertInstanceof(layer, ol.layer.Vector); + layer.getSkippedFeatures().remove(feature); + } + delete hash[uid]; +}; + + +/** + * @private + * @todo stability experimental + */ +ol.interaction.Select.prototype.removeAllFeatures_ = function() { + var i, ii, + features = this.featureOverlay_.getFeatures(); + for (ii = features.getLength() - 1, i = ii; i >= 0; i--) { + this.removeFeature_(/** @type {ol.Feature} */ (features.getAt(i))); } - return false; }; From e91db0f9af810b95f7f37460519bdb2851eddc43 Mon Sep 17 00:00:00 2001 From: Antoine Abt Date: Tue, 4 Mar 2014 13:59:40 +0100 Subject: [PATCH 04/13] Check for null layers (for postcompose hitdetection) --- src/ol/interaction/selectinteraction.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ol/interaction/selectinteraction.js b/src/ol/interaction/selectinteraction.js index 660af12e48..e0de6a694d 100644 --- a/src/ol/interaction/selectinteraction.js +++ b/src/ol/interaction/selectinteraction.js @@ -200,8 +200,10 @@ ol.interaction.Select.prototype.removeFeature_ = function(feature) { features.remove(feature); for (i = 0, ii = hash[uid].length; i < ii; i++) { layer = hash[uid][i]; - goog.asserts.assertInstanceof(layer, ol.layer.Vector); - layer.getSkippedFeatures().remove(feature); + if (!goog.isNull(layer)) { + goog.asserts.assertInstanceof(layer, ol.layer.Vector); + layer.getSkippedFeatures().remove(feature); + } } delete hash[uid]; }; From 0d875161350f363c2fc1118f55753a93134b832b Mon Sep 17 00:00:00 2001 From: Antoine Abt Date: Wed, 19 Mar 2014 14:53:41 +0100 Subject: [PATCH 05/13] Map stores skippedFeatures instead of layers --- externs/oli.js | 4 ++ src/ol/interaction/selectinteraction.js | 38 +++---------- src/ol/layer/vectorlayer.js | 56 ------------------- src/ol/map.js | 19 +++++++ .../canvas/canvasvectorlayerrenderer.js | 10 +--- 5 files changed, 32 insertions(+), 95 deletions(-) diff --git a/externs/oli.js b/externs/oli.js index c6c2204bd2..e8bef6d3a8 100644 --- a/externs/oli.js +++ b/externs/oli.js @@ -92,6 +92,10 @@ oli.FrameState.prototype.postRenderFunctions; oli.FrameState.prototype.size; +/** @type {Array.} */ +oli.FrameState.prototype.skippedFeaturesIds; + + /** @type {ol.TileQueue} */ oli.FrameState.prototype.tileQueue; diff --git a/src/ol/interaction/selectinteraction.js b/src/ol/interaction/selectinteraction.js index e0de6a694d..78b9e40f83 100644 --- a/src/ol/interaction/selectinteraction.js +++ b/src/ol/interaction/selectinteraction.js @@ -7,7 +7,6 @@ goog.require('ol.Feature'); goog.require('ol.FeatureOverlay'); goog.require('ol.events.condition'); goog.require('ol.interaction.Interaction'); -goog.require('ol.layer.Vector'); @@ -90,12 +89,6 @@ ol.interaction.Select = function(options) { style: options.style }); - /** - * @private - * @type {Object} - */ - this.featuresLayerHash_ = {}; - }; goog.inherits(ol.interaction.Select, ol.interaction.Interaction); @@ -127,7 +120,7 @@ ol.interaction.Select.prototype.handleMapBrowserEvent = * @param {ol.layer.Layer} layer Layer. */ function(feature, layer) { - this.addFeature_(feature, layer, add, remove, toggle); + this.addFeature_(feature, add, remove, toggle); return feature; }, this, this.layerFilter_); if (!goog.isDef(feature) && !add && !remove) { @@ -139,17 +132,15 @@ ol.interaction.Select.prototype.handleMapBrowserEvent = /** * @param {?ol.Feature|undefined} feature Feature. - * @param {ol.layer.Layer} layer Layer. * @param {Boolean} add Add * @param {Boolean} remove Remove * @param {Boolean} toggle Toggle * @private * @todo stability experimental */ -ol.interaction.Select.prototype.addFeature_ = function(feature, layer, add, +ol.interaction.Select.prototype.addFeature_ = function(feature, add, remove, toggle) { var features = this.featureOverlay_.getFeatures(), - hash = this.featuresLayerHash_, uid, index = -1, i, ii; if ((!goog.isDef(feature) || goog.isNull(feature)) && !add) { @@ -176,14 +167,10 @@ ol.interaction.Select.prototype.addFeature_ = function(feature, layer, add, if (remove) { return; } - if (index >= 0) { - goog.array.insert(hash[uid], layer); - return; + if (index == -1) { + features.push(feature); + this.getMap().getSkippedFeatures().push(feature); } - features.push(feature); - goog.asserts.assertInstanceof(layer, ol.layer.Vector); - layer.getSkippedFeatures().push(feature); - hash[uid] = [layer]; }; @@ -193,19 +180,8 @@ ol.interaction.Select.prototype.addFeature_ = function(feature, layer, add, * @todo stability experimental */ ol.interaction.Select.prototype.removeFeature_ = function(feature) { - var features = this.featureOverlay_.getFeatures(), - hash = this.featuresLayerHash_, - uid = goog.getUid(feature), - i, ii, layer; - features.remove(feature); - for (i = 0, ii = hash[uid].length; i < ii; i++) { - layer = hash[uid][i]; - if (!goog.isNull(layer)) { - goog.asserts.assertInstanceof(layer, ol.layer.Vector); - layer.getSkippedFeatures().remove(feature); - } - } - delete hash[uid]; + this.featureOverlay_.getFeatures().remove(feature); + this.getMap().getSkippedFeatures().remove(feature); }; diff --git a/src/ol/layer/vectorlayer.js b/src/ol/layer/vectorlayer.js index e5bb858d38..1758fae0c5 100644 --- a/src/ol/layer/vectorlayer.js +++ b/src/ol/layer/vectorlayer.js @@ -1,11 +1,7 @@ goog.provide('ol.layer.Vector'); goog.require('goog.array'); -goog.require('goog.events'); -goog.require('goog.events.EventType'); goog.require('goog.object'); -goog.require('ol.Collection'); -goog.require('ol.CollectionEventType'); goog.require('ol.feature'); goog.require('ol.layer.Layer'); @@ -45,25 +41,6 @@ ol.layer.Vector = function(opt_options) { this.setStyle(options.style); } - /** - * Collection of Features to skip drawing. - * @type {ol.Collection} - * @private - */ - this.skippedFeatures_ = new ol.Collection(); - - /** - * Array of Feature ids to skip drawing. - * @type {Array.} - * @private - */ - this.skippedFeaturesIds_ = []; - - goog.events.listen(this.skippedFeatures_, [ - ol.CollectionEventType.REMOVE, - ol.CollectionEventType.ADD - ], this.updateSkippedFeaturesArray_, false, this); - }; goog.inherits(ol.layer.Vector, ol.layer.Layer); @@ -102,36 +79,3 @@ ol.layer.Vector.prototype.setStyle = function(style) { this.styleFunction_ = ol.feature.createStyleFunction(style); this.dispatchChangeEvent(); }; - - -/** - * Update Features Ids internal array. - * @private - */ -ol.layer.Vector.prototype.updateSkippedFeaturesArray_ = function() { - this.skippedFeaturesIds_ = goog.array.map( - this.skippedFeatures_.getArray(), goog.getUid); - // Don’t use dispatchChangeEvent here because we don’t want the batch - // to be re-created, just replayed. - this.dispatchEvent(goog.events.EventType.CHANGE); -}; - - -/** - * Get the collection of features to be skipped. - * @return {ol.Collection} Features collection. - * @todo stability experimental - */ -ol.layer.Vector.prototype.getSkippedFeatures = function() { - return this.skippedFeatures_; -}; - - -/** - * Get the feature’s ids to be skipped. - * @return {Array.} Array of features Ids - * @todo stability experimental - */ -ol.layer.Vector.prototype.getSkippedFeaturesIds = function() { - return this.skippedFeaturesIds_; -}; diff --git a/src/ol/map.js b/src/ol/map.js index 0af7b31379..49fd9eb46a 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -359,6 +359,13 @@ ol.Map = function(options) { goog.bind(this.getTilePriority, this), goog.bind(this.handleTileChange_, this)); + /** + * Collection of Features to skip drawing. + * @type {ol.Collection} + * @private + */ + this.skippedFeatures_ = new ol.Collection(); + goog.events.listen( this, ol.Object.getChangeEventType(ol.MapProperty.LAYERGROUP), this.handleLayerGroupChanged_, false, this); @@ -797,6 +804,16 @@ ol.Map.prototype.getTilePriority = }; +/** + * Get the collection of features to be skipped. + * @return {ol.Collection} Features collection. + * @todo stability experimental + */ +ol.Map.prototype.getSkippedFeatures = function() { + return this.skippedFeatures_; +}; + + /** * @param {goog.events.BrowserEvent} browserEvent Browser event. * @param {string=} opt_type Type. @@ -1181,6 +1198,8 @@ ol.Map.prototype.renderFrame_ = function(time) { pixelToCoordinateMatrix: this.pixelToCoordinateMatrix_, postRenderFunctions: [], size: size, + skippedFeaturesIds: goog.array.map( + this.skippedFeatures_.getArray(), goog.getUid), tileQueue: this.tileQueue_, time: time, usedTiles: {}, diff --git a/src/ol/renderer/canvas/canvasvectorlayerrenderer.js b/src/ol/renderer/canvas/canvasvectorlayerrenderer.js index 30cb9f3130..73d610d1b2 100644 --- a/src/ol/renderer/canvas/canvasvectorlayerrenderer.js +++ b/src/ol/renderer/canvas/canvasvectorlayerrenderer.js @@ -95,13 +95,10 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame = } else { replayContext = context; } - goog.asserts.assertInstanceof(layer, ol.layer.Vector); - var skippedFeaturesIds = layer.getSkippedFeaturesIds(); - goog.asserts.assert(goog.isArray(skippedFeaturesIds)); replayContext.globalAlpha = layerState.opacity; replayGroup.replay( replayContext, frameState.extent, frameState.pixelRatio, transform, - frameState.view2DState.rotation, skippedFeaturesIds); + frameState.view2DState.rotation, frameState.skippedFeaturesIds); if (replayContext != context) { this.dispatchRenderEvent(replayContext, frameState, transform); @@ -126,11 +123,8 @@ ol.renderer.canvas.VectorLayer.prototype.forEachFeatureAtPixel = var resolution = frameState.view2DState.resolution; var rotation = frameState.view2DState.rotation; var layer = this.getLayer(); - goog.asserts.assertInstanceof(layer, ol.layer.Vector); - var skippedFeaturesIds = layer.getSkippedFeaturesIds(); - goog.asserts.assert(goog.isArray(skippedFeaturesIds)); return this.replayGroup_.forEachGeometryAtPixel(extent, resolution, - rotation, coordinate, skippedFeaturesIds, + rotation, coordinate, frameState.skippedFeaturesIds, /** * @param {ol.geom.Geometry} geometry Geometry. * @param {Object} data Data. From e1e4969599bc6d66dda8434aa0ccb4ce65c21a30 Mon Sep 17 00:00:00 2001 From: Antoine Abt Date: Thu, 20 Mar 2014 10:24:39 +0100 Subject: [PATCH 06/13] Name frameState skippedFeaturesIds as private --- externs/oli.js | 2 +- src/ol/renderer/canvas/canvasvectorlayerrenderer.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/externs/oli.js b/externs/oli.js index e8bef6d3a8..d214f823f4 100644 --- a/externs/oli.js +++ b/externs/oli.js @@ -93,7 +93,7 @@ oli.FrameState.prototype.size; /** @type {Array.} */ -oli.FrameState.prototype.skippedFeaturesIds; +oli.FrameState.prototype.skippedFeaturesIds_; /** @type {ol.TileQueue} */ diff --git a/src/ol/renderer/canvas/canvasvectorlayerrenderer.js b/src/ol/renderer/canvas/canvasvectorlayerrenderer.js index 73d610d1b2..e5131bd7a1 100644 --- a/src/ol/renderer/canvas/canvasvectorlayerrenderer.js +++ b/src/ol/renderer/canvas/canvasvectorlayerrenderer.js @@ -98,7 +98,7 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame = replayContext.globalAlpha = layerState.opacity; replayGroup.replay( replayContext, frameState.extent, frameState.pixelRatio, transform, - frameState.view2DState.rotation, frameState.skippedFeaturesIds); + frameState.view2DState.rotation, frameState.skippedFeaturesIds_); if (replayContext != context) { this.dispatchRenderEvent(replayContext, frameState, transform); @@ -124,7 +124,7 @@ ol.renderer.canvas.VectorLayer.prototype.forEachFeatureAtPixel = var rotation = frameState.view2DState.rotation; var layer = this.getLayer(); return this.replayGroup_.forEachGeometryAtPixel(extent, resolution, - rotation, coordinate, frameState.skippedFeaturesIds, + rotation, coordinate, frameState.skippedFeaturesIds_, /** * @param {ol.geom.Geometry} geometry Geometry. * @param {Object} data Data. From d0f2dd354bfd6ae8095cdf7dd3b0121ef15e9ae7 Mon Sep 17 00:00:00 2001 From: Antoine Abt Date: Thu, 20 Mar 2014 10:25:45 +0100 Subject: [PATCH 07/13] Trigger render on skippedFeatures change --- src/ol/map.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ol/map.js b/src/ol/map.js index 49fd9eb46a..a179dd23af 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -365,6 +365,10 @@ ol.Map = function(options) { * @private */ this.skippedFeatures_ = new ol.Collection(); + goog.events.listen(this.skippedFeatures_, + [ol.CollectionEventType.ADD, ol.CollectionEventType.remove], + this.render, false, this); + this.registerDisposable(this.skippedFeatures_); goog.events.listen( this, ol.Object.getChangeEventType(ol.MapProperty.LAYERGROUP), From 78039aceb8cd57c0038cc9cd7a8c77c780360e68 Mon Sep 17 00:00:00 2001 From: Antoine Abt Date: Thu, 20 Mar 2014 13:03:31 +0100 Subject: [PATCH 08/13] Use a hash to store features uids --- externs/oli.js | 4 +- src/ol/map.js | 36 +++++++++++++-- src/ol/render/canvas/canvasreplay.js | 46 +++++++++---------- .../canvas/canvasvectorlayerrenderer.js | 4 +- src/ol/source/imagevectorsource.js | 4 +- 5 files changed, 61 insertions(+), 33 deletions(-) diff --git a/externs/oli.js b/externs/oli.js index d214f823f4..8ad98ea52a 100644 --- a/externs/oli.js +++ b/externs/oli.js @@ -92,8 +92,8 @@ oli.FrameState.prototype.postRenderFunctions; oli.FrameState.prototype.size; -/** @type {Array.} */ -oli.FrameState.prototype.skippedFeaturesIds_; +/** @type {Object} */ +oli.FrameState.prototype.skippedFeaturesHash_; /** @type {ol.TileQueue} */ diff --git a/src/ol/map.js b/src/ol/map.js index a179dd23af..0b5b72465b 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -366,10 +366,17 @@ ol.Map = function(options) { */ this.skippedFeatures_ = new ol.Collection(); goog.events.listen(this.skippedFeatures_, - [ol.CollectionEventType.ADD, ol.CollectionEventType.remove], - this.render, false, this); + [ol.CollectionEventType.ADD, ol.CollectionEventType.REMOVE], + this.handleSkippedFeaturesChange_, false, this); this.registerDisposable(this.skippedFeatures_); + /** + * Hash of features uid to skip drawing. + * @type {Object} + * @private + */ + this.skippedFeaturesHash_ = {}; + goog.events.listen( this, ol.Object.getChangeEventType(ol.MapProperty.LAYERGROUP), this.handleLayerGroupChanged_, false, this); @@ -818,6 +825,16 @@ ol.Map.prototype.getSkippedFeatures = function() { }; +/** + * Get the hash of features uids to be skipped. + * @return {Object} Features uids hash + * @todo stability experimental + */ +ol.Map.prototype.getSkippedFeaturesHash = function() { + return this.skippedFeaturesHash_; +}; + + /** * @param {goog.events.BrowserEvent} browserEvent Browser event. * @param {string=} opt_type Type. @@ -917,6 +934,18 @@ ol.Map.prototype.handleSizeChanged_ = function() { }; +/** + * @private + */ +ol.Map.prototype.handleSkippedFeaturesChange_ = function() { + this.skippedFeaturesHash_ = {}; + this.skippedFeatures_.forEach(function(feature) { + this.skippedFeaturesHash_[goog.getUid(feature).toString()] = true; + }, this); + this.render(); +}; + + /** * @private */ @@ -1202,8 +1231,7 @@ ol.Map.prototype.renderFrame_ = function(time) { pixelToCoordinateMatrix: this.pixelToCoordinateMatrix_, postRenderFunctions: [], size: size, - skippedFeaturesIds: goog.array.map( - this.skippedFeatures_.getArray(), goog.getUid), + skippedFeaturesHash_: this.skippedFeaturesHash_, tileQueue: this.tileQueue_, time: time, usedTiles: {}, diff --git a/src/ol/render/canvas/canvasreplay.js b/src/ol/render/canvas/canvasreplay.js index 0d2787ce55..18a15c9db5 100644 --- a/src/ol/render/canvas/canvasreplay.js +++ b/src/ol/render/canvas/canvasreplay.js @@ -209,7 +209,7 @@ ol.render.canvas.Replay.prototype.beginGeometry = function(geometry, uid) { this.beginGeometryInstruction1_ = [ol.render.canvas.Instruction.BEGIN_GEOMETRY, geometry, 0]; this.instructions.push(this.beginGeometryInstruction1_); - this.instructionIndices_[this.instructions.length - 1] = uid; + this.instructionIndices_[this.instructions.length - 1] = uid.toString(); this.beginGeometryInstruction2_ = [ol.render.canvas.Instruction.BEGIN_GEOMETRY, geometry, 0]; this.hitDetectionInstructions.push(this.beginGeometryInstruction2_); @@ -222,7 +222,7 @@ ol.render.canvas.Replay.prototype.beginGeometry = function(geometry, uid) { * @param {number} pixelRatio Pixel ratio. * @param {goog.vec.Mat4.Number} transform Transform. * @param {number} viewRotation View rotation. - * @param {Array.} skippedFeaturesIds Ids of features to skip. + * @param {Object} skippedFeaturesHash Ids of features to skip. * @param {Array.<*>} instructions Instructions array. * @param {function(ol.geom.Geometry, Object): T|undefined} geometryCallback * Geometry callback. @@ -230,7 +230,7 @@ ol.render.canvas.Replay.prototype.beginGeometry = function(geometry, uid) { * @template T */ ol.render.canvas.Replay.prototype.replay_ = function( - context, pixelRatio, transform, viewRotation, skippedFeaturesIds, + context, pixelRatio, transform, viewRotation, skippedFeaturesHash, instructions, geometryCallback) { /** @type {Array.} */ var pixelCoordinates; @@ -254,8 +254,8 @@ ol.render.canvas.Replay.prototype.replay_ = function( switch (type) { case ol.render.canvas.Instruction.BEGIN_GEOMETRY: geometry = /** @type {ol.geom.Geometry} */ (instruction[1]); - if (!goog.array.contains(skippedFeaturesIds, - this.instructionIndices_[i])) { + if (!goog.isDef(goog.object.get(skippedFeaturesHash, + this.instructionIndices_[i]))) { ++i; } else { i = /** @type {number} */ (instruction[2]); @@ -461,15 +461,15 @@ ol.render.canvas.Replay.prototype.replay_ = function( * @param {number} pixelRatio Pixel ratio. * @param {goog.vec.Mat4.Number} transform Transform. * @param {number} viewRotation View rotation. - * @param {Array.} skippedFeaturesIds Ids of features to skip + * @param {Object} skippedFeaturesHash Ids of features to skip * @return {T|undefined} Callback result. * @template T */ ol.render.canvas.Replay.prototype.replay = function( - context, pixelRatio, transform, viewRotation, skippedFeaturesIds) { + context, pixelRatio, transform, viewRotation, skippedFeaturesHash) { var instructions = this.instructions; return this.replay_(context, pixelRatio, transform, viewRotation, - skippedFeaturesIds, instructions, undefined); + skippedFeaturesHash, instructions, undefined); }; @@ -477,18 +477,18 @@ ol.render.canvas.Replay.prototype.replay = function( * @param {CanvasRenderingContext2D} context Context. * @param {goog.vec.Mat4.Number} transform Transform. * @param {number} viewRotation View rotation. - * @param {Array.} skippedFeaturesIds Ids of features to skip + * @param {Object} skippedFeaturesHash Ids of features to skip * @param {function(ol.geom.Geometry, Object): T=} opt_geometryCallback * Geometry callback. * @return {T|undefined} Callback result. * @template T */ ol.render.canvas.Replay.prototype.replayHitDetection = function( - context, transform, viewRotation, skippedFeaturesIds, + context, transform, viewRotation, skippedFeaturesHash, opt_geometryCallback) { var instructions = this.hitDetectionInstructions; return this.replay_(context, 1, transform, viewRotation, - skippedFeaturesIds, instructions, opt_geometryCallback); + skippedFeaturesHash, instructions, opt_geometryCallback); }; @@ -1850,17 +1850,17 @@ ol.render.canvas.ReplayGroup = function(tolerance, maxExtent, resolution) { * @param {number} pixelRatio Pixel ratio. * @param {goog.vec.Mat4.Number} transform Transform. * @param {number} viewRotation View rotation. - * @param {Array.} skippedFeaturesIds Ids of features to skip + * @param {Object} skippedFeaturesHash Ids of features to skip * @return {T|undefined} Callback result. * @template T */ ol.render.canvas.ReplayGroup.prototype.replay = function(context, extent, - pixelRatio, transform, viewRotation, skippedFeaturesIds) { + pixelRatio, transform, viewRotation, skippedFeaturesHash) { /** @type {Array.} */ var zs = goog.array.map(goog.object.getKeys(this.replaysByZIndex_), Number); goog.array.sort(zs); return this.replay_(zs, context, extent, pixelRatio, transform, - viewRotation, skippedFeaturesIds); + viewRotation, skippedFeaturesHash); }; @@ -1871,14 +1871,14 @@ ol.render.canvas.ReplayGroup.prototype.replay = function(context, extent, * @param {ol.Extent} extent Extent. * @param {goog.vec.Mat4.Number} transform Transform. * @param {number} viewRotation View rotation. - * @param {Array.} skippedFeaturesIds Ids of features to skip + * @param {Object} skippedFeaturesHash Ids of features to skip * @param {function(ol.geom.Geometry, Object): T} geometryCallback Geometry * callback. * @return {T|undefined} Callback result. * @template T */ ol.render.canvas.ReplayGroup.prototype.replayHitDetection_ = function( - zs, context, extent, transform, viewRotation, skippedFeaturesIds, + zs, context, extent, transform, viewRotation, skippedFeaturesHash, geometryCallback) { var i, ii, replays, replayType, replay, result; for (i = 0, ii = zs.length; i < ii; ++i) { @@ -1887,7 +1887,7 @@ ol.render.canvas.ReplayGroup.prototype.replayHitDetection_ = function( replay = replays[replayType]; if (ol.extent.intersects(extent, replay.getExtent())) { result = replay.replayHitDetection(context, transform, viewRotation, - skippedFeaturesIds, geometryCallback); + skippedFeaturesHash, geometryCallback); if (result) { return result; } @@ -1906,13 +1906,13 @@ ol.render.canvas.ReplayGroup.prototype.replayHitDetection_ = function( * @param {number} pixelRatio Pixel ratio. * @param {goog.vec.Mat4.Number} transform Transform. * @param {number} viewRotation View rotation. - * @param {Array.} skippedFeaturesIds Ids of features to skip + * @param {Object} skippedFeaturesHash Ids of features to skip * @return {T|undefined} Callback result. * @template T */ ol.render.canvas.ReplayGroup.prototype.replay_ = function( zs, context, extent, pixelRatio, transform, viewRotation, - skippedFeaturesIds) { + skippedFeaturesHash) { var maxExtent = this.maxExtent_; var minX = maxExtent[0]; @@ -1938,7 +1938,7 @@ ol.render.canvas.ReplayGroup.prototype.replay_ = function( if (goog.isDef(replay) && ol.extent.intersects(extent, replay.getExtent())) { result = replay.replay(context, pixelRatio, transform, viewRotation, - skippedFeaturesIds); + skippedFeaturesHash); if (result) { return result; } @@ -1956,14 +1956,14 @@ ol.render.canvas.ReplayGroup.prototype.replay_ = function( * @param {number} resolution Resolution. * @param {number} rotation Rotation. * @param {ol.Coordinate} coordinate Coordinate. - * @param {Array.} skippedFeaturesIds Ids of features to skip + * @param {Object} skippedFeaturesHash Ids of features to skip * @param {function(ol.geom.Geometry, Object): T} callback Geometry callback. * @return {T|undefined} Callback result. * @template T */ ol.render.canvas.ReplayGroup.prototype.forEachGeometryAtPixel = function( extent, resolution, rotation, coordinate, - skippedFeaturesIds, callback) { + skippedFeaturesHash, callback) { var transform = this.hitDetectionTransform_; ol.vec.Mat4.makeTransform2D(transform, 0.5, 0.5, @@ -1978,7 +1978,7 @@ ol.render.canvas.ReplayGroup.prototype.forEachGeometryAtPixel = function( context.clearRect(0, 0, 1, 1); return this.replayHitDetection_(zs, context, extent, transform, - rotation, skippedFeaturesIds, + rotation, skippedFeaturesHash, /** * @param {ol.geom.Geometry} geometry Geometry. * @param {Object} data Opaque data object. diff --git a/src/ol/renderer/canvas/canvasvectorlayerrenderer.js b/src/ol/renderer/canvas/canvasvectorlayerrenderer.js index e5131bd7a1..98cb70b2f9 100644 --- a/src/ol/renderer/canvas/canvasvectorlayerrenderer.js +++ b/src/ol/renderer/canvas/canvasvectorlayerrenderer.js @@ -98,7 +98,7 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame = replayContext.globalAlpha = layerState.opacity; replayGroup.replay( replayContext, frameState.extent, frameState.pixelRatio, transform, - frameState.view2DState.rotation, frameState.skippedFeaturesIds_); + frameState.view2DState.rotation, frameState.skippedFeaturesHash_); if (replayContext != context) { this.dispatchRenderEvent(replayContext, frameState, transform); @@ -124,7 +124,7 @@ ol.renderer.canvas.VectorLayer.prototype.forEachFeatureAtPixel = var rotation = frameState.view2DState.rotation; var layer = this.getLayer(); return this.replayGroup_.forEachGeometryAtPixel(extent, resolution, - rotation, coordinate, frameState.skippedFeaturesIds_, + rotation, coordinate, frameState.skippedFeaturesHash_, /** * @param {ol.geom.Geometry} geometry Geometry. * @param {Object} data Data. diff --git a/src/ol/source/imagevectorsource.js b/src/ol/source/imagevectorsource.js index f4a436ee17..be8d85e463 100644 --- a/src/ol/source/imagevectorsource.js +++ b/src/ol/source/imagevectorsource.js @@ -141,7 +141,7 @@ ol.source.ImageVector.prototype.canvasFunctionInternal_ = var transform = this.getTransform_(ol.extent.getCenter(extent), resolution, pixelRatio, size); replayGroup.replay(this.canvasContext_, extent, pixelRatio, transform, 0, - []); + {}); this.replayGroup_ = replayGroup; @@ -158,7 +158,7 @@ ol.source.ImageVector.prototype.forEachFeatureAtPixel = return undefined; } else { return this.replayGroup_.forEachGeometryAtPixel( - extent, resolution, 0, coordinate, [], + extent, resolution, 0, coordinate, {}, /** * @param {ol.geom.Geometry} geometry Geometry. * @param {Object} data Data. From 6a4c2bccc5e54de975dbec88e70ec955665b1917 Mon Sep 17 00:00:00 2001 From: Antoine Abt Date: Thu, 20 Mar 2014 13:08:10 +0100 Subject: [PATCH 09/13] Coding style --- src/ol/interaction/selectinteraction.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/ol/interaction/selectinteraction.js b/src/ol/interaction/selectinteraction.js index 78b9e40f83..2398b850e8 100644 --- a/src/ol/interaction/selectinteraction.js +++ b/src/ol/interaction/selectinteraction.js @@ -140,15 +140,14 @@ ol.interaction.Select.prototype.handleMapBrowserEvent = */ ol.interaction.Select.prototype.addFeature_ = function(feature, add, remove, toggle) { - var features = this.featureOverlay_.getFeatures(), - uid, index = -1, - i, ii; + var features = this.featureOverlay_.getFeatures(); + var index = -1; + var i, ii; if ((!goog.isDef(feature) || goog.isNull(feature)) && !add) { this.removeAllFeatures_(); return; } goog.asserts.assertInstanceof(feature, ol.Feature); - uid = goog.getUid(feature); index = features.getArray().indexOf(feature); if (index == -1) { if (!add && !remove && (features.getLength() > 0)) { From 435e5e69164cccedba96c68049d5a2f83097db24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Thu, 20 Mar 2014 13:19:54 +0100 Subject: [PATCH 10/13] Better type checking in ol.Map --- externs/oli.js | 2 +- src/ol/map.js | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/externs/oli.js b/externs/oli.js index 8ad98ea52a..36d3f19097 100644 --- a/externs/oli.js +++ b/externs/oli.js @@ -92,7 +92,7 @@ oli.FrameState.prototype.postRenderFunctions; oli.FrameState.prototype.size; -/** @type {Object} */ +/** @type {Object.} */ oli.FrameState.prototype.skippedFeaturesHash_; diff --git a/src/ol/map.js b/src/ol/map.js index 0b5b72465b..1a72f3bbac 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -372,7 +372,7 @@ ol.Map = function(options) { /** * Hash of features uid to skip drawing. - * @type {Object} + * @type {Object.} * @private */ this.skippedFeaturesHash_ = {}; @@ -939,9 +939,14 @@ ol.Map.prototype.handleSizeChanged_ = function() { */ ol.Map.prototype.handleSkippedFeaturesChange_ = function() { this.skippedFeaturesHash_ = {}; - this.skippedFeatures_.forEach(function(feature) { - this.skippedFeaturesHash_[goog.getUid(feature).toString()] = true; - }, this); + this.skippedFeatures_.forEach( + /** + * @param {ol.Feature} feature Feature. + * @this {ol.Map} + */ + function(feature) { + this.skippedFeaturesHash_[goog.getUid(feature).toString()] = true; + }, this); this.render(); }; From 71484d9a53446c52833664028d8e79e0d71d69b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Thu, 20 Mar 2014 13:25:20 +0100 Subject: [PATCH 11/13] Better API doc strings in ol.Map --- src/ol/map.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ol/map.js b/src/ol/map.js index 1a72f3bbac..a9d24ec2ea 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -360,7 +360,7 @@ ol.Map = function(options) { goog.bind(this.handleTileChange_, this)); /** - * Collection of Features to skip drawing. + * Features to skip at rendering time. * @type {ol.Collection} * @private */ @@ -371,7 +371,7 @@ ol.Map = function(options) { this.registerDisposable(this.skippedFeatures_); /** - * Hash of features uid to skip drawing. + * Uids of features to skip at rendering time. * @type {Object.} * @private */ @@ -816,7 +816,7 @@ ol.Map.prototype.getTilePriority = /** - * Get the collection of features to be skipped. + * Get the collection of features to skip. * @return {ol.Collection} Features collection. * @todo stability experimental */ @@ -826,8 +826,8 @@ ol.Map.prototype.getSkippedFeatures = function() { /** - * Get the hash of features uids to be skipped. - * @return {Object} Features uids hash + * Get the uids of features to skip. + * @return {Object} Feature uids. * @todo stability experimental */ ol.Map.prototype.getSkippedFeaturesHash = function() { From c4b654b26c55b9d9afa3254155c4eff9f6339fc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Thu, 20 Mar 2014 13:29:30 +0100 Subject: [PATCH 12/13] Rename skippedFeaturesHash to skippedFeatureUids --- externs/oli.js | 2 +- src/ol/map.js | 12 ++++++------ src/ol/renderer/canvas/canvasvectorlayerrenderer.js | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/externs/oli.js b/externs/oli.js index 36d3f19097..30945f1a70 100644 --- a/externs/oli.js +++ b/externs/oli.js @@ -93,7 +93,7 @@ oli.FrameState.prototype.size; /** @type {Object.} */ -oli.FrameState.prototype.skippedFeaturesHash_; +oli.FrameState.prototype.skippedFeatureUids_; /** @type {ol.TileQueue} */ diff --git a/src/ol/map.js b/src/ol/map.js index a9d24ec2ea..f0206605ec 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -375,7 +375,7 @@ ol.Map = function(options) { * @type {Object.} * @private */ - this.skippedFeaturesHash_ = {}; + this.skippedFeatureUids_ = {}; goog.events.listen( this, ol.Object.getChangeEventType(ol.MapProperty.LAYERGROUP), @@ -830,8 +830,8 @@ ol.Map.prototype.getSkippedFeatures = function() { * @return {Object} Feature uids. * @todo stability experimental */ -ol.Map.prototype.getSkippedFeaturesHash = function() { - return this.skippedFeaturesHash_; +ol.Map.prototype.getSkippedFeatureUids = function() { + return this.skippedFeatureUids_; }; @@ -938,14 +938,14 @@ ol.Map.prototype.handleSizeChanged_ = function() { * @private */ ol.Map.prototype.handleSkippedFeaturesChange_ = function() { - this.skippedFeaturesHash_ = {}; + this.skippedFeatureUids_ = {}; this.skippedFeatures_.forEach( /** * @param {ol.Feature} feature Feature. * @this {ol.Map} */ function(feature) { - this.skippedFeaturesHash_[goog.getUid(feature).toString()] = true; + this.skippedFeatureUids_[goog.getUid(feature).toString()] = true; }, this); this.render(); }; @@ -1236,7 +1236,7 @@ ol.Map.prototype.renderFrame_ = function(time) { pixelToCoordinateMatrix: this.pixelToCoordinateMatrix_, postRenderFunctions: [], size: size, - skippedFeaturesHash_: this.skippedFeaturesHash_, + skippedFeatureUids_: this.skippedFeatureUids_, tileQueue: this.tileQueue_, time: time, usedTiles: {}, diff --git a/src/ol/renderer/canvas/canvasvectorlayerrenderer.js b/src/ol/renderer/canvas/canvasvectorlayerrenderer.js index 98cb70b2f9..37eeaffe8d 100644 --- a/src/ol/renderer/canvas/canvasvectorlayerrenderer.js +++ b/src/ol/renderer/canvas/canvasvectorlayerrenderer.js @@ -98,7 +98,7 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame = replayContext.globalAlpha = layerState.opacity; replayGroup.replay( replayContext, frameState.extent, frameState.pixelRatio, transform, - frameState.view2DState.rotation, frameState.skippedFeaturesHash_); + frameState.view2DState.rotation, frameState.skippedFeatureUids_); if (replayContext != context) { this.dispatchRenderEvent(replayContext, frameState, transform); @@ -124,7 +124,7 @@ ol.renderer.canvas.VectorLayer.prototype.forEachFeatureAtPixel = var rotation = frameState.view2DState.rotation; var layer = this.getLayer(); return this.replayGroup_.forEachGeometryAtPixel(extent, resolution, - rotation, coordinate, frameState.skippedFeaturesHash_, + rotation, coordinate, frameState.skippedFeatureUids_, /** * @param {ol.geom.Geometry} geometry Geometry. * @param {Object} data Data. From 3b642ae54906a9b8193291addae67182b6ca7060 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Thu, 20 Mar 2014 13:30:45 +0100 Subject: [PATCH 13/13] Remove the getSkippedFeatureUids function --- src/ol/map.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/ol/map.js b/src/ol/map.js index f0206605ec..fbe46a52cd 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -825,16 +825,6 @@ ol.Map.prototype.getSkippedFeatures = function() { }; -/** - * Get the uids of features to skip. - * @return {Object} Feature uids. - * @todo stability experimental - */ -ol.Map.prototype.getSkippedFeatureUids = function() { - return this.skippedFeatureUids_; -}; - - /** * @param {goog.events.BrowserEvent} browserEvent Browser event. * @param {string=} opt_type Type.