From 42f45edfce726d6e77fb17040dd026df4a7b5894 Mon Sep 17 00:00:00 2001 From: Stefan Forsgren <33832077+steff-o@users.noreply.github.com> Date: Tue, 31 Oct 2023 15:14:25 +0100 Subject: [PATCH] Added support for MultiLine, MultiPolygon and MultiPoint in drawtools (#1883) Co-authored-by: Stefan Forsgren --- src/controls/editor/copyTool.js | 24 +++--------------- src/controls/editor/drawtools.js | 5 +++- src/controls/editor/edithandler.js | 39 ++++++++++++++++++++++++++++-- src/controls/editor/shapes.js | 9 +++++++ 4 files changed, 53 insertions(+), 24 deletions(-) diff --git a/src/controls/editor/copyTool.js b/src/controls/editor/copyTool.js index d2b010bbd..64ba4ec23 100644 --- a/src/controls/editor/copyTool.js +++ b/src/controls/editor/copyTool.js @@ -1,15 +1,14 @@ import Select from 'ol/interaction/Select'; import Feature from 'ol/Feature'; -import { MultiPolygon, MultiLineString, MultiPoint } from 'ol/geom'; + import dispatcher from './editdispatcher'; // Point of entry. Create on of these each time the tool is selected // viewer: the viewer // editLayer: the destination layer for edits // options: the current drawTools configuration for this layer -const copyTool = function copyTool(viewer, editLayer, options) { +const copyTool = function copyTool(viewer, options) { const map = viewer.getMap(); - const destinationLayer = editLayer; let selectLayers = []; let hasGoups = false; @@ -72,24 +71,7 @@ const copyTool = function copyTool(viewer, editLayer, options) { const accept = window.confirm('Kopiera vald geometri? Avbryt för att välja en annan'); if (accept) { const f = new Feature(e.selected[0].getGeometry().clone()); - const featureGeometryType = f.getGeometry().getType(); - const layerGeometryType = destinationLayer.get('geometryType'); - // Correct geometry type to conform to edit layer - // it will fail in edit handler if geometry is incorrect type - if (featureGeometryType !== layerGeometryType) { - if (featureGeometryType === 'Polygon' && layerGeometryType === 'MultiPolygon') { - const multiPoly = new MultiPolygon([f.getGeometry()]); - f.setGeometry(multiPoly); - } - if (featureGeometryType === 'LineString' && layerGeometryType === 'MultiLineString') { - const multiLine = new MultiLineString([f.getGeometry()]); - f.setGeometry(multiLine); - } - if (featureGeometryType === 'Point' && layerGeometryType === 'MultiPoint') { - const multiPoint = new MultiPoint([f.getGeometry()]); - f.setGeometry(multiPoint); - } - } + cancelTool(); // Important! Remove handler so it won't linger document.removeEventListener('toggleEdit', onToggleEdit, { once: true }); diff --git a/src/controls/editor/drawtools.js b/src/controls/editor/drawtools.js index 65d75fef1..feccd3914 100644 --- a/src/controls/editor/drawtools.js +++ b/src/controls/editor/drawtools.js @@ -11,8 +11,11 @@ let layer; const drawToolsSelector = function drawToolsSelector(tools, defaultLayer, v) { const toolNames = { Polygon: 'Polygon', + MultiPolygon: 'Polygon', Point: 'Punkt', + MultiPoint: 'Punkt', Line: 'Linje', + MultiLine: 'Linje', box: 'Rektangel', Copy: 'Kopiera' }; @@ -73,7 +76,7 @@ const drawToolsSelector = function drawToolsSelector(tools, defaultLayer, v) { // Copy tool is handled entirely in copyTool. Only notify edithandler to back off // and call copyTool to do its stuff. dispatcher.emitChangeEditorShapes('custom'); - copyTool(viewer, layer, drawTools.find((tool) => tool.toolName === 'Copy')); + copyTool(viewer, drawTools.find((tool) => tool.toolName === 'Copy')); break; default: // This is an OL shape tool. Let edithandler handle it diff --git a/src/controls/editor/edithandler.js b/src/controls/editor/edithandler.js index b9bfc6f63..3b5038a10 100644 --- a/src/controls/editor/edithandler.js +++ b/src/controls/editor/edithandler.js @@ -4,7 +4,7 @@ import Modify from 'ol/interaction/Modify'; import Snap from 'ol/interaction/Snap'; import Collection from 'ol/Collection'; import Feature from 'ol/Feature'; -import { LineString } from 'ol/geom'; +import { LineString, MultiPolygon, MultiLineString, MultiPoint } from 'ol/geom'; import { noModifierKeys } from 'ol/events/condition'; import { Button, Element as El, Modal } from '../../ui'; import Infowindow from '../../components/infowindow'; @@ -280,6 +280,35 @@ async function addFeature(feature) { editAttributes(feature); } } +/** + * Checks if a feature's geometry type is same as current edit layer's type. If it can be converted to + * correct type it will do that e.g. creating a multi variant of a single geometry. + * @param {any} f Feature to check + * @returns {boolean} True if feature matches layer + */ +function ensureCorrectGeometryType(f) { + // Correct geometry type to conform to edit layer + const featureGeometryType = f.getGeometry().getType(); + const layerGeometryType = editLayers[currentLayer].get('geometryType'); + if (featureGeometryType !== layerGeometryType) { + if (featureGeometryType === 'Polygon' && layerGeometryType === 'MultiPolygon') { + const multiPoly = new MultiPolygon([f.getGeometry()]); + f.setGeometry(multiPoly); + return true; + } + if (featureGeometryType === 'LineString' && layerGeometryType === 'MultiLineString') { + const multiLine = new MultiLineString([f.getGeometry()]); + f.setGeometry(multiLine); + return true; + } + if (featureGeometryType === 'Point' && layerGeometryType === 'MultiPoint') { + const multiPoint = new MultiPoint([f.getGeometry()]); + f.setGeometry(multiPoint); + return true; + } + } + return featureGeometryType === layerGeometryType; +} // Handler for OL Draw interaction function onDrawEnd(evt) { @@ -295,6 +324,12 @@ function onDrawEnd(evt) { // freehand produces so many vertices that a clean up is still a good idea. f.setGeometry(f.getGeometry().simplify(0.00001)); + if (!ensureCorrectGeometryType(f)) { + // This is a configuration problem. You have added a tool that produces incorrect geometry type + console.error('Incorrect geometry type for layer'); + return; + } + // If live validation did its job, we should not have to validate here, but freehand bypasses all controls and we can't tell if freehand was used. if (validateOnDraw && !topology.isGeometryValid(f.getGeometry())) { alert('Kan ej spara, geometrin är ogiltig'); @@ -422,7 +457,7 @@ function onCustomDrawEnd(e) { // Check if a feature has been created, or tool canceled const feature = e.detail.feature; if (feature) { - if (feature.getGeometry().getType() !== editLayers[currentLayer].get('geometryType')) { + if (!ensureCorrectGeometryType(feature)) { alert('Kan inte lägga till en geometri av den typen i det lagret'); } else { // Must move geometry to correct property. Setting geometryName is not enough. diff --git a/src/controls/editor/shapes.js b/src/controls/editor/shapes.js index 30d963ccd..260de9157 100644 --- a/src/controls/editor/shapes.js +++ b/src/controls/editor/shapes.js @@ -9,11 +9,20 @@ export default (drawType) => { Line: { type: 'LineString' }, + MultiLine: { + type: 'MultiLineString' + }, Polygon: { type: 'Polygon' }, + MultiPolygon: { + type: 'MultiPolygon' + }, Point: { type: 'Point' + }, + MultiPoint: { + type: 'MultiPoint' } };