799 lines
24 KiB
JavaScript
799 lines
24 KiB
JavaScript
/* Copyright (c) 2016 Jean-Marc VIGLINO,
|
|
released under the CeCILL-B license (French BSD license)
|
|
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
|
*/
|
|
|
|
import ol_style_Style from 'ol/style/Style.js'
|
|
import ol_style_Stroke from 'ol/style/Stroke.js'
|
|
import ol_source_Vector from 'ol/source/Vector.js'
|
|
import ol_style_Fill from 'ol/style/Fill.js'
|
|
import ol_style_Circle from 'ol/style/Circle.js'
|
|
import ol_layer_Vector from 'ol/layer/Vector.js'
|
|
import ol_geom_Point from 'ol/geom/Point.js'
|
|
import ol_Feature from 'ol/Feature.js'
|
|
import ol_geom_LineString from 'ol/geom/LineString.js'
|
|
import ol_interaction_Interaction from 'ol/interaction/Interaction.js'
|
|
import {ol_coordinate_dist2d, ol_coordinate_equal} from "../geom/GeomUtils.js";
|
|
import {boundingExtent as ol_extent_boundingExtent} from 'ol/extent.js'
|
|
import {buffer as ol_extent_buffer} from 'ol/extent.js'
|
|
import {altKeyOnly as ol_events_condition_altKeyOnly} from 'ol/events/condition.js'
|
|
import {primaryAction as ol_events_condition_primaryAction} from 'ol/events/condition.js'
|
|
import {always as ol_events_condition_always} from 'ol/events/condition.js'
|
|
|
|
import ol_ext_element from '../util/element.js'
|
|
import '../geom/LineStringSplitAt.js'
|
|
|
|
/** Interaction for modifying feature geometries. Similar to the core ol/interaction/Modify.
|
|
* The interaction is more suitable to use to handle feature modification: only features concerned
|
|
* by the modification are passed to the events (instead of all feature with ol/interaction/Modify)
|
|
* - the modifystart event is fired before the feature is modified (no points still inserted)
|
|
* - the modifyend event is fired after the modification
|
|
* - it fires a modifying event
|
|
* @constructor
|
|
* @extends {ol_interaction_Interaction}
|
|
* @fires modifystart
|
|
* @fires modifying
|
|
* @fires modifyend
|
|
* @fires select
|
|
* @param {*} options
|
|
* @param {ol.source.Vector} options.source a source to modify (configured with useSpatialIndex set to true)
|
|
* @param {ol.source.Vector|Array<ol.source.Vector>} options.sources a list of source to modify (configured with useSpatialIndex set to true)
|
|
* @param {ol.Collection.<ol.Feature>} options.features collection of feature to modify
|
|
* @param {integer} options.pixelTolerance Pixel tolerance for considering the pointer close enough to a segment or vertex for editing. Default is 10.
|
|
* @param {function|undefined} options.filter a filter that takes a feature and return true if it can be modified, default always true.
|
|
* @param {ol.style.Style | Array<ol.style.Style> | undefined} options.style Style for the sketch features.
|
|
* @param {ol.EventsConditionType | undefined} options.condition A function that takes an ol.MapBrowserEvent and returns a boolean to indicate whether that event will be considered to add or move a vertex to the sketch. Default is ol.events.condition.primaryAction.
|
|
* @param {ol.EventsConditionType | undefined} options.deleteCondition A function that takes an ol.MapBrowserEvent and returns a boolean to indicate whether that event should be handled. By default, ol.events.condition.singleClick with ol.events.condition.altKeyOnly results in a vertex deletion.
|
|
* @param {ol.EventsConditionType | undefined} options.insertVertexCondition A function that takes an ol.MapBrowserEvent and returns a boolean to indicate whether a new vertex can be added to the sketch features. Default is ol.events.condition.always
|
|
* @param {boolean} options.wrapX Wrap the world horizontally on the sketch overlay, default false
|
|
*/
|
|
var ol_interaction_ModifyFeature = class olinteractionModifyFeature extends ol_interaction_Interaction {
|
|
constructor(options) {
|
|
options = options || {}
|
|
|
|
var dragging, modifying
|
|
super({
|
|
handleEvent: function (e) {
|
|
switch (e.type) {
|
|
case 'pointerdown': {
|
|
dragging = this.handleDownEvent(e)
|
|
modifying = dragging || this._deleteCondition(e)
|
|
return !dragging
|
|
}
|
|
case 'pointerup': {
|
|
dragging = false
|
|
return this.handleUpEvent(e)
|
|
}
|
|
case 'pointerdrag': {
|
|
if (dragging)
|
|
return this.handleDragEvent(e)
|
|
else
|
|
return true
|
|
}
|
|
case 'pointermove': {
|
|
if (!dragging){
|
|
return this.handleMoveEvent(e)
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
case 'singleclick':
|
|
case 'click': {
|
|
// Prevent click when modifying
|
|
return !modifying
|
|
}
|
|
default: return true
|
|
}
|
|
}
|
|
})
|
|
|
|
// Snap distance (in px)
|
|
this.snapDistance_ = options.pixelTolerance || 10
|
|
// Split tolerance between the calculated intersection and the geometry
|
|
this.tolerance_ = 1e-10
|
|
// Cursor
|
|
this.cursor_ = options.cursor
|
|
|
|
// List of source to split
|
|
this.sources_ = options.sources ? (options.sources instanceof Array) ? options.sources : [options.sources] : []
|
|
if (options.source) {
|
|
this.sources_.push(options.source)
|
|
}
|
|
if (options.features) {
|
|
this.sources_.push(new ol_source_Vector({ features: options.features }))
|
|
}
|
|
// Get all features candidate
|
|
this.filterSplit_ = options.filter || function () { return true }
|
|
|
|
this._condition = options.condition || ol_events_condition_primaryAction
|
|
this._deleteCondition = options.deleteCondition || ol_events_condition_altKeyOnly
|
|
this._insertVertexCondition = options.insertVertexCondition || ol_events_condition_always
|
|
|
|
// Default style
|
|
var sketchStyle = function () {
|
|
return [new ol_style_Style({
|
|
image: new ol_style_Circle({
|
|
radius: 6,
|
|
fill: new ol_style_Fill({ color: [0, 153, 255, 1] }),
|
|
stroke: new ol_style_Stroke({ color: '#FFF', width: 1.25 })
|
|
})
|
|
})
|
|
]
|
|
}
|
|
|
|
// Custom style
|
|
if (options.style) {
|
|
if (typeof (options.style) === 'function') {
|
|
sketchStyle = options.style
|
|
} else {
|
|
sketchStyle = function () { return options.style }
|
|
}
|
|
}
|
|
|
|
// Create a new overlay for the sketch
|
|
this.overlayLayer_ = new ol_layer_Vector({
|
|
source: new ol_source_Vector({
|
|
useSpatialIndex: false
|
|
}),
|
|
name: 'Modify overlay',
|
|
displayInLayerSwitcher: false,
|
|
style: sketchStyle,
|
|
wrapX: options.wrapX
|
|
})
|
|
|
|
}
|
|
/**
|
|
* Remove the interaction from its current map, if any, and attach it to a new
|
|
* map, if any. Pass `null` to just remove the interaction from the current map.
|
|
* @param {ol.Map} map Map.
|
|
* @api stable
|
|
*/
|
|
setMap(map) {
|
|
if (this.getMap()) this.getMap().removeLayer(this.overlayLayer_)
|
|
super.setMap(map)
|
|
this.overlayLayer_.setMap(map)
|
|
}
|
|
/**
|
|
* Activate or deactivate the interaction + remove the sketch.
|
|
* @param {boolean} active.
|
|
* @api stable
|
|
*/
|
|
setActive(active) {
|
|
super.setActive(active)
|
|
if (this.overlayLayer_) this.overlayLayer_.getSource().clear()
|
|
}
|
|
/** Change the filter function
|
|
* @param {function|undefined} options.filter a filter that takes a feature and return true if it can be modified, default always true.
|
|
*/
|
|
setFilter(filter) {
|
|
if (typeof (filter) === 'function')
|
|
this.filterSplit_ = filter
|
|
else if (filter === undefined)
|
|
this.filterSplit_ = function () { return true }
|
|
}
|
|
/** Get closest feature at pixel
|
|
* @param {ol.Pixel}
|
|
* @return {*}
|
|
* @private
|
|
*/
|
|
getClosestFeature(e) {
|
|
var f, c, d = this.snapDistance_ + 1
|
|
for (var i = 0; i < this.sources_.length; i++) {
|
|
var source = this.sources_[i]
|
|
f = source.getClosestFeatureToCoordinate(e.coordinate)
|
|
if (f && this.filterSplit_(f)) {
|
|
var ci = f.getGeometry().getClosestPoint(e.coordinate)
|
|
var di = ol_coordinate_dist2d(e.coordinate, ci) / e.frameState.viewState.resolution
|
|
if (di < d) {
|
|
d = di
|
|
c = ci
|
|
}
|
|
break
|
|
}
|
|
}
|
|
if (d > this.snapDistance_) {
|
|
if (this.currentFeature)
|
|
this.dispatchEvent({ type: 'select', selected: [], deselected: [this.currentFeature] })
|
|
this.currentFeature = null
|
|
return false
|
|
} else {
|
|
// Snap to node
|
|
var coord = this.getNearestCoord(c, f.getGeometry())
|
|
if (coord) {
|
|
coord = coord.coord
|
|
var p = this.getMap().getPixelFromCoordinate(coord)
|
|
if (ol_coordinate_dist2d(e.pixel, p) < this.snapDistance_) {
|
|
c = coord
|
|
}
|
|
//
|
|
if (this.currentFeature !== f)
|
|
this.dispatchEvent({ type: 'select', selected: [f], deselected: [this.currentFeature] })
|
|
this.currentFeature = f
|
|
return { source: source, feature: f, coord: c }
|
|
}
|
|
}
|
|
}
|
|
/** Get nearest coordinate in a list
|
|
* @param {ol.coordinate} pt the point to find nearest
|
|
* @param {ol.geom} coords list of coordinates
|
|
* @return {*} the nearest point with a coord (projected point), dist (distance to the geom), ring (if Polygon)
|
|
*/
|
|
getNearestCoord(pt, geom) {
|
|
var i, l, p, p0, dm
|
|
switch (geom.getType()) {
|
|
case 'Point': {
|
|
return { coord: geom.getCoordinates(), dist: ol_coordinate_dist2d(geom.getCoordinates(), pt) }
|
|
}
|
|
case 'MultiPoint': {
|
|
return this.getNearestCoord(pt, new ol_geom_LineString(geom.getCoordinates()))
|
|
}
|
|
case 'LineString':
|
|
case 'LinearRing': {
|
|
var d
|
|
dm = Number.MAX_VALUE
|
|
var coords = geom.getCoordinates()
|
|
for (i = 0; i < coords.length; i++) {
|
|
d = ol_coordinate_dist2d(pt, coords[i])
|
|
if (d < dm) {
|
|
dm = d
|
|
p0 = coords[i]
|
|
}
|
|
}
|
|
return { coord: p0, dist: dm }
|
|
}
|
|
case 'MultiLineString': {
|
|
var lstring = geom.getLineStrings()
|
|
p0 = false, dm = Number.MAX_VALUE
|
|
for (i = 0; l = lstring[i]; i++) {
|
|
p = this.getNearestCoord(pt, l)
|
|
if (p && p.dist < dm) {
|
|
p0 = p
|
|
dm = p.dist
|
|
p0.ring = i
|
|
}
|
|
}
|
|
return p0
|
|
}
|
|
case 'Polygon': {
|
|
var lring = geom.getLinearRings()
|
|
p0 = false
|
|
dm = Number.MAX_VALUE
|
|
for (i = 0; l = lring[i]; i++) {
|
|
p = this.getNearestCoord(pt, l)
|
|
if (p && p.dist < dm) {
|
|
p0 = p
|
|
dm = p.dist
|
|
p0.ring = i
|
|
}
|
|
}
|
|
return p0
|
|
}
|
|
case 'MultiPolygon': {
|
|
var poly = geom.getPolygons()
|
|
p0 = false
|
|
dm = Number.MAX_VALUE
|
|
for (i = 0; l = poly[i]; i++) {
|
|
p = this.getNearestCoord(pt, l)
|
|
if (p && p.dist < dm) {
|
|
p0 = p
|
|
dm = p.dist
|
|
p0.poly = i
|
|
}
|
|
}
|
|
return p0
|
|
}
|
|
case 'GeometryCollection': {
|
|
var g = geom.getGeometries()
|
|
p0 = false
|
|
dm = Number.MAX_VALUE
|
|
for (i = 0; l = g[i]; i++) {
|
|
p = this.getNearestCoord(pt, l)
|
|
if (p && p.dist < dm) {
|
|
p0 = p
|
|
dm = p.dist
|
|
p0.geom = i
|
|
}
|
|
}
|
|
return p0
|
|
}
|
|
default: return false
|
|
}
|
|
}
|
|
/** Get arcs concerned by a modification
|
|
* @param {ol.geom} geom the geometry concerned
|
|
* @param {ol.coordinate} coord pointed coordinates
|
|
*/
|
|
getArcs(geom, coord) {
|
|
var arcs = false
|
|
var coords, i, s, l, g
|
|
switch (geom.getType()) {
|
|
case 'Point': {
|
|
if (ol_coordinate_equal(coord, geom.getCoordinates())) {
|
|
arcs = {
|
|
geom: geom,
|
|
type: geom.getType(),
|
|
coord1: [],
|
|
coord2: [],
|
|
node: true
|
|
}
|
|
}
|
|
break
|
|
}
|
|
case 'MultiPoint': {
|
|
coords = geom.getCoordinates()
|
|
for (i = 0; i < coords.length; i++) {
|
|
if (ol_coordinate_equal(coord, coords[i])) {
|
|
arcs = {
|
|
geom: geom,
|
|
type: geom.getType(),
|
|
index: i,
|
|
coord1: [],
|
|
coord2: [],
|
|
node: true
|
|
}
|
|
break
|
|
}
|
|
}
|
|
break
|
|
}
|
|
case 'LinearRing':
|
|
case 'LineString': {
|
|
var p = geom.getClosestPoint(coord)
|
|
if (ol_coordinate_dist2d(p, coord) < 1.5 * this.tolerance_) {
|
|
var split
|
|
// Split the line in two
|
|
if (geom.getType() === 'LinearRing') {
|
|
g = new ol_geom_LineString(geom.getCoordinates())
|
|
split = g.splitAt(coord, this.tolerance_)
|
|
} else {
|
|
split = geom.splitAt(coord, this.tolerance_)
|
|
}
|
|
// If more than 2
|
|
if (split.length > 2) {
|
|
coords = split[1].getCoordinates()
|
|
for (i = 2; s = split[i]; i++) {
|
|
var c = s.getCoordinates()
|
|
c.shift()
|
|
coords = coords.concat(c)
|
|
}
|
|
split = [split[0], new ol_geom_LineString(coords)]
|
|
}
|
|
// Split in two
|
|
if (split.length === 2) {
|
|
var c0 = split[0].getCoordinates()
|
|
var c1 = split[1].getCoordinates()
|
|
var nbpt = c0.length + c1.length - 1
|
|
c0.pop()
|
|
c1.shift()
|
|
arcs = {
|
|
geom: geom,
|
|
type: geom.getType(),
|
|
coord1: c0,
|
|
coord2: c1,
|
|
node: (geom.getCoordinates().length === nbpt),
|
|
closed: false
|
|
}
|
|
} else if (split.length === 1) {
|
|
s = split[0].getCoordinates()
|
|
var start = ol_coordinate_equal(s[0], coord)
|
|
var end = ol_coordinate_equal(s[s.length - 1], coord)
|
|
// Move first point
|
|
if (start) {
|
|
s.shift()
|
|
if (end)
|
|
s.pop()
|
|
arcs = {
|
|
geom: geom,
|
|
type: geom.getType(),
|
|
coord1: [],
|
|
coord2: s,
|
|
node: true,
|
|
closed: end
|
|
}
|
|
} else if (end) {
|
|
// Move last point
|
|
s.pop()
|
|
arcs = {
|
|
geom: geom,
|
|
type: geom.getType(),
|
|
coord1: s,
|
|
coord2: [],
|
|
node: true,
|
|
closed: false
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break
|
|
}
|
|
case 'MultiLineString': {
|
|
var lstring = geom.getLineStrings()
|
|
for (i = 0; l = lstring[i]; i++) {
|
|
arcs = this.getArcs(l, coord)
|
|
if (arcs) {
|
|
arcs.geom = geom
|
|
arcs.type = geom.getType()
|
|
arcs.lstring = i
|
|
break
|
|
}
|
|
}
|
|
break
|
|
}
|
|
case 'Polygon': {
|
|
var lring = geom.getLinearRings()
|
|
for (i = 0; l = lring[i]; i++) {
|
|
arcs = this.getArcs(l, coord)
|
|
if (arcs) {
|
|
arcs.geom = geom
|
|
arcs.type = geom.getType()
|
|
arcs.index = i
|
|
break
|
|
}
|
|
}
|
|
break
|
|
}
|
|
case 'MultiPolygon': {
|
|
var poly = geom.getPolygons()
|
|
for (i = 0; l = poly[i]; i++) {
|
|
arcs = this.getArcs(l, coord)
|
|
if (arcs) {
|
|
arcs.geom = geom
|
|
arcs.type = geom.getType()
|
|
arcs.poly = i
|
|
break
|
|
}
|
|
}
|
|
break
|
|
}
|
|
case 'GeometryCollection': {
|
|
g = geom.getGeometries()
|
|
for (i = 0; l = g[i]; i++) {
|
|
arcs = this.getArcs(l, coord)
|
|
if (arcs) {
|
|
arcs.geom = geom
|
|
arcs.g = i
|
|
arcs.typeg = arcs.type
|
|
arcs.type = geom.getType()
|
|
break
|
|
}
|
|
}
|
|
break
|
|
}
|
|
default: {
|
|
console.error('ol/interaction/ModifyFeature ' + geom.getType() + ' not supported!')
|
|
break
|
|
}
|
|
}
|
|
return arcs
|
|
}
|
|
/**
|
|
* @param {ol.MapBrowserEvent} evt Map browser event.
|
|
* @return {boolean} `true` to start the drag sequence.
|
|
*/
|
|
handleDownEvent(evt) {
|
|
if (!this.getActive())
|
|
return false
|
|
|
|
// Something to move ?
|
|
var current = this.getClosestFeature(evt)
|
|
|
|
if (current && (this._condition(evt) || this._deleteCondition(evt))) {
|
|
var features = []
|
|
this.arcs = []
|
|
|
|
// Get features concerned
|
|
this.sources_.forEach(function (s) {
|
|
var extent = ol_extent_buffer(ol_extent_boundingExtent([current.coord]), this.tolerance_)
|
|
features = features.concat(features, s.getFeaturesInExtent(extent))
|
|
}.bind(this))
|
|
|
|
// Get arcs concerned
|
|
this._modifiedFeatures = []
|
|
features.forEach(function (f) {
|
|
var a = this.getArcs(f.getGeometry(), current.coord)
|
|
if (a) {
|
|
if (this._insertVertexCondition(evt) || a.node) {
|
|
a.feature = f
|
|
this._modifiedFeatures.push(f)
|
|
this.arcs.push(a)
|
|
}
|
|
}
|
|
}.bind(this))
|
|
|
|
if (this._modifiedFeatures.length) {
|
|
if (this._deleteCondition(evt)) {
|
|
return !this._removePoint(current, evt)
|
|
} else {
|
|
this.dispatchEvent({
|
|
type: 'modifystart',
|
|
coordinate: current.coord,
|
|
originalEvent: evt.originalEvent,
|
|
features: this._modifiedFeatures
|
|
})
|
|
this.handleDragEvent({
|
|
coordinate: current.coord,
|
|
originalEvent: evt.originalEvent
|
|
})
|
|
return true
|
|
}
|
|
} else {
|
|
return true
|
|
}
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
/** Get modified features
|
|
* @return {Array<ol.Feature>} list of modified features
|
|
*/
|
|
getModifiedFeatures() {
|
|
return this._modifiedFeatures || []
|
|
}
|
|
/** Removes the vertex currently being pointed.
|
|
*/
|
|
removePoint() {
|
|
this._removePoint({}, {})
|
|
}
|
|
/**
|
|
* @private
|
|
*/
|
|
_getModification(a) {
|
|
var coords = a.coord1.concat(a.coord2)
|
|
switch (a.type) {
|
|
case 'LineString': {
|
|
if (a.closed)
|
|
coords.push(coords[0])
|
|
if (coords.length > 1) {
|
|
if (a.geom.getCoordinates().length != coords.length) {
|
|
a.coords = coords
|
|
return true
|
|
}
|
|
}
|
|
break
|
|
}
|
|
case 'MultiLineString': {
|
|
if (a.closed)
|
|
coords.push(coords[0])
|
|
if (coords.length > 1) {
|
|
var c = a.geom.getCoordinates()
|
|
if (c[a.lstring].length != coords.length) {
|
|
c[a.lstring] = coords
|
|
a.coords = c
|
|
return true
|
|
}
|
|
}
|
|
break
|
|
}
|
|
case 'Polygon': {
|
|
if (a.closed)
|
|
coords.push(coords[0])
|
|
if (coords.length > 3) {
|
|
c = a.geom.getCoordinates()
|
|
if (c[a.index].length != coords.length) {
|
|
c[a.index] = coords
|
|
a.coords = c
|
|
return true
|
|
}
|
|
}
|
|
break
|
|
}
|
|
case 'MultiPolygon': {
|
|
if (a.closed)
|
|
coords.push(coords[0])
|
|
if (coords.length > 3) {
|
|
c = a.geom.getCoordinates()
|
|
if (c[a.poly][a.index].length != coords.length) {
|
|
c[a.poly][a.index] = coords
|
|
a.coords = c
|
|
return true
|
|
}
|
|
}
|
|
break
|
|
}
|
|
case 'GeometryCollection': {
|
|
a.type = a.typeg
|
|
var geom = a.geom
|
|
var geoms = geom.getGeometries()
|
|
a.geom = geoms[a.g]
|
|
var found = this._getModification(a)
|
|
// Restore current arc
|
|
geom.setGeometries(geoms)
|
|
a.geom = geom
|
|
a.type = 'GeometryCollection'
|
|
return found
|
|
}
|
|
default: {
|
|
//console.error('ol/interaction/ModifyFeature '+a.type+' not supported!');
|
|
break
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
/** Removes the vertex currently being pointed.
|
|
* @private
|
|
*/
|
|
_removePoint(current, evt) {
|
|
if (!this.arcs)
|
|
return false
|
|
|
|
this.overlayLayer_.getSource().clear()
|
|
|
|
var found = false
|
|
// Get all modifications
|
|
this.arcs.forEach(function (a) {
|
|
found = found || this._getModification(a)
|
|
}.bind(this))
|
|
|
|
// Almost one point is removed
|
|
if (found) {
|
|
this.dispatchEvent({
|
|
type: 'modifystart',
|
|
coordinate: current.coord,
|
|
originalEvent: evt.originalEvent,
|
|
features: this._modifiedFeatures
|
|
})
|
|
this.arcs.forEach(function (a) {
|
|
if (a.geom.getType() === 'GeometryCollection') {
|
|
if (a.coords) {
|
|
var geoms = a.geom.getGeometries()
|
|
geoms[a.g].setCoordinates(a.coords)
|
|
a.geom.setGeometries(geoms)
|
|
}
|
|
} else {
|
|
if (a.coords)
|
|
a.geom.setCoordinates(a.coords)
|
|
}
|
|
}.bind(this))
|
|
this.dispatchEvent({
|
|
type: 'modifyend',
|
|
coordinate: current.coord,
|
|
originalEvent: evt.originalEvent,
|
|
features: this._modifiedFeatures
|
|
})
|
|
}
|
|
|
|
this.arcs = []
|
|
return found
|
|
}
|
|
/**
|
|
* @private
|
|
*/
|
|
handleUpEvent(e) {
|
|
if (!this.getActive())
|
|
return false
|
|
if (!this.arcs || !this.arcs.length)
|
|
return true
|
|
|
|
this.overlayLayer_.getSource().clear()
|
|
this.dispatchEvent({
|
|
type: 'modifyend',
|
|
coordinate: e.coordinate,
|
|
originalEvent: e.originalEvent,
|
|
features: this._modifiedFeatures
|
|
})
|
|
|
|
this.arcs = []
|
|
return true
|
|
}
|
|
/**
|
|
* @private
|
|
*/
|
|
setArcCoordinates(a, coords) {
|
|
var c
|
|
switch (a.type) {
|
|
case 'Point': {
|
|
a.geom.setCoordinates(coords[0])
|
|
break
|
|
}
|
|
case 'MultiPoint': {
|
|
c = a.geom.getCoordinates()
|
|
c[a.index] = coords[0]
|
|
a.geom.setCoordinates(c)
|
|
break
|
|
}
|
|
case 'LineString': {
|
|
a.geom.setCoordinates(coords)
|
|
break
|
|
}
|
|
case 'MultiLineString': {
|
|
c = a.geom.getCoordinates()
|
|
c[a.lstring] = coords
|
|
a.geom.setCoordinates(c)
|
|
break
|
|
}
|
|
case 'Polygon': {
|
|
c = a.geom.getCoordinates()
|
|
c[a.index] = coords
|
|
a.geom.setCoordinates(c)
|
|
break
|
|
}
|
|
case 'MultiPolygon': {
|
|
c = a.geom.getCoordinates()
|
|
c[a.poly][a.index] = coords
|
|
a.geom.setCoordinates(c)
|
|
break
|
|
}
|
|
case 'GeometryCollection': {
|
|
a.type = a.typeg
|
|
var geom = a.geom
|
|
var geoms = geom.getGeometries()
|
|
a.geom = geoms[a.g]
|
|
this.setArcCoordinates(a, coords)
|
|
geom.setGeometries(geoms)
|
|
a.geom = geom
|
|
a.type = 'GeometryCollection'
|
|
break
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* @private
|
|
*/
|
|
handleDragEvent(e) {
|
|
if (!this.getActive()) return false
|
|
if (!this.arcs) return true
|
|
|
|
// Show sketch
|
|
this.overlayLayer_.getSource().clear()
|
|
var p = new ol_Feature(new ol_geom_Point(e.coordinate))
|
|
this.overlayLayer_.getSource().addFeature(p)
|
|
|
|
// Nothing to do
|
|
if (!this.arcs.length) return true
|
|
|
|
// Move arcs
|
|
this.arcs.forEach(function (a) {
|
|
var coords = a.coord1.concat([e.coordinate], a.coord2)
|
|
if (a.closed) coords.push(e.coordinate)
|
|
this.setArcCoordinates(a, coords)
|
|
}.bind(this))
|
|
|
|
this.dispatchEvent({
|
|
type: 'modifying',
|
|
coordinate: e.coordinate,
|
|
originalEvent: e.originalEvent,
|
|
features: this._modifiedFeatures
|
|
})
|
|
|
|
return true
|
|
}
|
|
/**
|
|
* @param {ol.MapBrowserEvent} evt Event.
|
|
* @private
|
|
*/
|
|
handleMoveEvent(e) {
|
|
if (!this.getActive()) return true
|
|
|
|
this.overlayLayer_.getSource().clear()
|
|
var current = this.getClosestFeature(e)
|
|
|
|
// Draw sketch
|
|
if (current) {
|
|
var p = new ol_Feature(new ol_geom_Point(current.coord))
|
|
this.overlayLayer_.getSource().addFeature(p)
|
|
}
|
|
|
|
// Show cursor
|
|
var element = e.map.getTargetElement()
|
|
if (this.cursor_) {
|
|
if (current) {
|
|
if (element.style.cursor != this.cursor_) {
|
|
this.previousCursor_ = element.style.cursor
|
|
ol_ext_element.setCursor(element, this.cursor_)
|
|
}
|
|
} else if (this.previousCursor_ !== undefined) {
|
|
ol_ext_element.setCursor(element, this.previousCursor_)
|
|
this.previousCursor_ = undefined
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
/** Get the current feature to modify
|
|
* @return {ol.Feature}
|
|
*/
|
|
getCurrentFeature() {
|
|
return this.currentFeature
|
|
}
|
|
}
|
|
|
|
export default ol_interaction_ModifyFeature |