Compare commits

...

4 Commits
docs ... v4.6.5

Author SHA1 Message Date
ahocevar
2eea8df75a Update package version to 4.6.5 2018-03-18 23:33:43 +01:00
ahocevar
c3870aed81 Changelog for v4.6.5 2018-03-18 23:32:50 +01:00
ahocevar
98d0fc05c8 Backport types 2018-03-18 23:20:32 +01:00
Andreas Hocevar
2912a5d7a7 Merge pull request #7669 from ahocevar/hit-detect-declutter
Use declutter tree only for text and image replays
2018-03-18 22:45:40 +01:00
5 changed files with 62 additions and 62 deletions

7
changelog/v4.6.5.md Normal file
View File

@@ -0,0 +1,7 @@
# 4.6.5
The v4.6.5 release fixes a hit detection issue when `declutter: true` is set on an `ol.layer.VectorTile`.
## Fixes
* [#7669](https://github.com/openlayers/openlayers/pull/7559) - Use declutter tree only for text and image replays ([@ahocevar](https://github.com/ahocevar))

View File

@@ -1,6 +1,6 @@
{ {
"name": "openlayers", "name": "openlayers",
"version": "4.6.4", "version": "4.6.5",
"description": "Build tools and sources for developing OpenLayers based mapping applications", "description": "Build tools and sources for developing OpenLayers based mapping applications",
"keywords": [ "keywords": [
"map", "map",

View File

@@ -1,6 +1,6 @@
{ {
"name": "ol", "name": "ol",
"version": "4.6.4", "version": "4.6.5",
"description": "OpenLayers as ES2015 modules", "description": "OpenLayers as ES2015 modules",
"main": "index.js", "main": "index.js",
"module": "index.js", "module": "index.js",

View File

@@ -321,18 +321,21 @@ ol.render.canvas.ReplayGroup.prototype.forEachFeatureAtCoordinate = function(
}); });
} }
var replayType;
/** /**
* @param {ol.Feature|ol.render.Feature} feature Feature. * @param {ol.Feature|ol.render.Feature} feature Feature.
* @return {?} Callback result. * @return {?} Callback result.
*/ */
function hitDetectionCallback(feature) { function featureCallback(feature) {
var imageData = context.getImageData(0, 0, contextSize, contextSize).data; var imageData = context.getImageData(0, 0, contextSize, contextSize).data;
for (var i = 0; i < contextSize; i++) { for (var i = 0; i < contextSize; i++) {
for (var j = 0; j < contextSize; j++) { for (var j = 0; j < contextSize; j++) {
if (mask[i][j]) { if (mask[i][j]) {
if (imageData[(j * contextSize + i) * 4 + 3] > 0) { if (imageData[(j * contextSize + i) * 4 + 3] > 0) {
var result; var result;
if (!declutteredFeatures || declutteredFeatures.indexOf(feature) !== -1) { if (!(declutteredFeatures && (replayType == ol.render.ReplayType.IMAGE || replayType == ol.render.ReplayType.TEXT)) ||
declutteredFeatures.indexOf(feature) !== -1) {
result = callback(feature); result = callback(feature);
} }
if (result) { if (result) {
@@ -347,8 +350,37 @@ ol.render.canvas.ReplayGroup.prototype.forEachFeatureAtCoordinate = function(
} }
} }
return this.replayHitDetection_(context, transform, rotation, /** @type {Array.<number>} */
skippedFeaturesHash, hitDetectionCallback, hitExtent, declutterReplays); var zs = Object.keys(this.replaysByZIndex_).map(Number);
zs.sort(ol.array.numberSafeCompareFunction);
var i, j, replays, replay, result;
for (i = zs.length - 1; i >= 0; --i) {
var zIndexKey = zs[i].toString();
replays = this.replaysByZIndex_[zIndexKey];
for (j = ol.render.replay.ORDER.length - 1; j >= 0; --j) {
replayType = ol.render.replay.ORDER[j];
replay = replays[replayType];
if (replay !== undefined) {
if (declutterReplays &&
(replayType == ol.render.ReplayType.IMAGE || replayType == ol.render.ReplayType.TEXT)) {
var declutter = declutterReplays[zIndexKey];
if (!declutter) {
declutterReplays[zIndexKey] = [replay, transform.slice(0)];
} else {
declutter.push(replay, transform.slice(0));
}
} else {
result = replay.replayHitDetection(context, transform, rotation,
skippedFeaturesHash, featureCallback, hitExtent);
if (result) {
return result;
}
}
}
}
}
return undefined;
}; };
@@ -457,59 +489,6 @@ ol.render.canvas.ReplayGroup.prototype.replay = function(context,
}; };
/**
* @private
* @param {CanvasRenderingContext2D} context Context.
* @param {ol.Transform} transform Transform.
* @param {number} viewRotation View rotation.
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
* to skip.
* @param {function((ol.Feature|ol.render.Feature)): T} featureCallback
* Feature callback.
* @param {ol.Extent=} opt_hitExtent Only check features that intersect this
* extent.
* @param {Object.<string, ol.DeclutterGroup>=} opt_declutterReplays Declutter
* replays.
* @return {T|undefined} Callback result.
* @template T
*/
ol.render.canvas.ReplayGroup.prototype.replayHitDetection_ = function(
context, transform, viewRotation, skippedFeaturesHash,
featureCallback, opt_hitExtent, opt_declutterReplays) {
/** @type {Array.<number>} */
var zs = Object.keys(this.replaysByZIndex_).map(Number);
zs.sort(ol.array.numberSafeCompareFunction);
var i, j, replays, replay, result;
for (i = zs.length - 1; i >= 0; --i) {
var zIndexKey = zs[i].toString();
replays = this.replaysByZIndex_[zIndexKey];
for (j = ol.render.replay.ORDER.length - 1; j >= 0; --j) {
var replayType = ol.render.replay.ORDER[j];
replay = replays[replayType];
if (replay !== undefined) {
if (opt_declutterReplays &&
(replayType == ol.render.ReplayType.IMAGE || replayType == ol.render.ReplayType.TEXT)) {
var declutter = opt_declutterReplays[zIndexKey];
if (!declutter) {
opt_declutterReplays[zIndexKey] = [replay, transform.slice(0)];
} else {
declutter.push(replay, transform.slice(0));
}
} else {
result = replay.replayHitDetection(context, transform, viewRotation,
skippedFeaturesHash, featureCallback, opt_hitExtent);
if (result) {
return result;
}
}
}
}
}
return undefined;
};
/** /**
* @const * @const
* @private * @private

View File

@@ -5,7 +5,7 @@ goog.require('ol.Map');
goog.require('ol.MapEvent'); goog.require('ol.MapEvent');
goog.require('ol.Overlay'); goog.require('ol.Overlay');
goog.require('ol.View'); goog.require('ol.View');
goog.require('ol.geom.Point'); goog.require('ol.geom.LineString');
goog.require('ol.has'); goog.require('ol.has');
goog.require('ol.interaction'); goog.require('ol.interaction');
goog.require('ol.interaction.DoubleClickZoom'); goog.require('ol.interaction.DoubleClickZoom');
@@ -199,12 +199,12 @@ describe('ol.Map', function() {
target: target, target: target,
layers: [new ol.layer.Vector({ layers: [new ol.layer.Vector({
source: new ol.source.Vector({ source: new ol.source.Vector({
features: [new ol.Feature(new ol.geom.Point([0, 0]))] features: [new ol.Feature(new ol.geom.LineString([[-50, 0], [50, 0]]))]
}) })
})], })],
view: new ol.View({ view: new ol.View({
center: [0, 0], center: [0, 0],
zoom: 2 zoom: 17
}) })
}); });
map.renderSync(); map.renderSync();
@@ -224,6 +224,20 @@ describe('ol.Map', function() {
expect(features[0]).to.be.an(ol.Feature); expect(features[0]).to.be.an(ol.Feature);
}); });
it('returns an array of found features with declutter: true', function() {
var layer = map.getLayers().item(0);
map.removeLayer(layer);
var otherLayer = new ol.layer.Vector({
declutter: true,
source: layer.getSource()
});
map.addLayer(otherLayer);
map.renderSync();
var features = map.getFeaturesAtPixel([50, 50]);
expect(features).to.be.an(Array);
expect(features[0]).to.be.an(ol.Feature);
});
it('respects options', function() { it('respects options', function() {
var otherLayer = new ol.layer.Vector({ var otherLayer = new ol.layer.Vector({
source: new ol.source.Vector source: new ol.source.Vector