/* Copyright (c) 2019 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_layer_Vector from 'ol/layer/Vector.js' import ol_style_Style from 'ol/style/Style.js' import ol_style_RegularShape from 'ol/style/RegularShape.js' import ol_style_Stroke from 'ol/style/Stroke.js' import ol_source_Vector from 'ol/source/Vector.js' import ol_Feature from 'ol/Feature.js' import ol_geom_Point from 'ol/geom/Point.js' import ol_geom_LineString from 'ol/geom/LineString.js' import ol_geom_Polygon from 'ol/geom/Polygon.js' import ol_geom_Circle from 'ol/geom/Circle.js' import ol_style_Style_defaultStyle from '../style/defaultStyle.js' import {ol_coordinate_dist2d} from "../geom/GeomUtils.js"; /** A sketch layer used as overlay to handle drawing sketch (helper for drawing tools) * @constructor * @extends {ol/layer/Vector} * @fires drawstart * @fires drawend * @fires drawabort * @param {*} options * @param {string} options.type Geometry type, default LineString * @param {ol_style_Style|Array} options.style Drawing style * @param {ol_style_Style|Array} options.sketchStyle Sketch style */ var ol_layer_SketchOverlay = class ollayerSketchOverlay extends ol_layer_Vector { constructor(options) { options = options || {} var style = options.style || ol_style_Style_defaultStyle(true) var sketchStyle = options.sketchStyle if (!sketchStyle) { sketchStyle = ol_style_Style_defaultStyle() sketchStyle = [ new ol_style_Style({ image: new ol_style_RegularShape({ points: 4, radius: 10, radius2: 0, stroke: new ol_style_Stroke({ color: [255, 255, 255, .5], width: 3 }) }) }), sketchStyle[0].clone() ] sketchStyle[1].setImage(new ol_style_RegularShape({ points: 4, radius: 10, radius2: 0, stroke: new ol_style_Stroke({ color: [0, 153, 255, 1], width: 1.25 }) })) } super({ name: 'sketch', source: new ol_source_Vector({ useSpatialIndex: false }), style: function (f) { return (f.get('sketch') ? sketchStyle : style) }, updateWhileAnimating: true, updateWhileInteracting: true }) this._geom = [] // Sketch features this.getSource().addFeatures([ new ol_Feature({ sketch: true, geometry: new ol_geom_Point([]) }), new ol_Feature({ sketch: true, geometry: new ol_geom_LineString([]) }), new ol_Feature(), new ol_Feature(new ol_geom_Point([])) ]) this.setGeometryType(options.type) } /** Set geometry type * @param {string} type Geometry type * @return {string} the current type */ setGeometryType(type) { var t = /^Point$|^LineString$|^Polygon$|^Circle$/.test(type) ? type : 'LineString' if (t !== this._type) { this.abortDrawing() this._type = t } return this._type } /** Get geometry type * @return {string} Geometry type */ getGeometryType() { return this._type } /** Add a new Point to the sketch * @param {ol.coordinate} coord * @return {boolean} true if point has been added, false if same coord */ addPoint(coord) { if (this._lastCoord !== this._position) { if (!this._geom.length) { this.startDrawing() } this._geom.push(coord) this._lastCoord = coord this._position = coord this.drawSketch() if (this.getGeometryType() === 'Point') { this.finishDrawing() } if (this.getGeometryType() === 'Circle' && this._geom.length >= 2) { this.finishDrawing() } return true } return false } /** Remove the last Point from the sketch */ removeLastPoint() { this._geom.pop() this._lastCoord = this._geom[this._geom.length - 1] this.drawSketch() } /** Strat a new drawing * @param {*} options * @param {string} type Geometry type, default the current type * @param {Array} coordinates a list of coordinates to extend * @param {ol.Feature} feature a feature to extend (LineString or Polygon only) * @param {boolean} atstart extent coordinates or feature at start, default false (extend at end) */ startDrawing(options) { options = options || {} this._geom = [] if (options.type) this.setGeometryType(options.type) this.drawSketch() if (!this._drawing) { this.dispatchEvent({ type: 'drawstart', feature: this.getFeature() }) } this._drawing = true } /** Finish drawing * @return {ol.Feature} the drawed feature */ finishDrawing(valid) { var f = this.getSource().getFeatures()[2].clone() var isvalid = !!f switch (this.getGeometryType()) { case 'Circle': case 'LineString': { isvalid = this._geom.length > 1 break } case 'Polygon': { isvalid = this._geom.length > 2 break } } if (valid && !isvalid) return false this._geom = [] this._lastCoord = null this.drawSketch() if (this._drawing) { this.dispatchEvent({ type: 'drawend', valid: isvalid, feature: f }) } this._drawing = false return f } /** Abort drawing */ abortDrawing() { if (this._drawing) { this.dispatchEvent({ type: 'drawabort', feature: this.getFeature() }) } this._drawing = false this._geom = [] this._lastCoord = null this.drawSketch() } /** Set current position * @param {ol.coordinate} coord */ setPosition(coord) { this._position = coord this.drawLink() } /** Get current position * @return {ol.coordinate} */ getPosition() { return this._position } /** Draw/refresh link */ drawLink() { var features = this.getSource().getFeatures() if (this._position) { if (this._lastCoord && this._lastCoord === this._position) { features[0].getGeometry().setCoordinates([]) } else { features[0].getGeometry().setCoordinates(this._position) } if (this._geom.length) { if (this.getGeometryType() === 'Circle') { features[1].setGeometry(new ol_geom_Circle(this._geom[0], ol_coordinate_dist2d(this._geom[0], this._position))) } else if (this.getGeometryType() === 'Polygon') { features[1].setGeometry(new ol_geom_LineString([this._lastCoord, this._position, this._geom[0]])) } else { features[1].setGeometry(new ol_geom_LineString([this._lastCoord, this._position])) } } else { features[1].setGeometry(new ol_geom_LineString([])) } } else { features[0].getGeometry().setCoordinates([]) features[1].setGeometry(new ol_geom_LineString([])) } } /** Get current feature */ getFeature() { return this.getSource().getFeatures()[2] } /** Draw/refresh sketch */ drawSketch() { this.drawLink() var features = this.getSource().getFeatures() if (!this._geom.length) { features[2].setGeometry(null) features[3].setGeometry(new ol_geom_Point([])) } else { if (!this._lastCoord) this._lastCoord = this._geom[this._geom.length - 1] features[3].getGeometry().setCoordinates(this._lastCoord) switch (this._type) { case 'Point': { features[2].setGeometry(new ol_geom_Point(this._lastCoord)) break } case 'Circle': { if (!features[2].getGeometry()) { features[2].setGeometry(new ol_geom_Circle(this._geom[0], ol_coordinate_dist2d(this._geom[0], this._geom[this._geom.length - 1]))) } else { features[2].getGeometry().setRadius(ol_coordinate_dist2d(this._geom[0], this._geom[this._geom.length - 1])) } break } case 'LineString': { if (!features[2].getGeometry()) { features[2].setGeometry(new ol_geom_LineString(this._geom)) } else { features[2].getGeometry().setCoordinates(this._geom) } break } case 'Polygon': { this._geom.push(this._geom[0]) if (!features[2].getGeometry()) { features[2].setGeometry(new ol_geom_Polygon([this._geom])) } else { features[2].getGeometry().setCoordinates([this._geom]) } this._geom.pop() break } default: { console.error('[ol/layer/SketchOverlay~drawSketch] geometry type not supported (' + this._type + ')') break } } } } } export default ol_layer_SketchOverlay