Merge pull request #1959 from elemoine/feature-box-selection
Add a feature box selection example
This commit is contained in:
@@ -159,8 +159,7 @@ ol.extent.closestSquaredDistanceXY = function(extent, x, y) {
|
||||
* @api stable
|
||||
*/
|
||||
ol.extent.containsCoordinate = function(extent, coordinate) {
|
||||
return extent[0] <= coordinate[0] && coordinate[0] <= extent[2] &&
|
||||
extent[1] <= coordinate[1] && coordinate[1] <= extent[3];
|
||||
return ol.extent.containsXY(extent, coordinate[0], coordinate[1]);
|
||||
};
|
||||
|
||||
|
||||
@@ -178,6 +177,20 @@ ol.extent.containsExtent = function(extent1, extent2) {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the passed coordinate is contained or on the edge of the extent.
|
||||
*
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {number} x X coordinate.
|
||||
* @param {number} y Y coordinate.
|
||||
* @return {boolean} Contains.
|
||||
* @api stable
|
||||
*/
|
||||
ol.extent.containsXY = function(extent, x, y) {
|
||||
return extent[0] <= x && x <= extent[2] && extent[1] <= y && y <= extent[3];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the relationship between a coordinate and extent.
|
||||
* @param {ol.Extent} extent The extent.
|
||||
@@ -426,6 +439,38 @@ ol.extent.extendXY = function(extent, x, y) {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This function calls `callback` for each corner of the extent. If the
|
||||
* callback returns a truthy value the function returns that value
|
||||
* immediately. Otherwise the function returns `false`.
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {function(this:T, ol.Coordinate): S} callback Callback.
|
||||
* @param {T=} opt_this Value to use as `this` when executing `callback`.
|
||||
* @return {S|boolean} Value.
|
||||
* @template S, T
|
||||
*/
|
||||
ol.extent.forEachCorner = function(extent, callback, opt_this) {
|
||||
var val;
|
||||
val = callback.call(opt_this, ol.extent.getBottomLeft(extent));
|
||||
if (val) {
|
||||
return val;
|
||||
}
|
||||
val = callback.call(opt_this, ol.extent.getBottomRight(extent));
|
||||
if (val) {
|
||||
return val;
|
||||
}
|
||||
val = callback.call(opt_this, ol.extent.getTopRight(extent));
|
||||
if (val) {
|
||||
return val;
|
||||
}
|
||||
val = callback.call(opt_this, ol.extent.getBottomRight(extent));
|
||||
if (val) {
|
||||
return val;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @return {number} Area.
|
||||
@@ -729,7 +774,7 @@ ol.extent.scaleFromCenter = function(extent, value) {
|
||||
* @param {ol.Coordinate} end Segment end coordinate.
|
||||
* @return {boolean} The segment intersects the extent.
|
||||
*/
|
||||
ol.extent.segmentIntersects = function(extent, start, end) {
|
||||
ol.extent.intersectsSegment = function(extent, start, end) {
|
||||
var intersects = false;
|
||||
var startRel = ol.extent.coordinateRelationship(extent, start);
|
||||
var endRel = ol.extent.coordinateRelationship(extent, end);
|
||||
|
||||
@@ -1,6 +1,29 @@
|
||||
goog.provide('ol.geom.flat.contains');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('ol.extent');
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @return {boolean} Contains extent.
|
||||
*/
|
||||
ol.geom.flat.contains.linearRingContainsExtent =
|
||||
function(flatCoordinates, offset, end, stride, extent) {
|
||||
var outside = ol.extent.forEachCorner(extent,
|
||||
/**
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
*/
|
||||
function(coordinate) {
|
||||
return !ol.geom.flat.contains.linearRingContainsXY(flatCoordinates,
|
||||
offset, end, stride, coordinate[0], coordinate[1]);
|
||||
});
|
||||
return !outside;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
|
||||
154
src/ol/geom/flat/intersectsextent.js
Normal file
154
src/ol/geom/flat/intersectsextent.js
Normal file
@@ -0,0 +1,154 @@
|
||||
goog.provide('ol.geom.flat.intersectsextent');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.geom.flat.contains');
|
||||
goog.require('ol.geom.flat.segments');
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @return {boolean} True if the geometry and the extent intersect.
|
||||
*/
|
||||
ol.geom.flat.intersectsextent.lineString =
|
||||
function(flatCoordinates, offset, end, stride, extent) {
|
||||
var coordinatesExtent = ol.extent.extendFlatCoordinates(
|
||||
ol.extent.createEmpty(), flatCoordinates, offset, end, stride);
|
||||
if (!ol.extent.intersects(extent, coordinatesExtent)) {
|
||||
return false;
|
||||
}
|
||||
if (ol.extent.containsExtent(extent, coordinatesExtent)) {
|
||||
return true;
|
||||
}
|
||||
if (coordinatesExtent[0] >= extent[0] &&
|
||||
coordinatesExtent[2] <= extent[2]) {
|
||||
return true;
|
||||
}
|
||||
if (coordinatesExtent[1] >= extent[1] &&
|
||||
coordinatesExtent[3] <= extent[3]) {
|
||||
return true;
|
||||
}
|
||||
return ol.geom.flat.segments.forEach(flatCoordinates, offset, end, stride,
|
||||
/**
|
||||
* @param {ol.Coordinate} point1 Start point.
|
||||
* @param {ol.Coordinate} point2 End point.
|
||||
* @return {boolean} `true` if the segment and the extent intersect,
|
||||
* `false` otherwise.
|
||||
*/
|
||||
function(point1, point2) {
|
||||
return ol.extent.intersectsSegment(extent, point1, point2);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<number>} ends Ends.
|
||||
* @param {number} stride Stride.
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @return {boolean} True if the geometry and the extent intersect.
|
||||
*/
|
||||
ol.geom.flat.intersectsextent.lineStrings =
|
||||
function(flatCoordinates, offset, ends, stride, extent) {
|
||||
var i, ii;
|
||||
for (i = 0, ii = ends.length; i < ii; ++i) {
|
||||
if (ol.geom.flat.intersectsextent.lineString(
|
||||
flatCoordinates, offset, ends[i], stride, extent)) {
|
||||
return true;
|
||||
}
|
||||
offset = ends[i];
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @return {boolean} True if the geometry and the extent intersect.
|
||||
*/
|
||||
ol.geom.flat.intersectsextent.linearRing =
|
||||
function(flatCoordinates, offset, end, stride, extent) {
|
||||
if (ol.geom.flat.intersectsextent.lineString(
|
||||
flatCoordinates, offset, end, stride, extent)) {
|
||||
return true;
|
||||
}
|
||||
if (ol.geom.flat.contains.linearRingContainsXY(
|
||||
flatCoordinates, offset, end, stride, extent[0], extent[1])) {
|
||||
return true;
|
||||
}
|
||||
if (ol.geom.flat.contains.linearRingContainsXY(
|
||||
flatCoordinates, offset, end, stride, extent[0], extent[3])) {
|
||||
return true;
|
||||
}
|
||||
if (ol.geom.flat.contains.linearRingContainsXY(
|
||||
flatCoordinates, offset, end, stride, extent[2], extent[1])) {
|
||||
return true;
|
||||
}
|
||||
if (ol.geom.flat.contains.linearRingContainsXY(
|
||||
flatCoordinates, offset, end, stride, extent[2], extent[3])) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<number>} ends Ends.
|
||||
* @param {number} stride Stride.
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @return {boolean} True if the geometry and the extent intersect.
|
||||
*/
|
||||
ol.geom.flat.intersectsextent.linearRings =
|
||||
function(flatCoordinates, offset, ends, stride, extent) {
|
||||
goog.asserts.assert(ends.length > 0);
|
||||
if (!ol.geom.flat.intersectsextent.linearRing(
|
||||
flatCoordinates, offset, ends[0], stride, extent)) {
|
||||
return false;
|
||||
}
|
||||
if (ends.length === 1) {
|
||||
return true;
|
||||
}
|
||||
var i, ii;
|
||||
for (i = 1, ii = ends.length; i < ii; ++i) {
|
||||
if (ol.geom.flat.contains.linearRingContainsExtent(
|
||||
flatCoordinates, ends[i - 1], ends[i], stride, extent)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<Array.<number>>} endss Endss.
|
||||
* @param {number} stride Stride.
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @return {boolean} True if the geometry and the extent intersect.
|
||||
*/
|
||||
ol.geom.flat.intersectsextent.linearRingss =
|
||||
function(flatCoordinates, offset, endss, stride, extent) {
|
||||
goog.asserts.assert(endss.length > 0);
|
||||
var i, ii;
|
||||
for (i = 0, ii = endss.length; i < ii; ++i) {
|
||||
var ends = endss[i];
|
||||
if (ol.geom.flat.intersectsextent.linearRings(
|
||||
flatCoordinates, offset, ends, stride, extent)) {
|
||||
return true;
|
||||
}
|
||||
offset = ends[ends.length - 1];
|
||||
}
|
||||
return false;
|
||||
};
|
||||
33
src/ol/geom/flat/segmentsflatgeom.js
Normal file
33
src/ol/geom/flat/segmentsflatgeom.js
Normal file
@@ -0,0 +1,33 @@
|
||||
goog.provide('ol.geom.flat.segments');
|
||||
|
||||
|
||||
/**
|
||||
* This function calls `callback` for each segment of the flat coordinates
|
||||
* array. If the callback returns a truthy value the function returns that
|
||||
* value immediately. Otherwise the function returns `false`.
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
* @param {function(ol.Coordinate, ol.Coordinate): T} callback Function
|
||||
* called for each segment.
|
||||
* @return {T|boolean} Value.
|
||||
* @template T
|
||||
*/
|
||||
ol.geom.flat.segments.forEach =
|
||||
function(flatCoordinates, offset, end, stride, callback) {
|
||||
var point1 = [flatCoordinates[offset], flatCoordinates[offset + 1]];
|
||||
var point2 = [];
|
||||
var ret;
|
||||
for (; (offset + stride) < end; offset += stride) {
|
||||
point2[0] = flatCoordinates[offset + stride];
|
||||
point2[1] = flatCoordinates[offset + stride + 1];
|
||||
ret = callback(point1, point2);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
point1[0] = point2[0];
|
||||
point1[1] = point2[1];
|
||||
}
|
||||
return false;
|
||||
};
|
||||
@@ -184,6 +184,16 @@ ol.geom.Geometry.prototype.getType = goog.abstractMethod;
|
||||
ol.geom.Geometry.prototype.applyTransform = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Test if the geometry and the passed extent intersect.
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @return {boolean} `true` if the geometry and the extent intersect.
|
||||
* @function
|
||||
* @api
|
||||
*/
|
||||
ol.geom.Geometry.prototype.intersectsExtent = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Transform each coordinate of the geometry from one coordinate reference
|
||||
* system to another. The geometry is modified in place.
|
||||
|
||||
@@ -218,6 +218,22 @@ ol.geom.GeometryCollection.prototype.getType = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @api
|
||||
*/
|
||||
ol.geom.GeometryCollection.prototype.intersectsExtent = function(extent) {
|
||||
var geometries = this.geometries_;
|
||||
var i, ii;
|
||||
for (i = 0, ii = geometries.length; i < ii; ++i) {
|
||||
if (geometries[i].intersectsExtent(extent)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Is empty.
|
||||
*/
|
||||
|
||||
@@ -9,6 +9,7 @@ goog.require('ol.geom.flat.closest');
|
||||
goog.require('ol.geom.flat.deflate');
|
||||
goog.require('ol.geom.flat.inflate');
|
||||
goog.require('ol.geom.flat.interpolate');
|
||||
goog.require('ol.geom.flat.intersectsextent');
|
||||
goog.require('ol.geom.flat.length');
|
||||
goog.require('ol.geom.flat.simplify');
|
||||
|
||||
@@ -190,6 +191,17 @@ ol.geom.LineString.prototype.getType = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @api
|
||||
*/
|
||||
ol.geom.LineString.prototype.intersectsExtent = function(extent) {
|
||||
return ol.geom.flat.intersectsextent.lineString(
|
||||
this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
|
||||
extent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<ol.Coordinate>} coordinates Coordinates.
|
||||
* @param {ol.geom.GeometryLayout=} opt_layout Layout.
|
||||
|
||||
@@ -10,6 +10,7 @@ goog.require('ol.geom.flat.closest');
|
||||
goog.require('ol.geom.flat.deflate');
|
||||
goog.require('ol.geom.flat.inflate');
|
||||
goog.require('ol.geom.flat.interpolate');
|
||||
goog.require('ol.geom.flat.intersectsextent');
|
||||
goog.require('ol.geom.flat.simplify');
|
||||
|
||||
|
||||
@@ -244,6 +245,16 @@ ol.geom.MultiLineString.prototype.getType = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @api
|
||||
*/
|
||||
ol.geom.MultiLineString.prototype.intersectsExtent = function(extent) {
|
||||
return ol.geom.flat.intersectsextent.lineStrings(
|
||||
this.flatCoordinates, 0, this.ends_, this.stride, extent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<Array.<ol.Coordinate>>} coordinates Coordinates.
|
||||
* @param {ol.geom.GeometryLayout=} opt_layout Layout.
|
||||
|
||||
@@ -142,6 +142,25 @@ ol.geom.MultiPoint.prototype.getType = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @api
|
||||
*/
|
||||
ol.geom.MultiPoint.prototype.intersectsExtent = function(extent) {
|
||||
var flatCoordinates = this.flatCoordinates;
|
||||
var stride = this.stride;
|
||||
var i, ii, x, y;
|
||||
for (i = 0, ii = flatCoordinates.length; i < ii; i += stride) {
|
||||
x = flatCoordinates[i];
|
||||
y = flatCoordinates[i + 1];
|
||||
if (ol.extent.containsXY(extent, x, y)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<ol.Coordinate>} coordinates Coordinates.
|
||||
* @param {ol.geom.GeometryLayout=} opt_layout Layout.
|
||||
|
||||
@@ -14,6 +14,7 @@ goog.require('ol.geom.flat.contains');
|
||||
goog.require('ol.geom.flat.deflate');
|
||||
goog.require('ol.geom.flat.inflate');
|
||||
goog.require('ol.geom.flat.interiorpoint');
|
||||
goog.require('ol.geom.flat.intersectsextent');
|
||||
goog.require('ol.geom.flat.orient');
|
||||
goog.require('ol.geom.flat.simplify');
|
||||
|
||||
@@ -315,6 +316,16 @@ ol.geom.MultiPolygon.prototype.getType = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @api
|
||||
*/
|
||||
ol.geom.MultiPolygon.prototype.intersectsExtent = function(extent) {
|
||||
return ol.geom.flat.intersectsextent.linearRingss(
|
||||
this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride, extent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<Array.<Array.<ol.Coordinate>>>} coordinates Coordinates.
|
||||
* @param {ol.geom.GeometryLayout=} opt_layout Layout.
|
||||
|
||||
@@ -93,6 +93,16 @@ ol.geom.Point.prototype.getType = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @api
|
||||
*/
|
||||
ol.geom.Point.prototype.intersectsExtent = function(extent) {
|
||||
return ol.extent.containsXY(extent,
|
||||
this.flatCoordinates[0], this.flatCoordinates[1]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate} coordinates Coordinates.
|
||||
* @param {ol.geom.GeometryLayout=} opt_layout Layout.
|
||||
|
||||
@@ -14,6 +14,7 @@ goog.require('ol.geom.flat.contains');
|
||||
goog.require('ol.geom.flat.deflate');
|
||||
goog.require('ol.geom.flat.inflate');
|
||||
goog.require('ol.geom.flat.interiorpoint');
|
||||
goog.require('ol.geom.flat.intersectsextent');
|
||||
goog.require('ol.geom.flat.orient');
|
||||
goog.require('ol.geom.flat.simplify');
|
||||
|
||||
@@ -296,6 +297,16 @@ ol.geom.Polygon.prototype.getType = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @api
|
||||
*/
|
||||
ol.geom.Polygon.prototype.intersectsExtent = function(extent) {
|
||||
return ol.geom.flat.intersectsextent.linearRings(
|
||||
this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride, extent);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array.<Array.<ol.Coordinate>>} coordinates Coordinates.
|
||||
* @param {ol.geom.GeometryLayout=} opt_layout Layout.
|
||||
|
||||
@@ -247,6 +247,39 @@ ol.source.Vector.prototype.forEachFeatureInExtentAtResolution =
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This function executes the `callback` function once for each feature
|
||||
* intersecting the `extent` until `callback` returns a truthy value. When
|
||||
* `callback` returns a truthy value the function immediately returns that
|
||||
* value. Otherwise the function returns `undefined`.
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {function(this: T, ol.Feature): S} f Callback.
|
||||
* @param {T=} opt_this The object to use as `this` in `f`.
|
||||
* @return {S|undefined}
|
||||
* @template T,S
|
||||
* @api
|
||||
*/
|
||||
ol.source.Vector.prototype.forEachFeatureIntersectingExtent =
|
||||
function(extent, f, opt_this) {
|
||||
return this.forEachFeatureInExtent(extent,
|
||||
/**
|
||||
* @param {ol.Feature} feature Feature.
|
||||
* @return {S|undefined}
|
||||
* @template S
|
||||
*/
|
||||
function(feature) {
|
||||
var geometry = feature.getGeometry();
|
||||
goog.asserts.assert(goog.isDefAndNotNull(geometry));
|
||||
if (geometry.intersectsExtent(extent)) {
|
||||
var result = f.call(opt_this, feature);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array.<ol.Feature>} Features.
|
||||
* @api stable
|
||||
|
||||
Reference in New Issue
Block a user