From 9cccdc522883a8a813394e63a69d7552b4291096 Mon Sep 17 00:00:00 2001 From: Benjamin Morel Date: Mon, 22 Jan 2024 23:32:56 +0100 Subject: [PATCH] Implement makeValid() TODO README --- src/Engine/DatabaseEngine.php | 5 +++++ src/Engine/GEOSEngine.php | 5 +++++ src/Engine/GeometryEngine.php | 9 +++++++++ tests/GeometryEngineTest.php | 29 +++++++++++++++++++++++++++++ 4 files changed, 48 insertions(+) diff --git a/src/Engine/DatabaseEngine.php b/src/Engine/DatabaseEngine.php index 95bf100..08227ef 100644 --- a/src/Engine/DatabaseEngine.php +++ b/src/Engine/DatabaseEngine.php @@ -339,6 +339,11 @@ public function isRing(Curve $curve) : bool } } + public function makeValid(Geometry $g) : Geometry + { + return $this->queryGeometry('ST_MakeValid', $g); + } + public function equals(Geometry $a, Geometry $b) : bool { return $this->queryBoolean('ST_Equals', $a, $b); diff --git a/src/Engine/GEOSEngine.php b/src/Engine/GEOSEngine.php index a6eda7d..8665ffd 100644 --- a/src/Engine/GEOSEngine.php +++ b/src/Engine/GEOSEngine.php @@ -201,6 +201,11 @@ public function isRing(Curve $curve) : bool } } + public function makeValid(Geometry $g): Geometry + { + throw GeometryEngineException::unimplementedMethod(__METHOD__); + } + public function equals(Geometry $a, Geometry $b) : bool { try { diff --git a/src/Engine/GeometryEngine.php b/src/Engine/GeometryEngine.php index b0f511b..ed721ea 100644 --- a/src/Engine/GeometryEngine.php +++ b/src/Engine/GeometryEngine.php @@ -188,6 +188,15 @@ public function isSimple(Geometry $g) : bool; */ public function isRing(Curve $curve) : bool; + /** + * Attempts to create a valid representation of a given invalid geometry without losing any of the input vertices. + * + * Valid geometries are returned unchanged. + * + * @throws GeometryEngineException If the operation is not supported by the engine. + */ + public function makeValid(Geometry $g) : Geometry; + /** * Returns true if the given geometries are spatially equal. * diff --git a/tests/GeometryEngineTest.php b/tests/GeometryEngineTest.php index 23886a7..75165ad 100644 --- a/tests/GeometryEngineTest.php +++ b/tests/GeometryEngineTest.php @@ -401,6 +401,35 @@ public function providerIsValid() : array ['POLYGON ((0 0, 0 1, 1 0, 1 1, 0 0))', false], ]; } + + /** + * @dataProvider providerMakeValid + * + * @param string $geometry The WKT of the geometry to test. + * @param string $validGeometry The WKT of the expected geometry. + */ + public function testMakeValid(string $geometry, string $validGeometry) : void + { + $geometryEngine = $this->getGeometryEngine(); + + $this->requireEngine(['SpatiaLite', 'PostGIS']); + + $geometry = Geometry::fromText($geometry); + $validGeometry = Geometry::fromText($validGeometry); + + $this->assertGeometryEquals($validGeometry, $geometryEngine->makeValid($geometry)); + } + + public function providerMakeValid() : array + { + return [ + ['POINT (1 2)', 'POINT (1 2)'], + ['LINESTRING (1 2, 3 4)', 'LINESTRING (1 2, 3 4)'], + ['MULTIPOLYGON(((0 2, 10 12, 12 10, 2 0, 0 2)),((0 6, 6 12, 12 6, 6 0, 0 6)))', 'MULTIPOLYGON(((2 0,0 2,2 4,4 2,2 0)),((0 6,6 12,8 10,2 4,0 6)),((12 6,6 0,4 2,10 8,12 6)),((8 10,10 12,12 10,10 8,8 10)))'], + ['MULTIPOLYGON(((0 2, 10 12, 12 10, 2 0, 0 2)),((0 6, 6 12, 12 6, 6 0, 0 6)))', 'MULTIPOLYGON(((0 2, 2 4, 4 2, 2 0, 0 2)), ((0 6, 6 12, 8 10, 2 4, 0 6)), ((10 12, 12 10, 10 8, 8 10, 10 12)), ((12 6, 6 0, 4 2, 10 8, 12 6)))'], + ]; + } + /** * @dataProvider providerIsClosed *