Merge pull request #13691 from burleight/vectorSource-getFeaturesInExtent-wrapX

#13690 VectorSource#getFeaturesInExtent add projection parameter
This commit is contained in:
Andreas Hocevar
2022-05-24 09:37:10 +02:00
committed by GitHub
4 changed files with 150 additions and 3 deletions

View File

@@ -858,3 +858,47 @@ export function wrapX(extent, projection) {
}
return extent;
}
/**
* Fits the extent to the real world
*
* If the extent does not cross the anti meridian, this will return the extent in an array
* If the extent crosses the anti meridian, the extent will be sliced, so each part fits within the
* real world
*
*
* @param {Extent} extent Extent.
* @param {import("./proj/Projection.js").default} projection Projection
* @return {Array<Extent>} The extent within the real world extent.
*/
export function wrapAndSliceX(extent, projection) {
if (projection.canWrapX()) {
const projectionExtent = projection.getExtent();
if (!isFinite(extent[0]) || !isFinite(extent[2])) {
return [[projectionExtent[0], extent[1], projectionExtent[2], extent[3]]];
}
wrapX(extent, projection);
const worldWidth = getWidth(projectionExtent);
if (getWidth(extent) > worldWidth) {
// the extent wraps around on itself
return [[projectionExtent[0], extent[1], projectionExtent[2], extent[3]]];
} else if (extent[0] < projectionExtent[0]) {
// the extent crosses the anti meridian, so it needs to be sliced
return [
[extent[0] + worldWidth, extent[1], projectionExtent[2], extent[3]],
[projectionExtent[0], extent[1], extent[2], extent[3]],
];
} else if (extent[2] > projectionExtent[2]) {
// the extent crosses the anti meridian, so it needs to be sliced
return [
[extent[0], extent[1], projectionExtent[2], extent[3]],
[projectionExtent[0], extent[1], extent[2] - worldWidth, extent[3]],
];
}
}
return [extent];
}

View File

@@ -14,7 +14,7 @@ import VectorEventType from './VectorEventType.js';
import {TRUE, VOID} from '../functions.js';
import {all as allStrategy} from '../loadingstrategy.js';
import {assert} from '../asserts.js';
import {containsExtent, equals} from '../extent.js';
import {containsExtent, equals, wrapAndSliceX} from '../extent.js';
import {extend} from '../array.js';
import {getUid} from '../util.js';
import {getValues, isEmpty} from '../obj.js';
@@ -736,12 +736,25 @@ class VectorSource extends Source {
* features.
*
* @param {import("../extent.js").Extent} extent Extent.
* @param {import("../proj/Projection.js").default} [opt_projection] Include features
* where `extent` exceeds the x-axis bounds of `projection` and wraps around the world.
* @return {Array<import("../Feature.js").default<Geometry>>} Features.
* @api
*/
getFeaturesInExtent(extent) {
getFeaturesInExtent(extent, opt_projection) {
if (this.featuresRtree_) {
return this.featuresRtree_.getInExtent(extent);
const multiWorld =
opt_projection && opt_projection.canWrapX() && this.getWrapX();
if (!multiWorld) {
return this.featuresRtree_.getInExtent(extent);
}
const extents = wrapAndSliceX(extent, opt_projection);
return [].concat(
...extents.map((anExtent) => this.featuresRtree_.getInExtent(anExtent))
);
} else if (this.featuresCollection_) {
return this.featuresCollection_.getArray().slice(0);
} else {