Refactoring for better layer management

The only feature on the temporary layer is now the
vertexFeature, and the temporary layer's style is dynamically
changed to the style of the layer whose segment is being edited
(the topmost layer if more than one segment are being edited).
With this simplification, we can also put all segments on a
single RTree. Finally, we no longer rely on structures set on
layers - all we need is now on the instance itself.

This refactoring also changes the way we define layers to
participate in modification - by using an array or a filter
function, or assuming all layers if no layers property is set.
This commit is contained in:
ahocevar
2013-11-12 16:51:24 +01:00
parent 06406d968f
commit 39a5a8e291
4 changed files with 324 additions and 200 deletions
+1
View File
@@ -44,6 +44,7 @@
</div> </div>
<script src="loader.js?id=modify-features" type="text/javascript"></script> <script src="loader.js?id=modify-features" type="text/javascript"></script>
<script src="../resources/example-behaviour.js" type="text/javascript"></script>
</body> </body>
</html> </html>
+2 -2
View File
@@ -379,8 +379,8 @@
/** /**
* @typedef {Object} ol.interaction.ModifyOptions * @typedef {Object} ol.interaction.ModifyOptions
* @property {undefined|function(ol.layer.Layer):boolean} layerFilter Filter * @property {undefined|Array.<ol.layer.Layer>|function(ol.layer.Layer):boolean} layers
* function to restrict modification to a subset of layers. * Layers or filter function to restrict modification to a subset of layers.
* @property {number|undefined} pixelTolerance Pixel tolerance for considering * @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 20 pixels.
*/ */
@@ -0,0 +1 @@
@exportClass ol.interaction.Modify ol.interaction.ModifyOptions
+320 -198
View File
@@ -3,7 +3,9 @@ goog.provide('ol.interaction.Modify');
goog.require('goog.array'); goog.require('goog.array');
goog.require('goog.asserts'); goog.require('goog.asserts');
goog.require('goog.events'); goog.require('goog.events');
goog.require('goog.functions');
goog.require('goog.object'); goog.require('goog.object');
goog.require('ol.CollectionEventType');
goog.require('ol.Feature'); goog.require('ol.Feature');
goog.require('ol.MapBrowserEvent.EventType'); goog.require('ol.MapBrowserEvent.EventType');
goog.require('ol.ViewHint'); goog.require('ol.ViewHint');
@@ -15,12 +17,24 @@ goog.require('ol.geom.LinearRing');
goog.require('ol.geom.Point'); goog.require('ol.geom.Point');
goog.require('ol.geom.Polygon'); goog.require('ol.geom.Polygon');
goog.require('ol.interaction.Drag'); goog.require('ol.interaction.Drag');
goog.require('ol.layer.Layer');
goog.require('ol.layer.Vector'); goog.require('ol.layer.Vector');
goog.require('ol.layer.VectorEventType'); goog.require('ol.layer.VectorEventType');
goog.require('ol.layer.VectorLayerRenderIntent'); goog.require('ol.layer.VectorLayerRenderIntent');
goog.require('ol.source.Vector');
goog.require('ol.structs.RTree'); goog.require('ol.structs.RTree');
/**
* @typedef {{feature: ol.Feature,
* geometry: ol.geom.Geometry,
* index: (number|undefined),
* style: ol.style.Style,
* segment: (Array.<ol.Extent>|undefined)}}
*/
ol.interaction.SegmentDataType;
/** /**
* @constructor * @constructor
@@ -32,18 +46,32 @@ ol.interaction.Modify = function(opt_options) {
var options = goog.isDef(opt_options) ? opt_options : {}; var options = goog.isDef(opt_options) ? opt_options : {};
var layerFilter = options.layers;
if (!goog.isDef(layerFilter)) {
layerFilter = goog.functions.TRUE;
} else if (goog.isArray(layerFilter)) {
layerFilter = function(layer) {return options.layers.indexOf(layer) > -1;};
}
/** /**
* @type {null|function(ol.layer.Layer):boolean} * @type {null|function(ol.layer.Layer):boolean}
* @private * @private
*/ */
this.layerFilter_ = goog.isDef(options.layerFilter) ? this.layerFilter_ = goog.isDef(layerFilter) ? layerFilter : null;
options.layerFilter : null;
/** /**
* @type {Array.<ol.layer.Layer>} * Temporary sketch layer.
* @type {ol.layer.Vector}
* @private * @private
*/ */
this.layers_ = null; this.sketchLayer_ = null;
/**
* Editing vertex.
* @type {ol.Feature}
* @private
*/
this.vertexFeature_ = null;
/** /**
* @type {boolean} * @type {boolean}
@@ -51,6 +79,13 @@ ol.interaction.Modify = function(opt_options) {
*/ */
this.modifiable_ = false; this.modifiable_ = false;
/**
* Segment RTree for each layer
* @type {Object.<*, ol.structs.RTree>}
* @private
*/
this.rTree_ = null;
/** /**
* @type {number} * @type {number}
* @private * @private
@@ -70,21 +105,140 @@ goog.inherits(ol.interaction.Modify, ol.interaction.Drag);
/** /**
* @param {ol.layer.Vector} layer The vector layer. * @inheritDoc
* @param {Array.<ol.Feature>} features Array of features. */
ol.interaction.Modify.prototype.setMap = function(map) {
var oldMap = this.getMap();
var layers;
if (!goog.isNull(oldMap)) {
oldMap.removeLayer(this.sketchLayer_);
layers = oldMap.getLayerGroup().getLayers();
goog.asserts.assert(goog.isDef(layers));
layers.unlisten(ol.CollectionEventType.ADD, this.handleLayerAdded_, false,
this);
layers.unlisten(ol.CollectionEventType.REMOVE, this.handleLayerRemoved_,
false, this);
}
if (!goog.isNull(map)) {
if (goog.isNull(this.rTree_)) {
this.rTree_ = new ol.structs.RTree();
}
if (goog.isNull(this.sketchLayer_)) {
var sketchLayer = new ol.layer.Vector({
source: new ol.source.Vector({parser: null})
});
this.sketchLayer_ = sketchLayer;
sketchLayer.setTemporary(true);
map.addLayer(sketchLayer);
}
layers = map.getLayerGroup().getLayers();
goog.asserts.assert(goog.isDef(layers));
var that = this;
layers.forEach(function(layer) { that.addLayer(layer); });
layers.listen(ol.CollectionEventType.ADD, this.handleLayerAdded_, false,
this);
layers.listen(ol.CollectionEventType.REMOVE, this.handleLayerRemoved_,
false, this);
} else {
// removing from a map, clean up
this.rTree_ = null;
this.sketchLayer_ = null;
}
goog.base(this, 'setMap', map);
};
/**
* @param {ol.CollectionEvent} evt Event.
* @private * @private
*/ */
ol.interaction.Modify.prototype.addIndex_ = function(layer, features) { ol.interaction.Modify.prototype.handleLayerAdded_ = function(evt) {
var layer = evt.getElement();
goog.asserts.assertInstanceof(layer, ol.layer.Layer);
if (this.layerFilter_(layer)) {
this.addLayer(layer);
}
};
/**
* Add a layer for modification.
* @param {ol.layer.Layer} layer Layer.
*/
ol.interaction.Modify.prototype.addLayer = function(layer) {
if (layer instanceof ol.layer.Vector && !layer.getTemporary()) {
this.addIndex_(layer.getFeatures(ol.layer.Vector.selectedFeaturesFilter),
layer);
goog.events.listen(layer, ol.layer.VectorEventType.INTENTCHANGE,
this.handleIntentChange_, false, this);
}
};
/**
* @param {ol.CollectionEvent} evt Event.
* @private
*/
ol.interaction.Modify.prototype.handleLayerRemoved_ = function(evt) {
var layer = evt.getElement();
goog.asserts.assertInstanceof(layer, ol.layer.Layer);
if (this.layerFilter_(layer)) {
this.removeLayer(layer);
}
};
/**
* Remove a layer for modification.
* @param {ol.layer.Layer} layer Layer.
*/
ol.interaction.Modify.prototype.removeLayer = function(layer) {
if (layer instanceof ol.layer.Vector && !layer.getTemporary()) {
this.removeIndex_(
layer.getFeatures(ol.layer.Vector.selectedFeaturesFilter));
goog.events.unlisten(layer, ol.layer.VectorEventType.INTENTCHANGE,
this.handleIntentChange_, false, this);
}
};
/**
* @param {Array.<ol.Feature>} features Array of features.
* @param {ol.layer.Vector} layer Layer the features belong to.
* @private
*/
ol.interaction.Modify.prototype.addIndex_ = function(features, layer) {
for (var i = 0, ii = features.length; i < ii; ++i) { for (var i = 0, ii = features.length; i < ii; ++i) {
var feature = features[i]; var feature = features[i];
var geometry = feature.getGeometry(); var geometry = feature.getGeometry();
if (geometry instanceof ol.geom.AbstractCollection) { if (geometry instanceof ol.geom.AbstractCollection) {
var components = geometry.getComponents(); var components = geometry.getComponents();
for (var j = 0, jj = components.length; j < jj; ++j) { for (var j = 0, jj = components.length; j < jj; ++j) {
this.addSegments_(layer, feature, components[j]); this.addSegments_(feature, components[j], layer);
} }
} else { } else {
this.addSegments_(layer, feature, geometry); this.addSegments_(feature, geometry, layer);
}
}
};
/**
* @param {Array.<ol.Feature>} features Array of features.
* @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);
} }
} }
}; };
@@ -95,81 +249,84 @@ ol.interaction.Modify.prototype.addIndex_ = function(layer, features) {
* @param {ol.layer.VectorEvent} evt Event object. * @param {ol.layer.VectorEvent} evt Event object.
* @private * @private
*/ */
ol.interaction.Modify.prototype.handleFeaturesAdded_ = function(evt) { ol.interaction.Modify.prototype.handleIntentChange_ = function(evt) {
goog.asserts.assertInstanceof(evt.target, ol.layer.Vector); var layer = evt.target;
this.addIndex_(/** @type {ol.layer.Vector} */ (evt.target), evt.features); goog.asserts.assertInstanceof(layer, ol.layer.Vector);
}; var features = evt.features;
for (var i = 0, ii = features.length; i < ii; ++i) {
var feature = features[i];
/** var renderIntent = feature.getRenderIntent();
* @param {ol.layer.Layer} layer Layer. if (renderIntent == ol.layer.VectorLayerRenderIntent.SELECTED) {
*/ this.addIndex_([feature], layer);
ol.interaction.Modify.prototype.addLayer = function(layer) { } else {
var selectionData = layer.getSelectionData(); this.removeIndex_([feature]);
var selectionLayer = selectionData.layer; }
var editData = selectionLayer.getEditData();
if (goog.isNull(editData.rTree)) {
editData.rTree = new ol.structs.RTree();
} }
this.addIndex_(selectionLayer,
goog.object.getValues(selectionData.selectedFeaturesByFeatureUid));
goog.events.listen(selectionLayer, ol.layer.VectorEventType.ADD,
this.handleFeaturesAdded_, false, this);
goog.events.listen(selectionLayer, ol.layer.VectorEventType.REMOVE,
this.handleFeaturesRemoved_, false, this);
}; };
/** /**
* @param {ol.layer.Vector} selectionLayer Selection layer.
* @param {ol.Feature} feature Feature to add segments for. * @param {ol.Feature} feature Feature to add segments for.
* @param {ol.geom.Geometry} geometry Geometry to add segments for. * @param {ol.geom.Geometry} geometry Geometry to add segments for.
* @param {ol.layer.Vector} layer Vector layer to add segments for.
* @private * @private
*/ */
ol.interaction.Modify.prototype.addSegments_ = ol.interaction.Modify.prototype.addSegments_ =
function(selectionLayer, feature, geometry) { function(feature, geometry, layer) {
var uid = goog.getUid(feature); var uid = goog.getUid(feature);
var rTree = selectionLayer.getEditData().rTree; var rTree = this.rTree_;
var vertex, segment, segmentData, coordinates; var segment, segmentData, coordinates;
if (geometry instanceof ol.geom.Point) { if (geometry instanceof ol.geom.Point) {
vertex = geometry.getCoordinates(); segmentData = /** @type {ol.interaction.SegmentDataType} */ ({
segmentData = [[vertex, vertex], feature, geometry, NaN]; feature: feature,
geometry: geometry,
style: layer.getStyle()
});
rTree.insert(geometry.getBounds(), segmentData, uid); rTree.insert(geometry.getBounds(), segmentData, uid);
} else if (geometry instanceof ol.geom.LineString || } else if (geometry instanceof ol.geom.LineString ||
geometry instanceof ol.geom.LinearRing) { geometry instanceof ol.geom.LinearRing) {
coordinates = geometry.getCoordinates(); coordinates = geometry.getCoordinates();
for (var i = 0, ii = coordinates.length - 1; i < ii; ++i) { for (var i = 0, ii = coordinates.length - 1; i < ii; ++i) {
segment = coordinates.slice(i, i + 2); segment = coordinates.slice(i, i + 2);
segmentData = [segment, feature, geometry, i]; segmentData = /** @type {ol.interaction.SegmentDataType} */ ({
feature: feature,
geometry: geometry,
index: i,
style: layer.getStyle(),
segment: segment
});
rTree.insert(ol.extent.boundingExtent(segment), segmentData, uid); rTree.insert(ol.extent.boundingExtent(segment), segmentData, uid);
} }
} else if (geometry instanceof ol.geom.Polygon) { } else if (geometry instanceof ol.geom.Polygon) {
var rings = geometry.getRings(); var rings = geometry.getRings();
for (var j = 0, jj = rings.length; j < jj; ++j) { for (var j = 0, jj = rings.length; j < jj; ++j) {
this.addSegments_(selectionLayer, feature, rings[j]); this.addSegments_(feature, rings[j], layer);
} }
} }
}; };
/** /**
* @param {ol.layer.Vector} selectionLayer Selection layer. * @param {ol.style.Style} style Style of the layer that the feature being
* modified belongs to.
* @param {ol.Coordinate} coordinates Coordinates. * @param {ol.Coordinate} coordinates Coordinates.
* @return {ol.Feature} Vertex feature. * @return {ol.Feature} Vertex feature.
* @private
*/ */
ol.interaction.Modify.prototype.createOrUpdateVertexFeature = ol.interaction.Modify.prototype.createOrUpdateVertexFeature_ =
function(selectionLayer, coordinates) { function(style, coordinates) {
var editData = selectionLayer.getEditData(); var vertexFeature = this.vertexFeature_;
var vertexFeature = editData.vertexFeature;
if (goog.isNull(vertexFeature)) { if (goog.isNull(vertexFeature)) {
vertexFeature = new ol.Feature({g: new ol.geom.Point(coordinates)}); vertexFeature = new ol.Feature({g: new ol.geom.Point(coordinates)});
selectionLayer.addFeatures([vertexFeature]); this.vertexFeature_ = vertexFeature;
editData.vertexFeature = vertexFeature; this.sketchLayer_.addFeatures([vertexFeature]);
} else { } else {
var geometry = vertexFeature.getGeometry(); var geometry = vertexFeature.getGeometry();
geometry.setCoordinates(coordinates); geometry.setCoordinates(coordinates);
} }
if (this.sketchLayer_.getStyle() !== style) {
this.sketchLayer_.setStyle(style);
}
return vertexFeature; return vertexFeature;
}; };
@@ -179,44 +336,41 @@ ol.interaction.Modify.prototype.createOrUpdateVertexFeature =
*/ */
ol.interaction.Modify.prototype.handleDragStart = function(evt) { ol.interaction.Modify.prototype.handleDragStart = function(evt) {
this.dragSegments_ = []; this.dragSegments_ = [];
for (var i = 0, ii = this.layers_.length; i < ii; ++i) { var vertexFeature = this.vertexFeature_;
var layer = this.layers_[i]; var renderIntent = vertexFeature.getRenderIntent();
var selectionData = layer.getSelectionData(); if (goog.isDef(vertexFeature) &&
var selectionLayer = selectionData.layer; renderIntent != ol.layer.VectorLayerRenderIntent.HIDDEN) {
if (!goog.isNull(selectionLayer)) { var insertVertices = [];
var editData = selectionLayer.getEditData(); var vertex = vertexFeature.getGeometry().getCoordinates();
var vertexFeature = editData.vertexFeature; var vertexExtent = ol.extent.boundingExtent([vertex]);
var insertVertices = []; var segmentDataMatches = this.rTree_.search(vertexExtent);
if (!goog.isNull(vertexFeature) && vertexFeature.renderIntent != var distinctFeatures = {};
ol.layer.VectorLayerRenderIntent.HIDDEN) { for (var i = 0, ii = segmentDataMatches.length; i < ii; ++i) {
var vertex = vertexFeature.getGeometry().getCoordinates(); var segmentDataMatch = segmentDataMatches[i];
var vertexExtent = ol.extent.boundingExtent([vertex]); var segment = segmentDataMatch.segment;
var segments = editData.rTree.search(vertexExtent); if (!(goog.getUid(segmentDataMatch.feature) in distinctFeatures)) {
for (var j = 0, jj = segments.length; j < jj; ++j) { var feature = segmentDataMatch.feature;
var segmentData = segments[j]; distinctFeatures[goog.getUid(feature)] = true;
var segment = segmentData[0]; var original = new ol.Feature(feature.getAttributes());
var feature = segmentData[1]; original.setGeometry(feature.getGeometry().clone());
var featureId = goog.getUid(feature); original.setId(feature.getId());
var original = selectionData.featuresBySelectedFeatureUid[featureId]; original.setOriginal(feature.getOriginal());
if (vertexFeature.renderIntent == original.setSymbolizers(feature.getSymbolizers());
ol.layer.VectorLayerRenderIntent.TEMPORARY) { feature.setOriginal(original);
if (ol.coordinate.equals(segment[0], vertex)) {
this.dragSegments_.push([selectionLayer, segmentData, 0]);
feature.setOriginal(original);
} else if (ol.coordinate.equals(segment[1], vertex)) {
this.dragSegments_.push([selectionLayer, segmentData, 1]);
feature.setOriginal(original);
}
} else if (
ol.coordinate.squaredDistanceToSegment(vertex, segment) === 0) {
insertVertices.push([selectionLayer, segmentData, vertex]);
feature.setOriginal(original);
}
}
for (j = insertVertices.length - 1; j >= 0; --j) {
this.insertVertex_.apply(this, insertVertices[j]);
}
} }
if (renderIntent == ol.layer.VectorLayerRenderIntent.TEMPORARY) {
if (ol.coordinate.equals(segment[0], vertex)) {
this.dragSegments_.push([segmentDataMatch, 0]);
} else if (ol.coordinate.equals(segment[1], vertex)) {
this.dragSegments_.push([segmentDataMatch, 1]);
}
} else if (
ol.coordinate.squaredDistanceToSegment(vertex, segment) === 0) {
insertVertices.push([segmentDataMatch, vertex]);
}
}
for (i = insertVertices.length - 1; i >= 0; --i) {
this.insertVertex_.apply(this, insertVertices[i]);
} }
} }
return this.modifiable_; return this.modifiable_;
@@ -230,22 +384,28 @@ ol.interaction.Modify.prototype.handleDrag = function(evt) {
var vertex = evt.getCoordinate(); var vertex = evt.getCoordinate();
for (var i = 0, ii = this.dragSegments_.length; i < ii; ++i) { for (var i = 0, ii = this.dragSegments_.length; i < ii; ++i) {
var dragSegment = this.dragSegments_[i]; var dragSegment = this.dragSegments_[i];
var selectionLayer = dragSegment[0]; var segmentData = dragSegment[0];
var segmentData = dragSegment[1]; var feature = segmentData.feature;
var feature = segmentData[1]; var geometry = segmentData.geometry;
var geometry = segmentData[2];
var coordinates = geometry.getCoordinates(); var coordinates = geometry.getCoordinates();
var index = dragSegment[2];
coordinates[segmentData[3] + index] = vertex;
geometry.setCoordinates(coordinates);
var editData = selectionLayer.getEditData(); var oldBounds, newBounds;
var segment = segmentData[0]; if (geometry instanceof ol.geom.Point) {
editData.rTree.remove(ol.extent.boundingExtent(segment), segmentData); oldBounds = geometry.getBounds();
segment[index] = vertex; geometry.setCoordinates(vertex);
this.createOrUpdateVertexFeature(selectionLayer, vertex); newBounds = geometry.getBounds();
editData.rTree.insert(ol.extent.boundingExtent(segment), segmentData, } else {
goog.getUid(feature)); var index = dragSegment[1];
coordinates[segmentData.index + index] = vertex;
geometry.setCoordinates(coordinates);
var segment = segmentData.segment;
oldBounds = ol.extent.boundingExtent(segment);
segment[index] = vertex;
newBounds = ol.extent.boundingExtent(segment);
}
this.createOrUpdateVertexFeature_(segmentData.style, vertex);
this.rTree_.remove(oldBounds, segmentData);
this.rTree_.insert(newBounds, segmentData, goog.getUid(feature));
} }
}; };
@@ -271,17 +431,11 @@ ol.interaction.Modify.prototype.handleMapBrowserEvent =
*/ */
ol.interaction.Modify.prototype.handleMouseMove_ = function(evt) { ol.interaction.Modify.prototype.handleMouseMove_ = function(evt) {
var map = evt.map; var map = evt.map;
var layers = goog.array.filter(map.getLayerGroup().getLayers().getArray(),
this.ignoreTemporaryLayersFilter_);
if (!goog.isNull(this.layerFilter_)) {
layers = goog.array.filter(layers, this.layerFilter_);
}
this.layers_ = layers;
var pixel = evt.getPixel(); var pixel = evt.getPixel();
var pixelCoordinate = map.getCoordinateFromPixel(pixel); var pixelCoordinate = map.getCoordinateFromPixel(pixel);
var sortByDistance = function(a, b) { var sortByDistance = function(a, b) {
return ol.coordinate.squaredDistanceToSegment(pixelCoordinate, a[0]) - return ol.coordinate.squaredDistanceToSegment(pixelCoordinate, a.segment) -
ol.coordinate.squaredDistanceToSegment(pixelCoordinate, b[0]); ol.coordinate.squaredDistanceToSegment(pixelCoordinate, b.segment);
}; };
var lowerLeft = map.getCoordinateFromPixel( var lowerLeft = map.getCoordinateFromPixel(
@@ -289,115 +443,83 @@ ol.interaction.Modify.prototype.handleMouseMove_ = function(evt) {
var upperRight = map.getCoordinateFromPixel( var upperRight = map.getCoordinateFromPixel(
[pixel[0] + this.pixelTolerance_, pixel[1] - this.pixelTolerance_]); [pixel[0] + this.pixelTolerance_, pixel[1] - this.pixelTolerance_]);
var box = ol.extent.boundingExtent([lowerLeft, upperRight]); var box = ol.extent.boundingExtent([lowerLeft, upperRight]);
var vertexFeature;
this.modifiable_ = false; this.modifiable_ = false;
for (var i = layers.length - 1; i >= 0; --i) { var vertexFeature = this.vertexFeature_;
var layer = layers[i]; var rTree = this.rTree_;
var selectionLayer = layer.getSelectionData().layer; var segmentDataMatches = rTree.search(box);
if (!goog.isNull(selectionLayer)) { var renderIntent = ol.layer.VectorLayerRenderIntent.HIDDEN;
var listener = goog.events.getListener(selectionLayer, if (segmentDataMatches.length > 0) {
ol.layer.VectorEventType.ADD, segmentDataMatches.sort(sortByDistance);
this.handleFeaturesAdded_, false, this); var segmentDataMatch = segmentDataMatches[0];
if (goog.isNull(listener)) { var segment = segmentDataMatch.segment; // the closest segment
this.addLayer(layer); var vertex = (ol.coordinate.closestOnSegment(pixelCoordinate, segment));
} var vertexPixel = map.getPixelFromCoordinate(vertex);
var editData = selectionLayer.getEditData(); if (Math.sqrt(ol.coordinate.squaredDistance(pixel, vertexPixel)) <=
vertexFeature = editData.vertexFeature; this.pixelTolerance_) {
var segments = editData.rTree.search(box); var pixel1 = map.getPixelFromCoordinate(segment[0]);
var renderIntent = ol.layer.VectorLayerRenderIntent.HIDDEN; var pixel2 = map.getPixelFromCoordinate(segment[1]);
if (segments.length > 0) { var squaredDist1 = ol.coordinate.squaredDistance(vertexPixel, pixel1);
segments.sort(sortByDistance); var squaredDist2 = ol.coordinate.squaredDistance(vertexPixel, pixel2);
var segment = segments[0][0]; // the closest segment var dist = Math.sqrt(Math.min(squaredDist1, squaredDist2));
var vertex = (ol.coordinate.closestOnSegment(pixelCoordinate, segment)); renderIntent = ol.layer.VectorLayerRenderIntent.FUTURE;
var vertexPixel = map.getPixelFromCoordinate(vertex); if (dist <= 10) {
if (Math.sqrt(ol.coordinate.squaredDistance(pixel, vertexPixel)) <= vertex = squaredDist1 > squaredDist2 ? segment[1] : segment[0];
this.pixelTolerance_) { renderIntent = ol.layer.VectorLayerRenderIntent.TEMPORARY;
var pixel1 = map.getPixelFromCoordinate(segment[0]);
var pixel2 = map.getPixelFromCoordinate(segment[1]);
var squaredDist1 = ol.coordinate.squaredDistance(vertexPixel, pixel1);
var squaredDist2 = ol.coordinate.squaredDistance(vertexPixel, pixel2);
var dist = Math.sqrt(Math.min(squaredDist1, squaredDist2));
renderIntent = ol.layer.VectorLayerRenderIntent.FUTURE;
if (dist <= 10) {
vertex = squaredDist1 > squaredDist2 ? segment[1] : segment[0];
renderIntent = ol.layer.VectorLayerRenderIntent.TEMPORARY;
}
vertexFeature =
this.createOrUpdateVertexFeature(selectionLayer, vertex);
this.modifiable_ = true;
}
}
if (!goog.isNull(vertexFeature) &&
vertexFeature.renderIntent != renderIntent) {
selectionLayer.setRenderIntent(renderIntent, [vertexFeature]);
} }
vertexFeature = this.createOrUpdateVertexFeature_(segmentDataMatch.style,
vertex);
this.modifiable_ = true;
} }
} }
if (!goog.isNull(vertexFeature) &&
renderIntent != vertexFeature.getRenderIntent()) {
vertexFeature.setRenderIntent(renderIntent);
}
}; };
/** /**
* @param {ol.layer.Layer} layer Layer. * @param {ol.interaction.SegmentDataType} segmentData Segment data.
* @return {boolean} Whether the layer is no temporary vector layer.
* @private
*/
ol.interaction.Modify.prototype.ignoreTemporaryLayersFilter_ = function(layer) {
return !(layer instanceof ol.layer.Vector && layer.getTemporary());
};
/**
* @param {ol.layer.Vector} selectionLayer Selection layer.
* @param {Array} segmentData Segment data.
* @param {ol.Coordinate} vertex Vertex. * @param {ol.Coordinate} vertex Vertex.
* @private * @private
*/ */
ol.interaction.Modify.prototype.insertVertex_ = ol.interaction.Modify.prototype.insertVertex_ =
function(selectionLayer, segmentData, vertex) { function(segmentData, vertex) {
var segment = segmentData[0]; var segment = segmentData.segment;
var feature = segmentData[1]; var feature = segmentData.feature;
var geometry = segmentData[2]; var geometry = segmentData.geometry;
var index = segmentData[3]; var index = segmentData.index;
var coordinates = geometry.getCoordinates(); var coordinates = geometry.getCoordinates();
coordinates.splice(index + 1, 0, vertex); coordinates.splice(index + 1, 0, vertex);
geometry.setCoordinates(coordinates); geometry.setCoordinates(coordinates);
var rTree = selectionLayer.getEditData().rTree; var rTree = this.rTree_;
goog.asserts.assert(goog.isDef(segment));
rTree.remove(ol.extent.boundingExtent(segment), segmentData); rTree.remove(ol.extent.boundingExtent(segment), segmentData);
var uid = goog.getUid(feature); var featureUid = goog.getUid(feature);
var allSegments = rTree.search(geometry.getBounds(), uid); var segmentDataMatches = this.rTree_.search(geometry.getBounds(), featureUid);
for (var i = 0, ii = allSegments.length; i < ii; ++i) { for (var i = 0, ii = segmentDataMatches.length; i < ii; ++i) {
var allSegmentsData = allSegments[i]; var segmentDataMatch = segmentDataMatches[i];
if (allSegmentsData[2] === geometry && allSegmentsData[3] > index) { if (segmentDataMatch.geometry === geometry &&
++allSegmentsData[3]; segmentDataMatch.index > index) {
} ++segmentDataMatch.index;
}
var newSegment = [segment[0], vertex];
var newSegmentData = [newSegment, feature, geometry, index];
rTree.insert(ol.extent.boundingExtent(newSegment), newSegmentData, uid);
this.dragSegments_.push([selectionLayer, newSegmentData, 1]);
newSegment = [vertex, segment[1]];
newSegmentData = [newSegment, feature, geometry, index + 1];
rTree.insert(ol.extent.boundingExtent(newSegment), newSegmentData, uid);
this.dragSegments_.push([selectionLayer, newSegmentData, 0]);
};
/**
* Listen for feature removals.
* @param {ol.layer.VectorEvent} evt Event object.
* @private
*/
ol.interaction.Modify.prototype.handleFeaturesRemoved_ = function(evt) {
var layer = evt.target;
var rTree = layer.getEditData().rTree;
var features = evt.features;
for (var i = 0, ii = features.length; i < ii; ++i) {
var feature = features[i];
var segments = rTree.search(feature.getGeometry().getBounds(),
goog.getUid(feature));
for (var j = segments.length - 1; j >= 0; --j) {
var segment = segments[j];
rTree.remove(ol.extent.boundingExtent(segment[0]), segment);
} }
} }
var newSegmentData = /** @type {ol.interaction.SegmentDataType} */ ({
style: segmentData.style,
segment: [segment[0], vertex],
feature: feature,
geometry: geometry,
index: index
});
rTree.insert(ol.extent.boundingExtent(newSegmentData.segment), newSegmentData,
featureUid);
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,
featureUid);
this.dragSegments_.push([newSegmentData, 0]);
}; };