diff --git a/src/ol/interaction/modifyinteraction.js b/src/ol/interaction/modifyinteraction.js index 2966f635e5..6854a49856 100644 --- a/src/ol/interaction/modifyinteraction.js +++ b/src/ol/interaction/modifyinteraction.js @@ -4,7 +4,6 @@ goog.require('goog.array'); goog.require('goog.asserts'); goog.require('goog.events'); goog.require('goog.functions'); -goog.require('goog.object'); goog.require('ol.CollectionEventType'); goog.require('ol.Feature'); goog.require('ol.MapBrowserEvent.EventType'); @@ -22,7 +21,7 @@ goog.require('ol.layer.Vector'); goog.require('ol.layer.VectorEventType'); goog.require('ol.layer.VectorLayerRenderIntent'); goog.require('ol.source.Vector'); -goog.require('ol.structs.RTree'); +goog.require('ol.structs.RBush'); /** @@ -81,11 +80,11 @@ ol.interaction.Modify = function(opt_options) { this.modifiable_ = false; /** - * Segment RTree for each layer - * @type {Object.<*, ol.structs.RTree>} + * Segment RBush for each layer + * @type {Object.<*, ol.structs.RBush>} * @private */ - this.rTree_ = null; + this.rBush_ = null; /** * @type {number} @@ -122,8 +121,8 @@ ol.interaction.Modify.prototype.setMap = function(map) { } if (!goog.isNull(map)) { - if (goog.isNull(this.rTree_)) { - this.rTree_ = new ol.structs.RTree(); + if (goog.isNull(this.rBush_)) { + this.rBush_ = new ol.structs.RBush(); } if (goog.isNull(this.sketchLayer_)) { var sketchLayer = new ol.layer.Vector({ @@ -142,7 +141,7 @@ ol.interaction.Modify.prototype.setMap = function(map) { false, this); } else { // removing from a map, clean up - this.rTree_ = null; + this.rBush_ = null; this.sketchLayer_ = null; } @@ -230,16 +229,19 @@ ol.interaction.Modify.prototype.addIndex_ = function(features, layer) { * @private */ ol.interaction.Modify.prototype.removeIndex_ = function(features) { - var rTree = this.rTree_; - for (var i = 0, ii = features.length; i < ii; ++i) { - var feature = features[i]; - var segmentDataMatches = rTree.search(feature.getGeometry().getBounds(), - goog.getUid(feature)); - for (var j = segmentDataMatches.length - 1; j >= 0; --j) { - var segmentDataMatch = segmentDataMatches[j]; - rTree.remove(ol.extent.boundingExtent(segmentDataMatch.segment), - segmentDataMatch); - } + var rBush = this.rBush_; + var i, feature, nodesToRemove; + for (i = features.length - 1; i >= 0; --i) { + feature = features[i]; + nodesToRemove = []; + rBush.forEachInExtent(feature.getGeometry().getBounds(), function(node) { + if (feature === node.feature) { + nodesToRemove.push(node); + } + }); + } + for (i = nodesToRemove.length - 1; i >= 0; --i) { + rBush.remove(nodesToRemove[i]); } }; @@ -273,8 +275,7 @@ ol.interaction.Modify.prototype.handleIntentChange_ = function(evt) { */ ol.interaction.Modify.prototype.addSegments_ = function(feature, geometry, layer) { - var uid = goog.getUid(feature); - var rTree = this.rTree_; + var rBush = this.rBush_; var segment, segmentData, coordinates; if (geometry instanceof ol.geom.Point) { coordinates = geometry.getCoordinates(); @@ -284,7 +285,7 @@ ol.interaction.Modify.prototype.addSegments_ = segment: [coordinates, coordinates], style: layer.getStyle() }); - rTree.insert(geometry.getBounds(), segmentData, uid); + rBush.insert(geometry.getBounds(), segmentData); } else if (geometry instanceof ol.geom.LineString || geometry instanceof ol.geom.LinearRing) { coordinates = geometry.getCoordinates(); @@ -297,7 +298,7 @@ ol.interaction.Modify.prototype.addSegments_ = style: layer.getStyle(), segment: segment }); - rTree.insert(ol.extent.boundingExtent(segment), segmentData, uid); + rBush.insert(ol.extent.boundingExtent(segment), segmentData); } } else if (geometry instanceof ol.geom.Polygon) { var rings = geometry.getRings(); @@ -345,13 +346,12 @@ ol.interaction.Modify.prototype.handleDragStart = function(evt) { var insertVertices = []; var vertex = vertexFeature.getGeometry().getCoordinates(); var vertexExtent = ol.extent.boundingExtent([vertex]); - var segmentDataMatches = this.rTree_.search(vertexExtent); var distinctFeatures = {}; - for (var i = 0, ii = segmentDataMatches.length; i < ii; ++i) { - var segmentDataMatch = segmentDataMatches[i]; - var segment = segmentDataMatch.segment; - if (!(goog.getUid(segmentDataMatch.feature) in distinctFeatures)) { - var feature = segmentDataMatch.feature; + var dragSegments = this.dragSegments_; + this.rBush_.forEachInExtent(vertexExtent, function(node) { + var segment = node.segment; + if (!(goog.getUid(node.feature) in distinctFeatures)) { + var feature = node.feature; distinctFeatures[goog.getUid(feature)] = true; var original = new ol.Feature(feature.getAttributes()); original.setGeometry(feature.getGeometry().clone()); @@ -362,16 +362,16 @@ ol.interaction.Modify.prototype.handleDragStart = function(evt) { } if (renderIntent == ol.layer.VectorLayerRenderIntent.TEMPORARY) { if (ol.coordinate.equals(segment[0], vertex)) { - this.dragSegments_.push([segmentDataMatch, 0]); + dragSegments.push([node, 0]); } else if (ol.coordinate.equals(segment[1], vertex)) { - this.dragSegments_.push([segmentDataMatch, 1]); + dragSegments.push([node, 1]); } } else if ( ol.coordinate.squaredDistanceToSegment(vertex, segment) === 0) { - insertVertices.push([segmentDataMatch, vertex]); + insertVertices.push([node, vertex]); } - } - for (i = insertVertices.length - 1; i >= 0; --i) { + }); + for (var i = insertVertices.length - 1; i >= 0; --i) { this.insertVertex_.apply(this, insertVertices[i]); } } @@ -387,12 +387,9 @@ ol.interaction.Modify.prototype.handleDrag = function(evt) { for (var i = 0, ii = this.dragSegments_.length; i < ii; ++i) { var dragSegment = this.dragSegments_[i]; var segmentData = dragSegment[0]; - var feature = segmentData.feature; var geometry = segmentData.geometry; var coordinates = geometry.getCoordinates(); - var segment = segmentData.segment; - var oldBounds = ol.extent.boundingExtent(segment); if (geometry instanceof ol.geom.Point) { coordinates = vertex; segment[0] = segment[1] = vertex; @@ -402,10 +399,20 @@ ol.interaction.Modify.prototype.handleDrag = function(evt) { segment[index] = vertex; } geometry.setCoordinates(coordinates); - var newBounds = ol.extent.boundingExtent(segment); this.createOrUpdateVertexFeature_(segmentData.style, vertex); - this.rTree_.remove(oldBounds, segmentData); - this.rTree_.insert(newBounds, segmentData, goog.getUid(feature)); + } +}; + + +/** + * @inheritDoc + */ +ol.interaction.Modify.prototype.handleDragEnd = 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); } }; @@ -446,13 +453,13 @@ ol.interaction.Modify.prototype.handleMouseMove_ = function(evt) { this.modifiable_ = false; var vertexFeature = this.vertexFeature_; - var rTree = this.rTree_; - var segmentDataMatches = rTree.search(box); + var rBush = this.rBush_; + var nodes = rBush.allInExtent(box); var renderIntent = ol.layer.VectorLayerRenderIntent.HIDDEN; - if (segmentDataMatches.length > 0) { - segmentDataMatches.sort(sortByDistance); - var segmentDataMatch = segmentDataMatches[0]; - var segment = segmentDataMatch.segment; // the closest segment + if (nodes.length > 0) { + nodes.sort(sortByDistance); + var node = nodes[0]; + var segment = node.segment; // the closest segment var vertex = (ol.coordinate.closestOnSegment(pixelCoordinate, segment)); var vertexPixel = map.getPixelFromCoordinate(vertex); if (Math.sqrt(ol.coordinate.squaredDistance(pixel, vertexPixel)) <= @@ -467,8 +474,7 @@ ol.interaction.Modify.prototype.handleMouseMove_ = function(evt) { vertex = squaredDist1 > squaredDist2 ? segment[1] : segment[0]; renderIntent = ol.layer.VectorLayerRenderIntent.TEMPORARY; } - vertexFeature = this.createOrUpdateVertexFeature_(segmentDataMatch.style, - vertex); + vertexFeature = this.createOrUpdateVertexFeature_(node.style, vertex); this.modifiable_ = true; } } @@ -494,18 +500,14 @@ ol.interaction.Modify.prototype.insertVertex_ = var coordinates = geometry.getCoordinates(); coordinates.splice(index + 1, 0, vertex); geometry.setCoordinates(coordinates); - var rTree = this.rTree_; + var rBush = this.rBush_; goog.asserts.assert(goog.isDef(segment)); - rTree.remove(ol.extent.boundingExtent(segment), segmentData); - var uid = goog.getUid(feature); - var segmentDataMatches = this.rTree_.search(geometry.getBounds(), uid); - for (var i = 0, ii = segmentDataMatches.length; i < ii; ++i) { - var segmentDataMatch = segmentDataMatches[i]; - if (segmentDataMatch.geometry === geometry && - segmentDataMatch.index > index) { - ++segmentDataMatch.index; + rBush.remove(segmentData); + this.rBush_.forEachInExtent(geometry.getBounds(), function(node) { + if (node.geometry === geometry && node.index > index) { + ++node.index; } - } + }); var newSegmentData = /** @type {ol.interaction.SegmentDataType} */ ({ style: segmentData.style, segment: [segment[0], vertex], @@ -513,13 +515,17 @@ ol.interaction.Modify.prototype.insertVertex_ = geometry: geometry, index: index }); - rTree.insert(ol.extent.boundingExtent(newSegmentData.segment), newSegmentData, - uid); + rBush.insert(ol.extent.boundingExtent(newSegmentData.segment), + newSegmentData); this.dragSegments_.push([newSegmentData, 1]); - newSegmentData = goog.object.clone(newSegmentData); - newSegmentData.segment = [vertex, segment[1]]; - newSegmentData.index += 1; - rTree.insert(ol.extent.boundingExtent(newSegmentData.segment), newSegmentData, - uid); + newSegmentData = /** @type {ol.interaction.SegmentDataType} */ ({ + style: segmentData.style, + segment: [vertex, segment[1]], + feature: feature, + geometry: geometry, + index: index + 1 + }); + rBush.insert(ol.extent.boundingExtent(newSegmentData.segment), + newSegmentData); this.dragSegments_.push([newSegmentData, 0]); };