Implement forEachLayerAtPixel for canvas

This commit is contained in:
tsauerwein
2015-01-23 16:50:42 +01:00
parent 225f0739ec
commit b4cb786f29
3 changed files with 114 additions and 0 deletions

View File

@@ -4,11 +4,13 @@ goog.require('goog.asserts');
goog.require('goog.vec.Mat4'); goog.require('goog.vec.Mat4');
goog.require('ol.ImageBase'); goog.require('ol.ImageBase');
goog.require('ol.ViewHint'); goog.require('ol.ViewHint');
goog.require('ol.dom');
goog.require('ol.extent'); goog.require('ol.extent');
goog.require('ol.layer.Image'); goog.require('ol.layer.Image');
goog.require('ol.proj'); goog.require('ol.proj');
goog.require('ol.renderer.Map'); goog.require('ol.renderer.Map');
goog.require('ol.renderer.canvas.Layer'); goog.require('ol.renderer.canvas.Layer');
goog.require('ol.source.ImageVector');
goog.require('ol.vec.Mat4'); goog.require('ol.vec.Mat4');
@@ -35,6 +37,18 @@ ol.renderer.canvas.ImageLayer = function(mapRenderer, imageLayer) {
*/ */
this.imageTransform_ = goog.vec.Mat4.createNumber(); 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); 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 * @inheritDoc
*/ */
@@ -135,6 +197,7 @@ ol.renderer.canvas.ImageLayer.prototype.prepareFrame =
viewRotation, viewRotation,
imagePixelRatio * (imageExtent[0] - viewCenter[0]) / imageResolution, imagePixelRatio * (imageExtent[0] - viewCenter[0]) / imageResolution,
imagePixelRatio * (viewCenter[1] - imageExtent[3]) / imageResolution); imagePixelRatio * (viewCenter[1] - imageExtent[3]) / imageResolution);
this.imageTransformInv_ = null;
this.updateAttributions(frameState.attributions, image.getAttributions()); this.updateAttributions(frameState.attributions, image.getAttributions());
this.updateLogos(frameState, imageSource); this.updateLogos(frameState, imageSource);
} }

View File

@@ -216,6 +216,22 @@ ol.renderer.canvas.Layer.prototype.getTransform = function(frameState) {
ol.renderer.canvas.Layer.prototype.prepareFrame = goog.abstractMethod; 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. * @param {ol.Size} size Size.
* @return {boolean} True when the canvas with the current size does not exceed * @return {boolean} True when the canvas with the current size does not exceed

View File

@@ -60,6 +60,12 @@ ol.renderer.canvas.TileLayer = function(mapRenderer, tileLayer) {
*/ */
this.imageTransform_ = goog.vec.Mat4.createNumber(); this.imageTransform_ = goog.vec.Mat4.createNumber();
/**
* @private
* @type {?goog.vec.Mat4.Number}
*/
this.imageTransformInv_ = null;
/** /**
* @private * @private
* @type {number} * @type {number}
@@ -408,6 +414,35 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame =
viewState.rotation, viewState.rotation,
(origin[0] - center[0]) / tilePixelResolution, (origin[0] - center[0]) / tilePixelResolution,
(center[1] - origin[1]) / tilePixelResolution); (center[1] - origin[1]) / tilePixelResolution);
this.imageTransformInv_ = null;
return true; 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;
}
};