Reuse declutter tree for hit detection
Replaying for hit detection no longer declutters, but uses the declutter tree from the previous rendered frame.
This commit is contained in:
@@ -483,8 +483,9 @@ ol.render.canvas.Replay.prototype.setStrokeStyle_ = function(context, instructio
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {ol.DeclutterGroup} declutterGroup Declutter group.
|
* @param {ol.DeclutterGroup} declutterGroup Declutter group.
|
||||||
|
* @param {ol.Feature|ol.render.Feature} feature Feature.
|
||||||
*/
|
*/
|
||||||
ol.render.canvas.Replay.prototype.renderDeclutter_ = function(declutterGroup) {
|
ol.render.canvas.Replay.prototype.renderDeclutter_ = function(declutterGroup, feature) {
|
||||||
if (declutterGroup && declutterGroup.length > 5) {
|
if (declutterGroup && declutterGroup.length > 5) {
|
||||||
var groupCount = declutterGroup[4];
|
var groupCount = declutterGroup[4];
|
||||||
if (groupCount == 1 || groupCount == declutterGroup.length - 5) {
|
if (groupCount == 1 || groupCount == declutterGroup.length - 5) {
|
||||||
@@ -493,7 +494,8 @@ ol.render.canvas.Replay.prototype.renderDeclutter_ = function(declutterGroup) {
|
|||||||
minX: /** @type {number} */ (declutterGroup[0]),
|
minX: /** @type {number} */ (declutterGroup[0]),
|
||||||
minY: /** @type {number} */ (declutterGroup[1]),
|
minY: /** @type {number} */ (declutterGroup[1]),
|
||||||
maxX: /** @type {number} */ (declutterGroup[2]),
|
maxX: /** @type {number} */ (declutterGroup[2]),
|
||||||
maxY: /** @type {number} */ (declutterGroup[3])
|
maxY: /** @type {number} */ (declutterGroup[3]),
|
||||||
|
value: feature
|
||||||
};
|
};
|
||||||
if (!this.declutterTree.collides(box)) {
|
if (!this.declutterTree.collides(box)) {
|
||||||
this.declutterTree.insert(box);
|
this.declutterTree.insert(box);
|
||||||
@@ -651,7 +653,7 @@ ol.render.canvas.Replay.prototype.replay_ = function(
|
|||||||
// Remaining arguments in DRAW_IMAGE are in alphabetical order
|
// Remaining arguments in DRAW_IMAGE are in alphabetical order
|
||||||
anchorX = /** @type {number} */ (instruction[4]);
|
anchorX = /** @type {number} */ (instruction[4]);
|
||||||
anchorY = /** @type {number} */ (instruction[5]);
|
anchorY = /** @type {number} */ (instruction[5]);
|
||||||
declutterGroup = /** @type {ol.DeclutterGroup} */ (instruction[6]);
|
declutterGroup = featureCallback ? null : /** @type {ol.DeclutterGroup} */ (instruction[6]);
|
||||||
var height = /** @type {number} */ (instruction[7]);
|
var height = /** @type {number} */ (instruction[7]);
|
||||||
var opacity = /** @type {number} */ (instruction[8]);
|
var opacity = /** @type {number} */ (instruction[8]);
|
||||||
var originX = /** @type {number} */ (instruction[9]);
|
var originX = /** @type {number} */ (instruction[9]);
|
||||||
@@ -683,14 +685,14 @@ ol.render.canvas.Replay.prototype.replay_ = function(
|
|||||||
backgroundFill ? /** @type {Array.<*>} */ (lastFillInstruction) : null,
|
backgroundFill ? /** @type {Array.<*>} */ (lastFillInstruction) : null,
|
||||||
backgroundStroke ? /** @type {Array.<*>} */ (lastStrokeInstruction) : null);
|
backgroundStroke ? /** @type {Array.<*>} */ (lastStrokeInstruction) : null);
|
||||||
}
|
}
|
||||||
this.renderDeclutter_(declutterGroup);
|
this.renderDeclutter_(declutterGroup, feature);
|
||||||
++i;
|
++i;
|
||||||
break;
|
break;
|
||||||
case ol.render.canvas.Instruction.DRAW_CHARS:
|
case ol.render.canvas.Instruction.DRAW_CHARS:
|
||||||
var begin = /** @type {number} */ (instruction[1]);
|
var begin = /** @type {number} */ (instruction[1]);
|
||||||
var end = /** @type {number} */ (instruction[2]);
|
var end = /** @type {number} */ (instruction[2]);
|
||||||
var baseline = /** @type {number} */ (instruction[3]);
|
var baseline = /** @type {number} */ (instruction[3]);
|
||||||
declutterGroup = /** @type {ol.DeclutterGroup} */ (instruction[4]);
|
declutterGroup = featureCallback ? null : /** @type {ol.DeclutterGroup} */ (instruction[4]);
|
||||||
var overflow = /** @type {number} */ (instruction[5]);
|
var overflow = /** @type {number} */ (instruction[5]);
|
||||||
var fillKey = /** @type {string} */ (instruction[6]);
|
var fillKey = /** @type {string} */ (instruction[6]);
|
||||||
var maxAngle = /** @type {number} */ (instruction[7]);
|
var maxAngle = /** @type {number} */ (instruction[7]);
|
||||||
@@ -741,7 +743,7 @@ ol.render.canvas.Replay.prototype.replay_ = function(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.renderDeclutter_(declutterGroup);
|
this.renderDeclutter_(declutterGroup, feature);
|
||||||
++i;
|
++i;
|
||||||
break;
|
break;
|
||||||
case ol.render.canvas.Instruction.END_GEOMETRY:
|
case ol.render.canvas.Instruction.END_GEOMETRY:
|
||||||
|
|||||||
@@ -185,32 +185,20 @@ ol.render.canvas.ReplayGroup.getCircleArray_ = function(radius) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {!Object.<string, Array.<*>>} declutterReplays Declutter replays.
|
||||||
|
* @param {CanvasRenderingContext2D} context Context.
|
||||||
|
* @param {number} rotation Rotation.
|
||||||
|
*/
|
||||||
ol.render.canvas.ReplayGroup.replayDeclutter = function(declutterReplays, context, rotation) {
|
ol.render.canvas.ReplayGroup.replayDeclutter = function(declutterReplays, context, rotation) {
|
||||||
var zs = Object.keys(declutterReplays).map(Number).sort(ol.array.numberSafeCompareFunction);
|
var zs = Object.keys(declutterReplays).map(Number).sort(ol.array.numberSafeCompareFunction);
|
||||||
|
var skippedFeatureUids = {};
|
||||||
for (var z = 0, zz = zs.length; z < zz; ++z) {
|
for (var z = 0, zz = zs.length; z < zz; ++z) {
|
||||||
var replayData = declutterReplays[zs[z].toString()];
|
var replayData = declutterReplays[zs[z].toString()];
|
||||||
for (var i = 0, ii = replayData.length; i < ii;) {
|
for (var i = 0, ii = replayData.length; i < ii;) {
|
||||||
var replay = replayData[i++];
|
var replay = replayData[i++];
|
||||||
var transform = replayData[i++];
|
var transform = replayData[i++];
|
||||||
replay.replay(context, transform, rotation, {});
|
replay.replay(context, transform, rotation, skippedFeatureUids);
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
ol.render.canvas.ReplayGroup.replayDeclutterHitDetection = function(
|
|
||||||
declutterReplays, context, rotation, featureCallback, hitExtent) {
|
|
||||||
var zs = Object.keys(declutterReplays).map(Number).sort(ol.array.numberSafeCompareFunction);
|
|
||||||
for (var z = 0, zz = zs.length; z < zz; ++z) {
|
|
||||||
var replayData = declutterReplays[zs[z].toString()];
|
|
||||||
for (var i = replayData.length - 1; i >= 0;) {
|
|
||||||
var transform = replayData[i--];
|
|
||||||
var replay = replayData[i--];
|
|
||||||
var result = replay.replayHitDetection(context, transform, rotation, {},
|
|
||||||
featureCallback, hitExtent);
|
|
||||||
if (result) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -326,6 +314,12 @@ ol.render.canvas.ReplayGroup.prototype.forEachFeatureAtCoordinate = function(
|
|||||||
}
|
}
|
||||||
|
|
||||||
var mask = ol.render.canvas.ReplayGroup.getCircleArray_(hitTolerance);
|
var mask = ol.render.canvas.ReplayGroup.getCircleArray_(hitTolerance);
|
||||||
|
var declutteredFeatures;
|
||||||
|
if (this.declutterTree_) {
|
||||||
|
declutteredFeatures = this.declutterTree_.all().map(function(entry) {
|
||||||
|
return entry.value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {ol.Feature|ol.render.Feature} feature Feature.
|
* @param {ol.Feature|ol.render.Feature} feature Feature.
|
||||||
@@ -337,7 +331,10 @@ ol.render.canvas.ReplayGroup.prototype.forEachFeatureAtCoordinate = function(
|
|||||||
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 = callback(feature);
|
var result;
|
||||||
|
if (!declutteredFeatures || declutteredFeatures.indexOf(feature) !== -1) {
|
||||||
|
result = callback(feature);
|
||||||
|
}
|
||||||
if (result) {
|
if (result) {
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
@@ -350,13 +347,8 @@ ol.render.canvas.ReplayGroup.prototype.forEachFeatureAtCoordinate = function(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = this.replayHitDetection_(context, transform, rotation,
|
return this.replayHitDetection_(context, transform, rotation,
|
||||||
skippedFeaturesHash, hitDetectionCallback, hitExtent, declutterReplays);
|
skippedFeaturesHash, hitDetectionCallback, hitExtent, declutterReplays);
|
||||||
if (!result && declutterReplays) {
|
|
||||||
result = ol.render.canvas.ReplayGroup.replayDeclutterHitDetection(
|
|
||||||
declutterReplays, context, rotation, hitDetectionCallback, hitExtent);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -138,6 +138,9 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame = function(frameState, lay
|
|||||||
}
|
}
|
||||||
var replayGroup = this.replayGroup_;
|
var replayGroup = this.replayGroup_;
|
||||||
if (replayGroup && !replayGroup.isEmpty()) {
|
if (replayGroup && !replayGroup.isEmpty()) {
|
||||||
|
if (this.declutterTree_) {
|
||||||
|
this.declutterTree_.clear();
|
||||||
|
}
|
||||||
var layer = /** @type {ol.layer.Vector} */ (this.getLayer());
|
var layer = /** @type {ol.layer.Vector} */ (this.getLayer());
|
||||||
var drawOffsetX = 0;
|
var drawOffsetX = 0;
|
||||||
var drawOffsetY = 0;
|
var drawOffsetY = 0;
|
||||||
@@ -229,9 +232,6 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame = function(frameState, lay
|
|||||||
if (clipped) {
|
if (clipped) {
|
||||||
context.restore();
|
context.restore();
|
||||||
}
|
}
|
||||||
if (this.declutterTree_) {
|
|
||||||
this.declutterTree_.clear();
|
|
||||||
}
|
|
||||||
this.postCompose(context, frameState, layerState, transform);
|
this.postCompose(context, frameState, layerState, transform);
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -249,7 +249,6 @@ ol.renderer.canvas.VectorLayer.prototype.forEachFeatureAtCoordinate = function(c
|
|||||||
var layer = /** @type {ol.layer.Vector} */ (this.getLayer());
|
var layer = /** @type {ol.layer.Vector} */ (this.getLayer());
|
||||||
/** @type {Object.<string, boolean>} */
|
/** @type {Object.<string, boolean>} */
|
||||||
var features = {};
|
var features = {};
|
||||||
var declutterReplays = layer.getDeclutter() ? {} : null;
|
|
||||||
var result = this.replayGroup_.forEachFeatureAtCoordinate(coordinate, resolution,
|
var result = this.replayGroup_.forEachFeatureAtCoordinate(coordinate, resolution,
|
||||||
rotation, hitTolerance, {},
|
rotation, hitTolerance, {},
|
||||||
/**
|
/**
|
||||||
@@ -262,10 +261,7 @@ ol.renderer.canvas.VectorLayer.prototype.forEachFeatureAtCoordinate = function(c
|
|||||||
features[key] = true;
|
features[key] = true;
|
||||||
return callback.call(thisArg, feature, layer);
|
return callback.call(thisArg, feature, layer);
|
||||||
}
|
}
|
||||||
}, declutterReplays);
|
}, null);
|
||||||
if (this.declutterTree_) {
|
|
||||||
this.declutterTree_.clear();
|
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -270,7 +270,6 @@ ol.renderer.canvas.VectorTileLayer.prototype.forEachFeatureAtCoordinate = functi
|
|||||||
var rotation = frameState.viewState.rotation;
|
var rotation = frameState.viewState.rotation;
|
||||||
hitTolerance = hitTolerance == undefined ? 0 : hitTolerance;
|
hitTolerance = hitTolerance == undefined ? 0 : hitTolerance;
|
||||||
var layer = this.getLayer();
|
var layer = this.getLayer();
|
||||||
var declutterReplays = layer.getDeclutter() ? {} : null;
|
|
||||||
/** @type {Object.<string, boolean>} */
|
/** @type {Object.<string, boolean>} */
|
||||||
var features = {};
|
var features = {};
|
||||||
|
|
||||||
@@ -308,12 +307,9 @@ ol.renderer.canvas.VectorTileLayer.prototype.forEachFeatureAtCoordinate = functi
|
|||||||
features[key] = true;
|
features[key] = true;
|
||||||
return callback.call(thisArg, feature, layer);
|
return callback.call(thisArg, feature, layer);
|
||||||
}
|
}
|
||||||
}, declutterReplays);
|
}, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.declutterTree_) {
|
|
||||||
this.declutterTree_.clear();
|
|
||||||
}
|
|
||||||
return found;
|
return found;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -387,6 +383,9 @@ ol.renderer.canvas.VectorTileLayer.prototype.postCompose = function(context, fra
|
|||||||
offsetY = Math.round(pixelRatio * size[1] / 2);
|
offsetY = Math.round(pixelRatio * size[1] / 2);
|
||||||
ol.render.canvas.rotateAtOffset(context, -rotation, offsetX, offsetY);
|
ol.render.canvas.rotateAtOffset(context, -rotation, offsetX, offsetY);
|
||||||
}
|
}
|
||||||
|
if (declutterReplays) {
|
||||||
|
this.declutterTree_.clear();
|
||||||
|
}
|
||||||
var tiles = this.renderedTiles;
|
var tiles = this.renderedTiles;
|
||||||
var tileGrid = source.getTileGridForProjection(frameState.viewState.projection);
|
var tileGrid = source.getTileGridForProjection(frameState.viewState.projection);
|
||||||
var clips = [];
|
var clips = [];
|
||||||
@@ -443,7 +442,6 @@ ol.renderer.canvas.VectorTileLayer.prototype.postCompose = function(context, fra
|
|||||||
}
|
}
|
||||||
if (declutterReplays) {
|
if (declutterReplays) {
|
||||||
ol.render.canvas.ReplayGroup.replayDeclutter(declutterReplays, context, rotation);
|
ol.render.canvas.ReplayGroup.replayDeclutter(declutterReplays, context, rotation);
|
||||||
this.declutterTree_.clear();
|
|
||||||
}
|
}
|
||||||
if (rotation) {
|
if (rotation) {
|
||||||
ol.render.canvas.rotateAtOffset(context, rotation,
|
ol.render.canvas.rotateAtOffset(context, rotation,
|
||||||
|
|||||||
@@ -152,12 +152,13 @@ ol.source.ImageVector.prototype.canvasFunctionInternal_ = function(extent, resol
|
|||||||
this.canvasContext_.clearRect(0, 0, size[0], size[1]);
|
this.canvasContext_.clearRect(0, 0, size[0], size[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.declutterTree_.clear();
|
||||||
|
|
||||||
var transform = this.getTransform_(ol.extent.getCenter(extent),
|
var transform = this.getTransform_(ol.extent.getCenter(extent),
|
||||||
resolution, pixelRatio, size);
|
resolution, pixelRatio, size);
|
||||||
replayGroup.replay(this.canvasContext_, transform, 0, {});
|
replayGroup.replay(this.canvasContext_, transform, 0, {});
|
||||||
|
|
||||||
this.replayGroup_ = replayGroup;
|
this.replayGroup_ = replayGroup;
|
||||||
this.declutterTree_.clear();
|
|
||||||
|
|
||||||
return this.canvasContext_.canvas;
|
return this.canvasContext_.canvas;
|
||||||
};
|
};
|
||||||
@@ -186,7 +187,6 @@ ol.source.ImageVector.prototype.forEachFeatureAtCoordinate = function(
|
|||||||
return callback(feature);
|
return callback(feature);
|
||||||
}
|
}
|
||||||
}, null);
|
}, null);
|
||||||
this.declutterTree_.clear();
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user