From 7feb8b22f687046e0c1b7b238c5304893e0d5f30 Mon Sep 17 00:00:00 2001 From: tsauerwein Date: Fri, 23 Jan 2015 15:07:02 +0100 Subject: [PATCH 01/10] Rename forEachGeometryAtPixel --- src/ol/render/canvas/canvasreplay.js | 2 +- src/ol/renderer/canvas/canvasvectorlayerrenderer.js | 2 +- src/ol/renderer/dom/domvectorlayerrenderer.js | 2 +- src/ol/renderer/maprenderer.js | 2 +- src/ol/source/imagevectorsource.js | 2 +- test/spec/ol/renderer/canvas/canvasvectorlayerrenderer.test.js | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ol/render/canvas/canvasreplay.js b/src/ol/render/canvas/canvasreplay.js index 8b8eed5689..97619a1629 100644 --- a/src/ol/render/canvas/canvasreplay.js +++ b/src/ol/render/canvas/canvasreplay.js @@ -1866,7 +1866,7 @@ ol.render.canvas.ReplayGroup.prototype.finish = function() { * @return {T|undefined} Callback result. * @template T */ -ol.render.canvas.ReplayGroup.prototype.forEachGeometryAtPixel = function( +ol.render.canvas.ReplayGroup.prototype.forEachFeatureAtPixel = function( resolution, rotation, coordinate, skippedFeaturesHash, callback) { var transform = this.hitDetectionTransform_; diff --git a/src/ol/renderer/canvas/canvasvectorlayerrenderer.js b/src/ol/renderer/canvas/canvasvectorlayerrenderer.js index 1588568263..a7c4842698 100644 --- a/src/ol/renderer/canvas/canvasvectorlayerrenderer.js +++ b/src/ol/renderer/canvas/canvasvectorlayerrenderer.js @@ -126,7 +126,7 @@ ol.renderer.canvas.VectorLayer.prototype.forEachFeatureAtPixel = var layer = this.getLayer(); /** @type {Object.} */ var features = {}; - return this.replayGroup_.forEachGeometryAtPixel(resolution, + return this.replayGroup_.forEachFeatureAtPixel(resolution, rotation, coordinate, frameState.skippedFeatureUids, /** * @param {ol.Feature} feature Feature. diff --git a/src/ol/renderer/dom/domvectorlayerrenderer.js b/src/ol/renderer/dom/domvectorlayerrenderer.js index 90fa5127b2..8c46bce8d0 100644 --- a/src/ol/renderer/dom/domvectorlayerrenderer.js +++ b/src/ol/renderer/dom/domvectorlayerrenderer.js @@ -186,7 +186,7 @@ ol.renderer.dom.VectorLayer.prototype.forEachFeatureAtPixel = var layer = this.getLayer(); /** @type {Object.} */ var features = {}; - return this.replayGroup_.forEachGeometryAtPixel(resolution, + return this.replayGroup_.forEachFeatureAtPixel(resolution, rotation, coordinate, frameState.skippedFeatureUids, /** * @param {ol.Feature} feature Feature. diff --git a/src/ol/renderer/maprenderer.js b/src/ol/renderer/maprenderer.js index fb8adbcb42..10b0429bd8 100644 --- a/src/ol/renderer/maprenderer.js +++ b/src/ol/renderer/maprenderer.js @@ -131,7 +131,7 @@ ol.renderer.Map.prototype.forEachFeatureAtPixel = if (!goog.isNull(this.replayGroup)) { /** @type {Object.} */ var features = {}; - result = this.replayGroup.forEachGeometryAtPixel(viewResolution, + result = this.replayGroup.forEachFeatureAtPixel(viewResolution, viewRotation, coordinate, {}, /** * @param {ol.Feature} feature Feature. diff --git a/src/ol/source/imagevectorsource.js b/src/ol/source/imagevectorsource.js index ee40500e33..0bdd75a319 100644 --- a/src/ol/source/imagevectorsource.js +++ b/src/ol/source/imagevectorsource.js @@ -159,7 +159,7 @@ ol.source.ImageVector.prototype.forEachFeatureAtPixel = function( } else { /** @type {Object.} */ var features = {}; - return this.replayGroup_.forEachGeometryAtPixel( + return this.replayGroup_.forEachFeatureAtPixel( resolution, 0, coordinate, skippedFeatureUids, /** * @param {ol.Feature} feature Feature. diff --git a/test/spec/ol/renderer/canvas/canvasvectorlayerrenderer.test.js b/test/spec/ol/renderer/canvas/canvasvectorlayerrenderer.test.js index 65971bb0a6..a1165aebaa 100644 --- a/test/spec/ol/renderer/canvas/canvasvectorlayerrenderer.test.js +++ b/test/spec/ol/renderer/canvas/canvasvectorlayerrenderer.test.js @@ -70,7 +70,7 @@ describe('ol.renderer.canvas.VectorLayer', function() { map.getRenderer(), layer); var replayGroup = {}; renderer.replayGroup_ = replayGroup; - replayGroup.forEachGeometryAtPixel = function(resolution, + replayGroup.forEachFeatureAtPixel = function(resolution, rotation, coordinate, skippedFeaturesUids, callback) { var geometry = new ol.geom.Point([0, 0]); var feature = new ol.Feature(); From 225f0739ecec03b2585a971fe1a52d184032ab14 Mon Sep 17 00:00:00 2001 From: tsauerwein Date: Fri, 23 Jan 2015 16:16:06 +0100 Subject: [PATCH 02/10] Add forEachLayerAtPixel --- src/ol/map.js | 38 +++++++++++++++++++++++ src/ol/renderer/layerrenderer.js | 21 +++++++++++++ src/ol/renderer/maprenderer.js | 53 ++++++++++++++++++++++++++++++++ 3 files changed, 112 insertions(+) diff --git a/src/ol/map.js b/src/ol/map.js index c353275e55..11f38bba82 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -589,6 +589,44 @@ ol.Map.prototype.forEachFeatureAtPixel = }; +/** + * Detect layers that have a colour value at a pixel on the viewport, and + * execute a callback with each matching layer. Layers included in the + * detection can be configured through `opt_layerFilter`. Feature overlays will + * always be included in the detection. + * @param {ol.Pixel} pixel Pixel. + * @param {function(this: S, ol.layer.Layer): T} callback Layer + * callback. If the detected feature is not on a layer, but on a + * {@link ol.FeatureOverlay}, then the argument to this function will + * be `null`. To stop detection, callback functions can return a truthy + * value. + * @param {S=} opt_this Value to use as `this` when executing `callback`. + * @param {(function(this: U, ol.layer.Layer): boolean)=} opt_layerFilter Layer + * filter function, only layers which are visible and for which this + * function returns `true` will be tested for features. By default, all + * visible layers will be tested. Feature overlays will always be tested. + * @param {U=} opt_this2 Value to use as `this` when executing `layerFilter`. + * @return {T|undefined} Callback result, i.e. the return value of last + * callback execution, or the first truthy callback return value. + * @template S,T,U + * @api stable + */ +ol.Map.prototype.forEachLayerAtPixel = + function(pixel, callback, opt_this, opt_layerFilter, opt_this2) { + if (goog.isNull(this.frameState_)) { + return; + } + var coordinate = this.getCoordinateFromPixel(pixel); + var thisArg = goog.isDef(opt_this) ? opt_this : null; + var layerFilter = goog.isDef(opt_layerFilter) ? + opt_layerFilter : goog.functions.TRUE; + var thisArg2 = goog.isDef(opt_this2) ? opt_this2 : null; + return this.renderer_.forEachLayerAtPixel( + coordinate, this.frameState_, callback, thisArg, + layerFilter, thisArg2); +}; + + /** * Detect if features intersect a pixel on the viewport. Layers included in the * detection can be configured through `opt_layerFilter`. Feature overlays will diff --git a/src/ol/renderer/layerrenderer.js b/src/ol/renderer/layerrenderer.js index 77b76f17f9..490751926e 100644 --- a/src/ol/renderer/layerrenderer.js +++ b/src/ol/renderer/layerrenderer.js @@ -56,6 +56,27 @@ goog.inherits(ol.renderer.Layer, goog.Disposable); ol.renderer.Layer.prototype.forEachFeatureAtPixel = goog.nullFunction; +/** + * @param {ol.Coordinate} coordinate Coordinate. + * @param {olx.FrameState} frameState Frame state. + * @param {function(this: S, ol.layer.Layer): T} callback Layer callback. + * @param {S} thisArg Value to use as `this` when executing `callback`. + * @return {T|undefined} Callback result. + * @template S,T + */ +ol.renderer.Layer.prototype.forEachLayerAtPixel = + function(coordinate, frameState, callback, thisArg) { + var hasFeature = this.forEachFeatureAtPixel( + coordinate, frameState, goog.functions.TRUE, this); + + if (hasFeature) { + return callback.call(thisArg, this.layer_); + } else { + return undefined; + } +}; + + /** * @param {ol.Coordinate} coordinate Coordinate. * @param {olx.FrameState} frameState Frame state. diff --git a/src/ol/renderer/maprenderer.js b/src/ol/renderer/maprenderer.js index 10b0429bd8..82dc358f2c 100644 --- a/src/ol/renderer/maprenderer.js +++ b/src/ol/renderer/maprenderer.js @@ -169,6 +169,59 @@ ol.renderer.Map.prototype.forEachFeatureAtPixel = }; +/** + * @param {ol.Coordinate} coordinate Coordinate. + * @param {olx.FrameState} frameState FrameState. + * @param {function(this: S, ol.layer.Layer): T} callback Layer + * callback. + * @param {S} thisArg Value to use as `this` when executing `callback`. + * @param {function(this: U, ol.layer.Layer): boolean} layerFilter Layer filter + * function, only layers which are visible and for which this function + * returns `true` will be tested for features. By default, all visible + * layers will be tested. + * @param {U} thisArg2 Value to use as `this` when executing `layerFilter`. + * @return {T|undefined} Callback result. + * @template S,T,U + */ +ol.renderer.Map.prototype.forEachLayerAtPixel = + function(coordinate, frameState, callback, thisArg, + layerFilter, thisArg2) { + var result; + var viewState = frameState.viewState; + var viewResolution = viewState.resolution; + var viewRotation = viewState.rotation; + + if (!goog.isNull(this.replayGroup)) { + var hasFeature = this.replayGroup.forEachFeatureAtPixel(viewResolution, + viewRotation, coordinate, {}, goog.functions.TRUE); + + if (hasFeature) { + result = callback.call(thisArg, null); + if (result) { + return result; + } + } + } + var layerStates = frameState.layerStatesArray; + var numLayers = layerStates.length; + var i; + for (i = numLayers - 1; i >= 0; --i) { + var layerState = layerStates[i]; + var layer = layerState.layer; + if (ol.layer.Layer.visibleAtResolution(layerState, viewResolution) && + layerFilter.call(thisArg2, layer)) { + var layerRenderer = this.getLayerRenderer(layer); + result = layerRenderer.forEachLayerAtPixel( + coordinate, frameState, callback, thisArg); + if (result) { + return result; + } + } + } + return undefined; +}; + + /** * @param {ol.Coordinate} coordinate Coordinate. * @param {olx.FrameState} frameState FrameState. From b4cb786f2901add9438ad60ee7be13a38fd504bf Mon Sep 17 00:00:00 2001 From: tsauerwein Date: Fri, 23 Jan 2015 16:50:42 +0100 Subject: [PATCH 03/10] Implement forEachLayerAtPixel for canvas --- .../canvas/canvasimagelayerrenderer.js | 63 +++++++++++++++++++ src/ol/renderer/canvas/canvaslayerrenderer.js | 16 +++++ .../canvas/canvastilelayerrenderer.js | 35 +++++++++++ 3 files changed, 114 insertions(+) diff --git a/src/ol/renderer/canvas/canvasimagelayerrenderer.js b/src/ol/renderer/canvas/canvasimagelayerrenderer.js index 834f0e771f..abc974a832 100644 --- a/src/ol/renderer/canvas/canvasimagelayerrenderer.js +++ b/src/ol/renderer/canvas/canvasimagelayerrenderer.js @@ -4,11 +4,13 @@ goog.require('goog.asserts'); goog.require('goog.vec.Mat4'); goog.require('ol.ImageBase'); goog.require('ol.ViewHint'); +goog.require('ol.dom'); goog.require('ol.extent'); goog.require('ol.layer.Image'); goog.require('ol.proj'); goog.require('ol.renderer.Map'); goog.require('ol.renderer.canvas.Layer'); +goog.require('ol.source.ImageVector'); goog.require('ol.vec.Mat4'); @@ -35,6 +37,18 @@ ol.renderer.canvas.ImageLayer = function(mapRenderer, imageLayer) { */ this.imageTransform_ = goog.vec.Mat4.createNumber(); + /** + * @private + * @type {?goog.vec.Mat4.Number} + */ + this.imageTransformInv_ = null; + + /** + * @private + * @type {CanvasRenderingContext2D} + */ + this.hitCanvasContext_ = null; + }; goog.inherits(ol.renderer.canvas.ImageLayer, ol.renderer.canvas.Layer); @@ -61,6 +75,54 @@ ol.renderer.canvas.ImageLayer.prototype.forEachFeatureAtPixel = }; +/** + * @inheritDoc + */ +ol.renderer.canvas.ImageLayer.prototype.forEachLayerAtPixel = + function(coordinate, frameState, callback, thisArg) { + if (goog.isNull(this.getImage())) { + return undefined; + } + + if (this.getLayer().getSource() instanceof ol.source.ImageVector) { + // for ImageVector sources use the original hit-detection logic, + // so that for example also transparent polygons are detected + var hasFeature = this.forEachFeatureAtPixel( + coordinate, frameState, goog.functions.TRUE, this); + + if (hasFeature) { + return callback.call(thisArg, this.getLayer()); + } else { + return undefined; + } + } else { + // for all other image sources directly check the image + if (goog.isNull(this.imageTransformInv_)) { + this.imageTransformInv_ = goog.vec.Mat4.createNumber(); + goog.vec.Mat4.invert(this.imageTransform_, this.imageTransformInv_); + } + + var pixelOnCanvas = + this.getPixelFromCoordinates(coordinate, this.imageTransformInv_); + + if (goog.isNull(this.hitCanvasContext_)) { + this.hitCanvasContext_ = ol.dom.createCanvasContext2D(1, 1); + } + + this.hitCanvasContext_.clearRect(0, 0, 1, 1); + this.hitCanvasContext_.drawImage( + this.getImage(), pixelOnCanvas[0], pixelOnCanvas[1], 1, 1, 0, 0, 1, 1); + + var imageData = this.hitCanvasContext_.getImageData(0, 0, 1, 1).data; + if (imageData[3] > 0) { + return callback.call(thisArg, this.getLayer()); + } else { + return undefined; + } + } +}; + + /** * @inheritDoc */ @@ -135,6 +197,7 @@ ol.renderer.canvas.ImageLayer.prototype.prepareFrame = viewRotation, imagePixelRatio * (imageExtent[0] - viewCenter[0]) / imageResolution, imagePixelRatio * (viewCenter[1] - imageExtent[3]) / imageResolution); + this.imageTransformInv_ = null; this.updateAttributions(frameState.attributions, image.getAttributions()); this.updateLogos(frameState, imageSource); } diff --git a/src/ol/renderer/canvas/canvaslayerrenderer.js b/src/ol/renderer/canvas/canvaslayerrenderer.js index a9a699d8b2..90712130af 100644 --- a/src/ol/renderer/canvas/canvaslayerrenderer.js +++ b/src/ol/renderer/canvas/canvaslayerrenderer.js @@ -216,6 +216,22 @@ ol.renderer.canvas.Layer.prototype.getTransform = function(frameState) { ol.renderer.canvas.Layer.prototype.prepareFrame = goog.abstractMethod; +/** + * @param {ol.Coordinate} coordinate Coordinate. + * @param {goog.vec.Mat4.Number} imageTransformInv The transformation matrix + * to convert from a map pixel to a canvas pixel. + * @return {ol.Pixel} + * @protected + */ +ol.renderer.canvas.Layer.prototype.getPixelFromCoordinates = + function(coordinate, imageTransformInv) { + var pixelOnMap = this.getMap().getPixelFromCoordinate(coordinate); + var pixelOnCanvas = [0, 0]; + ol.vec.Mat4.multVec2(imageTransformInv, pixelOnMap, pixelOnCanvas); + return pixelOnCanvas; +}; + + /** * @param {ol.Size} size Size. * @return {boolean} True when the canvas with the current size does not exceed diff --git a/src/ol/renderer/canvas/canvastilelayerrenderer.js b/src/ol/renderer/canvas/canvastilelayerrenderer.js index b4549b1ad8..cb7859a0d8 100644 --- a/src/ol/renderer/canvas/canvastilelayerrenderer.js +++ b/src/ol/renderer/canvas/canvastilelayerrenderer.js @@ -60,6 +60,12 @@ ol.renderer.canvas.TileLayer = function(mapRenderer, tileLayer) { */ this.imageTransform_ = goog.vec.Mat4.createNumber(); + /** + * @private + * @type {?goog.vec.Mat4.Number} + */ + this.imageTransformInv_ = null; + /** * @private * @type {number} @@ -408,6 +414,35 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame = viewState.rotation, (origin[0] - center[0]) / tilePixelResolution, (center[1] - origin[1]) / tilePixelResolution); + this.imageTransformInv_ = null; return true; }; + + +/** + * @inheritDoc + */ +ol.renderer.canvas.TileLayer.prototype.forEachLayerAtPixel = + function(coordinate, frameState, callback, thisArg) { + if (goog.isNull(this.context_)) { + return undefined; + } + + if (goog.isNull(this.imageTransformInv_)) { + this.imageTransformInv_ = goog.vec.Mat4.createNumber(); + goog.vec.Mat4.invert(this.imageTransform_, this.imageTransformInv_); + } + + var pixelOnCanvas = + this.getPixelFromCoordinates(coordinate, this.imageTransformInv_); + + var imageData = this.context_.getImageData( + pixelOnCanvas[0], pixelOnCanvas[1], 1, 1).data; + + if (imageData[3] > 0) { + return callback.call(thisArg, this.getLayer()); + } else { + return undefined; + } +}; From 6cc5bd466dff0c29924bab30fe1d274aa9d23fe1 Mon Sep 17 00:00:00 2001 From: tsauerwein Date: Fri, 23 Jan 2015 17:32:09 +0100 Subject: [PATCH 04/10] Add hasFeatureAtPixel for ImageLayer --- src/ol/renderer/webgl/webglimagelayerrenderer.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/ol/renderer/webgl/webglimagelayerrenderer.js b/src/ol/renderer/webgl/webglimagelayerrenderer.js index 13d3c7af16..922136574f 100644 --- a/src/ol/renderer/webgl/webglimagelayerrenderer.js +++ b/src/ol/renderer/webgl/webglimagelayerrenderer.js @@ -193,3 +193,14 @@ ol.renderer.webgl.ImageLayer.prototype.updateProjectionMatrix_ = goog.vec.Mat4.translate(projectionMatrix, 1, 1, 0); }; + + +/** + * @inheritDoc + */ +ol.renderer.webgl.ImageLayer.prototype.hasFeatureAtPixel = + function(coordinate, frameState) { + var hasFeature = this.forEachFeatureAtPixel( + coordinate, frameState, goog.functions.TRUE, this); + return goog.isDef(hasFeature); +}; From dce4210a5b51f157ecb8ced91f3fe74e5ba7bac7 Mon Sep 17 00:00:00 2001 From: tsauerwein Date: Fri, 23 Jan 2015 17:35:07 +0100 Subject: [PATCH 05/10] Implement forEachLayerAtPixel for webgl --- .../renderer/webgl/webglimagelayerrenderer.js | 116 ++++++++++++++++++ src/ol/renderer/webgl/webglmaprenderer.js | 51 ++++++++ .../renderer/webgl/webgltilelayerrenderer.js | 37 ++++++ .../webgl/webglvectorlayerrenderer.js | 15 +++ 4 files changed, 219 insertions(+) diff --git a/src/ol/renderer/webgl/webglimagelayerrenderer.js b/src/ol/renderer/webgl/webglimagelayerrenderer.js index 922136574f..ce1a625f3e 100644 --- a/src/ol/renderer/webgl/webglimagelayerrenderer.js +++ b/src/ol/renderer/webgl/webglimagelayerrenderer.js @@ -7,10 +7,13 @@ goog.require('ol.Coordinate'); goog.require('ol.Extent'); goog.require('ol.ImageBase'); goog.require('ol.ViewHint'); +goog.require('ol.dom'); goog.require('ol.extent'); goog.require('ol.layer.Image'); goog.require('ol.proj'); goog.require('ol.renderer.webgl.Layer'); +goog.require('ol.source.ImageVector'); +goog.require('ol.vec.Mat4'); goog.require('ol.webgl.Context'); @@ -32,6 +35,18 @@ ol.renderer.webgl.ImageLayer = function(mapRenderer, imageLayer) { */ this.image_ = null; + /** + * @private + * @type {CanvasRenderingContext2D} + */ + this.hitCanvasContext_ = null; + + /** + * @private + * @type {?goog.vec.Mat4.Number} + */ + this.hitTransformationMatrix_ = null; + }; goog.inherits(ol.renderer.webgl.ImageLayer, ol.renderer.webgl.Layer); @@ -143,6 +158,7 @@ ol.renderer.webgl.ImageLayer.prototype.prepareFrame = this.updateProjectionMatrix_(canvas.width, canvas.height, viewCenter, viewResolution, viewRotation, image.getExtent()); + this.hitTransformationMatrix_ = null; // Translate and scale to flip the Y coord. var texCoordMatrix = this.texCoordMatrix; @@ -204,3 +220,103 @@ ol.renderer.webgl.ImageLayer.prototype.hasFeatureAtPixel = coordinate, frameState, goog.functions.TRUE, this); return goog.isDef(hasFeature); }; + + +/** + * @inheritDoc + */ +ol.renderer.webgl.ImageLayer.prototype.forEachLayerAtPixel = + function(coordinate, frameState, callback, thisArg) { + if (goog.isNull(this.image_) || goog.isNull(this.image_.getImage())) { + return undefined; + } + + if (this.getLayer().getSource() instanceof ol.source.ImageVector) { + // for ImageVector sources use the original hit-detection logic, + // so that for example also transparent polygons are detected + var hasFeature = this.forEachFeatureAtPixel( + coordinate, frameState, goog.functions.TRUE, this); + + if (hasFeature) { + return callback.call(thisArg, this.getLayer()); + } else { + return undefined; + } + } else { + var imageSize = + [this.image_.getImage().width, this.image_.getImage().height]; + + if (goog.isNull(this.hitTransformationMatrix_)) { + this.hitTransformationMatrix_ = this.getHitTransformationMatrix_( + frameState.size, imageSize); + } + + var pixelOnMap = this.getMap().getPixelFromCoordinate(coordinate); + var pixelOnFrameBuffer = [0, 0]; + ol.vec.Mat4.multVec2( + this.hitTransformationMatrix_, pixelOnMap, pixelOnFrameBuffer); + + if (pixelOnFrameBuffer[0] < 0 || pixelOnFrameBuffer[0] > imageSize[0] || + pixelOnFrameBuffer[1] < 0 || pixelOnFrameBuffer[1] > imageSize[1]) { + // outside the image, no need to check + return undefined; + } + + if (goog.isNull(this.hitCanvasContext_)) { + this.hitCanvasContext_ = ol.dom.createCanvasContext2D(1, 1); + } + + this.hitCanvasContext_.clearRect(0, 0, 1, 1); + this.hitCanvasContext_.drawImage(this.image_.getImage(), + pixelOnFrameBuffer[0], pixelOnFrameBuffer[1], 1, 1, 0, 0, 1, 1); + + var imageData = this.hitCanvasContext_.getImageData(0, 0, 1, 1).data; + if (imageData[3] > 0) { + return callback.call(thisArg, this.getLayer()); + } else { + return undefined; + } + } +}; + + +/** + * The transformation matrix to get the pixel on the image for a + * pixel on the map. + * @param {ol.Size} mapSize + * @param {ol.Size} imageSize + * @return {goog.vec.Mat4.Number} + * @private + */ +ol.renderer.webgl.ImageLayer.prototype.getHitTransformationMatrix_ = + function(mapSize, imageSize) { + // the first matrix takes a map pixel, flips the y-axis and scales to + // a range between -1 ... 1 + var mapCoordMatrix = goog.vec.Mat4.createNumber(); + goog.vec.Mat4.makeIdentity(mapCoordMatrix); + goog.vec.Mat4.translate(mapCoordMatrix, -1, -1, 0); + goog.vec.Mat4.scale(mapCoordMatrix, 2 / mapSize[0], 2 / mapSize[1], 1); + goog.vec.Mat4.translate(mapCoordMatrix, 0, mapSize[1], 0); + goog.vec.Mat4.scale(mapCoordMatrix, 1, -1, 1); + + // the second matrix is the inverse of the projection matrix used in the + // shader for drawing + var projectionMatrixInv = goog.vec.Mat4.createNumber(); + goog.vec.Mat4.invert(this.projectionMatrix, projectionMatrixInv); + + // the third matrix scales to the image dimensions and flips the y-axis again + var imageCoordMatrix = goog.vec.Mat4.createNumber(); + goog.vec.Mat4.makeIdentity(imageCoordMatrix); + goog.vec.Mat4.translate(imageCoordMatrix, 0, imageSize[1], 0); + goog.vec.Mat4.scale(imageCoordMatrix, 1, -1, 1); + goog.vec.Mat4.scale(imageCoordMatrix, imageSize[0] / 2, imageSize[1] / 2, 1); + goog.vec.Mat4.translate(imageCoordMatrix, 1, 1, 0); + + var transformMatrix = goog.vec.Mat4.createNumber(); + goog.vec.Mat4.multMat( + imageCoordMatrix, projectionMatrixInv, transformMatrix); + goog.vec.Mat4.multMat( + transformMatrix, mapCoordMatrix, transformMatrix); + + return transformMatrix; +}; diff --git a/src/ol/renderer/webgl/webglmaprenderer.js b/src/ol/renderer/webgl/webglmaprenderer.js index c5985c194b..a9c4205659 100644 --- a/src/ol/renderer/webgl/webglmaprenderer.js +++ b/src/ol/renderer/webgl/webglmaprenderer.js @@ -648,6 +648,57 @@ ol.renderer.webgl.Map.prototype.hasFeatureAtPixel = }; +/** + * @inheritDoc + */ +ol.renderer.webgl.Map.prototype.forEachLayerAtPixel = + function(coordinate, frameState, callback, thisArg, + layerFilter, thisArg2) { + if (this.getGL().isContextLost()) { + return false; + } + + var context = this.getContext(); + var viewState = frameState.viewState; + var result; + + // do the hit-detection for the overlays first + if (!goog.isNull(this.replayGroup)) { + // use default color values + var d = ol.renderer.webgl.Map.DEFAULT_COLOR_VALUES_; + + var hasFeature = this.replayGroup.hasFeatureAtPixel(context, + viewState.center, viewState.resolution, viewState.rotation, + frameState.size, frameState.pixelRatio, + d.opacity, d.brightness, d.contrast, d.hue, d.saturation, {}, + coordinate); + if (hasFeature) { + result = callback.call(thisArg, null); + if (result) { + return result; + } + } + } + var layerStates = frameState.layerStatesArray; + var numLayers = layerStates.length; + var i; + for (i = numLayers - 1; i >= 0; --i) { + var layerState = layerStates[i]; + var layer = layerState.layer; + if (ol.layer.Layer.visibleAtResolution(layerState, viewState.resolution) && + layerFilter.call(thisArg, layer)) { + var layerRenderer = this.getLayerRenderer(layer); + result = layerRenderer.forEachLayerAtPixel( + coordinate, frameState, callback, thisArg); + if (result) { + return result; + } + } + } + return undefined; +}; + + /** * @private * @const diff --git a/src/ol/renderer/webgl/webgltilelayerrenderer.js b/src/ol/renderer/webgl/webgltilelayerrenderer.js index 68ceed8d0d..455fce7427 100644 --- a/src/ol/renderer/webgl/webgltilelayerrenderer.js +++ b/src/ol/renderer/webgl/webgltilelayerrenderer.js @@ -17,6 +17,7 @@ goog.require('ol.math'); goog.require('ol.renderer.webgl.Layer'); goog.require('ol.renderer.webgl.tilelayer.shader'); goog.require('ol.tilecoord'); +goog.require('ol.vec.Mat4'); goog.require('ol.webgl.Buffer'); @@ -326,3 +327,39 @@ ol.renderer.webgl.TileLayer.prototype.prepareFrame = return true; }; + + +/** + * @inheritDoc + */ +ol.renderer.webgl.TileLayer.prototype.forEachLayerAtPixel = + function(coordinate, frameState, callback, thisArg) { + if (goog.isNull(this.framebuffer)) { + return undefined; + } + var mapSize = this.getMap().getSize(); + + var pixelOnMap = this.getMap().getPixelFromCoordinate(coordinate); + var pixelOnMapScaled = [ + pixelOnMap[0] / mapSize[0], + (mapSize[1] - pixelOnMap[1]) / mapSize[1]]; + + var pixelOnFrameBufferScaled = [0, 0]; + ol.vec.Mat4.multVec2( + this.texCoordMatrix, pixelOnMapScaled, pixelOnFrameBufferScaled); + var pixelOnFrameBuffer = [ + pixelOnFrameBufferScaled[0] * this.framebufferDimension, + pixelOnFrameBufferScaled[1] * this.framebufferDimension]; + + var gl = this.getWebGLMapRenderer().getContext().getGL(); + gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer); + var imageData = new Uint8Array(4); + gl.readPixels(pixelOnFrameBuffer[0], pixelOnFrameBuffer[1], 1, 1, + gl.RGBA, gl.UNSIGNED_BYTE, imageData); + + if (imageData[3] > 0) { + return callback.call(thisArg, this.getLayer()); + } else { + return undefined; + } +}; diff --git a/src/ol/renderer/webgl/webglvectorlayerrenderer.js b/src/ol/renderer/webgl/webglvectorlayerrenderer.js index f2a00be9e0..904f496e95 100644 --- a/src/ol/renderer/webgl/webglvectorlayerrenderer.js +++ b/src/ol/renderer/webgl/webglvectorlayerrenderer.js @@ -162,6 +162,21 @@ ol.renderer.webgl.VectorLayer.prototype.hasFeatureAtPixel = }; +/** + * @inheritDoc + */ +ol.renderer.webgl.VectorLayer.prototype.forEachLayerAtPixel = + function(coordinate, frameState, callback, thisArg) { + var hasFeature = this.hasFeatureAtPixel(coordinate, frameState); + + if (hasFeature) { + return callback.call(thisArg, this.getLayer()); + } else { + return undefined; + } +}; + + /** * Handle changes in image style state. * @param {goog.events.Event} event Image style change event. From b7415219a63f60085bda6c98857c5a03f92d63de Mon Sep 17 00:00:00 2001 From: tsauerwein Date: Mon, 26 Jan 2015 11:20:59 +0100 Subject: [PATCH 06/10] Use forEachLayerAtPx in example --- examples/getfeatureinfo-image.html | 4 +++- examples/getfeatureinfo-image.js | 12 +++++++++++- examples/getfeatureinfo-tile.html | 4 +++- examples/getfeatureinfo-tile.js | 12 +++++++++++- 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/examples/getfeatureinfo-image.html b/examples/getfeatureinfo-image.html index 85b3044acd..bde7a8501d 100644 --- a/examples/getfeatureinfo-image.html +++ b/examples/getfeatureinfo-image.html @@ -35,9 +35,11 @@

GetFeatureInfo example (image layer)

This example shows how to trigger WMS GetFeatureInfo requests on click for a WMS image layer.

+

Additionally map.forEachLayerAtPixel is used to change the mouse + pointer when hovering a non-transparent pixel on the map.

See the getfeatureinfo-image.js source to see how this is done.

-
getfeatureinfo
+
getfeatureinfo, forEachLayerAtPixel
diff --git a/examples/getfeatureinfo-image.js b/examples/getfeatureinfo-image.js index 1806cae784..5ec90dc8ca 100644 --- a/examples/getfeatureinfo-image.js +++ b/examples/getfeatureinfo-image.js @@ -7,7 +7,8 @@ goog.require('ol.source.ImageWMS'); var wmsSource = new ol.source.ImageWMS({ url: 'http://demo.boundlessgeo.com/geoserver/wms', params: {'LAYERS': 'ne:ne'}, - serverType: 'geoserver' + serverType: 'geoserver', + crossOrigin: '' }); var wmsLayer = new ol.layer.Image({ @@ -20,6 +21,7 @@ var view = new ol.View({ }); var map = new ol.Map({ + renderer: exampleNS.getRendererFromQueryString(), layers: [wmsLayer], target: 'map', view: view @@ -36,3 +38,11 @@ map.on('singleclick', function(evt) { ''; } }); + +$(map.getViewport()).on('mousemove', function(evt) { + var pixel = map.getEventPixel(evt.originalEvent); + var hit = map.forEachLayerAtPixel(pixel, function(layer) { + return true; + }); + map.getTargetElement().style.cursor = hit ? 'pointer' : ''; +}); diff --git a/examples/getfeatureinfo-tile.html b/examples/getfeatureinfo-tile.html index 46a5289c4b..b59b9205ec 100644 --- a/examples/getfeatureinfo-tile.html +++ b/examples/getfeatureinfo-tile.html @@ -35,9 +35,11 @@

WMS GetFeatureInfo example (tile layer)

This example shows how to trigger WMS GetFeatureInfo requests on click for a WMS tile layer.

+

Additionally map.forEachLayerAtPixel is used to change the mouse + pointer when hovering a non-transparent pixel on the map.

See the getfeatureinfo-tile.js source to see how this is done.

-
getfeatureinfo
+
getfeatureinfo, forEachLayerAtPixel
diff --git a/examples/getfeatureinfo-tile.js b/examples/getfeatureinfo-tile.js index 70704a7b8f..901b87db57 100644 --- a/examples/getfeatureinfo-tile.js +++ b/examples/getfeatureinfo-tile.js @@ -7,7 +7,8 @@ goog.require('ol.source.TileWMS'); var wmsSource = new ol.source.TileWMS({ url: 'http://demo.boundlessgeo.com/geoserver/wms', params: {'LAYERS': 'ne:ne'}, - serverType: 'geoserver' + serverType: 'geoserver', + crossOrigin: '' }); var wmsLayer = new ol.layer.Tile({ @@ -20,6 +21,7 @@ var view = new ol.View({ }); var map = new ol.Map({ + renderer: exampleNS.getRendererFromQueryString(), layers: [wmsLayer], target: 'map', view: view @@ -36,3 +38,11 @@ map.on('singleclick', function(evt) { ''; } }); + +$(map.getViewport()).on('mousemove', function(evt) { + var pixel = map.getEventPixel(evt.originalEvent); + var hit = map.forEachLayerAtPixel(pixel, function(layer) { + return true; + }); + map.getTargetElement().style.cursor = hit ? 'pointer' : ''; +}); From 054227fd264b83a6f220ef3e1f01c912cb58c5b1 Mon Sep 17 00:00:00 2001 From: tsauerwein Date: Thu, 29 Jan 2015 11:16:22 +0100 Subject: [PATCH 07/10] Make signature for *AtPixel methods more consistent pixel/coordinate is the first argument. --- src/ol/render/canvas/canvasreplay.js | 4 ++-- src/ol/render/webgl/webglreplay.js | 13 ++++++------- .../canvas/canvasimagelayerrenderer.js | 2 +- .../canvas/canvasvectorlayerrenderer.js | 4 ++-- src/ol/renderer/dom/domimagelayerrenderer.js | 2 +- src/ol/renderer/dom/domvectorlayerrenderer.js | 4 ++-- src/ol/renderer/maprenderer.js | 8 ++++---- .../renderer/webgl/webglimagelayerrenderer.js | 2 +- src/ol/renderer/webgl/webglmaprenderer.js | 19 ++++++++----------- .../webgl/webglvectorlayerrenderer.js | 12 +++++------- src/ol/source/imagevectorsource.js | 4 ++-- src/ol/source/source.js | 2 +- 12 files changed, 35 insertions(+), 41 deletions(-) diff --git a/src/ol/render/canvas/canvasreplay.js b/src/ol/render/canvas/canvasreplay.js index 97619a1629..866823231e 100644 --- a/src/ol/render/canvas/canvasreplay.js +++ b/src/ol/render/canvas/canvasreplay.js @@ -1858,16 +1858,16 @@ ol.render.canvas.ReplayGroup.prototype.finish = function() { /** + * @param {ol.Coordinate} coordinate Coordinate. * @param {number} resolution Resolution. * @param {number} rotation Rotation. - * @param {ol.Coordinate} coordinate Coordinate. * @param {Object} skippedFeaturesHash Ids of features to skip * @param {function(ol.Feature): T} callback Feature callback. * @return {T|undefined} Callback result. * @template T */ ol.render.canvas.ReplayGroup.prototype.forEachFeatureAtPixel = function( - resolution, rotation, coordinate, skippedFeaturesHash, callback) { + coordinate, resolution, rotation, skippedFeaturesHash, callback) { var transform = this.hitDetectionTransform_; ol.vec.Mat4.makeTransform2D(transform, 0.5, 0.5, diff --git a/src/ol/render/webgl/webglreplay.js b/src/ol/render/webgl/webglreplay.js index 9af1caa62d..2913c010a7 100644 --- a/src/ol/render/webgl/webglreplay.js +++ b/src/ol/render/webgl/webglreplay.js @@ -1154,6 +1154,7 @@ ol.render.webgl.ReplayGroup.prototype.replayHitDetection_ = function(context, /** + * @param {ol.Coordinate} coordinate Coordinate. * @param {ol.webgl.Context} context Context. * @param {ol.Coordinate} center Center. * @param {number} resolution Resolution. @@ -1166,15 +1167,14 @@ ol.render.webgl.ReplayGroup.prototype.replayHitDetection_ = function(context, * @param {number} hue Global hue. * @param {number} saturation Global saturation. * @param {Object} skippedFeaturesHash Ids of features to skip. - * @param {ol.Coordinate} coordinate Coordinate. * @param {function(ol.Feature): T|undefined} callback Feature callback. * @return {T|undefined} Callback result. * @template T */ ol.render.webgl.ReplayGroup.prototype.forEachFeatureAtPixel = function( - context, center, resolution, rotation, size, pixelRatio, + coordinate, context, center, resolution, rotation, size, pixelRatio, opacity, brightness, contrast, hue, saturation, skippedFeaturesHash, - coordinate, callback) { + callback) { var gl = context.getGL(); gl.bindFramebuffer( gl.FRAMEBUFFER, context.getHitDetectionFramebuffer()); @@ -1215,6 +1215,7 @@ ol.render.webgl.ReplayGroup.prototype.forEachFeatureAtPixel = function( /** + * @param {ol.Coordinate} coordinate Coordinate. * @param {ol.webgl.Context} context Context. * @param {ol.Coordinate} center Center. * @param {number} resolution Resolution. @@ -1227,13 +1228,11 @@ ol.render.webgl.ReplayGroup.prototype.forEachFeatureAtPixel = function( * @param {number} hue Global hue. * @param {number} saturation Global saturation. * @param {Object} skippedFeaturesHash Ids of features to skip. - * @param {ol.Coordinate} coordinate Coordinate. * @return {boolean} Is there a feature at the given pixel? */ ol.render.webgl.ReplayGroup.prototype.hasFeatureAtPixel = function( - context, center, resolution, rotation, size, pixelRatio, - opacity, brightness, contrast, hue, saturation, skippedFeaturesHash, - coordinate) { + coordinate, context, center, resolution, rotation, size, pixelRatio, + opacity, brightness, contrast, hue, saturation, skippedFeaturesHash) { var gl = context.getGL(); gl.bindFramebuffer( gl.FRAMEBUFFER, context.getHitDetectionFramebuffer()); diff --git a/src/ol/renderer/canvas/canvasimagelayerrenderer.js b/src/ol/renderer/canvas/canvasimagelayerrenderer.js index abc974a832..dd8d3361bf 100644 --- a/src/ol/renderer/canvas/canvasimagelayerrenderer.js +++ b/src/ol/renderer/canvas/canvasimagelayerrenderer.js @@ -64,7 +64,7 @@ ol.renderer.canvas.ImageLayer.prototype.forEachFeatureAtPixel = var rotation = frameState.viewState.rotation; var skippedFeatureUids = frameState.skippedFeatureUids; return source.forEachFeatureAtPixel( - resolution, rotation, coordinate, skippedFeatureUids, + coordinate, resolution, rotation, skippedFeatureUids, /** * @param {ol.Feature} feature Feature. * @return {?} Callback result. diff --git a/src/ol/renderer/canvas/canvasvectorlayerrenderer.js b/src/ol/renderer/canvas/canvasvectorlayerrenderer.js index a7c4842698..e8baf6274c 100644 --- a/src/ol/renderer/canvas/canvasvectorlayerrenderer.js +++ b/src/ol/renderer/canvas/canvasvectorlayerrenderer.js @@ -126,8 +126,8 @@ ol.renderer.canvas.VectorLayer.prototype.forEachFeatureAtPixel = var layer = this.getLayer(); /** @type {Object.} */ var features = {}; - return this.replayGroup_.forEachFeatureAtPixel(resolution, - rotation, coordinate, frameState.skippedFeatureUids, + return this.replayGroup_.forEachFeatureAtPixel(coordinate, + resolution, rotation, frameState.skippedFeatureUids, /** * @param {ol.Feature} feature Feature. * @return {?} Callback result. diff --git a/src/ol/renderer/dom/domimagelayerrenderer.js b/src/ol/renderer/dom/domimagelayerrenderer.js index 624fa8f0c2..334357da44 100644 --- a/src/ol/renderer/dom/domimagelayerrenderer.js +++ b/src/ol/renderer/dom/domimagelayerrenderer.js @@ -55,7 +55,7 @@ ol.renderer.dom.ImageLayer.prototype.forEachFeatureAtPixel = var rotation = frameState.viewState.rotation; var skippedFeatureUids = frameState.skippedFeatureUids; return source.forEachFeatureAtPixel( - resolution, rotation, coordinate, skippedFeatureUids, + coordinate, resolution, rotation, skippedFeatureUids, /** * @param {ol.Feature} feature Feature. * @return {?} Callback result. diff --git a/src/ol/renderer/dom/domvectorlayerrenderer.js b/src/ol/renderer/dom/domvectorlayerrenderer.js index 8c46bce8d0..fe7cee6af2 100644 --- a/src/ol/renderer/dom/domvectorlayerrenderer.js +++ b/src/ol/renderer/dom/domvectorlayerrenderer.js @@ -186,8 +186,8 @@ ol.renderer.dom.VectorLayer.prototype.forEachFeatureAtPixel = var layer = this.getLayer(); /** @type {Object.} */ var features = {}; - return this.replayGroup_.forEachFeatureAtPixel(resolution, - rotation, coordinate, frameState.skippedFeatureUids, + return this.replayGroup_.forEachFeatureAtPixel(coordinate, + resolution, rotation, frameState.skippedFeatureUids, /** * @param {ol.Feature} feature Feature. * @return {?} Callback result. diff --git a/src/ol/renderer/maprenderer.js b/src/ol/renderer/maprenderer.js index 82dc358f2c..6c4cce1ee3 100644 --- a/src/ol/renderer/maprenderer.js +++ b/src/ol/renderer/maprenderer.js @@ -131,8 +131,8 @@ ol.renderer.Map.prototype.forEachFeatureAtPixel = if (!goog.isNull(this.replayGroup)) { /** @type {Object.} */ var features = {}; - result = this.replayGroup.forEachFeatureAtPixel(viewResolution, - viewRotation, coordinate, {}, + result = this.replayGroup.forEachFeatureAtPixel(coordinate, + viewResolution, viewRotation, {}, /** * @param {ol.Feature} feature Feature. * @return {?} Callback result. @@ -192,8 +192,8 @@ ol.renderer.Map.prototype.forEachLayerAtPixel = var viewRotation = viewState.rotation; if (!goog.isNull(this.replayGroup)) { - var hasFeature = this.replayGroup.forEachFeatureAtPixel(viewResolution, - viewRotation, coordinate, {}, goog.functions.TRUE); + var hasFeature = this.replayGroup.forEachFeatureAtPixel(coordinate, + viewResolution, viewRotation, {}, goog.functions.TRUE); if (hasFeature) { result = callback.call(thisArg, null); diff --git a/src/ol/renderer/webgl/webglimagelayerrenderer.js b/src/ol/renderer/webgl/webglimagelayerrenderer.js index ce1a625f3e..6755b4f2d5 100644 --- a/src/ol/renderer/webgl/webglimagelayerrenderer.js +++ b/src/ol/renderer/webgl/webglimagelayerrenderer.js @@ -81,7 +81,7 @@ ol.renderer.webgl.ImageLayer.prototype.forEachFeatureAtPixel = var rotation = frameState.viewState.rotation; var skippedFeatureUids = frameState.skippedFeatureUids; return source.forEachFeatureAtPixel( - resolution, rotation, coordinate, skippedFeatureUids, + coordinate, resolution, rotation, skippedFeatureUids, /** * @param {ol.Feature} feature Feature. diff --git a/src/ol/renderer/webgl/webglmaprenderer.js b/src/ol/renderer/webgl/webglmaprenderer.js index a9c4205659..49ae80457e 100644 --- a/src/ol/renderer/webgl/webglmaprenderer.js +++ b/src/ol/renderer/webgl/webglmaprenderer.js @@ -560,11 +560,10 @@ ol.renderer.webgl.Map.prototype.forEachFeatureAtPixel = // use default color values var d = ol.renderer.webgl.Map.DEFAULT_COLOR_VALUES_; - result = this.replayGroup.forEachFeatureAtPixel(context, - viewState.center, viewState.resolution, viewState.rotation, + result = this.replayGroup.forEachFeatureAtPixel(coordinate, + context, viewState.center, viewState.resolution, viewState.rotation, frameState.size, frameState.pixelRatio, d.opacity, d.brightness, d.contrast, d.hue, d.saturation, {}, - coordinate, /** * @param {ol.Feature} feature Feature. * @return {?} Callback result. @@ -620,11 +619,10 @@ ol.renderer.webgl.Map.prototype.hasFeatureAtPixel = // use default color values var d = ol.renderer.webgl.Map.DEFAULT_COLOR_VALUES_; - hasFeature = this.replayGroup.hasFeatureAtPixel(context, - viewState.center, viewState.resolution, viewState.rotation, + hasFeature = this.replayGroup.hasFeatureAtPixel(coordinate, + context, viewState.center, viewState.resolution, viewState.rotation, frameState.size, frameState.pixelRatio, - d.opacity, d.brightness, d.contrast, d.hue, d.saturation, {}, - coordinate); + d.opacity, d.brightness, d.contrast, d.hue, d.saturation, {}); if (hasFeature) { return true; } @@ -667,11 +665,10 @@ ol.renderer.webgl.Map.prototype.forEachLayerAtPixel = // use default color values var d = ol.renderer.webgl.Map.DEFAULT_COLOR_VALUES_; - var hasFeature = this.replayGroup.hasFeatureAtPixel(context, - viewState.center, viewState.resolution, viewState.rotation, + var hasFeature = this.replayGroup.hasFeatureAtPixel(coordinate, + context, viewState.center, viewState.resolution, viewState.rotation, frameState.size, frameState.pixelRatio, - d.opacity, d.brightness, d.contrast, d.hue, d.saturation, {}, - coordinate); + d.opacity, d.brightness, d.contrast, d.hue, d.saturation, {}); if (hasFeature) { result = callback.call(thisArg, null); if (result) { diff --git a/src/ol/renderer/webgl/webglvectorlayerrenderer.js b/src/ol/renderer/webgl/webglvectorlayerrenderer.js index 904f496e95..443310543c 100644 --- a/src/ol/renderer/webgl/webglvectorlayerrenderer.js +++ b/src/ol/renderer/webgl/webglvectorlayerrenderer.js @@ -118,12 +118,11 @@ ol.renderer.webgl.VectorLayer.prototype.forEachFeatureAtPixel = var layerState = this.layerState_; /** @type {Object.} */ var features = {}; - return this.replayGroup_.forEachFeatureAtPixel(context, - viewState.center, viewState.resolution, viewState.rotation, + return this.replayGroup_.forEachFeatureAtPixel(coordinate, + context, viewState.center, viewState.resolution, viewState.rotation, frameState.size, frameState.pixelRatio, layerState.opacity, layerState.brightness, layerState.contrast, layerState.hue, layerState.saturation, frameState.skippedFeatureUids, - coordinate, /** * @param {ol.Feature} feature Feature. * @return {?} Callback result. @@ -152,12 +151,11 @@ ol.renderer.webgl.VectorLayer.prototype.hasFeatureAtPixel = var context = mapRenderer.getContext(); var viewState = frameState.viewState; var layerState = this.layerState_; - return this.replayGroup_.hasFeatureAtPixel(context, - viewState.center, viewState.resolution, viewState.rotation, + return this.replayGroup_.hasFeatureAtPixel(coordinate, + context, viewState.center, viewState.resolution, viewState.rotation, frameState.size, frameState.pixelRatio, layerState.opacity, layerState.brightness, layerState.contrast, - layerState.hue, layerState.saturation, frameState.skippedFeatureUids, - coordinate); + layerState.hue, layerState.saturation, frameState.skippedFeatureUids); } }; diff --git a/src/ol/source/imagevectorsource.js b/src/ol/source/imagevectorsource.js index 0bdd75a319..0ce9683a6f 100644 --- a/src/ol/source/imagevectorsource.js +++ b/src/ol/source/imagevectorsource.js @@ -153,14 +153,14 @@ ol.source.ImageVector.prototype.canvasFunctionInternal_ = * @inheritDoc */ ol.source.ImageVector.prototype.forEachFeatureAtPixel = function( - resolution, rotation, coordinate, skippedFeatureUids, callback) { + coordinate, resolution, rotation, skippedFeatureUids, callback) { if (goog.isNull(this.replayGroup_)) { return undefined; } else { /** @type {Object.} */ var features = {}; return this.replayGroup_.forEachFeatureAtPixel( - resolution, 0, coordinate, skippedFeatureUids, + coordinate, resolution, 0, skippedFeatureUids, /** * @param {ol.Feature} feature Feature. * @return {?} Callback result. diff --git a/src/ol/source/source.js b/src/ol/source/source.js index ea2c84c9c9..0113df474d 100644 --- a/src/ol/source/source.js +++ b/src/ol/source/source.js @@ -77,9 +77,9 @@ goog.inherits(ol.source.Source, ol.Observable); /** + * @param {ol.Coordinate} coordinate Coordinate. * @param {number} resolution Resolution. * @param {number} rotation Rotation. - * @param {ol.Coordinate} coordinate Coordinate. * @param {Object.} skippedFeatureUids Skipped feature uids. * @param {function(ol.Feature): T} callback Feature callback. * @return {T|undefined} Callback result. From 4d4bed454aeffb1e52010aae3d38f8a1045e9e7b Mon Sep 17 00:00:00 2001 From: tsauerwein Date: Thu, 29 Jan 2015 11:33:57 +0100 Subject: [PATCH 08/10] Avoid pixel->coord->pixel conversion --- src/ol/map.js | 3 +-- src/ol/renderer/canvas/canvasimagelayerrenderer.js | 5 +++-- src/ol/renderer/canvas/canvaslayerrenderer.js | 7 +++---- src/ol/renderer/canvas/canvastilelayerrenderer.js | 4 ++-- src/ol/renderer/layerrenderer.js | 5 +++-- src/ol/renderer/maprenderer.js | 7 ++++--- src/ol/renderer/webgl/webglimagelayerrenderer.js | 6 +++--- src/ol/renderer/webgl/webglmaprenderer.js | 5 +++-- src/ol/renderer/webgl/webgltilelayerrenderer.js | 7 +++---- src/ol/renderer/webgl/webglvectorlayerrenderer.js | 3 ++- 10 files changed, 27 insertions(+), 25 deletions(-) diff --git a/src/ol/map.js b/src/ol/map.js index 11f38bba82..5a21e4a7d0 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -616,13 +616,12 @@ ol.Map.prototype.forEachLayerAtPixel = if (goog.isNull(this.frameState_)) { return; } - var coordinate = this.getCoordinateFromPixel(pixel); var thisArg = goog.isDef(opt_this) ? opt_this : null; var layerFilter = goog.isDef(opt_layerFilter) ? opt_layerFilter : goog.functions.TRUE; var thisArg2 = goog.isDef(opt_this2) ? opt_this2 : null; return this.renderer_.forEachLayerAtPixel( - coordinate, this.frameState_, callback, thisArg, + pixel, this.frameState_, callback, thisArg, layerFilter, thisArg2); }; diff --git a/src/ol/renderer/canvas/canvasimagelayerrenderer.js b/src/ol/renderer/canvas/canvasimagelayerrenderer.js index dd8d3361bf..f87b6723ba 100644 --- a/src/ol/renderer/canvas/canvasimagelayerrenderer.js +++ b/src/ol/renderer/canvas/canvasimagelayerrenderer.js @@ -79,7 +79,7 @@ ol.renderer.canvas.ImageLayer.prototype.forEachFeatureAtPixel = * @inheritDoc */ ol.renderer.canvas.ImageLayer.prototype.forEachLayerAtPixel = - function(coordinate, frameState, callback, thisArg) { + function(pixel, frameState, callback, thisArg) { if (goog.isNull(this.getImage())) { return undefined; } @@ -87,6 +87,7 @@ ol.renderer.canvas.ImageLayer.prototype.forEachLayerAtPixel = if (this.getLayer().getSource() instanceof ol.source.ImageVector) { // for ImageVector sources use the original hit-detection logic, // so that for example also transparent polygons are detected + var coordinate = this.getMap().getCoordinateFromPixel(pixel); var hasFeature = this.forEachFeatureAtPixel( coordinate, frameState, goog.functions.TRUE, this); @@ -103,7 +104,7 @@ ol.renderer.canvas.ImageLayer.prototype.forEachLayerAtPixel = } var pixelOnCanvas = - this.getPixelFromCoordinates(coordinate, this.imageTransformInv_); + this.getPixelOnCanvas(pixel, this.imageTransformInv_); if (goog.isNull(this.hitCanvasContext_)) { this.hitCanvasContext_ = ol.dom.createCanvasContext2D(1, 1); diff --git a/src/ol/renderer/canvas/canvaslayerrenderer.js b/src/ol/renderer/canvas/canvaslayerrenderer.js index 90712130af..7e8dc1cefc 100644 --- a/src/ol/renderer/canvas/canvaslayerrenderer.js +++ b/src/ol/renderer/canvas/canvaslayerrenderer.js @@ -217,15 +217,14 @@ ol.renderer.canvas.Layer.prototype.prepareFrame = goog.abstractMethod; /** - * @param {ol.Coordinate} coordinate Coordinate. + * @param {ol.Pixel} pixelOnMap Pixel. * @param {goog.vec.Mat4.Number} imageTransformInv The transformation matrix * to convert from a map pixel to a canvas pixel. * @return {ol.Pixel} * @protected */ -ol.renderer.canvas.Layer.prototype.getPixelFromCoordinates = - function(coordinate, imageTransformInv) { - var pixelOnMap = this.getMap().getPixelFromCoordinate(coordinate); +ol.renderer.canvas.Layer.prototype.getPixelOnCanvas = + function(pixelOnMap, imageTransformInv) { var pixelOnCanvas = [0, 0]; ol.vec.Mat4.multVec2(imageTransformInv, pixelOnMap, pixelOnCanvas); return pixelOnCanvas; diff --git a/src/ol/renderer/canvas/canvastilelayerrenderer.js b/src/ol/renderer/canvas/canvastilelayerrenderer.js index cb7859a0d8..f583b6aa48 100644 --- a/src/ol/renderer/canvas/canvastilelayerrenderer.js +++ b/src/ol/renderer/canvas/canvastilelayerrenderer.js @@ -424,7 +424,7 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame = * @inheritDoc */ ol.renderer.canvas.TileLayer.prototype.forEachLayerAtPixel = - function(coordinate, frameState, callback, thisArg) { + function(pixel, frameState, callback, thisArg) { if (goog.isNull(this.context_)) { return undefined; } @@ -435,7 +435,7 @@ ol.renderer.canvas.TileLayer.prototype.forEachLayerAtPixel = } var pixelOnCanvas = - this.getPixelFromCoordinates(coordinate, this.imageTransformInv_); + this.getPixelOnCanvas(pixel, this.imageTransformInv_); var imageData = this.context_.getImageData( pixelOnCanvas[0], pixelOnCanvas[1], 1, 1).data; diff --git a/src/ol/renderer/layerrenderer.js b/src/ol/renderer/layerrenderer.js index 490751926e..35dad5de78 100644 --- a/src/ol/renderer/layerrenderer.js +++ b/src/ol/renderer/layerrenderer.js @@ -57,7 +57,7 @@ ol.renderer.Layer.prototype.forEachFeatureAtPixel = goog.nullFunction; /** - * @param {ol.Coordinate} coordinate Coordinate. + * @param {ol.Pixel} pixel Pixel. * @param {olx.FrameState} frameState Frame state. * @param {function(this: S, ol.layer.Layer): T} callback Layer callback. * @param {S} thisArg Value to use as `this` when executing `callback`. @@ -65,7 +65,8 @@ ol.renderer.Layer.prototype.forEachFeatureAtPixel = goog.nullFunction; * @template S,T */ ol.renderer.Layer.prototype.forEachLayerAtPixel = - function(coordinate, frameState, callback, thisArg) { + function(pixel, frameState, callback, thisArg) { + var coordinate = this.getMap().getCoordinateFromPixel(pixel); var hasFeature = this.forEachFeatureAtPixel( coordinate, frameState, goog.functions.TRUE, this); diff --git a/src/ol/renderer/maprenderer.js b/src/ol/renderer/maprenderer.js index 6c4cce1ee3..c57765c4e5 100644 --- a/src/ol/renderer/maprenderer.js +++ b/src/ol/renderer/maprenderer.js @@ -170,7 +170,7 @@ ol.renderer.Map.prototype.forEachFeatureAtPixel = /** - * @param {ol.Coordinate} coordinate Coordinate. + * @param {ol.Pixel} pixel Pixel. * @param {olx.FrameState} frameState FrameState. * @param {function(this: S, ol.layer.Layer): T} callback Layer * callback. @@ -184,7 +184,7 @@ ol.renderer.Map.prototype.forEachFeatureAtPixel = * @template S,T,U */ ol.renderer.Map.prototype.forEachLayerAtPixel = - function(coordinate, frameState, callback, thisArg, + function(pixel, frameState, callback, thisArg, layerFilter, thisArg2) { var result; var viewState = frameState.viewState; @@ -192,6 +192,7 @@ ol.renderer.Map.prototype.forEachLayerAtPixel = var viewRotation = viewState.rotation; if (!goog.isNull(this.replayGroup)) { + var coordinate = this.getMap().getCoordinateFromPixel(pixel); var hasFeature = this.replayGroup.forEachFeatureAtPixel(coordinate, viewResolution, viewRotation, {}, goog.functions.TRUE); @@ -212,7 +213,7 @@ ol.renderer.Map.prototype.forEachLayerAtPixel = layerFilter.call(thisArg2, layer)) { var layerRenderer = this.getLayerRenderer(layer); result = layerRenderer.forEachLayerAtPixel( - coordinate, frameState, callback, thisArg); + pixel, frameState, callback, thisArg); if (result) { return result; } diff --git a/src/ol/renderer/webgl/webglimagelayerrenderer.js b/src/ol/renderer/webgl/webglimagelayerrenderer.js index 6755b4f2d5..418efd1ae7 100644 --- a/src/ol/renderer/webgl/webglimagelayerrenderer.js +++ b/src/ol/renderer/webgl/webglimagelayerrenderer.js @@ -226,7 +226,7 @@ ol.renderer.webgl.ImageLayer.prototype.hasFeatureAtPixel = * @inheritDoc */ ol.renderer.webgl.ImageLayer.prototype.forEachLayerAtPixel = - function(coordinate, frameState, callback, thisArg) { + function(pixel, frameState, callback, thisArg) { if (goog.isNull(this.image_) || goog.isNull(this.image_.getImage())) { return undefined; } @@ -234,6 +234,7 @@ ol.renderer.webgl.ImageLayer.prototype.forEachLayerAtPixel = if (this.getLayer().getSource() instanceof ol.source.ImageVector) { // for ImageVector sources use the original hit-detection logic, // so that for example also transparent polygons are detected + var coordinate = this.getMap().getCoordinateFromPixel(pixel); var hasFeature = this.forEachFeatureAtPixel( coordinate, frameState, goog.functions.TRUE, this); @@ -251,10 +252,9 @@ ol.renderer.webgl.ImageLayer.prototype.forEachLayerAtPixel = frameState.size, imageSize); } - var pixelOnMap = this.getMap().getPixelFromCoordinate(coordinate); var pixelOnFrameBuffer = [0, 0]; ol.vec.Mat4.multVec2( - this.hitTransformationMatrix_, pixelOnMap, pixelOnFrameBuffer); + this.hitTransformationMatrix_, pixel, pixelOnFrameBuffer); if (pixelOnFrameBuffer[0] < 0 || pixelOnFrameBuffer[0] > imageSize[0] || pixelOnFrameBuffer[1] < 0 || pixelOnFrameBuffer[1] > imageSize[1]) { diff --git a/src/ol/renderer/webgl/webglmaprenderer.js b/src/ol/renderer/webgl/webglmaprenderer.js index 49ae80457e..14ed190a15 100644 --- a/src/ol/renderer/webgl/webglmaprenderer.js +++ b/src/ol/renderer/webgl/webglmaprenderer.js @@ -650,7 +650,7 @@ ol.renderer.webgl.Map.prototype.hasFeatureAtPixel = * @inheritDoc */ ol.renderer.webgl.Map.prototype.forEachLayerAtPixel = - function(coordinate, frameState, callback, thisArg, + function(pixel, frameState, callback, thisArg, layerFilter, thisArg2) { if (this.getGL().isContextLost()) { return false; @@ -664,6 +664,7 @@ ol.renderer.webgl.Map.prototype.forEachLayerAtPixel = if (!goog.isNull(this.replayGroup)) { // use default color values var d = ol.renderer.webgl.Map.DEFAULT_COLOR_VALUES_; + var coordinate = this.getMap().getCoordinateFromPixel(pixel); var hasFeature = this.replayGroup.hasFeatureAtPixel(coordinate, context, viewState.center, viewState.resolution, viewState.rotation, @@ -686,7 +687,7 @@ ol.renderer.webgl.Map.prototype.forEachLayerAtPixel = layerFilter.call(thisArg, layer)) { var layerRenderer = this.getLayerRenderer(layer); result = layerRenderer.forEachLayerAtPixel( - coordinate, frameState, callback, thisArg); + pixel, frameState, callback, thisArg); if (result) { return result; } diff --git a/src/ol/renderer/webgl/webgltilelayerrenderer.js b/src/ol/renderer/webgl/webgltilelayerrenderer.js index 455fce7427..9e79e8ce19 100644 --- a/src/ol/renderer/webgl/webgltilelayerrenderer.js +++ b/src/ol/renderer/webgl/webgltilelayerrenderer.js @@ -333,16 +333,15 @@ ol.renderer.webgl.TileLayer.prototype.prepareFrame = * @inheritDoc */ ol.renderer.webgl.TileLayer.prototype.forEachLayerAtPixel = - function(coordinate, frameState, callback, thisArg) { + function(pixel, frameState, callback, thisArg) { if (goog.isNull(this.framebuffer)) { return undefined; } var mapSize = this.getMap().getSize(); - var pixelOnMap = this.getMap().getPixelFromCoordinate(coordinate); var pixelOnMapScaled = [ - pixelOnMap[0] / mapSize[0], - (mapSize[1] - pixelOnMap[1]) / mapSize[1]]; + pixel[0] / mapSize[0], + (mapSize[1] - pixel[1]) / mapSize[1]]; var pixelOnFrameBufferScaled = [0, 0]; ol.vec.Mat4.multVec2( diff --git a/src/ol/renderer/webgl/webglvectorlayerrenderer.js b/src/ol/renderer/webgl/webglvectorlayerrenderer.js index 443310543c..845770f017 100644 --- a/src/ol/renderer/webgl/webglvectorlayerrenderer.js +++ b/src/ol/renderer/webgl/webglvectorlayerrenderer.js @@ -143,7 +143,7 @@ ol.renderer.webgl.VectorLayer.prototype.forEachFeatureAtPixel = * @inheritDoc */ ol.renderer.webgl.VectorLayer.prototype.hasFeatureAtPixel = - function(coordinate, frameState) { + function(pixel, frameState) { if (goog.isNull(this.replayGroup_) || goog.isNull(this.layerState_)) { return false; } else { @@ -151,6 +151,7 @@ ol.renderer.webgl.VectorLayer.prototype.hasFeatureAtPixel = var context = mapRenderer.getContext(); var viewState = frameState.viewState; var layerState = this.layerState_; + var coordinate = this.getMap().getCoordinateFromPixel(pixel); return this.replayGroup_.hasFeatureAtPixel(coordinate, context, viewState.center, viewState.resolution, viewState.rotation, frameState.size, frameState.pixelRatio, From f4500c8f893a4af447651fe1833acf9229bb6233 Mon Sep 17 00:00:00 2001 From: tsauerwein Date: Thu, 29 Jan 2015 12:20:40 +0100 Subject: [PATCH 09/10] Rename *AtPixel to *AtCoordinate if coordinate --- src/ol/map.js | 4 ++-- src/ol/render/canvas/canvasreplay.js | 2 +- src/ol/render/webgl/webglreplay.js | 6 +++--- .../renderer/canvas/canvasimagelayerrenderer.js | 6 +++--- .../renderer/canvas/canvasvectorlayerrenderer.js | 4 ++-- src/ol/renderer/dom/domimagelayerrenderer.js | 4 ++-- src/ol/renderer/dom/domvectorlayerrenderer.js | 4 ++-- src/ol/renderer/layerrenderer.js | 8 ++++---- src/ol/renderer/maprenderer.js | 14 +++++++------- src/ol/renderer/webgl/webglimagelayerrenderer.js | 10 +++++----- src/ol/renderer/webgl/webglmaprenderer.js | 15 ++++++++------- .../renderer/webgl/webglvectorlayerrenderer.js | 16 ++++++++-------- src/ol/source/imagevectorsource.js | 4 ++-- src/ol/source/source.js | 2 +- src/ol/source/vectorsource.js | 4 ++-- .../canvas/canvasvectorlayerrenderer.test.js | 8 ++++---- 16 files changed, 56 insertions(+), 55 deletions(-) diff --git a/src/ol/map.js b/src/ol/map.js index 5a21e4a7d0..9b019ed2eb 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -583,7 +583,7 @@ ol.Map.prototype.forEachFeatureAtPixel = var layerFilter = goog.isDef(opt_layerFilter) ? opt_layerFilter : goog.functions.TRUE; var thisArg2 = goog.isDef(opt_this2) ? opt_this2 : null; - return this.renderer_.forEachFeatureAtPixel( + return this.renderer_.forEachFeatureAtCoordinate( coordinate, this.frameState_, callback, thisArg, layerFilter, thisArg2); }; @@ -649,7 +649,7 @@ ol.Map.prototype.hasFeatureAtPixel = var layerFilter = goog.isDef(opt_layerFilter) ? opt_layerFilter : goog.functions.TRUE; var thisArg = goog.isDef(opt_this) ? opt_this : null; - return this.renderer_.hasFeatureAtPixel( + return this.renderer_.hasFeatureAtCoordinate( coordinate, this.frameState_, layerFilter, thisArg); }; diff --git a/src/ol/render/canvas/canvasreplay.js b/src/ol/render/canvas/canvasreplay.js index 866823231e..e8f70c7c1d 100644 --- a/src/ol/render/canvas/canvasreplay.js +++ b/src/ol/render/canvas/canvasreplay.js @@ -1866,7 +1866,7 @@ ol.render.canvas.ReplayGroup.prototype.finish = function() { * @return {T|undefined} Callback result. * @template T */ -ol.render.canvas.ReplayGroup.prototype.forEachFeatureAtPixel = function( +ol.render.canvas.ReplayGroup.prototype.forEachFeatureAtCoordinate = function( coordinate, resolution, rotation, skippedFeaturesHash, callback) { var transform = this.hitDetectionTransform_; diff --git a/src/ol/render/webgl/webglreplay.js b/src/ol/render/webgl/webglreplay.js index 2913c010a7..5432e0aab6 100644 --- a/src/ol/render/webgl/webglreplay.js +++ b/src/ol/render/webgl/webglreplay.js @@ -1171,7 +1171,7 @@ ol.render.webgl.ReplayGroup.prototype.replayHitDetection_ = function(context, * @return {T|undefined} Callback result. * @template T */ -ol.render.webgl.ReplayGroup.prototype.forEachFeatureAtPixel = function( +ol.render.webgl.ReplayGroup.prototype.forEachFeatureAtCoordinate = function( coordinate, context, center, resolution, rotation, size, pixelRatio, opacity, brightness, contrast, hue, saturation, skippedFeaturesHash, callback) { @@ -1228,9 +1228,9 @@ ol.render.webgl.ReplayGroup.prototype.forEachFeatureAtPixel = function( * @param {number} hue Global hue. * @param {number} saturation Global saturation. * @param {Object} skippedFeaturesHash Ids of features to skip. - * @return {boolean} Is there a feature at the given pixel? + * @return {boolean} Is there a feature at the given coordinate? */ -ol.render.webgl.ReplayGroup.prototype.hasFeatureAtPixel = function( +ol.render.webgl.ReplayGroup.prototype.hasFeatureAtCoordinate = function( coordinate, context, center, resolution, rotation, size, pixelRatio, opacity, brightness, contrast, hue, saturation, skippedFeaturesHash) { var gl = context.getGL(); diff --git a/src/ol/renderer/canvas/canvasimagelayerrenderer.js b/src/ol/renderer/canvas/canvasimagelayerrenderer.js index f87b6723ba..8edd16d709 100644 --- a/src/ol/renderer/canvas/canvasimagelayerrenderer.js +++ b/src/ol/renderer/canvas/canvasimagelayerrenderer.js @@ -56,14 +56,14 @@ goog.inherits(ol.renderer.canvas.ImageLayer, ol.renderer.canvas.Layer); /** * @inheritDoc */ -ol.renderer.canvas.ImageLayer.prototype.forEachFeatureAtPixel = +ol.renderer.canvas.ImageLayer.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, callback, thisArg) { var layer = this.getLayer(); var source = layer.getSource(); var resolution = frameState.viewState.resolution; var rotation = frameState.viewState.rotation; var skippedFeatureUids = frameState.skippedFeatureUids; - return source.forEachFeatureAtPixel( + return source.forEachFeatureAtCoordinate( coordinate, resolution, rotation, skippedFeatureUids, /** * @param {ol.Feature} feature Feature. @@ -88,7 +88,7 @@ ol.renderer.canvas.ImageLayer.prototype.forEachLayerAtPixel = // for ImageVector sources use the original hit-detection logic, // so that for example also transparent polygons are detected var coordinate = this.getMap().getCoordinateFromPixel(pixel); - var hasFeature = this.forEachFeatureAtPixel( + var hasFeature = this.forEachFeatureAtCoordinate( coordinate, frameState, goog.functions.TRUE, this); if (hasFeature) { diff --git a/src/ol/renderer/canvas/canvasvectorlayerrenderer.js b/src/ol/renderer/canvas/canvasvectorlayerrenderer.js index e8baf6274c..219288c185 100644 --- a/src/ol/renderer/canvas/canvasvectorlayerrenderer.js +++ b/src/ol/renderer/canvas/canvasvectorlayerrenderer.js @@ -116,7 +116,7 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame = /** * @inheritDoc */ -ol.renderer.canvas.VectorLayer.prototype.forEachFeatureAtPixel = +ol.renderer.canvas.VectorLayer.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, callback, thisArg) { if (goog.isNull(this.replayGroup_)) { return undefined; @@ -126,7 +126,7 @@ ol.renderer.canvas.VectorLayer.prototype.forEachFeatureAtPixel = var layer = this.getLayer(); /** @type {Object.} */ var features = {}; - return this.replayGroup_.forEachFeatureAtPixel(coordinate, + return this.replayGroup_.forEachFeatureAtCoordinate(coordinate, resolution, rotation, frameState.skippedFeatureUids, /** * @param {ol.Feature} feature Feature. diff --git a/src/ol/renderer/dom/domimagelayerrenderer.js b/src/ol/renderer/dom/domimagelayerrenderer.js index 334357da44..cce9db4785 100644 --- a/src/ol/renderer/dom/domimagelayerrenderer.js +++ b/src/ol/renderer/dom/domimagelayerrenderer.js @@ -47,14 +47,14 @@ goog.inherits(ol.renderer.dom.ImageLayer, ol.renderer.dom.Layer); /** * @inheritDoc */ -ol.renderer.dom.ImageLayer.prototype.forEachFeatureAtPixel = +ol.renderer.dom.ImageLayer.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, callback, thisArg) { var layer = this.getLayer(); var source = layer.getSource(); var resolution = frameState.viewState.resolution; var rotation = frameState.viewState.rotation; var skippedFeatureUids = frameState.skippedFeatureUids; - return source.forEachFeatureAtPixel( + return source.forEachFeatureAtCoordinate( coordinate, resolution, rotation, skippedFeatureUids, /** * @param {ol.Feature} feature Feature. diff --git a/src/ol/renderer/dom/domvectorlayerrenderer.js b/src/ol/renderer/dom/domvectorlayerrenderer.js index fe7cee6af2..bcb5ec63f8 100644 --- a/src/ol/renderer/dom/domvectorlayerrenderer.js +++ b/src/ol/renderer/dom/domvectorlayerrenderer.js @@ -176,7 +176,7 @@ ol.renderer.dom.VectorLayer.prototype.dispatchEvent_ = /** * @inheritDoc */ -ol.renderer.dom.VectorLayer.prototype.forEachFeatureAtPixel = +ol.renderer.dom.VectorLayer.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, callback, thisArg) { if (goog.isNull(this.replayGroup_)) { return undefined; @@ -186,7 +186,7 @@ ol.renderer.dom.VectorLayer.prototype.forEachFeatureAtPixel = var layer = this.getLayer(); /** @type {Object.} */ var features = {}; - return this.replayGroup_.forEachFeatureAtPixel(coordinate, + return this.replayGroup_.forEachFeatureAtCoordinate(coordinate, resolution, rotation, frameState.skippedFeatureUids, /** * @param {ol.Feature} feature Feature. diff --git a/src/ol/renderer/layerrenderer.js b/src/ol/renderer/layerrenderer.js index 35dad5de78..1519d679d1 100644 --- a/src/ol/renderer/layerrenderer.js +++ b/src/ol/renderer/layerrenderer.js @@ -53,7 +53,7 @@ goog.inherits(ol.renderer.Layer, goog.Disposable); * @return {T|undefined} Callback result. * @template S,T */ -ol.renderer.Layer.prototype.forEachFeatureAtPixel = goog.nullFunction; +ol.renderer.Layer.prototype.forEachFeatureAtCoordinate = goog.nullFunction; /** @@ -67,7 +67,7 @@ ol.renderer.Layer.prototype.forEachFeatureAtPixel = goog.nullFunction; ol.renderer.Layer.prototype.forEachLayerAtPixel = function(pixel, frameState, callback, thisArg) { var coordinate = this.getMap().getCoordinateFromPixel(pixel); - var hasFeature = this.forEachFeatureAtPixel( + var hasFeature = this.forEachFeatureAtCoordinate( coordinate, frameState, goog.functions.TRUE, this); if (hasFeature) { @@ -81,9 +81,9 @@ ol.renderer.Layer.prototype.forEachLayerAtPixel = /** * @param {ol.Coordinate} coordinate Coordinate. * @param {olx.FrameState} frameState Frame state. - * @return {boolean} Is there a feature at the given pixel? + * @return {boolean} Is there a feature at the given coordinate? */ -ol.renderer.Layer.prototype.hasFeatureAtPixel = goog.functions.FALSE; +ol.renderer.Layer.prototype.hasFeatureAtCoordinate = goog.functions.FALSE; /** diff --git a/src/ol/renderer/maprenderer.js b/src/ol/renderer/maprenderer.js index c57765c4e5..bc6ba4666c 100644 --- a/src/ol/renderer/maprenderer.js +++ b/src/ol/renderer/maprenderer.js @@ -121,7 +121,7 @@ ol.renderer.Map.expireIconCache_ = function(map, frameState) { * @return {T|undefined} Callback result. * @template S,T,U */ -ol.renderer.Map.prototype.forEachFeatureAtPixel = +ol.renderer.Map.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, callback, thisArg, layerFilter, thisArg2) { var result; @@ -131,7 +131,7 @@ ol.renderer.Map.prototype.forEachFeatureAtPixel = if (!goog.isNull(this.replayGroup)) { /** @type {Object.} */ var features = {}; - result = this.replayGroup.forEachFeatureAtPixel(coordinate, + result = this.replayGroup.forEachFeatureAtCoordinate(coordinate, viewResolution, viewRotation, {}, /** * @param {ol.Feature} feature Feature. @@ -158,7 +158,7 @@ ol.renderer.Map.prototype.forEachFeatureAtPixel = if (ol.layer.Layer.visibleAtResolution(layerState, viewResolution) && layerFilter.call(thisArg2, layer)) { var layerRenderer = this.getLayerRenderer(layer); - result = layerRenderer.forEachFeatureAtPixel( + result = layerRenderer.forEachFeatureAtCoordinate( coordinate, frameState, callback, thisArg); if (result) { return result; @@ -193,7 +193,7 @@ ol.renderer.Map.prototype.forEachLayerAtPixel = if (!goog.isNull(this.replayGroup)) { var coordinate = this.getMap().getCoordinateFromPixel(pixel); - var hasFeature = this.replayGroup.forEachFeatureAtPixel(coordinate, + var hasFeature = this.replayGroup.forEachFeatureAtCoordinate(coordinate, viewResolution, viewRotation, {}, goog.functions.TRUE); if (hasFeature) { @@ -231,12 +231,12 @@ ol.renderer.Map.prototype.forEachLayerAtPixel = * returns `true` will be tested for features. By default, all visible * layers will be tested. * @param {U} thisArg Value to use as `this` when executing `layerFilter`. - * @return {boolean} Is there a feature at the given pixel? + * @return {boolean} Is there a feature at the given coordinate? * @template U */ -ol.renderer.Map.prototype.hasFeatureAtPixel = +ol.renderer.Map.prototype.hasFeatureAtCoordinate = function(coordinate, frameState, layerFilter, thisArg) { - var hasFeature = this.forEachFeatureAtPixel( + var hasFeature = this.forEachFeatureAtCoordinate( coordinate, frameState, goog.functions.TRUE, this, layerFilter, thisArg); return goog.isDef(hasFeature); diff --git a/src/ol/renderer/webgl/webglimagelayerrenderer.js b/src/ol/renderer/webgl/webglimagelayerrenderer.js index 418efd1ae7..af74c1e244 100644 --- a/src/ol/renderer/webgl/webglimagelayerrenderer.js +++ b/src/ol/renderer/webgl/webglimagelayerrenderer.js @@ -73,14 +73,14 @@ ol.renderer.webgl.ImageLayer.prototype.createTexture_ = function(image) { /** * @inheritDoc */ -ol.renderer.webgl.ImageLayer.prototype.forEachFeatureAtPixel = +ol.renderer.webgl.ImageLayer.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, callback, thisArg) { var layer = this.getLayer(); var source = layer.getSource(); var resolution = frameState.viewState.resolution; var rotation = frameState.viewState.rotation; var skippedFeatureUids = frameState.skippedFeatureUids; - return source.forEachFeatureAtPixel( + return source.forEachFeatureAtCoordinate( coordinate, resolution, rotation, skippedFeatureUids, /** @@ -214,9 +214,9 @@ ol.renderer.webgl.ImageLayer.prototype.updateProjectionMatrix_ = /** * @inheritDoc */ -ol.renderer.webgl.ImageLayer.prototype.hasFeatureAtPixel = +ol.renderer.webgl.ImageLayer.prototype.hasFeatureAtCoordinate = function(coordinate, frameState) { - var hasFeature = this.forEachFeatureAtPixel( + var hasFeature = this.forEachFeatureAtCoordinate( coordinate, frameState, goog.functions.TRUE, this); return goog.isDef(hasFeature); }; @@ -235,7 +235,7 @@ ol.renderer.webgl.ImageLayer.prototype.forEachLayerAtPixel = // for ImageVector sources use the original hit-detection logic, // so that for example also transparent polygons are detected var coordinate = this.getMap().getCoordinateFromPixel(pixel); - var hasFeature = this.forEachFeatureAtPixel( + var hasFeature = this.forEachFeatureAtCoordinate( coordinate, frameState, goog.functions.TRUE, this); if (hasFeature) { diff --git a/src/ol/renderer/webgl/webglmaprenderer.js b/src/ol/renderer/webgl/webglmaprenderer.js index 14ed190a15..7fd95f3580 100644 --- a/src/ol/renderer/webgl/webglmaprenderer.js +++ b/src/ol/renderer/webgl/webglmaprenderer.js @@ -540,7 +540,7 @@ ol.renderer.webgl.Map.prototype.renderFrame = function(frameState) { /** * @inheritDoc */ -ol.renderer.webgl.Map.prototype.forEachFeatureAtPixel = +ol.renderer.webgl.Map.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, callback, thisArg, layerFilter, thisArg2) { var result; @@ -560,7 +560,7 @@ ol.renderer.webgl.Map.prototype.forEachFeatureAtPixel = // use default color values var d = ol.renderer.webgl.Map.DEFAULT_COLOR_VALUES_; - result = this.replayGroup.forEachFeatureAtPixel(coordinate, + result = this.replayGroup.forEachFeatureAtCoordinate(coordinate, context, viewState.center, viewState.resolution, viewState.rotation, frameState.size, frameState.pixelRatio, d.opacity, d.brightness, d.contrast, d.hue, d.saturation, {}, @@ -589,7 +589,7 @@ ol.renderer.webgl.Map.prototype.forEachFeatureAtPixel = if (ol.layer.Layer.visibleAtResolution(layerState, viewState.resolution) && layerFilter.call(thisArg2, layer)) { var layerRenderer = this.getLayerRenderer(layer); - result = layerRenderer.forEachFeatureAtPixel( + result = layerRenderer.forEachFeatureAtCoordinate( coordinate, frameState, callback, thisArg); if (result) { return result; @@ -603,7 +603,7 @@ ol.renderer.webgl.Map.prototype.forEachFeatureAtPixel = /** * @inheritDoc */ -ol.renderer.webgl.Map.prototype.hasFeatureAtPixel = +ol.renderer.webgl.Map.prototype.hasFeatureAtCoordinate = function(coordinate, frameState, layerFilter, thisArg) { var hasFeature = false; @@ -619,7 +619,7 @@ ol.renderer.webgl.Map.prototype.hasFeatureAtPixel = // use default color values var d = ol.renderer.webgl.Map.DEFAULT_COLOR_VALUES_; - hasFeature = this.replayGroup.hasFeatureAtPixel(coordinate, + hasFeature = this.replayGroup.hasFeatureAtCoordinate(coordinate, context, viewState.center, viewState.resolution, viewState.rotation, frameState.size, frameState.pixelRatio, d.opacity, d.brightness, d.contrast, d.hue, d.saturation, {}); @@ -636,7 +636,8 @@ ol.renderer.webgl.Map.prototype.hasFeatureAtPixel = if (ol.layer.Layer.visibleAtResolution(layerState, viewState.resolution) && layerFilter.call(thisArg, layer)) { var layerRenderer = this.getLayerRenderer(layer); - hasFeature = layerRenderer.hasFeatureAtPixel(coordinate, frameState); + hasFeature = + layerRenderer.hasFeatureAtCoordinate(coordinate, frameState); if (hasFeature) { return true; } @@ -666,7 +667,7 @@ ol.renderer.webgl.Map.prototype.forEachLayerAtPixel = var d = ol.renderer.webgl.Map.DEFAULT_COLOR_VALUES_; var coordinate = this.getMap().getCoordinateFromPixel(pixel); - var hasFeature = this.replayGroup.hasFeatureAtPixel(coordinate, + var hasFeature = this.replayGroup.hasFeatureAtCoordinate(coordinate, context, viewState.center, viewState.resolution, viewState.rotation, frameState.size, frameState.pixelRatio, d.opacity, d.brightness, d.contrast, d.hue, d.saturation, {}); diff --git a/src/ol/renderer/webgl/webglvectorlayerrenderer.js b/src/ol/renderer/webgl/webglvectorlayerrenderer.js index 845770f017..7a3de9e676 100644 --- a/src/ol/renderer/webgl/webglvectorlayerrenderer.js +++ b/src/ol/renderer/webgl/webglvectorlayerrenderer.js @@ -106,7 +106,7 @@ ol.renderer.webgl.VectorLayer.prototype.disposeInternal = function() { /** * @inheritDoc */ -ol.renderer.webgl.VectorLayer.prototype.forEachFeatureAtPixel = +ol.renderer.webgl.VectorLayer.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, callback, thisArg) { if (goog.isNull(this.replayGroup_) || goog.isNull(this.layerState_)) { return undefined; @@ -118,7 +118,7 @@ ol.renderer.webgl.VectorLayer.prototype.forEachFeatureAtPixel = var layerState = this.layerState_; /** @type {Object.} */ var features = {}; - return this.replayGroup_.forEachFeatureAtPixel(coordinate, + return this.replayGroup_.forEachFeatureAtCoordinate(coordinate, context, viewState.center, viewState.resolution, viewState.rotation, frameState.size, frameState.pixelRatio, layerState.opacity, layerState.brightness, layerState.contrast, @@ -142,8 +142,8 @@ ol.renderer.webgl.VectorLayer.prototype.forEachFeatureAtPixel = /** * @inheritDoc */ -ol.renderer.webgl.VectorLayer.prototype.hasFeatureAtPixel = - function(pixel, frameState) { +ol.renderer.webgl.VectorLayer.prototype.hasFeatureAtCoordinate = + function(coordinate, frameState) { if (goog.isNull(this.replayGroup_) || goog.isNull(this.layerState_)) { return false; } else { @@ -151,8 +151,7 @@ ol.renderer.webgl.VectorLayer.prototype.hasFeatureAtPixel = var context = mapRenderer.getContext(); var viewState = frameState.viewState; var layerState = this.layerState_; - var coordinate = this.getMap().getCoordinateFromPixel(pixel); - return this.replayGroup_.hasFeatureAtPixel(coordinate, + return this.replayGroup_.hasFeatureAtCoordinate(coordinate, context, viewState.center, viewState.resolution, viewState.rotation, frameState.size, frameState.pixelRatio, layerState.opacity, layerState.brightness, layerState.contrast, @@ -165,8 +164,9 @@ ol.renderer.webgl.VectorLayer.prototype.hasFeatureAtPixel = * @inheritDoc */ ol.renderer.webgl.VectorLayer.prototype.forEachLayerAtPixel = - function(coordinate, frameState, callback, thisArg) { - var hasFeature = this.hasFeatureAtPixel(coordinate, frameState); + function(pixel, frameState, callback, thisArg) { + var coordinate = this.getMap().getCoordinateFromPixel(pixel); + var hasFeature = this.hasFeatureAtCoordinate(coordinate, frameState); if (hasFeature) { return callback.call(thisArg, this.getLayer()); diff --git a/src/ol/source/imagevectorsource.js b/src/ol/source/imagevectorsource.js index 0ce9683a6f..521ad8e8ae 100644 --- a/src/ol/source/imagevectorsource.js +++ b/src/ol/source/imagevectorsource.js @@ -152,14 +152,14 @@ ol.source.ImageVector.prototype.canvasFunctionInternal_ = /** * @inheritDoc */ -ol.source.ImageVector.prototype.forEachFeatureAtPixel = function( +ol.source.ImageVector.prototype.forEachFeatureAtCoordinate = function( coordinate, resolution, rotation, skippedFeatureUids, callback) { if (goog.isNull(this.replayGroup_)) { return undefined; } else { /** @type {Object.} */ var features = {}; - return this.replayGroup_.forEachFeatureAtPixel( + return this.replayGroup_.forEachFeatureAtCoordinate( coordinate, resolution, 0, skippedFeatureUids, /** * @param {ol.Feature} feature Feature. diff --git a/src/ol/source/source.js b/src/ol/source/source.js index 0113df474d..a54d304caa 100644 --- a/src/ol/source/source.js +++ b/src/ol/source/source.js @@ -85,7 +85,7 @@ goog.inherits(ol.source.Source, ol.Observable); * @return {T|undefined} Callback result. * @template T */ -ol.source.Source.prototype.forEachFeatureAtPixel = +ol.source.Source.prototype.forEachFeatureAtCoordinate = goog.nullFunction; diff --git a/src/ol/source/vectorsource.js b/src/ol/source/vectorsource.js index de1783e130..ccfe2cbaa0 100644 --- a/src/ol/source/vectorsource.js +++ b/src/ol/source/vectorsource.js @@ -295,7 +295,7 @@ ol.source.Vector.prototype.forEachFeature = function(callback, opt_this) { * @return {S|undefined} The return value from the last call to the callback. * @template T,S */ -ol.source.Vector.prototype.forEachFeatureAtCoordinate = +ol.source.Vector.prototype.forEachFeatureAtCoordinateDirect = function(coordinate, callback, opt_this) { var extent = [coordinate[0], coordinate[1], coordinate[0], coordinate[1]]; return this.forEachFeatureInExtent(extent, function(feature) { @@ -409,7 +409,7 @@ ol.source.Vector.prototype.getFeatures = function() { */ ol.source.Vector.prototype.getFeaturesAtCoordinate = function(coordinate) { var features = []; - this.forEachFeatureAtCoordinate(coordinate, function(feature) { + this.forEachFeatureAtCoordinateDirect(coordinate, function(feature) { features.push(feature); }); return features; diff --git a/test/spec/ol/renderer/canvas/canvasvectorlayerrenderer.test.js b/test/spec/ol/renderer/canvas/canvasvectorlayerrenderer.test.js index a1165aebaa..2457dae729 100644 --- a/test/spec/ol/renderer/canvas/canvasvectorlayerrenderer.test.js +++ b/test/spec/ol/renderer/canvas/canvasvectorlayerrenderer.test.js @@ -58,7 +58,7 @@ describe('ol.renderer.canvas.VectorLayer', function() { }); - describe('#forEachFeatureAtPixel', function() { + describe('#forEachFeatureAtCoordinate', function() { var renderer; beforeEach(function() { @@ -70,8 +70,8 @@ describe('ol.renderer.canvas.VectorLayer', function() { map.getRenderer(), layer); var replayGroup = {}; renderer.replayGroup_ = replayGroup; - replayGroup.forEachFeatureAtPixel = function(resolution, - rotation, coordinate, skippedFeaturesUids, callback) { + replayGroup.forEachFeatureAtCoordinate = function(coordinate, + resolution, rotation, skippedFeaturesUids, callback) { var geometry = new ol.geom.Point([0, 0]); var feature = new ol.Feature(); callback(geometry, feature); @@ -89,7 +89,7 @@ describe('ol.renderer.canvas.VectorLayer', function() { rotation: 0 } }; - renderer.forEachFeatureAtPixel( + renderer.forEachFeatureAtCoordinate( coordinate, frameState, spy, undefined); expect(spy.callCount).to.be(1); }); From b390c1bdf8e244b7c2f17349920a3e2a45065f4e Mon Sep 17 00:00:00 2001 From: tsauerwein Date: Fri, 30 Jan 2015 10:05:38 +0100 Subject: [PATCH 10/10] Use `dragging` flag in examples --- examples/getfeatureinfo-image.js | 5 ++++- examples/getfeatureinfo-tile.js | 5 ++++- src/ol/map.js | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/examples/getfeatureinfo-image.js b/examples/getfeatureinfo-image.js index 5ec90dc8ca..316fda17bc 100644 --- a/examples/getfeatureinfo-image.js +++ b/examples/getfeatureinfo-image.js @@ -39,7 +39,10 @@ map.on('singleclick', function(evt) { } }); -$(map.getViewport()).on('mousemove', function(evt) { +map.on('pointermove', function(evt) { + if (evt.dragging) { + return; + } var pixel = map.getEventPixel(evt.originalEvent); var hit = map.forEachLayerAtPixel(pixel, function(layer) { return true; diff --git a/examples/getfeatureinfo-tile.js b/examples/getfeatureinfo-tile.js index 901b87db57..022606b611 100644 --- a/examples/getfeatureinfo-tile.js +++ b/examples/getfeatureinfo-tile.js @@ -39,7 +39,10 @@ map.on('singleclick', function(evt) { } }); -$(map.getViewport()).on('mousemove', function(evt) { +map.on('pointermove', function(evt) { + if (evt.dragging) { + return; + } var pixel = map.getEventPixel(evt.originalEvent); var hit = map.forEachLayerAtPixel(pixel, function(layer) { return true; diff --git a/src/ol/map.js b/src/ol/map.js index 9b019ed2eb..16620afb8b 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -590,7 +590,7 @@ ol.Map.prototype.forEachFeatureAtPixel = /** - * Detect layers that have a colour value at a pixel on the viewport, and + * Detect layers that have a color value at a pixel on the viewport, and * execute a callback with each matching layer. Layers included in the * detection can be configured through `opt_layerFilter`. Feature overlays will * always be included in the detection.