From 5bcbd23ccaed13501bbad2853fc60e116fe8d6b8 Mon Sep 17 00:00:00 2001 From: Hubert Argasinski Date: Wed, 8 Jun 2022 18:36:37 -0400 Subject: [PATCH] Fix modifying polygons with overlapping vertices When a polygonal geometry, where one of the vertices overlaps the first vertex in the same ring, is modified, ensure the correct vertices are updated. --- src/ol/interaction/Modify.js | 27 +++++++++-- .../spec/ol/interaction/modify.test.js | 46 +++++++++++++++++++ 2 files changed, 68 insertions(+), 5 deletions(-) diff --git a/src/ol/interaction/Modify.js b/src/ol/interaction/Modify.js index 129db2ce90..9158308cbd 100644 --- a/src/ol/interaction/Modify.js +++ b/src/ol/interaction/Modify.js @@ -1042,15 +1042,32 @@ class Modify extends PointerInteraction { coordinatesEqual(segment[1], vertex) && !componentSegments[uid][1] ) { - // prevent dragging closed linestrings by the connecting node if ( - (segmentDataMatch.geometry.getType() === GeometryType.LINE_STRING || - segmentDataMatch.geometry.getType() === - GeometryType.MULTI_LINE_STRING) && componentSegments[uid][0] && componentSegments[uid][0].index === 0 ) { - continue; + let coordinates = segmentDataMatch.geometry.getCoordinates(); + switch (segmentDataMatch.geometry.getType()) { + // prevent dragging closed linestrings by the connecting node + case GeometryType.LINE_STRING: + case GeometryType.MULTI_LINE_STRING: + continue; + // if dragging the first vertex of a polygon, ensure the other segment + // belongs to the closing vertex of the linear ring + case GeometryType.MULTI_POLYGON: + coordinates = coordinates[depth[1]]; + /* falls through */ + case GeometryType.POLYGON: + if ( + segmentDataMatch.index !== + coordinates[depth[0]].length - 2 + ) { + continue; + } + break; + default: + // pass + } } this.dragSegments_.push([segmentDataMatch, 1]); diff --git a/test/browser/spec/ol/interaction/modify.test.js b/test/browser/spec/ol/interaction/modify.test.js index fe1bcb17bf..3dfab0cac6 100644 --- a/test/browser/spec/ol/interaction/modify.test.js +++ b/test/browser/spec/ol/interaction/modify.test.js @@ -419,6 +419,52 @@ describe('ol.interaction.Modify', function () { expect(lineFeature.getGeometry().getCoordinates()[2][2]).to.equal(30); expect(lineFeature.getGeometry().getCoordinates()[4][2]).to.equal(50); }); + + it('keeps polygon geometries valid', function () { + const overlappingVertexFeature = new Feature({ + geometry: new Polygon([ + [ + [10, 20], + [0, 20], + [0, 0], + [20, 0], + [20, 20], + [10, 20], + [15, 15], + [5, 15], + [10, 20], + ], + ]), + }); + features.length = 0; + features.push(overlappingVertexFeature); + + const modify = new Modify({ + features: new Collection(features), + }); + map.addInteraction(modify); + + let coords, exteriorRing; + coords = overlappingVertexFeature.getGeometry().getCoordinates(); + exteriorRing = coords[0]; + + expect(exteriorRing.length).to.equal(9); + expect(exteriorRing[0]).to.eql(exteriorRing[exteriorRing.length - 1]); + + // move the overlapping vertice + simulateEvent('pointermove', 10, -20, null, 0); + simulateEvent('pointerdown', 10, -20, null, 0); + simulateEvent('pointermove', 10, -25, null, 0); + simulateEvent('pointerdrag', 10, -25, null, 0); + simulateEvent('pointerup', 10, -25, null, 0); + + coords = overlappingVertexFeature.getGeometry().getCoordinates(); + exteriorRing = coords[0]; + + expect(exteriorRing.length).to.equal(9); + expect(exteriorRing[0]).to.eql([10, 25]); + expect(exteriorRing[0]).to.eql(exteriorRing[exteriorRing.length - 1]); + }); }); describe('vertex insertion', function () {