Skip to content

Commit

Permalink
Add GeometryEngine::split()
Browse files Browse the repository at this point in the history
  • Loading branch information
BenMorel committed Jun 5, 2024
1 parent 13f4cc0 commit e00b01d
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 41 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Changelog

## [0.11.0](https://github.com/brick/geo/releases/tag/0.11.0) - 2024-06-05

💥 **Breaking changes**

- interface `GeometryEngine` has a new method: `split()`

**New features**

- New engine method: `GeometryEngine::split()`

## [0.10.0](https://github.com/brick/geo/releases/tag/0.10.0) - 2024-01-23

💥 **Breaking changes**
Expand Down
69 changes: 35 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -272,46 +272,47 @@ Here is a list of all exceptions:
- `UnexpectedGeometryException` is thrown when a geometry is not an instance of the expected sub-type, for example when
calling `Point::fromText()` with a `LineString` WKT.

Spatial Function Reference
--------------------------
GeometryEngine methods reference
--------------------------------

This is a list of all functions which are currently implemented in the geo project. Some functions are only available
This is the list of all methods available in the `GeometryEngine` interface. Some methods are only available
if you use a specific geometry engine, sometimes with a minimum version.
This table also shows which functions are part of the OpenGIS standard.

| Function Name | GEOS | PostGIS | MySQL | MariaDB | SpatiaLite | OpenGIS standard |
|------------------|------|---------|--------|---------|------------|------------------|
| `area` |||||||
| `azimuth` | || | || |
| `boundary` ||| | |||
| `buffer` |||||||
| `centroid` |||||||
| `contains` |||||||
| `convexHull` ||| 5.7.6 | |||
| `crosses` |||||||
| `difference` |||||||
| `disjoint` |||||||
| `distance` |||||||
| `envelope` |||||||
| `equals` |||||||
| `intersects` |||||||
| `intersection` |||||||
| `isSimple` |||||||
| `isValid` ||| 5.7.6 | || |
| `length` |||||||
| `locateAlong` | || | || |
| `locateBetween` | || | || |
| `makeValid` | || | || |
| `maxDistance` | || | || |
| `overlaps` |||||||
| `pointOnSurface` ||| | |||
| `relate` ||| | |||
| `simplify` ||| 5.7.6 | | 4.1.0 | |
| `snapToGrid` | || | || |
| `symDifference` |||||||
| `touches` |||||||
| `union` |||||||
| `within` |||||||
| `area` |||||||
| `azimuth` | || | || |
| `boundary` ||| | |||
| `buffer` |||||||
| `centroid` |||||||
| `contains` |||||||
| `convexHull` ||| 5.7.6 | |||
| `crosses` |||||||
| `difference` |||||||
| `disjoint` |||||||
| `distance` |||||||
| `envelope` |||||||
| `equals` |||||||
| `intersection` |||||||
| `intersects` |||||||
| `isSimple` |||||||
| `isValid` ||| 5.7.6 | || |
| `length` |||||||
| `locateAlong` | || | || |
| `locateBetween` | || | || |
| `makeValid` | || | || |
| `maxDistance` | || | || |
| `overlaps` |||||||
| `pointOnSurface` ||| | |||
| `relate` ||| | |||
| `simplify` ||| 5.7.6 | | 4.1.0 | |
| `snapToGrid` | || | || |
| `split` | || | || |
| `symDifference` |||||||
| `touches` |||||||
| `union` |||||||
| `within` |||||||

Importing and exporting geometries
----------------------------------
Expand Down
5 changes: 5 additions & 0 deletions src/Engine/DatabaseEngine.php
Original file line number Diff line number Diff line change
Expand Up @@ -433,4 +433,9 @@ public function transform(Geometry $g, int $srid) : Geometry
{
return $this->queryGeometry('ST_Transform', $g, $srid);
}

public function split(Geometry $g, Geometry $blade) : Geometry
{
return $this->queryGeometry('ST_Split', $g, $blade);
}
}
5 changes: 5 additions & 0 deletions src/Engine/GEOSEngine.php
Original file line number Diff line number Diff line change
Expand Up @@ -375,4 +375,9 @@ public function transform(Geometry $g, int $srid) : Geometry
{
throw GeometryEngineException::unimplementedMethod(__METHOD__);
}

public function split(Geometry $g, Geometry $blade) : Geometry
{
throw GeometryEngineException::unimplementedMethod(__METHOD__);
}
}
5 changes: 5 additions & 0 deletions src/Engine/GeometryEngine.php
Original file line number Diff line number Diff line change
Expand Up @@ -486,4 +486,9 @@ public function boundingPolygons(Polygon $p) : MultiPolygon;
* Returns a new geometry with its coordinates transformed to a different spatial reference system.
*/
public function transform(Geometry $g, int $srid) : Geometry;

/**
* Splits a geometry into several geometries using a blade.
*/
public function split(Geometry $g, Geometry $blade) : Geometry;
}
45 changes: 38 additions & 7 deletions tests/GeometryEngineTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -323,10 +323,10 @@ public static function providerPointOnSurface() : array

/**
* @param string $geometry The WKT of the geometry to test.
* @param string $boundary The WKT of the expected boundary.
* @param string|string[] $boundary The WKT of the expected boundary. If multiple possible results, an array.
*/
#[DataProvider('providerBoundary')]
public function testBoundary(string $geometry, string $boundary) : void
public function testBoundary(string $geometry, string|array $boundary) : void
{
$geometryEngine = $this->getGeometryEngine();

Expand All @@ -344,16 +344,20 @@ public function testBoundary(string $geometry, string $boundary) : void
$this->expectException(GeometryEngineException::class);
}

self::assertSame($boundary, $geometryEngine->boundary($geometry)->asText());
if (is_array($boundary)) {
self::assertContains($geometryEngine->boundary($geometry)->asText(), $boundary);
} else {
self::assertSame($boundary, $geometryEngine->boundary($geometry)->asText());
}
}

public static function providerBoundary() : array
{
return [
['POINT (1 2)', 'GEOMETRYCOLLECTION EMPTY'],
['POINT Z (2 3 4)', 'GEOMETRYCOLLECTION EMPTY'],
['POINT M (3 4 5)', 'GEOMETRYCOLLECTION EMPTY'],
['POINT ZM (4 5 6 7)', 'GEOMETRYCOLLECTION EMPTY'],
['POINT (1 2)', ['POINT EMPTY', 'GEOMETRYCOLLECTION EMPTY']],
['POINT Z (2 3 4)', ['POINT Z EMPTY', 'GEOMETRYCOLLECTION EMPTY']],
['POINT M (3 4 5)', ['POINT M EMPTY', 'GEOMETRYCOLLECTION EMPTY']],
['POINT ZM (4 5 6 7)', ['POINT ZM EMPTY', 'GEOMETRYCOLLECTION EMPTY']],
['LINESTRING (1 1, 0 0, -1 1)', 'MULTIPOINT (1 1, -1 1)'],
['POLYGON ((1 1, 0 0, -1 1, 1 1))', 'LINESTRING (1 1, 0 0, -1 1, 1 1)'],
];
Expand Down Expand Up @@ -1158,6 +1162,33 @@ public static function providerTransform() : array
];
}

#[DataProvider('providerSplit')]
public function testSplit(string $originalWKT, string $bladeWKT, string $expectedWKT) : void
{
$geometryEngine = $this->getGeometryEngine();

if (! $this->isPostGIS()) {
self::markTestSkipped('This test currently runs on PostGIS only.');
}

$originalGeometry = Geometry::fromText($originalWKT);
$bladeGeometry = Geometry::fromText($bladeWKT);

$splitGeometry = $geometryEngine->split($originalGeometry, $bladeGeometry);

$this->assertSame($expectedWKT, $splitGeometry->asText());
}

public static function providerSplit() : array
{
return [
['LINESTRING (1 1, 3 3)', 'POINT (2 2)', 'GEOMETRYCOLLECTION (LINESTRING (1 1, 2 2), LINESTRING (2 2, 3 3))'],
['LINESTRING (1 1, 1 2, 2 2, 2 1, 1 1)', 'LINESTRING (0 0, 3 3)', 'GEOMETRYCOLLECTION (LINESTRING (1 1, 1 2, 2 2), LINESTRING (2 2, 2 1, 1 1))'],
['POLYGON ((1 1, 1 2, 2 2, 2 1, 1 1))', 'LINESTRING (0 0, 3 3)', 'GEOMETRYCOLLECTION (POLYGON ((1 1, 1 2, 2 2, 1 1)), POLYGON ((2 2, 2 1, 1 1, 2 2)))'],
['POLYGON ((1 1, 1 2, 3 2, 3 1, 1 1))', 'LINESTRING (1 1, 2 2, 3 1)', 'GEOMETRYCOLLECTION (POLYGON ((1 1, 1 2, 2 2, 1 1)), POLYGON ((1 1, 2 2, 3 1, 1 1)), POLYGON ((3 1, 2 2, 3 2, 3 1)))'],
];
}

private function getGeometryEngine(): GeometryEngine
{
if (! isset($GLOBALS['GEOMETRY_ENGINE'])) {
Expand Down

0 comments on commit e00b01d

Please sign in to comment.