Adding ModifyFeature interaction
This is a first draft. The way geometry changes are handled for now is a bit clumsy. Both updating the feature cache RTree and making the layer aware of feature and geometry changes could be handled in a smarter way if these changes would be made through the layer instead of directly on the geometry or feature.
This commit is contained in:
56
examples/modify-features.html
Normal file
56
examples/modify-features.html
Normal file
@@ -0,0 +1,56 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="chrome=1">
|
||||
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
|
||||
<link rel="stylesheet" href="../css/ol.css" type="text/css">
|
||||
<link rel="stylesheet" href="../resources/bootstrap/css/bootstrap.min.css" type="text/css">
|
||||
<link rel="stylesheet" href="../resources/layout.css" type="text/css">
|
||||
<link rel="stylesheet" href="../resources/bootstrap/css/bootstrap-responsive.min.css" type="text/css">
|
||||
<title>Modify features example</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="navbar-inner">
|
||||
<div class="container">
|
||||
<a class="brand" href="./">OpenLayers 3 Examples</a>
|
||||
<ul class="nav pull-right">
|
||||
<li><iframe class="github-watch-button" src="http://ghbtns.com/github-btn.html?user=openlayers&repo=ol3&type=watch&count=true"
|
||||
allowtransparency="true" frameborder="0" scrolling="0" height="20" width="90"></iframe></li>
|
||||
<li><a href="https://twitter.com/share" class="twitter-share-button" data-count="none" data-hashtags="openlayers"> </a></li>
|
||||
<li><div class="g-plusone-wrapper"><div class="g-plusone" data-size="medium" data-annotation="none"></div></div></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container-fluid">
|
||||
|
||||
<div class="row-fluid">
|
||||
<div class="span12">
|
||||
<div id="map" class="map"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row-fluid">
|
||||
|
||||
<div class="span12">
|
||||
<h4 id="title">Modify features example</h4>
|
||||
<p id="shortdesc">Example of using the Modify interaction. Select a feature and drag the circle that appears when the cursor gets close to the selected geometry.</p>
|
||||
<div id="docs">
|
||||
<p>See the <a href="modify-features.js" target="_blank">modify-features.js source</a> to see how this is done.</p>
|
||||
</div>
|
||||
<div id="tags">modify, edit, vector</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script src="loader.js?id=modify-features" type="text/javascript"></script>
|
||||
<script src="../resources/social-links.js" type="text/javascript"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
88
examples/modify-features.js
Normal file
88
examples/modify-features.js
Normal file
@@ -0,0 +1,88 @@
|
||||
goog.require('ol.Map');
|
||||
goog.require('ol.RendererHint');
|
||||
goog.require('ol.View2D');
|
||||
goog.require('ol.interaction');
|
||||
goog.require('ol.interaction.Modify');
|
||||
goog.require('ol.interaction.Select');
|
||||
goog.require('ol.layer.Tile');
|
||||
goog.require('ol.layer.Vector');
|
||||
goog.require('ol.parser.ogc.GML_v3');
|
||||
goog.require('ol.source.MapQuestOpenAerial');
|
||||
goog.require('ol.source.Vector');
|
||||
goog.require('ol.style.Fill');
|
||||
goog.require('ol.style.Rule');
|
||||
goog.require('ol.style.Shape');
|
||||
goog.require('ol.style.Stroke');
|
||||
goog.require('ol.style.Style');
|
||||
|
||||
var raster = new ol.layer.Tile({
|
||||
source: new ol.source.MapQuestOpenAerial()
|
||||
});
|
||||
|
||||
var vector = new ol.layer.Vector({
|
||||
id: 'vector',
|
||||
source: new ol.source.Vector({
|
||||
parser: new ol.parser.ogc.GML_v3(),
|
||||
url: 'data/gml/topp-states-wfs.xml'
|
||||
}),
|
||||
style: new ol.style.Style({
|
||||
rules: [
|
||||
new ol.style.Rule({
|
||||
filter: 'renderIntent("selected")',
|
||||
symbolizers: [
|
||||
new ol.style.Fill({
|
||||
color: '#ffffff',
|
||||
opacity: 0.5
|
||||
}),
|
||||
new ol.style.Stroke({
|
||||
color: '#6666ff',
|
||||
width: 0.5
|
||||
})
|
||||
]
|
||||
}),
|
||||
new ol.style.Rule({
|
||||
filter: 'renderIntent("temporary")',
|
||||
symbolizers: [
|
||||
new ol.style.Shape({
|
||||
fill: new ol.style.Fill({color: '#bada55'}),
|
||||
size: 16
|
||||
})
|
||||
]
|
||||
}),
|
||||
new ol.style.Rule({
|
||||
filter: 'renderIntent("future")',
|
||||
symbolizers: [
|
||||
new ol.style.Shape({
|
||||
fill: new ol.style.Fill({color: '#013'}),
|
||||
size: 16
|
||||
})
|
||||
]
|
||||
})
|
||||
],
|
||||
symbolizers: [
|
||||
new ol.style.Fill({
|
||||
color: '#ffffff',
|
||||
opacity: 0.25
|
||||
}),
|
||||
new ol.style.Stroke({
|
||||
color: '#6666ff'
|
||||
})
|
||||
]
|
||||
})
|
||||
});
|
||||
|
||||
var selectInteraction = new ol.interaction.Select({
|
||||
layerFilter: function(layer) { return layer.get('id') == 'vector'; }
|
||||
});
|
||||
|
||||
var map = new ol.Map({
|
||||
interactions: ol.interaction.defaults().extend(
|
||||
[selectInteraction, new ol.interaction.Modify()]),
|
||||
layers: [raster, vector],
|
||||
renderer: ol.RendererHint.CANVAS,
|
||||
target: 'map',
|
||||
view: new ol.View2D({
|
||||
center: [-11000000, 4600000],
|
||||
zoom: 4
|
||||
})
|
||||
});
|
||||
@@ -377,6 +377,14 @@
|
||||
* @todo stability experimental
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} ol.interaction.ModifyOptions
|
||||
* @property {undefined|function(ol.layer.Layer):boolean} layerFilter Filter
|
||||
* function to restrict modification to a subset of layers.
|
||||
* @property {number|undefined} pixelTolerance Pixel tolerance for considering
|
||||
* the pointer close enough to a vertex for editing. Default is 20 pixels.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} ol.interaction.SelectOptions
|
||||
* @property {ol.events.ConditionType|undefined} addCondition A conditional
|
||||
|
||||
@@ -26,6 +26,12 @@ ol.interaction.Drag = function() {
|
||||
*/
|
||||
this.dragging_ = false;
|
||||
|
||||
/**
|
||||
* @type {number} Delta for INTERACTING view hint. Subclasses that do not want
|
||||
* the INTERACTING hint to be set should override this to 0.
|
||||
*/
|
||||
this.interactingHint = 1;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
@@ -60,6 +66,14 @@ ol.interaction.Drag = function() {
|
||||
goog.inherits(ol.interaction.Drag, ol.interaction.Interaction);
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Whether we're dragging.
|
||||
*/
|
||||
ol.interaction.Drag.prototype.getDragging = function() {
|
||||
return this.dragging_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserEvent} mapBrowserEvent Event.
|
||||
* @protected
|
||||
@@ -115,7 +129,7 @@ ol.interaction.Drag.prototype.handleMapBrowserEvent =
|
||||
goog.asserts.assertInstanceof(browserEvent, goog.events.BrowserEvent);
|
||||
this.deltaX = browserEvent.clientX - this.startX;
|
||||
this.deltaY = browserEvent.clientY - this.startY;
|
||||
view.setHint(ol.ViewHint.INTERACTING, -1);
|
||||
view.setHint(ol.ViewHint.INTERACTING, -this.interactingHint);
|
||||
this.dragging_ = false;
|
||||
this.handleDragEnd(mapBrowserEvent);
|
||||
}
|
||||
@@ -131,7 +145,7 @@ ol.interaction.Drag.prototype.handleMapBrowserEvent =
|
||||
(mapBrowserEvent.getCoordinate());
|
||||
var handled = this.handleDragStart(mapBrowserEvent);
|
||||
if (handled) {
|
||||
view.setHint(ol.ViewHint.INTERACTING, 1);
|
||||
view.setHint(ol.ViewHint.INTERACTING, this.interactingHint);
|
||||
this.dragging_ = true;
|
||||
mapBrowserEvent.preventDefault();
|
||||
stopEvent = true;
|
||||
|
||||
391
src/ol/interaction/modifyinteraction.js
Normal file
391
src/ol/interaction/modifyinteraction.js
Normal file
@@ -0,0 +1,391 @@
|
||||
goog.provide('ol.interaction.Modify');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.object');
|
||||
goog.require('ol.Feature');
|
||||
goog.require('ol.MapBrowserEvent.EventType');
|
||||
goog.require('ol.ViewHint');
|
||||
goog.require('ol.coordinate');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.geom.AbstractCollection');
|
||||
goog.require('ol.geom.LineString');
|
||||
goog.require('ol.geom.LinearRing');
|
||||
goog.require('ol.geom.Point');
|
||||
goog.require('ol.geom.Polygon');
|
||||
goog.require('ol.interaction.Drag');
|
||||
goog.require('ol.layer.Vector');
|
||||
goog.require('ol.layer.VectorLayerEventType');
|
||||
goog.require('ol.layer.VectorLayerRenderIntent');
|
||||
goog.require('ol.structs.RTree');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol.interaction.Drag}
|
||||
* @param {ol.interaction.ModifyOptions=} opt_options Options.
|
||||
*/
|
||||
ol.interaction.Modify = function(opt_options) {
|
||||
goog.base(this);
|
||||
|
||||
var options = goog.isDef(opt_options) ? opt_options : {};
|
||||
|
||||
/**
|
||||
* @type {null|function(ol.layer.Layer):boolean}
|
||||
* @private
|
||||
*/
|
||||
this.layerFilter_ = goog.isDef(options.layerFilter) ?
|
||||
options.layerFilter : null;
|
||||
|
||||
/**
|
||||
* @type {Array.<ol.layer.Layer>}
|
||||
* @private
|
||||
*/
|
||||
this.layers_ = null;
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.modifiable_ = false;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.pixelTolerance_ = goog.isDef(options.pixelTolerance) ?
|
||||
options.pixelTolerance : 20;
|
||||
|
||||
/**
|
||||
* @type {Array}
|
||||
* @private
|
||||
*/
|
||||
this.dragVertices_ = null;
|
||||
|
||||
this.interactingHint = 0;
|
||||
};
|
||||
goog.inherits(ol.interaction.Modify, ol.interaction.Drag);
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.layer.VectorLayerEventObject} evt Event object.
|
||||
*/
|
||||
ol.interaction.Modify.prototype.addIndex = function(evt) {
|
||||
var layer = evt.target;
|
||||
var features = evt.features;
|
||||
for (var i = 0, ii = features.length; i < ii; ++i) {
|
||||
var feature = features[i];
|
||||
var geometry = feature.getGeometry();
|
||||
if (geometry instanceof ol.geom.AbstractCollection) {
|
||||
for (var j = 0, jj = geometry.components.length; j < jj; ++j) {
|
||||
this.addSegments_(layer, feature, geometry.components[j],
|
||||
[[geometry.components, j]]);
|
||||
}
|
||||
} else {
|
||||
this.addSegments_(layer, feature, geometry);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.layer.Layer} layer Layer.
|
||||
*/
|
||||
ol.interaction.Modify.prototype.addLayer = function(layer) {
|
||||
var selectionData = layer.getSelectionData();
|
||||
var selectionLayer = selectionData.layer;
|
||||
var editData = selectionLayer.getEditData();
|
||||
if (goog.isNull(editData.rTree)) {
|
||||
editData.rTree = new ol.structs.RTree();
|
||||
var vertexFeature = new ol.Feature();
|
||||
vertexFeature.renderIntent = ol.layer.VectorLayerRenderIntent.HIDDEN;
|
||||
vertexFeature.setGeometry(new ol.geom.Point([NaN, NaN]));
|
||||
selectionLayer.addFeatures([vertexFeature]);
|
||||
editData.vertexFeature = vertexFeature;
|
||||
}
|
||||
this.addIndex(/** @type {ol.layer.VectorLayerEventObject} */
|
||||
({target: selectionLayer, features: goog.object.getValues(
|
||||
selectionData.selectedFeaturesByFeatureUid)}));
|
||||
goog.events.listen(selectionLayer, ol.layer.VectorLayerEventType.ADD,
|
||||
this.addIndex, false, this);
|
||||
goog.events.listen(selectionLayer, ol.layer.VectorLayerEventType.REMOVE,
|
||||
this.removeIndex, false, this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.layer.Vector} selectionLayer Selection layer.
|
||||
* @param {ol.Feature} feature Feature to add segments for.
|
||||
* @param {ol.geom.Geometry} geometry Geometry to add segments for.
|
||||
* @param {Array=} opt_parent Parent structure on the feature that the geometry
|
||||
* belongs to. This array has two values:
|
||||
* [0] the parent array;
|
||||
* [1] the index of the geometry in the parent array.
|
||||
* @private
|
||||
*/
|
||||
ol.interaction.Modify.prototype.addSegments_ =
|
||||
function(selectionLayer, feature, geometry, opt_parent) {
|
||||
var uid = goog.getUid(feature);
|
||||
var rTree = selectionLayer.getEditData().rTree;
|
||||
var vertex, segment, segmentData, coordinates;
|
||||
if (geometry instanceof ol.geom.Point) {
|
||||
vertex = geometry.getCoordinates();
|
||||
segmentData = [[vertex, vertex], feature, geometry, NaN];
|
||||
if (goog.isDef(opt_parent)) {
|
||||
segmentData.push(opt_parent);
|
||||
}
|
||||
rTree.insert(geometry.getBounds(), segmentData, uid);
|
||||
} else if (geometry instanceof ol.geom.LineString ||
|
||||
geometry instanceof ol.geom.LinearRing) {
|
||||
coordinates = geometry.getCoordinates();
|
||||
for (var i = 0, ii = coordinates.length - 1; i < ii; ++i) {
|
||||
segment = coordinates.slice(i, i + 2);
|
||||
segmentData = [segment, feature, geometry, i];
|
||||
if (opt_parent) {
|
||||
segmentData.push(opt_parent);
|
||||
}
|
||||
rTree.insert(ol.extent.boundingExtent(segment), segmentData, uid);
|
||||
}
|
||||
} else if (geometry instanceof ol.geom.Polygon) {
|
||||
for (var j = 0, jj = geometry.rings.length; j < jj; ++j) {
|
||||
this.addSegments_(selectionLayer, feature, geometry.rings[j],
|
||||
[geometry.rings, j]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.Modify.prototype.handleDragStart = function(evt) {
|
||||
this.dragVertices_ = [];
|
||||
for (var i = 0, ii = this.layers_.length; i < ii; ++i) {
|
||||
var selectionData = this.layers_[i].getSelectionData();
|
||||
var selectionLayer = selectionData.layer;
|
||||
if (!goog.isNull(selectionLayer)) {
|
||||
var editData = selectionLayer.getEditData();
|
||||
var vertexFeature = editData.vertexFeature;
|
||||
if (!goog.isNull(vertexFeature) && vertexFeature.renderIntent !=
|
||||
ol.layer.VectorLayerRenderIntent.HIDDEN) {
|
||||
var vertex = vertexFeature.getGeometry().getCoordinates();
|
||||
var vertexExtent = ol.extent.boundingExtent([vertex]);
|
||||
var segments = editData.rTree.search(vertexExtent);
|
||||
for (var j = 0, jj = segments.length; j < jj; ++j) {
|
||||
var segmentData = segments[j];
|
||||
var segment = segmentData[0];
|
||||
if (vertexFeature.renderIntent ==
|
||||
ol.layer.VectorLayerRenderIntent.TEMPORARY) {
|
||||
if (ol.coordinate.equals(segment[0], vertex)) {
|
||||
this.dragVertices_.push([selectionLayer, segmentData, 0]);
|
||||
} else {
|
||||
this.dragVertices_.push([selectionLayer, segmentData, 1]);
|
||||
}
|
||||
} else {
|
||||
this.insertVertex_(selectionLayer, segmentData, vertex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.modifiable_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.Modify.prototype.handleDrag = function(evt) {
|
||||
var vertex = evt.getCoordinate();
|
||||
for (var i = 0, ii = this.dragVertices_.length; i < ii; ++i) {
|
||||
var dragVertex = this.dragVertices_[i];
|
||||
var selectionLayer = dragVertex[0];
|
||||
var segmentData = dragVertex[1];
|
||||
var feature = segmentData[1];
|
||||
var geometry = segmentData[2];
|
||||
var index = dragVertex[2];
|
||||
geometry.set(segmentData[3] + index, 0, vertex[0]);
|
||||
geometry.set(segmentData[3] + index, 1, vertex[1]);
|
||||
feature.getGeometry().invalidateBounds();
|
||||
|
||||
var editData = selectionLayer.getEditData();
|
||||
var vertexFeature = editData.vertexFeature;
|
||||
var vertexGeometry = vertexFeature.getGeometry();
|
||||
var segment = segmentData[0];
|
||||
editData.rTree.remove(ol.extent.boundingExtent(segment), segmentData);
|
||||
segment[index] = vertex;
|
||||
vertexGeometry.set(0, vertex[0]);
|
||||
vertexGeometry.set(1, vertex[1]);
|
||||
editData.rTree.insert(ol.extent.boundingExtent(segment), segmentData,
|
||||
goog.getUid(feature));
|
||||
|
||||
selectionLayer.updateFeatures([feature, vertexFeature]);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.interaction.Modify.prototype.handleMapBrowserEvent =
|
||||
function(mapBrowserEvent) {
|
||||
if (!mapBrowserEvent.map.getView().getHints()[ol.ViewHint.INTERACTING] &&
|
||||
!this.getDragging() &&
|
||||
mapBrowserEvent.type == ol.MapBrowserEvent.EventType.MOUSEMOVE) {
|
||||
this.handleMouseMove_(mapBrowserEvent);
|
||||
}
|
||||
goog.base(this, 'handleMapBrowserEvent', mapBrowserEvent);
|
||||
return !this.modifiable_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserEvent} evt Event.
|
||||
* @private
|
||||
*/
|
||||
ol.interaction.Modify.prototype.handleMouseMove_ = function(evt) {
|
||||
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 pixelCoordinate = map.getCoordinateFromPixel(pixel);
|
||||
var sortByDistance = function(a, b) {
|
||||
return ol.coordinate.closestOnSegment(pixelCoordinate, a[0])[2] -
|
||||
ol.coordinate.closestOnSegment(pixelCoordinate, b[0])[2];
|
||||
};
|
||||
|
||||
var lowerLeft = map.getCoordinateFromPixel(
|
||||
[pixel[0] - this.pixelTolerance_, pixel[1] + this.pixelTolerance_]);
|
||||
var upperRight = map.getCoordinateFromPixel(
|
||||
[pixel[0] + this.pixelTolerance_, pixel[1] - this.pixelTolerance_]);
|
||||
var box = ol.extent.boundingExtent([lowerLeft, upperRight]);
|
||||
var vertexFeature;
|
||||
this.modifiable_ = false;
|
||||
for (var i = layers.length - 1; i >= 0; --i) {
|
||||
var layer = layers[i];
|
||||
var selectionLayer = layer.getSelectionData().layer;
|
||||
if (!goog.isNull(selectionLayer)) {
|
||||
if (goog.isNull(goog.events.getListener(selectionLayer,
|
||||
ol.layer.VectorLayerEventType.ADD, this.addIndex, false, this))) {
|
||||
this.addLayer(layer);
|
||||
}
|
||||
var editData = selectionLayer.getEditData();
|
||||
vertexFeature = editData.vertexFeature;
|
||||
var segments = editData.rTree.search(box);
|
||||
var renderIntent = ol.layer.VectorLayerRenderIntent.HIDDEN;
|
||||
if (segments.length > 0) {
|
||||
segments.sort(sortByDistance);
|
||||
var segment = segments[0][0]; // the closest segment
|
||||
var geometry = vertexFeature.getGeometry();
|
||||
var vertex = /** @type {ol.Coordinate} */
|
||||
(ol.coordinate.closestOnSegment(pixelCoordinate, segment));
|
||||
var coordPixel = map.getPixelFromCoordinate(vertex);
|
||||
var pixel1 = map.getPixelFromCoordinate(segment[0]);
|
||||
var pixel2 = map.getPixelFromCoordinate(segment[1]);
|
||||
var squaredDist1 = ol.coordinate.squaredDistance(coordPixel, pixel1);
|
||||
var squaredDist2 = ol.coordinate.squaredDistance(coordPixel, 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;
|
||||
}
|
||||
geometry.set(0, vertex[0]);
|
||||
geometry.set(1, vertex[1]);
|
||||
selectionLayer.updateFeatures([vertexFeature]);
|
||||
this.modifiable_ = true;
|
||||
}
|
||||
if (vertexFeature.renderIntent != renderIntent) {
|
||||
selectionLayer.setRenderIntent(renderIntent, [vertexFeature]);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.layer.Layer} layer Layer.
|
||||
* @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.
|
||||
* @private
|
||||
*/
|
||||
ol.interaction.Modify.prototype.insertVertex_ =
|
||||
function(selectionLayer, segmentData, vertex) {
|
||||
var segment = segmentData[0];
|
||||
var feature = segmentData[1];
|
||||
var geometry = segmentData[2];
|
||||
var index = segmentData[3];
|
||||
var coordinates = geometry.getCoordinates();
|
||||
coordinates.splice(index + 1, 0, vertex);
|
||||
var oldGeometry = geometry;
|
||||
geometry = new geometry.constructor(coordinates);
|
||||
var parent;
|
||||
if (segmentData.length > 4) {
|
||||
parent = segmentData[4];
|
||||
parent[0][parent[1]] = geometry;
|
||||
feature.getGeometry().invalidateBounds();
|
||||
} else {
|
||||
feature.setGeometry(geometry);
|
||||
}
|
||||
var rTree = selectionLayer.getEditData().rTree;
|
||||
rTree.remove(ol.extent.boundingExtent(segment), segmentData);
|
||||
var uid = goog.getUid(feature);
|
||||
var allSegments = rTree.search(geometry.getBounds(), uid);
|
||||
for (var i = 0, ii = allSegments.length; i < ii; ++i) {
|
||||
var allSegmentsData = allSegments[i];
|
||||
if (allSegmentsData[2] === oldGeometry) {
|
||||
allSegmentsData[2] = geometry;
|
||||
if (allSegmentsData[3] > index) {
|
||||
++allSegmentsData[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
var newSegment = [segment[0], vertex];
|
||||
var newSegmentData = [newSegment, feature, geometry, index];
|
||||
if (goog.isDef(parent)) {
|
||||
newSegmentData.push(parent);
|
||||
}
|
||||
rTree.insert(ol.extent.boundingExtent(newSegment), newSegmentData, uid);
|
||||
this.dragVertices_.push([selectionLayer, newSegmentData, 1]);
|
||||
newSegment = [vertex, segment[1]];
|
||||
newSegmentData = [newSegment, feature, geometry, index + 1];
|
||||
if (goog.isDef(parent)) {
|
||||
newSegmentData.push(parent);
|
||||
}
|
||||
rTree.insert(ol.extent.boundingExtent(newSegment), newSegmentData, uid);
|
||||
this.dragVertices_.push([selectionLayer, newSegmentData, 0]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.layer.VectorLayerEventObject} evt Event object.
|
||||
*/
|
||||
ol.interaction.Modify.prototype.removeIndex = 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);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -158,7 +158,7 @@ ol.layer.Vector = function(options) {
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.temp_ = false;
|
||||
this.temporary_ = false;
|
||||
|
||||
};
|
||||
goog.inherits(ol.layer.Vector, ol.layer.Layer);
|
||||
@@ -241,7 +241,7 @@ ol.layer.Vector.prototype.clear = function() {
|
||||
* @return {boolean} Whether this layer is temporary.
|
||||
*/
|
||||
ol.layer.Vector.prototype.getTemporary = function() {
|
||||
return this.temp_;
|
||||
return this.temporary_;
|
||||
};
|
||||
|
||||
|
||||
@@ -463,10 +463,30 @@ ol.layer.Vector.prototype.removeFeatures = function(features) {
|
||||
|
||||
|
||||
/**
|
||||
* @param {boolean} temp Whether this layer is temporary.
|
||||
* @param {boolean} temporary Whether this layer is temporary.
|
||||
*/
|
||||
ol.layer.Vector.prototype.setTemporary = function(temp) {
|
||||
this.temp_ = temp;
|
||||
ol.layer.Vector.prototype.setTemporary = function(temporary) {
|
||||
this.temporary_ = temporary;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* TODO: This should go away - features should either fire events when changed,
|
||||
* or feature changes should be made through the layer.
|
||||
*
|
||||
* @param {Array.<ol.Feature>} features Features.
|
||||
*/
|
||||
ol.layer.Vector.prototype.updateFeatures = function(features) {
|
||||
var extent = ol.extent.createEmpty();
|
||||
for (var i = features.length - 1; i >= 0; --i) {
|
||||
var feature = features[i];
|
||||
var geometry = feature.getGeometry();
|
||||
this.featureCache_.remove(feature);
|
||||
this.featureCache_.add(feature);
|
||||
ol.extent.extend(extent, geometry.getBounds());
|
||||
}
|
||||
this.dispatchEvent(new ol.layer.VectorEvent(
|
||||
ol.layer.VectorLayerEventType.CHANGE, features, [extent]));
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ goog.provide('ol.layer.VectorLayerRenderIntent');
|
||||
*/
|
||||
ol.layer.VectorLayerRenderIntent = {
|
||||
DEFAULT: 'default',
|
||||
FUTURE: 'future',
|
||||
HIDDEN: 'hidden',
|
||||
SELECTED: 'selected',
|
||||
TEMPORARY: 'temporary'
|
||||
|
||||
@@ -36,7 +36,7 @@ goog.require('ol.extent');
|
||||
* leaf: (Object|undefined),
|
||||
* nodes: (Array.<ol.structs.RTreeNode>|undefined),
|
||||
* target: (Object|undefined),
|
||||
* type: (string|undefined)}}
|
||||
* type: (string|number|undefined)}}
|
||||
*/
|
||||
ol.structs.RTreeNode;
|
||||
|
||||
@@ -186,7 +186,8 @@ ol.structs.RTree.prototype.chooseLeafSubtree_ = function(rect, root) {
|
||||
*
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {Object} obj Object to insert.
|
||||
* @param {string=} opt_type Optional type to store along with the object.
|
||||
* @param {string|number=} opt_type Optional type to store along with the
|
||||
* object.
|
||||
*/
|
||||
ol.structs.RTree.prototype.insert = function(extent, obj, opt_type) {
|
||||
var node = /** @type {ol.structs.RTreeNode} */
|
||||
@@ -554,7 +555,8 @@ ol.structs.RTree.prototype.removeSubtree_ = function(rect, obj, root) {
|
||||
* Non-recursive search function
|
||||
*
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {string=} opt_type Optional type of the objects we want to find.
|
||||
* @param {string|number=} opt_type Optional type of the objects we want to
|
||||
* find.
|
||||
* @return {Array} Result.
|
||||
* @this {ol.structs.RTree}
|
||||
*/
|
||||
@@ -569,7 +571,8 @@ ol.structs.RTree.prototype.search = function(extent, opt_type) {
|
||||
* Non-recursive search function
|
||||
*
|
||||
* @param {ol.Extent} extent Extent.
|
||||
* @param {string=} opt_type Optional type of the objects we want to find.
|
||||
* @param {string|number=} opt_type Optional type of the objects we want to
|
||||
* find.
|
||||
* @return {Object} Result. Keys are UIDs of the values.
|
||||
* @this {ol.structs.RTree}
|
||||
*/
|
||||
@@ -587,7 +590,7 @@ ol.structs.RTree.prototype.searchReturningObject = function(extent, opt_type) {
|
||||
* @param {boolean} returnNode Do we return nodes?
|
||||
* @param {Array|Object} result Result.
|
||||
* @param {ol.structs.RTreeNode} root Root.
|
||||
* @param {string=} opt_type Optional type to search for.
|
||||
* @param {string|number=} opt_type Optional type to search for.
|
||||
* @param {boolean=} opt_resultAsObject If set, result will be an object keyed
|
||||
* by UID.
|
||||
* @private
|
||||
|
||||
Reference in New Issue
Block a user