Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GeometryEngine::split() #48

Merged
merged 2 commits into from
Jun 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Changelog

## UNRELEASED (0.11.0)

💥 **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 a 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;
}
46 changes: 46 additions & 0 deletions tests/GeometryEngineTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1164,6 +1164,52 @@ public static function providerTransform() : array
];
}

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

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

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

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

if (is_array($expectedWKT)) {
self::assertContains($splitGeometry->asText(), $expectedWKT);
} else {
$this->assertSame($expectedWKT, $splitGeometry->asText());
}
}

public static function providerSplit() : array
{
return [
['LINESTRING (1 1, 3 3)', 'POINT (2 2)', [
'MULTILINESTRING ((1 1, 2 2), (2 2, 3 3))',
'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)', [
'MULTILINESTRING ((1 1, 1 2, 2 2), (2 2, 2 1, 1 1))',
'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)', [
'MULTIPOLYGON (((1 1, 1 2, 2 2, 1 1)), ((2 2, 2 1, 1 1, 2 2)))',
'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)', [
'MULTIPOLYGON (((1 1, 1 2, 2 2, 1 1)), ((2 2, 3 2, 3 1, 2 2)), ((3 1, 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