diff --git a/externs/olx.js b/externs/olx.js
index 2472c92e83..3ebe0f635f 100644
--- a/externs/olx.js
+++ b/externs/olx.js
@@ -3098,7 +3098,9 @@ olx.interaction.SelectOptions.prototype.wrapX;
* @typedef {{
* features: (ol.Collection.
|undefined),
* pixelTolerance: (number|undefined),
- * source: (ol.source.Vector|undefined)
+ * source: (ol.source.Vector|undefined),
+ * edge: (boolean|undefined),
+ * vertex: (boolean|undefined)
* }}
* @api
*/
@@ -3112,6 +3114,21 @@ olx.interaction.SnapOptions;
*/
olx.interaction.SnapOptions.prototype.features;
+/**
+ * Snap to edges. Default is `true`.
+ * @type {boolean|undefined}
+ * @api
+ */
+olx.interaction.SnapOptions.prototype.edge;
+
+
+/**
+ * Snap to vertices. Default is `true`.
+ * @type {boolean|undefined}
+ * @api
+ */
+olx.interaction.SnapOptions.prototype.vertex;
+
/**
* Pixel tolerance for considering the pointer close enough to a segment or
diff --git a/src/ol/interaction/snapinteraction.js b/src/ol/interaction/snapinteraction.js
index b952c684a6..826a13b4f3 100644
--- a/src/ol/interaction/snapinteraction.js
+++ b/src/ol/interaction/snapinteraction.js
@@ -61,6 +61,18 @@ ol.interaction.Snap = function(opt_options) {
*/
this.source_ = options.source ? options.source : null;
+ /**
+ * @private
+ * @type {boolean}
+ */
+ this.vertex_ = options.vertex !== undefined ? options.vertex : true;
+
+ /**
+ * @private
+ * @type {boolean}
+ */
+ this.edge_ = options.edge !== undefined ? options.edge : true;
+
/**
* @type {ol.Collection.}
* @private
@@ -374,28 +386,48 @@ ol.interaction.Snap.prototype.snapTo = function(pixel, pixelCoordinate, map) {
var snapped = false;
var vertex = null;
var vertexPixel = null;
+ var dist, pixel1, pixel2, squaredDist1, squaredDist2;
if (segments.length > 0) {
this.pixelCoordinate_ = pixelCoordinate;
segments.sort(this.sortByDistance_);
var closestSegment = segments[0].segment;
- vertex = (ol.coordinate.closestOnSegment(pixelCoordinate,
- closestSegment));
- vertexPixel = map.getPixelFromCoordinate(vertex);
- if (Math.sqrt(ol.coordinate.squaredDistance(pixel, vertexPixel)) <=
- this.pixelTolerance_) {
- snapped = true;
- var pixel1 = map.getPixelFromCoordinate(closestSegment[0]);
- var pixel2 = map.getPixelFromCoordinate(closestSegment[1]);
- var squaredDist1 = ol.coordinate.squaredDistance(vertexPixel, pixel1);
- var squaredDist2 = ol.coordinate.squaredDistance(vertexPixel, pixel2);
- var dist = Math.sqrt(Math.min(squaredDist1, squaredDist2));
+ if (this.vertex_ && !this.edge_) {
+ pixel1 = map.getPixelFromCoordinate(closestSegment[0]);
+ pixel2 = map.getPixelFromCoordinate(closestSegment[1]);
+ squaredDist1 = ol.coordinate.squaredDistance(pixel, pixel1);
+ squaredDist2 = ol.coordinate.squaredDistance(pixel, pixel2);
+ dist = Math.sqrt(Math.min(squaredDist1, squaredDist2));
snappedToVertex = dist <= this.pixelTolerance_;
if (snappedToVertex) {
+ snapped = true;
vertex = squaredDist1 > squaredDist2 ?
closestSegment[1] : closestSegment[0];
vertexPixel = map.getPixelFromCoordinate(vertex);
- vertexPixel = [Math.round(vertexPixel[0]), Math.round(vertexPixel[1])];
}
+ } else if (this.edge_) {
+ vertex = (ol.coordinate.closestOnSegment(pixelCoordinate,
+ closestSegment));
+ vertexPixel = map.getPixelFromCoordinate(vertex);
+ if (Math.sqrt(ol.coordinate.squaredDistance(pixel, vertexPixel)) <=
+ this.pixelTolerance_) {
+ snapped = true;
+ if (this.vertex_) {
+ pixel1 = map.getPixelFromCoordinate(closestSegment[0]);
+ pixel2 = map.getPixelFromCoordinate(closestSegment[1]);
+ squaredDist1 = ol.coordinate.squaredDistance(vertexPixel, pixel1);
+ squaredDist2 = ol.coordinate.squaredDistance(vertexPixel, pixel2);
+ dist = Math.sqrt(Math.min(squaredDist1, squaredDist2));
+ snappedToVertex = dist <= this.pixelTolerance_;
+ if (snappedToVertex) {
+ vertex = squaredDist1 > squaredDist2 ?
+ closestSegment[1] : closestSegment[0];
+ vertexPixel = map.getPixelFromCoordinate(vertex);
+ }
+ }
+ }
+ }
+ if (snapped) {
+ vertexPixel = [Math.round(vertexPixel[0]), Math.round(vertexPixel[1])];
}
}
return /** @type {ol.interaction.Snap.ResultType} */ ({
diff --git a/test/spec/ol/interaction/snapinteraction.test.js b/test/spec/ol/interaction/snapinteraction.test.js
index d5df59cb7f..0b2b7fa07a 100644
--- a/test/spec/ol/interaction/snapinteraction.test.js
+++ b/test/spec/ol/interaction/snapinteraction.test.js
@@ -64,6 +64,42 @@ describe('ol.interaction.Snap', function() {
expect(event.coordinate).to.eql([0, 0]);
});
+ it('snaps to edges only', function() {
+ var point = new ol.Feature(new ol.geom.LineString([[-10, 0], [10, 0]]));
+ var snapInteraction = new ol.interaction.Snap({
+ features: new ol.Collection([point]),
+ pixelTolerance: 5,
+ vertex: false
+ });
+ snapInteraction.setMap(map);
+
+ var event = {
+ pixel: [7 + width / 2, height / 2 - 4],
+ coordinate: [7, 4],
+ map: map
+ };
+ ol.interaction.Snap.handleEvent_.call(snapInteraction, event);
+ expect(event.coordinate).to.eql([7, 0]);
+ });
+
+ it('snaps to vertices only', function() {
+ var point = new ol.Feature(new ol.geom.LineString([[-10, 0], [10, 0]]));
+ var snapInteraction = new ol.interaction.Snap({
+ features: new ol.Collection([point]),
+ pixelTolerance: 5,
+ edge: false
+ });
+ snapInteraction.setMap(map);
+
+ var event = {
+ pixel: [7 + width / 2, height / 2 - 4],
+ coordinate: [7, 4],
+ map: map
+ };
+ ol.interaction.Snap.handleEvent_.call(snapInteraction, event);
+ expect(event.coordinate).to.eql([10, 0]);
+ });
+
});
});
@@ -73,4 +109,5 @@ goog.require('ol.Feature');
goog.require('ol.Map');
goog.require('ol.View');
goog.require('ol.geom.Point');
+goog.require('ol.geom.LineString');
goog.require('ol.interaction.Snap');