From 444763f47b605e24f6446fb8e33a43d6554e4ea7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kr=C3=B6g?= Date: Sun, 6 Mar 2022 17:10:33 +0100 Subject: [PATCH 1/3] Set correct extent for multipoint points in Snap --- src/ol/interaction/Snap.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ol/interaction/Snap.js b/src/ol/interaction/Snap.js index a4fd3193c1..165cba6e83 100644 --- a/src/ol/interaction/Snap.js +++ b/src/ol/interaction/Snap.js @@ -625,7 +625,7 @@ class Snap extends PointerInteraction { feature: feature, segment: [point], }; - this.rBush_.insert(geometry.getExtent(), segmentData); + this.rBush_.insert(boundingExtent(segmentData.segment), segmentData); }); } From bcebd733889129f2be898dbcabc6ecd9420bd507 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kr=C3=B6g?= Date: Sun, 6 Mar 2022 17:16:05 +0100 Subject: [PATCH 2/3] Improve performance when adding features to Snap --- src/ol/interaction/Snap.js | 128 ++++++++++++++++--------------------- 1 file changed, 55 insertions(+), 73 deletions(-) diff --git a/src/ol/interaction/Snap.js b/src/ol/interaction/Snap.js index 165cba6e83..e163ca5bd9 100644 --- a/src/ol/interaction/Snap.js +++ b/src/ol/interaction/Snap.js @@ -181,18 +181,18 @@ class Snap extends PointerInteraction { /** * @const * @private - * @type {Object} + * @type {Object>, import("../geom/Geometry.js").default): void>} */ - this.SEGMENT_WRITERS_ = { - 'Point': this.writePointGeometry_.bind(this), - 'LineString': this.writeLineStringGeometry_.bind(this), - 'LinearRing': this.writeLineStringGeometry_.bind(this), - 'Polygon': this.writePolygonGeometry_.bind(this), - 'MultiPoint': this.writeMultiPointGeometry_.bind(this), - 'MultiLineString': this.writeMultiLineStringGeometry_.bind(this), - 'MultiPolygon': this.writeMultiPolygonGeometry_.bind(this), - 'GeometryCollection': this.writeGeometryCollectionGeometry_.bind(this), - 'Circle': this.writeCircleGeometry_.bind(this), + this.GEOMETRY_SEGMENTERS_ = { + 'Point': this.segmentPointGemetry_.bind(this), + 'LineString': this.segmentLineStringGemetry_.bind(this), + 'LinearRing': this.segmentLineStringGemetry_.bind(this), + 'Polygon': this.segmentPolygonGemetry_.bind(this), + 'MultiPoint': this.segmentMultiPointGemetry_.bind(this), + 'MultiLineString': this.segmentMultiLineStringGemetry_.bind(this), + 'MultiPolygon': this.segmentMultiPolygonGemetry_.bind(this), + 'GeometryCollection': this.segmentGeometryCollectionGemetry_.bind(this), + 'Circle': this.segmentCircleGemetry_.bind(this), }; } @@ -208,12 +208,27 @@ class Snap extends PointerInteraction { const feature_uid = getUid(feature); const geometry = feature.getGeometry(); if (geometry) { - const segmentWriter = this.SEGMENT_WRITERS_[geometry.getType()]; - if (segmentWriter) { + const segmenter = this.GEOMETRY_SEGMENTERS_[geometry.getType()]; + if (segmenter) { this.indexedFeaturesExtents_[feature_uid] = geometry.getExtent( createEmpty() ); - segmentWriter(feature, geometry); + const segments = + /** @type {Array>} */ ([]); + segmenter(segments, geometry); + if (segments.length === 1) { + this.rBush_.insert(boundingExtent(segments[0]), { + feature: feature, + segment: segments[0], + }); + } else if (segments.length > 1) { + const extents = segments.map((s) => boundingExtent(s)); + const segmentsData = segments.map((segment) => ({ + feature: feature, + segment: segment, + })); + this.rBush_.load(extents, segmentsData); + } } } @@ -534,11 +549,11 @@ class Snap extends PointerInteraction { } /** - * @param {import("../Feature.js").default} feature Feature + * @param {Array>} segments Segments * @param {import("../geom/Circle.js").default} geometry Geometry. * @private */ - writeCircleGeometry_(feature, geometry) { + segmentCircleGemetry_(segments, geometry) { const projection = this.getMap().getView().getProjection(); let circleGeometry = geometry; const userProjection = getUserProjection(); @@ -553,134 +568,101 @@ class Snap extends PointerInteraction { } const coordinates = polygon.getCoordinates()[0]; for (let i = 0, ii = coordinates.length - 1; i < ii; ++i) { - const segment = coordinates.slice(i, i + 2); - const segmentData = { - feature: feature, - segment: segment, - }; - this.rBush_.insert(boundingExtent(segment), segmentData); + segments.push(coordinates.slice(i, i + 2)); } } /** - * @param {import("../Feature.js").default} feature Feature + * @param {Array>} segments Segments * @param {import("../geom/GeometryCollection.js").default} geometry Geometry. * @private */ - writeGeometryCollectionGeometry_(feature, geometry) { + segmentGeometryCollectionGemetry_(segments, geometry) { const geometries = geometry.getGeometriesArray(); for (let i = 0; i < geometries.length; ++i) { - const segmentWriter = this.SEGMENT_WRITERS_[geometries[i].getType()]; - if (segmentWriter) { - segmentWriter(feature, geometries[i]); + const segmenter = this.GEOMETRY_SEGMENTERS_[geometries[i].getType()]; + if (segmenter) { + segmenter(segments, geometries[i]); } } } /** - * @param {import("../Feature.js").default} feature Feature + * @param {Array>} segments Segments * @param {import("../geom/LineString.js").default} geometry Geometry. * @private */ - writeLineStringGeometry_(feature, geometry) { + segmentLineStringGemetry_(segments, geometry) { const coordinates = geometry.getCoordinates(); for (let i = 0, ii = coordinates.length - 1; i < ii; ++i) { - const segment = coordinates.slice(i, i + 2); - const segmentData = { - feature: feature, - segment: segment, - }; - this.rBush_.insert(boundingExtent(segment), segmentData); + segments.push(coordinates.slice(i, i + 2)); } } /** - * @param {import("../Feature.js").default} feature Feature + * @param {Array>} segments Segments * @param {import("../geom/MultiLineString.js").default} geometry Geometry. * @private */ - writeMultiLineStringGeometry_(feature, geometry) { + segmentMultiLineStringGemetry_(segments, geometry) { const lines = geometry.getCoordinates(); for (let j = 0, jj = lines.length; j < jj; ++j) { const coordinates = lines[j]; for (let i = 0, ii = coordinates.length - 1; i < ii; ++i) { - const segment = coordinates.slice(i, i + 2); - const segmentData = { - feature: feature, - segment: segment, - }; - this.rBush_.insert(boundingExtent(segment), segmentData); + segments.push(coordinates.slice(i, i + 2)); } } } /** - * @param {import("../Feature.js").default} feature Feature + * @param {Array>} segments Segments * @param {import("../geom/MultiPoint.js").default} geometry Geometry. * @private */ - writeMultiPointGeometry_(feature, geometry) { + segmentMultiPointGemetry_(segments, geometry) { geometry.getCoordinates().forEach((point) => { - const segmentData = { - feature: feature, - segment: [point], - }; - this.rBush_.insert(boundingExtent(segmentData.segment), segmentData); + segments.push([point]); }); } /** - * @param {import("../Feature.js").default} feature Feature + * @param {Array>} segments Segments * @param {import("../geom/MultiPolygon.js").default} geometry Geometry. * @private */ - writeMultiPolygonGeometry_(feature, geometry) { + segmentMultiPolygonGemetry_(segments, geometry) { const polygons = geometry.getCoordinates(); for (let k = 0, kk = polygons.length; k < kk; ++k) { const rings = polygons[k]; for (let j = 0, jj = rings.length; j < jj; ++j) { const coordinates = rings[j]; for (let i = 0, ii = coordinates.length - 1; i < ii; ++i) { - const segment = coordinates.slice(i, i + 2); - const segmentData = { - feature: feature, - segment: segment, - }; - this.rBush_.insert(boundingExtent(segment), segmentData); + segments.push(coordinates.slice(i, i + 2)); } } } } /** - * @param {import("../Feature.js").default} feature Feature + * @param {Array>} segments Segments * @param {import("../geom/Point.js").default} geometry Geometry. * @private */ - writePointGeometry_(feature, geometry) { - const segmentData = { - feature: feature, - segment: [geometry.getCoordinates()], - }; - this.rBush_.insert(geometry.getExtent(), segmentData); + segmentPointGemetry_(segments, geometry) { + segments.push([geometry.getCoordinates()]); } /** - * @param {import("../Feature.js").default} feature Feature + * @param {Array>} segments Segments * @param {import("../geom/Polygon.js").default} geometry Geometry. * @private */ - writePolygonGeometry_(feature, geometry) { + segmentPolygonGemetry_(segments, geometry) { const rings = geometry.getCoordinates(); for (let j = 0, jj = rings.length; j < jj; ++j) { const coordinates = rings[j]; for (let i = 0, ii = coordinates.length - 1; i < ii; ++i) { - const segment = coordinates.slice(i, i + 2); - const segmentData = { - feature: feature, - segment: segment, - }; - this.rBush_.insert(boundingExtent(segment), segmentData); + segments.push(coordinates.slice(i, i + 2)); } } } From 3b637a793903d7ca721f2b63639e59422fdc2a7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kr=C3=B6g?= Date: Sun, 6 Mar 2022 17:28:36 +0100 Subject: [PATCH 3/3] Improve input form on snap example Put the geometry type select input next to the 'draw' radio and select this whenever the geometry type is changed. --- examples/snap.html | 15 ++++++--------- examples/snap.js | 28 ++++++++++++++-------------- 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/examples/snap.html b/examples/snap.html index 3827370d60..ecd7551103 100644 --- a/examples/snap.html +++ b/examples/snap.html @@ -16,15 +16,6 @@ tags: "draw, edit, modify, vector, snap" Draw   - -
- -
-
-
+
+ +
diff --git a/examples/snap.js b/examples/snap.js index 80cf489d11..c9f7c53ea5 100644 --- a/examples/snap.js +++ b/examples/snap.js @@ -94,18 +94,16 @@ const ExampleDraw = { source: vector.getSource(), type: 'Circle', }), - getActive: function () { - return this.activeType ? this[this.activeType].getActive() : false; - }, + activeDraw: null, setActive: function (active) { - const type = optionsForm.elements['draw-type'].value; + if (this.activeDraw) { + this.activeDraw.setActive(false); + this.activeDraw = null; + } if (active) { - this.activeType && this[this.activeType].setActive(false); - this[type].setActive(true); - this.activeType = type; - } else { - this.activeType && this[this.activeType].setActive(false); - this.activeType = null; + const type = optionsForm.elements['draw-type'].value; + this.activeDraw = this[type]; + this.activeDraw.setActive(true); } }, }; @@ -117,14 +115,16 @@ ExampleDraw.init(); */ optionsForm.onchange = function (e) { const type = e.target.getAttribute('name'); - const value = e.target.value; if (type == 'draw-type') { - ExampleDraw.getActive() && ExampleDraw.setActive(true); + ExampleModify.setActive(false); + ExampleDraw.setActive(true); + optionsForm.elements['interaction'].value = 'draw'; } else if (type == 'interaction') { - if (value == 'modify') { + const interactionType = e.target.value; + if (interactionType == 'modify') { ExampleDraw.setActive(false); ExampleModify.setActive(true); - } else if (value == 'draw') { + } else if (interactionType == 'draw') { ExampleDraw.setActive(true); ExampleModify.setActive(false); }