Skip to content
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
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"license": "MIT",
"require": {
"php": "^8.4",
"longitude-one/spatial-types": "0.0.1-alpha.1"
"longitude-one/spatial-types": "0.0.1-alpha.2"
},
"require-dev": {
"phpunit/phpunit": "^13",
Expand Down
8 changes: 4 additions & 4 deletions docs/strategies.md
Original file line number Diff line number Diff line change
Expand Up @@ -312,10 +312,10 @@ under the same caller responsibilities described above.

The approved MultiPoint contract rejects any EMPTY Point member with
`UnsupportedGeometryStructureException`, including an aggregate made entirely
of EMPTY members. No member is omitted or replaced. The installed spatial-types
`0.0.1-alpha.1` model currently prevents constructing such aggregates: its shared
point-collection constructor throws `LongitudeOne\SpatialTypes\Exception\InvalidValueException`
before the writer is called. An empty aggregate with no members remains supported.
of EMPTY members. No member is omitted or replaced. The required spatial-types
`0.0.1-alpha.2` model supports constructing these aggregates, so the writer rejects
them through its public structural exception. An empty aggregate with no members
remains supported.

The approved contracts for later geometry contributions preserve nested,
singleton and homogeneous GeometryCollections. These deliberately do not apply
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@

use LongitudeOne\SpatialTypes\Reference\SpatialReference;
use LongitudeOne\SpatialTypes\Types\Dimension2\Geography\MultiPoint;
use LongitudeOne\SpatialTypes\Types\Dimension2\Geography\Point;
use LongitudeOne\SpatialWriter\Exception\UnsupportedDimensionException;
use LongitudeOne\SpatialWriter\Exception\UnsupportedGeometryStructureException;
use LongitudeOne\SpatialWriter\Strategy\GeoJsonStrategy;
use LongitudeOne\SpatialWriter\Writer;
use PHPUnit\Framework\Attributes\CoversClass;
Expand Down Expand Up @@ -109,6 +111,38 @@ public function testRejectEmptyXyzm(): void
(new Writer(new GeoJsonStrategy()))->convert($multiPoint);
}

/** Reject an EMPTY member after a non-empty position without returning partial output. */
public function testRejectMixedEmptyMembersXy(): void
{
$multiPoint = new MultiPoint([new Point(1, 2), new Point()]);
$this->expectException(UnsupportedGeometryStructureException::class);
(new Writer(new GeoJsonStrategy()))->convert($multiPoint);
}

/** Reject an EMPTY member after a non-empty position without returning partial output. */
public function testRejectMixedEmptyMembersXyz(): void
{
$multiPoint = new \LongitudeOne\SpatialTypes\Types\Dimension3z\Geography\MultiPoint([new \LongitudeOne\SpatialTypes\Types\Dimension3z\Geography\Point(1, 2, 3), new \LongitudeOne\SpatialTypes\Types\Dimension3z\Geography\Point()]);
$this->expectException(UnsupportedGeometryStructureException::class);
(new Writer(new GeoJsonStrategy()))->convert($multiPoint);
}

/** Distinguish an aggregate containing only EMPTY members from one with no members. */
public function testRejectOnlyEmptyMembersXy(): void
{
$multiPoint = new MultiPoint([new Point(), new Point()]);
$this->expectException(UnsupportedGeometryStructureException::class);
(new Writer(new GeoJsonStrategy()))->convert($multiPoint);
}

/** Distinguish an aggregate containing only EMPTY members from one with no members. */
public function testRejectOnlyEmptyMembersXyz(): void
{
$multiPoint = new \LongitudeOne\SpatialTypes\Types\Dimension3z\Geography\MultiPoint([new \LongitudeOne\SpatialTypes\Types\Dimension3z\Geography\Point(), new \LongitudeOne\SpatialTypes\Types\Dimension3z\Geography\Point()]);
$this->expectException(UnsupportedGeometryStructureException::class);
(new Writer(new GeoJsonStrategy()))->convert($multiPoint);
}

/** Reject an incompatible concrete input without modifying it. */
public function testRejectXym(): void
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@

use LongitudeOne\SpatialTypes\Reference\SpatialReference;
use LongitudeOne\SpatialTypes\Types\Dimension2\Geometry\MultiPoint;
use LongitudeOne\SpatialTypes\Types\Dimension2\Geometry\Point;
use LongitudeOne\SpatialWriter\Exception\UnsupportedDimensionException;
use LongitudeOne\SpatialWriter\Exception\UnsupportedGeometryStructureException;
use LongitudeOne\SpatialWriter\Strategy\GeoJsonStrategy;
use LongitudeOne\SpatialWriter\Writer;
use PHPUnit\Framework\Attributes\CoversClass;
Expand Down Expand Up @@ -109,6 +111,38 @@ public function testRejectEmptyXyzm(): void
(new Writer(new GeoJsonStrategy()))->convert($multiPoint);
}

/** Reject an EMPTY member after a non-empty position without returning partial output. */
public function testRejectMixedEmptyMembersXy(): void
{
$multiPoint = new MultiPoint([new Point(1, 2), new Point()]);
$this->expectException(UnsupportedGeometryStructureException::class);
(new Writer(new GeoJsonStrategy()))->convert($multiPoint);
}

/** Reject an EMPTY member after a non-empty position without returning partial output. */
public function testRejectMixedEmptyMembersXyz(): void
{
$multiPoint = new \LongitudeOne\SpatialTypes\Types\Dimension3z\Geometry\MultiPoint([new \LongitudeOne\SpatialTypes\Types\Dimension3z\Geometry\Point(1, 2, 3), new \LongitudeOne\SpatialTypes\Types\Dimension3z\Geometry\Point()]);
$this->expectException(UnsupportedGeometryStructureException::class);
(new Writer(new GeoJsonStrategy()))->convert($multiPoint);
}

/** Distinguish an aggregate containing only EMPTY members from one with no members. */
public function testRejectOnlyEmptyMembersXy(): void
{
$multiPoint = new MultiPoint([new Point(), new Point()]);
$this->expectException(UnsupportedGeometryStructureException::class);
(new Writer(new GeoJsonStrategy()))->convert($multiPoint);
}

/** Distinguish an aggregate containing only EMPTY members from one with no members. */
public function testRejectOnlyEmptyMembersXyz(): void
{
$multiPoint = new \LongitudeOne\SpatialTypes\Types\Dimension3z\Geometry\MultiPoint([new \LongitudeOne\SpatialTypes\Types\Dimension3z\Geometry\Point(), new \LongitudeOne\SpatialTypes\Types\Dimension3z\Geometry\Point()]);
$this->expectException(UnsupportedGeometryStructureException::class);
(new Writer(new GeoJsonStrategy()))->convert($multiPoint);
}

/** Reject an incompatible concrete input without modifying it. */
public function testRejectXym(): void
{
Expand Down
3 changes: 3 additions & 0 deletions tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,3 +184,6 @@ failure and the unchanged internal exception for a missing LineString interface.
MultiPoint examples cover both families in XY/XYZ, empty aggregates, singletons,
duplicate positions, member and ordinate order, omitted reference metadata, and
XYM/XYZM rejection including empty aggregates.
Concrete XY/XYZ examples also verify rejection of mixed non-empty/EMPTY members
and aggregates containing only EMPTY Points in both families, using spatial-types
`0.0.1-alpha.2`.
Loading