Merge pull request #1283 from ahocevar/delete-vertex

Add a way to delete vertices with the Modify interaction
This commit is contained in:
Andreas Hocevar
2014-03-28 12:39:28 +01:00
2 changed files with 134 additions and 24 deletions
+1 -1
View File
@@ -488,7 +488,7 @@
/**
* @typedef {Object} olx.interaction.ModifyOptions
* @property {number|undefined} pixelTolerance Pixel tolerance for considering
* the pointer close enough to a vertex for editing. Default is 20 pixels.
* the pointer close enough to a vertex for editing. Default is 10 pixels.
* @property {ol.style.Style|Array.<ol.style.Style>|ol.feature.StyleFunction|undefined} style FeatureOverlay style.
* @property {ol.Collection} features The features the interaction works on.
*/
+133 -23
View File
@@ -63,6 +63,12 @@ ol.interaction.Modify = function(options) {
*/
this.modifiable_ = false;
/**
* @type {ol.Coordinate}
* @private
*/
this.lastVertexCoordinate_;
/**
* @type {ol.Pixel}
* @private
@@ -81,7 +87,7 @@ ol.interaction.Modify = function(options) {
* @private
*/
this.pixelTolerance_ = goog.isDef(options.pixelTolerance) ?
options.pixelTolerance : 20;
options.pixelTolerance : 10;
/**
* @type {Array}
@@ -401,6 +407,7 @@ ol.interaction.Modify.prototype.handlePointerDown = function(evt) {
for (i = insertVertices.length - 1; i >= 0; --i) {
this.insertVertex_.apply(this, insertVertices[i]);
}
this.lastVertexCoordinate_ = goog.array.clone(vertex);
}
return this.modifiable_;
};
@@ -457,11 +464,18 @@ ol.interaction.Modify.prototype.handlePointerDrag = function(evt) {
* @inheritDoc
*/
ol.interaction.Modify.prototype.handlePointerUp = function(evt) {
var segmentData;
for (var i = this.dragSegments_.length - 1; i >= 0; --i) {
segmentData = this.dragSegments_[i][0];
this.rBush_.update(ol.extent.boundingExtent(segmentData.segment),
segmentData);
var geometry = this.vertexFeature_.getGeometry();
goog.asserts.assertInstanceof(geometry, ol.geom.Point);
if (goog.array.equals(this.lastVertexCoordinate_,
geometry.getCoordinates())) {
this.removeVertex_();
} else {
var segmentData;
for (var i = this.dragSegments_.length - 1; i >= 0; --i) {
segmentData = this.dragSegments_[i][0];
this.rBush_.update(ol.extent.boundingExtent(segmentData.segment),
segmentData);
}
}
return false;
};
@@ -599,23 +613,8 @@ ol.interaction.Modify.prototype.insertVertex_ = function(segmentData, vertex) {
var rTree = this.rBush_;
goog.asserts.assert(goog.isDef(segment));
rTree.remove(segmentData);
var uid = goog.getUid(feature);
var segmentDataMatches = [];
this.rBush_.forEachInExtent(geometry.getExtent(),
function(segmentData) {
if (goog.getUid(segmentData.feature) === uid) {
segmentDataMatches.push(segmentData);
}
});
for (var i = 0, ii = segmentDataMatches.length; i < ii; ++i) {
var segmentDataMatch = segmentDataMatches[i];
if (segmentDataMatch.geometry === geometry &&
(!goog.isDef(depth) ||
goog.array.equals(segmentDataMatch.depth, depth)) &&
segmentDataMatch.index > index) {
++segmentDataMatch.index;
}
}
goog.asserts.assert(goog.isDef(index));
this.updateSegmentIndices_(geometry, index, depth, 1);
var newSegmentData = /** @type {ol.interaction.SegmentDataType} */ ({
segment: [segment[0], vertex],
feature: feature,
@@ -638,3 +637,114 @@ ol.interaction.Modify.prototype.insertVertex_ = function(segmentData, vertex) {
newSegmentData2);
this.dragSegments_.push([newSegmentData2, 0]);
};
/**
* Removes a vertex from all matching features.
* @private
*/
ol.interaction.Modify.prototype.removeVertex_ = function() {
var dragSegments = this.dragSegments_;
var segmentsByFeature = {};
var component, coordinates, deleted, dragSegment, geometry, i, index, left;
var newIndex, newSegment, right, segmentData, uid;
for (i = dragSegments.length - 1; i >= 0; --i) {
dragSegment = dragSegments[i];
segmentData = dragSegment[0];
geometry = segmentData.geometry;
coordinates = geometry.getCoordinates();
uid = goog.getUid(segmentData.feature);
left = right = index = undefined;
if (dragSegment[1] === 0) {
right = segmentData;
index = segmentData.index;
} else if (dragSegment[1] == 1) {
left = segmentData;
index = segmentData.index + 1;
}
if (!(uid in segmentsByFeature)) {
segmentsByFeature[uid] = [left, right, index];
}
newSegment = segmentsByFeature[uid];
if (goog.isDef(left)) {
newSegment[0] = left;
}
if (goog.isDef(right)) {
newSegment[1] = right;
}
if (goog.isDef(newSegment[0]) && goog.isDef(newSegment[1])) {
component = coordinates;
deleted = false;
newIndex = index - 1;
switch (geometry.getType()) {
case ol.geom.GeometryType.MULTI_LINE_STRING:
coordinates[segmentData.depth[0]].splice(index, 1);
deleted = true;
break;
case ol.geom.GeometryType.LINE_STRING:
coordinates.splice(index, 1);
deleted = true;
break;
case ol.geom.GeometryType.MULTI_POLYGON:
component = component[segmentData.depth[1]];
/* falls through */
case ol.geom.GeometryType.POLYGON:
component = component[segmentData.depth[0]];
if (component.length > 4) {
if (index == component.length - 1) {
index = 0;
}
component.splice(index, 1);
deleted = true;
if (index === 0) {
// close the ring again
component.pop();
component.push(component[0]);
newIndex = component.length - 1;
}
}
break;
}
if (deleted) {
this.rBush_.remove(newSegment[0]);
this.rBush_.remove(newSegment[1]);
geometry.setCoordinates(coordinates);
goog.asserts.assert(newIndex >= 0);
var newSegmentData = /** @type {ol.interaction.SegmentDataType} */ ({
depth: segmentData.depth,
feature: segmentData.feature,
geometry: segmentData.geometry,
index: newIndex,
segment: [newSegment[0].segment[0], newSegment[1].segment[1]]
});
this.rBush_.insert(ol.extent.boundingExtent(newSegmentData.segment),
newSegmentData);
this.updateSegmentIndices_(geometry, index, segmentData.depth, -1);
this.overlay_.removeFeature(this.vertexFeature_);
this.vertexFeature_ = null;
}
}
}
};
/**
* @param {ol.geom.SimpleGeometry} geometry Geometry.
* @param {number} index Index.
* @param {Array.<number>|undefined} depth Depth.
* @param {number} delta Delta (1 or -1).
* @private
*/
ol.interaction.Modify.prototype.updateSegmentIndices_ = function(
geometry, index, depth, delta) {
this.rBush_.forEachInExtent(geometry.getExtent(), function(segmentDataMatch) {
if (segmentDataMatch.geometry === geometry &&
(!goog.isDef(depth) ||
goog.array.equals(segmentDataMatch.depth, depth)) &&
segmentDataMatch.index > index) {
segmentDataMatch.index += delta;
}
});
};