From a4056f7e89125250efd3843d05245ff463a3ed24 Mon Sep 17 00:00:00 2001 From: Matan Yadaev Date: Tue, 19 Jul 2022 23:23:05 +0300 Subject: [PATCH 01/14] Add PhpStorm run configurations --- .run/Fix formatting.run.xml | 8 ++++++++ .run/Static code analysis.run.xml | 8 ++++++++ .run/Unnamed.run.xml | 11 +++++++++++ 3 files changed, 27 insertions(+) create mode 100644 .run/Fix formatting.run.xml create mode 100644 .run/Static code analysis.run.xml create mode 100644 .run/Unnamed.run.xml diff --git a/.run/Fix formatting.run.xml b/.run/Fix formatting.run.xml new file mode 100644 index 0000000..58c6cbe --- /dev/null +++ b/.run/Fix formatting.run.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/.run/Static code analysis.run.xml b/.run/Static code analysis.run.xml new file mode 100644 index 0000000..02486cf --- /dev/null +++ b/.run/Static code analysis.run.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/.run/Unnamed.run.xml b/.run/Unnamed.run.xml new file mode 100644 index 0000000..4fc55d4 --- /dev/null +++ b/.run/Unnamed.run.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file From be386c619cc4444057a189b7e75ab5d0b8198444 Mon Sep 17 00:00:00 2001 From: Matan Yadaev Date: Tue, 19 Jul 2022 23:40:44 +0300 Subject: [PATCH 02/14] Add test to `whereSrid` --- tests/SpatialBuilderTest.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/SpatialBuilderTest.php b/tests/SpatialBuilderTest.php index f5fd43a..214b5f7 100644 --- a/tests/SpatialBuilderTest.php +++ b/tests/SpatialBuilderTest.php @@ -283,3 +283,18 @@ expect($testPlaces)->toHaveCount(1); expect($testPlaces[0]->point)->toEqual($point1); }); + +it('filters by SRID', function (): void { + $point1 = new Point(0, 0, 4326); + $point2 = new Point(50, 50, 0); + TestPlace::factory()->create(['point' => $point1]); + TestPlace::factory()->create(['point' => $point2]); + + /** @var TestPlace[] $testPlaces */ + $testPlaces = TestPlace::query() + ->whereSrid('point', '=', 4326) + ->get(); + + expect($testPlaces)->toHaveCount(1); + expect($testPlaces[0]->point)->toEqual($point1); +}); From 7d01cae67745a37c8aafc20b27612baae20add86 Mon Sep 17 00:00:00 2001 From: Matan Yadaev Date: Tue, 19 Jul 2022 23:41:13 +0300 Subject: [PATCH 03/14] Add tests to Point --- tests/Objects/PointTest.php | 49 +++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/tests/Objects/PointTest.php b/tests/Objects/PointTest.php index 4b3c716..3c69614 100644 --- a/tests/Objects/PointTest.php +++ b/tests/Objects/PointTest.php @@ -16,6 +16,15 @@ expect($testPlace->point)->toEqual($point); }); +it('creates a model record with point with SRID', function (): void { + $point = new Point(180, 0, 4326); + + /** @var TestPlace $testPlace */ + $testPlace = TestPlace::factory()->create(['point' => $point]); + + expect($testPlace->point->srid)->toEqual(4326); +}); + it('creates point from JSON', function (): void { $point = new Point(180, 0); @@ -24,6 +33,46 @@ expect($pointFromJson)->toEqual($point); }); +it('creates point with SRID from JSON', function (): void { + $point = new Point(180, 0, 4326); + + $pointFromJson = Point::fromJson('{"type":"Point","coordinates":[0,180]}', 4326); + + expect($pointFromJson)->toEqual($point); +}); + +it('creates point from WKT', function (): void { + $point = new Point(180, 0); + + $pointFromWkt = Point::fromWkt('POINT(0 180)'); + + expect($pointFromWkt)->toEqual($point); +}); + +it('creates point with SRID from WKT', function (): void { + $point = new Point(180, 0, 4326); + + $pointFromWkt = Point::fromWkt('POINT(0 180)', 4326); + + expect($pointFromWkt)->toEqual($point); +}); + +it('creates point from WKB', function (): void { + $point = new Point(180, 0); + + $pointFromWkb = Point::fromWkb($point->toWkb()); + + expect($pointFromWkb)->toEqual($point); +}); + +it('creates point with SRID from WKB', function (): void { + $point = new Point(180, 0, 4326); + + $pointFromWkb = Point::fromWkb($point->toWkb(), 4326); + + expect($pointFromWkb)->toEqual($point); +}); + it('generates point json', function (): void { $point = new Point(180, 0); From 4aebccbe517949c3788d49ce83862264cf788d01 Mon Sep 17 00:00:00 2001 From: Matan Yadaev Date: Tue, 19 Jul 2022 23:46:10 +0300 Subject: [PATCH 04/14] Add tests to MultiPoint --- tests/Objects/MultiPointTest.php | 61 ++++++++++++++++++++++++++++++++ tests/Objects/PointTest.php | 32 ++++++++--------- 2 files changed, 77 insertions(+), 16 deletions(-) diff --git a/tests/Objects/MultiPointTest.php b/tests/Objects/MultiPointTest.php index 7e748da..2afa315 100644 --- a/tests/Objects/MultiPointTest.php +++ b/tests/Objects/MultiPointTest.php @@ -20,6 +20,17 @@ expect($testPlace->multi_point)->toEqual($multiPoint); }); +it('creates a model record with multi point with SRID', function (): void { + $multiPoint = new MultiPoint([ + new Point(180, 0), + ], 4326); + + /** @var TestPlace $testPlace */ + $testPlace = TestPlace::factory()->create(['multi_point' => $multiPoint]); + + expect($testPlace->multi_point->srid)->toBe(4326); +}); + it('creates multi point from JSON', function (): void { $multiPoint = new MultiPoint([ new Point(180, 0), @@ -30,6 +41,16 @@ expect($multiPointFromJson)->toEqual($multiPoint); }); +it('creates multi point with SRID from JSON', function (): void { + $multiPoint = new MultiPoint([ + new Point(180, 0), + ], 4326); + + $multiPointFromJson = MultiPoint::fromJson('{"type":"MultiPoint","coordinates":[[0,180]]}', 4326); + + expect($multiPointFromJson)->toEqual($multiPoint); +}); + it('generates multi point JSON', function (): void { $multiPoint = new MultiPoint([ new Point(180, 0), @@ -52,6 +73,46 @@ expect($multiPointFeatureCollectionJson)->toBe($expectedFeatureCollectionJson); }); +it('creates multi point from WKT', function (): void { + $multiPoint = new MultiPoint([ + new Point(180, 0), + ]); + + $multiPointFromWkt = MultiPoint::fromWkt('MULTIPOINT(0 180)'); + + expect($multiPointFromWkt)->toEqual($multiPoint); +}); + +it('creates multi point with SRID from WKT', function (): void { + $multiPoint = new MultiPoint([ + new Point(180, 0), + ], 4326); + + $multiPointFromWkt = MultiPoint::fromWkt('MULTIPOINT(0 180)', 4326); + + expect($multiPointFromWkt)->toEqual($multiPoint); +}); + +it('creates multi point from WKB', function (): void { + $multiPoint = new MultiPoint([ + new Point(180, 0), + ]); + + $multiPointFromWkb = MultiPoint::fromWkb($multiPoint->toWkb()); + + expect($multiPointFromWkb)->toEqual($multiPoint); +}); + +it('creates multi point with SRID from WKB', function (): void { + $multiPoint = new MultiPoint([ + new Point(180, 0), + ], 4326); + + $multiPointFromWkb = MultiPoint::fromWkb($multiPoint->toWkb(), 4326); + + expect($multiPointFromWkb)->toEqual($multiPoint); +}); + it('throws exception when multi point has no points', function (): void { expect(function (): void { new MultiPoint([]); diff --git a/tests/Objects/PointTest.php b/tests/Objects/PointTest.php index 3c69614..b11f93f 100644 --- a/tests/Objects/PointTest.php +++ b/tests/Objects/PointTest.php @@ -22,7 +22,7 @@ /** @var TestPlace $testPlace */ $testPlace = TestPlace::factory()->create(['point' => $point]); - expect($testPlace->point->srid)->toEqual(4326); + expect($testPlace->point->srid)->toBe(4326); }); it('creates point from JSON', function (): void { @@ -41,6 +41,21 @@ expect($pointFromJson)->toEqual($point); }); +it('generates point json', function (): void { + $point = new Point(180, 0); + + $json = $point->toJson(); + + $expectedJson = '{"type":"Point","coordinates":[0,180]}'; + expect($json)->toBe($expectedJson); +}); + +it('throws exception when creating point from invalid JSON', function (): void { + expect(function (): void { + Point::fromJson('{"type":"Point","coordinates":[]}'); + })->toThrow(InvalidArgumentException::class); +}); + it('creates point from WKT', function (): void { $point = new Point(180, 0); @@ -72,18 +87,3 @@ expect($pointFromWkb)->toEqual($point); }); - -it('generates point json', function (): void { - $point = new Point(180, 0); - - $json = $point->toJson(); - - $expectedJson = '{"type":"Point","coordinates":[0,180]}'; - expect($json)->toBe($expectedJson); -}); - -it('throws exception when creating point from invalid JSON', function (): void { - expect(function (): void { - Point::fromJson('{"type":"Point","coordinates":[]}'); - })->toThrow(InvalidArgumentException::class); -}); From 76f1aaf75c1bbf3ff694dbdb7002403c6d5eadfa Mon Sep 17 00:00:00 2001 From: Matan Yadaev Date: Tue, 19 Jul 2022 23:48:40 +0300 Subject: [PATCH 05/14] Add tests to LineString --- tests/Objects/LineStringTest.php | 67 ++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/tests/Objects/LineStringTest.php b/tests/Objects/LineStringTest.php index 7981c33..46c0d1c 100644 --- a/tests/Objects/LineStringTest.php +++ b/tests/Objects/LineStringTest.php @@ -21,6 +21,18 @@ expect($testPlace->line_string)->toEqual($lineString); }); +it('creates a model record with line string with SRID', function (): void { + $lineString = new LineString([ + new Point(180, 0), + new Point(179, 1), + ], 4326); + + /** @var TestPlace $testPlace */ + $testPlace = TestPlace::factory()->create(['line_string' => $lineString]); + + expect($testPlace->line_string->srid)->toBe(4326); +}); + it('creates line string from JSON', function (): void { $lineString = new LineString([ new Point(180, 0), @@ -32,6 +44,17 @@ expect($lineStringFromJson)->toEqual($lineString); }); +it('creates line string with SRID from JSON', function (): void { + $lineString = new LineString([ + new Point(180, 0), + new Point(179, 1), + ], 4326); + + $lineStringFromJson = LineString::fromJson('{"type":"LineString","coordinates":[[0,180],[1,179]]}', 4326); + + expect($lineStringFromJson)->toEqual($lineString); +}); + it('generates line string JSON', function (): void { $lineString = new LineString([ new Point(180, 0), @@ -56,6 +79,50 @@ expect($featureCollectionJson)->toBe($expectedFeatureCollectionJson); }); +it('creates line string from WKT', function (): void { + $lineString = new LineString([ + new Point(180, 0), + new Point(179, 1), + ]); + + $lineStringFromWkt = LineString::fromWkt('LINESTRING(0 180,1 179)'); + + expect($lineStringFromWkt)->toEqual($lineString); +}); + +it('creates line string with SRID from WKT', function (): void { + $lineString = new LineString([ + new Point(180, 0), + new Point(179, 1), + ], 4326); + + $lineStringFromWkt = LineString::fromWkt('LINESTRING(0 180,1 179)', 4326); + + expect($lineStringFromWkt)->toEqual($lineString); +}); + +it('creates line string from WKB', function (): void { + $lineString = new LineString([ + new Point(180, 0), + new Point(179, 1), + ]); + + $lineStringFromWkb = LineString::fromWkb($lineString->toWkb()); + + expect($lineStringFromWkb)->toEqual($lineString); +}); + +it('creates line string with SRID from WKB', function (): void { + $lineString = new LineString([ + new Point(180, 0), + new Point(179, 1), + ], 4326); + + $lineStringFromWkb = LineString::fromWkb($lineString->toWkb(), 4326); + + expect($lineStringFromWkb)->toEqual($lineString); +}); + it('throws exception when line string has less than two points', function (): void { expect(function (): void { new LineString([ From a93fccc544a34ee43dd5b919fc150ccf8abfba53 Mon Sep 17 00:00:00 2001 From: Matan Yadaev Date: Tue, 19 Jul 2022 23:50:52 +0300 Subject: [PATCH 06/14] Add tests to MultiLineString --- tests/Objects/MultiLineStringTest.php | 79 +++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/tests/Objects/MultiLineStringTest.php b/tests/Objects/MultiLineStringTest.php index 6767163..ace012f 100644 --- a/tests/Objects/MultiLineStringTest.php +++ b/tests/Objects/MultiLineStringTest.php @@ -23,6 +23,20 @@ expect($testPlace->multi_line_string)->toEqual($multiLineString); }); +it('creates a model record with multi line string with SRID', function (): void { + $multiLineString = new MultiLineString([ + new LineString([ + new Point(180, 0), + new Point(179, 1), + ]), + ], 4326); + + /** @var TestPlace $testPlace */ + $testPlace = TestPlace::factory()->create(['multi_line_string' => $multiLineString]); + + expect($testPlace->multi_line_string->srid)->toBe(4326); +}); + it('creates multi line string from JSON', function (): void { $multiLineString = new MultiLineString([ new LineString([ @@ -36,6 +50,19 @@ expect($multiLineStringFromJson)->toEqual($multiLineString); }); +it('creates multi line string with SRID from JSON', function (): void { + $multiLineString = new MultiLineString([ + new LineString([ + new Point(180, 0), + new Point(179, 1), + ]), + ], 4326); + + $multiLineStringFromJson = MultiLineString::fromJson('{"type":"MultiLineString","coordinates":[[[0,180],[1,179]]]}', 4326); + + expect($multiLineStringFromJson)->toEqual($multiLineString); +}); + it('generates multi line string JSON', function (): void { $multiLineString = new MultiLineString([ new LineString([ @@ -64,6 +91,58 @@ expect($featureCollectionJson)->toBe($expectedFeatureCollectionJson); }); +it('creates multi line string from WKT', function (): void { + $multiLineString = new MultiLineString([ + new LineString([ + new Point(180, 0), + new Point(179, 1), + ]), + ]); + + $multiLineStringFromWkt = MultiLineString::fromWkt('MULTILINESTRING((0 180,1 179))',); + + expect($multiLineStringFromWkt)->toEqual($multiLineString); +}); + +it('creates multi line string with SRID from WKT', function (): void { + $multiLineString = new MultiLineString([ + new LineString([ + new Point(180, 0), + new Point(179, 1), + ]), + ], 4326); + + $multiLineStringFromWkt = MultiLineString::fromWkt('MULTILINESTRING((0 180,1 179))', 4326); + + expect($multiLineStringFromWkt)->toEqual($multiLineString); +}); + +it('creates multi line string from WKB', function (): void { + $multiLineString = new MultiLineString([ + new LineString([ + new Point(180, 0), + new Point(179, 1), + ]), + ]); + + $multiLineStringFromWkb = MultiLineString::fromWkb($multiLineString->toWkb(),); + + expect($multiLineStringFromWkb)->toEqual($multiLineString); +}); + +it('creates multi line string with SRID from WKB', function (): void { + $multiLineString = new MultiLineString([ + new LineString([ + new Point(180, 0), + new Point(179, 1), + ]), + ], 4326); + + $multiLineStringFromWkb = MultiLineString::fromWkb($multiLineString->toWkb(), 4326); + + expect($multiLineStringFromWkb)->toEqual($multiLineString); +}); + it('throws exception when multi line string has no line strings', function (): void { expect(function (): void { new MultiLineString([]); From b03fdbe060bbb659fe6973695faf301addddbae7 Mon Sep 17 00:00:00 2001 From: Matan Yadaev Date: Tue, 19 Jul 2022 23:52:41 +0300 Subject: [PATCH 07/14] Add tests to Polygon --- tests/Objects/PolygonTest.php | 97 +++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/tests/Objects/PolygonTest.php b/tests/Objects/PolygonTest.php index 9b910d6..f00e4cc 100644 --- a/tests/Objects/PolygonTest.php +++ b/tests/Objects/PolygonTest.php @@ -26,6 +26,23 @@ expect($testPlace->polygon)->toEqual($polygon); }); +it('creates a model record with polygon with SRID', function (): void { + $polygon = new Polygon([ + new LineString([ + new Point(180, 0), + new Point(179, 1), + new Point(178, 2), + new Point(177, 3), + new Point(180, 0), + ]), + ], 4326); + + /** @var TestPlace $testPlace */ + $testPlace = TestPlace::factory()->create(['polygon' => $polygon]); + + expect($testPlace->polygon->srid)->toBe(4326); +}); + it('creates polygon from JSON', function (): void { $polygon = new Polygon([ new LineString([ @@ -42,6 +59,22 @@ expect($polygonFromJson)->toEqual($polygon); }); +it('creates polygon with SRID from JSON', function (): void { + $polygon = new Polygon([ + new LineString([ + new Point(180, 0), + new Point(179, 1), + new Point(178, 2), + new Point(177, 3), + new Point(180, 0), + ]), + ], 4326); + + $polygonFromJson = Polygon::fromJson('{"type":"Polygon","coordinates":[[[0,180],[1,179],[2,178],[3,177],[0,180]]]}', 4326); + + expect($polygonFromJson)->toEqual($polygon); +}); + it('generates polygon JSON', function (): void { $polygon = new Polygon([ new LineString([ @@ -76,6 +109,70 @@ expect($featureCollectionJson)->toBe($expectedFeatureCollectionJson); }); +it('creates polygon from WKT', function (): void { + $polygon = new Polygon([ + new LineString([ + new Point(180, 0), + new Point(179, 1), + new Point(178, 2), + new Point(177, 3), + new Point(180, 0), + ]), + ]); + + $polygonFromWkt = Polygon::fromWkt('POLYGON((0 180,1 179,2 178,3 177,0 180))'); + + expect($polygonFromWkt)->toEqual($polygon); +}); + +it('creates polygon with SRID from WKT', function (): void { + $polygon = new Polygon([ + new LineString([ + new Point(180, 0), + new Point(179, 1), + new Point(178, 2), + new Point(177, 3), + new Point(180, 0), + ]), + ], 4326); + + $polygonFromWkt = Polygon::fromWkt('POLYGON((0 180,1 179,2 178,3 177,0 180))', 4326); + + expect($polygonFromWkt)->toEqual($polygon); +}); + +it('creates polygon from WKB', function (): void { + $polygon = new Polygon([ + new LineString([ + new Point(180, 0), + new Point(179, 1), + new Point(178, 2), + new Point(177, 3), + new Point(180, 0), + ]), + ]); + + $polygonFromWkb = Polygon::fromWkb($polygon->toWkb()); + + expect($polygonFromWkb)->toEqual($polygon); +}); + +it('creates polygon with SRID from WKB', function (): void { + $polygon = new Polygon([ + new LineString([ + new Point(180, 0), + new Point(179, 1), + new Point(178, 2), + new Point(177, 3), + new Point(180, 0), + ]), + ], 4326); + + $polygonFromWkb = Polygon::fromWkb($polygon->toWkb(), 4326); + + expect($polygonFromWkb)->toEqual($polygon); +}); + it('throws exception when polygon has no line strings', function (): void { expect(function (): void { new Polygon([]); From 6a6b2c72560dcbb6589793c4be192aa33179471e Mon Sep 17 00:00:00 2001 From: Matan Yadaev Date: Tue, 19 Jul 2022 23:54:48 +0300 Subject: [PATCH 08/14] Add tests to MultiPolygon --- tests/Objects/MultiPolygonTest.php | 109 +++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/tests/Objects/MultiPolygonTest.php b/tests/Objects/MultiPolygonTest.php index a1d666e..124b6fa 100644 --- a/tests/Objects/MultiPolygonTest.php +++ b/tests/Objects/MultiPolygonTest.php @@ -29,6 +29,25 @@ expect($testPlace->multi_polygon)->toEqual($multiPolygon); }); +it('creates a model record with multi polygon with SRID', function (): void { + $multiPolygon = new MultiPolygon([ + new Polygon([ + new LineString([ + new Point(180, 0), + new Point(179, 1), + new Point(178, 2), + new Point(177, 3), + new Point(180, 0), + ]), + ]), + ], 4326); + + /** @var TestPlace $testPlace */ + $testPlace = TestPlace::factory()->create(['multi_polygon' => $multiPolygon]); + + expect($testPlace->multi_polygon->srid)->toBe(4326); +}); + it('creates multi polygon from JSON', function (): void { $multiPolygon = new MultiPolygon([ new Polygon([ @@ -47,6 +66,24 @@ expect($multiPolygonFromJson)->toEqual($multiPolygon); }); +it('creates multi polygon with SRID from JSON', function (): void { + $multiPolygon = new MultiPolygon([ + new Polygon([ + new LineString([ + new Point(180, 0), + new Point(179, 1), + new Point(178, 2), + new Point(177, 3), + new Point(180, 0), + ]), + ]), + ], 4326); + + $multiPolygonFromJson = MultiPolygon::fromJson('{"type":"MultiPolygon","coordinates":[[[[0,180],[1,179],[2,178],[3,177],[0,180]]]]}', 4326); + + expect($multiPolygonFromJson)->toEqual($multiPolygon); +}); + it('generates multi polygon JSON', function (): void { $multiPolygon = new MultiPolygon([ new Polygon([ @@ -85,6 +122,78 @@ expect($featureCollectionJson)->toBe($expectedFeatureCollectionJson); }); +it('creates multi polygon from WKT', function (): void { + $multiPolygon = new MultiPolygon([ + new Polygon([ + new LineString([ + new Point(180, 0), + new Point(179, 1), + new Point(178, 2), + new Point(177, 3), + new Point(180, 0), + ]), + ]), + ]); + + $multiPolygonFromWkt = MultiPolygon::fromWkt('MULTIPOLYGON(((0 180,1 179,2 178,3 177,0 180)))'); + + expect($multiPolygonFromWkt)->toEqual($multiPolygon); +}); + +it('creates multi polygon with SRID from WKT', function (): void { + $multiPolygon = new MultiPolygon([ + new Polygon([ + new LineString([ + new Point(180, 0), + new Point(179, 1), + new Point(178, 2), + new Point(177, 3), + new Point(180, 0), + ]), + ]), + ], 4326); + + $multiPolygonFromWkt = MultiPolygon::fromWkt('MULTIPOLYGON(((0 180,1 179,2 178,3 177,0 180)))', 4326); + + expect($multiPolygonFromWkt)->toEqual($multiPolygon); +}); + +it('creates multi polygon from WKB', function (): void { + $multiPolygon = new MultiPolygon([ + new Polygon([ + new LineString([ + new Point(180, 0), + new Point(179, 1), + new Point(178, 2), + new Point(177, 3), + new Point(180, 0), + ]), + ]), + ]); + + $multiPolygonFromWkb = MultiPolygon::fromWkt($multiPolygon->toWkb()); + + expect($multiPolygonFromWkb)->toEqual($multiPolygon); +}); + +it('creates multi polygon with SRID from WKB', function (): void { + $multiPolygon = new MultiPolygon([ + new Polygon([ + new LineString([ + new Point(180, 0), + new Point(179, 1), + new Point(178, 2), + new Point(177, 3), + new Point(180, 0), + ]), + ]), + ], 4326); + + $multiPolygonFromWkb = MultiPolygon::fromWkt($multiPolygon->toWkb(), 4326); + + expect($multiPolygonFromWkb)->toEqual($multiPolygon); +}); + it('throws exception when multi polygon has no polygons', function (): void { expect(function (): void { new MultiPolygon([]); From f80a2a721f662ea39d5f12b3744bbecf95d62395 Mon Sep 17 00:00:00 2001 From: Matan Yadaev Date: Tue, 19 Jul 2022 23:57:07 +0300 Subject: [PATCH 09/14] Add tests to GeometryCollection --- tests/Objects/GeometryCollectionTest.php | 115 +++++++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/tests/Objects/GeometryCollectionTest.php b/tests/Objects/GeometryCollectionTest.php index 5ffa774..22c1c2a 100644 --- a/tests/Objects/GeometryCollectionTest.php +++ b/tests/Objects/GeometryCollectionTest.php @@ -30,6 +30,26 @@ expect($testPlace->geometry_collection)->toEqual($geometryCollection); }); +it('creates a model record with geometry collection with SRID', function (): void { + $geometryCollection = new GeometryCollection([ + new Polygon([ + new LineString([ + new Point(180, 0), + new Point(179, 1), + new Point(178, 2), + new Point(177, 3), + new Point(180, 0), + ]), + ]), + new Point(180, 0), + ], 4326); + + /** @var TestPlace $testPlace */ + $testPlace = TestPlace::factory()->create(['geometry_collection' => $geometryCollection]); + + expect($testPlace->geometry_collection->srid)->toBe(4326); +}); + it('creates geometry collection from JSON', function (): void { $geometryCollection = new GeometryCollection([ new Polygon([ @@ -49,6 +69,25 @@ expect($geometryCollectionFromJson)->toEqual($geometryCollection); }); +it('creates geometry collection with SRID from JSON', function (): void { + $geometryCollection = new GeometryCollection([ + new Polygon([ + new LineString([ + new Point(180, 0), + new Point(179, 1), + new Point(178, 2), + new Point(177, 3), + new Point(180, 0), + ]), + ]), + new Point(180, 0), + ], 4326); + + $geometryCollectionFromJson = GeometryCollection::fromJson('{"type":"GeometryCollection","geometries":[{"type":"Polygon","coordinates":[[[0,180],[1,179],[2,178],[3,177],[0,180]]]},{"type":"Point","coordinates":[0,180]}]}', 4326); + + expect($geometryCollectionFromJson)->toEqual($geometryCollection); +}); + it('creates geometry collection from feature collection JSON', function (): void { $geometryCollection = new GeometryCollection([ new Polygon([ @@ -108,6 +147,82 @@ expect($featureCollectionJson)->toBe($expectedFeatureCollectionJson); }); +it('creates geometry collection from WKT', function (): void { + $geometryCollection = new GeometryCollection([ + new Polygon([ + new LineString([ + new Point(180, 0), + new Point(179, 1), + new Point(178, 2), + new Point(177, 3), + new Point(180, 0), + ]), + ]), + new Point(180, 0), + ]); + + $geometryCollectionFromWkt = GeometryCollection::fromWkt('GEOMETRYCOLLECTION(POLYGON((0 180,1 179,2 178,3 177,0 180)),POINT(0 180))'); + + expect($geometryCollectionFromWkt)->toEqual($geometryCollection); +}); + +it('creates geometry collection with SRID from WKT', function (): void { + $geometryCollection = new GeometryCollection([ + new Polygon([ + new LineString([ + new Point(180, 0), + new Point(179, 1), + new Point(178, 2), + new Point(177, 3), + new Point(180, 0), + ]), + ]), + new Point(180, 0), + ], 4326); + + $geometryCollectionFromWkt = GeometryCollection::fromWkt('GEOMETRYCOLLECTION(POLYGON((0 180,1 179,2 178,3 177,0 180)),POINT(0 180))', 4326); + + expect($geometryCollectionFromWkt)->toEqual($geometryCollection); +}); + +it('creates geometry collection from WKB', function (): void { + $geometryCollection = new GeometryCollection([ + new Polygon([ + new LineString([ + new Point(180, 0), + new Point(179, 1), + new Point(178, 2), + new Point(177, 3), + new Point(180, 0), + ]), + ]), + new Point(180, 0), + ]); + + $geometryCollectionFromWkb = GeometryCollection::fromWkb($geometryCollection->toWkb()); + + expect($geometryCollectionFromWkb)->toEqual($geometryCollection); +}); + +it('creates geometry collection with SRID from WKB', function (): void { + $geometryCollection = new GeometryCollection([ + new Polygon([ + new LineString([ + new Point(180, 0), + new Point(179, 1), + new Point(178, 2), + new Point(177, 3), + new Point(180, 0), + ]), + ]), + new Point(180, 0), + ], 4326); + + $geometryCollectionFromWkb = GeometryCollection::fromWkb($geometryCollection->toWkb(), 4326); + + expect($geometryCollectionFromWkb)->toEqual($geometryCollection); +}); + it('does not throw exception when geometry collection has no geometries', function (): void { $geometryCollection = new GeometryCollection([]); From 1f5c2d542588ab39c8d2b1eba5547bbc9f0cb63c Mon Sep 17 00:00:00 2001 From: Matan Yadaev Date: Tue, 19 Jul 2022 23:58:31 +0300 Subject: [PATCH 10/14] Implement `whereSrid` --- src/SpatialBuilder.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/SpatialBuilder.php b/src/SpatialBuilder.php index 0b316e8..2e1729b 100644 --- a/src/SpatialBuilder.php +++ b/src/SpatialBuilder.php @@ -242,6 +242,24 @@ public function whereEquals(string $column, Geometry|string $geometryOrColumn): return $this; } + public function whereSrid( + string $column, + string $operator, + int|float $value + ): self + { + $this->whereRaw( + sprintf( + 'ST_SRID(%s) %s %s', + "`{$column}`", + $operator, + $value, + ) + ); + + return $this; + } + protected function toExpression(Geometry|string $geometryOrColumn): Expression { if ($geometryOrColumn instanceof Geometry) { From 29c28270fb2f19ea52596c99e5b4123b496bb300 Mon Sep 17 00:00:00 2001 From: Matan Yadaev Date: Wed, 20 Jul 2022 00:35:54 +0300 Subject: [PATCH 11/14] Implement SRID --- src/Factory.php | 21 +++++++------ src/GeometryCast.php | 38 ++++++++++++++---------- src/Objects/Geometry.php | 32 ++++++++++---------- src/Objects/GeometryCollection.php | 8 +++-- src/Objects/MultiLineString.php | 5 ++-- src/Objects/MultiPolygon.php | 5 ++-- src/Objects/Point.php | 3 +- src/Objects/PointCollection.php | 5 ++-- tests/GeometryCastTest.php | 4 +-- tests/Objects/GeometryCollectionTest.php | 6 ++-- tests/Objects/LineStringTest.php | 6 ++-- tests/Objects/MultiLineStringTest.php | 8 ++--- tests/Objects/MultiPointTest.php | 2 +- tests/Objects/MultiPolygonTest.php | 8 ++--- tests/Objects/PointTest.php | 2 +- tests/Objects/PolygonTest.php | 6 ++-- 16 files changed, 86 insertions(+), 73 deletions(-) diff --git a/src/Factory.php b/src/Factory.php index e2dbc15..65cd6c5 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -28,7 +28,6 @@ class Factory public static function parse(string $value, bool $isWkb): Geometry { if ($isWkb) { - // MySQL adds 4 NULL bytes at the start of the WKB $value = substr($value, 4); } @@ -46,14 +45,14 @@ public static function parse(string $value, bool $isWkb): Geometry protected static function createFromGeometry(geoPHPGeometry $geometry): Geometry { + $srid = is_int($geometry->getSRID()) ? $geometry->getSRID() : 0; + if ($geometry instanceof geoPHPPoint) { if ($geometry->coords[0] === null || $geometry->coords[1] === null) { - if (! isset($geoPHPGeometry) || ! $geoPHPGeometry) { - throw new InvalidArgumentException('Invalid spatial value'); - } + throw new InvalidArgumentException('Invalid spatial value'); } - return new Point($geometry->coords[1], $geometry->coords[0]); + return new Point($geometry->coords[1], $geometry->coords[0], $srid); } /** @var geoPHPGeometryCollection $geometry */ @@ -63,25 +62,25 @@ protected static function createFromGeometry(geoPHPGeometry $geometry): Geometry }); if ($geometry::class === geoPHPMultiPoint::class) { - return new MultiPoint($components); + return new MultiPoint($components, $srid); } if ($geometry::class === geoPHPLineString::class) { - return new LineString($components); + return new LineString($components, $srid); } if ($geometry::class === geoPHPPolygon::class) { - return new Polygon($components); + return new Polygon($components, $srid); } if ($geometry::class === geoPHPMultiLineString::class) { - return new MultiLineString($components); + return new MultiLineString($components, $srid); } if ($geometry::class === geoPHPMultiPolygon::class) { - return new MultiPolygon($components); + return new MultiPolygon($components, $srid); } - return new GeometryCollection($components); + return new GeometryCollection($components, $srid); } } diff --git a/src/GeometryCast.php b/src/GeometryCast.php index 6275c5f..6ea6508 100644 --- a/src/GeometryCast.php +++ b/src/GeometryCast.php @@ -27,56 +27,64 @@ public function __construct(string $className) /** * @param Model $model * @param string $key - * @param string|Expression|null $wkbOrWKt + * @param string|Expression|null $value * @param array $attributes * @return Geometry|null */ - public function get($model, string $key, $wkbOrWKt, array $attributes): ?Geometry + public function get($model, string $key, $value, array $attributes): ?Geometry { - if (! $wkbOrWKt) { + if (! $value) { return null; } - if ($wkbOrWKt instanceof Expression) { - $wkt = $this->extractWktFromExpression($wkbOrWKt); + if ($value instanceof Expression) { + $wkt = $this->extractWktFromExpression($value); + $srid = $this->extractSridFromExpression($value); - return $this->className::fromWkt($wkt); + return $this->className::fromWkt($wkt, $srid); } - return $this->className::fromWkb($wkbOrWKt); + return $this->className::fromWkb($value); } /** * @param Model $model * @param string $key - * @param Geometry|mixed|null $geometry + * @param Geometry|mixed|null $value * @param array $attributes * @return Expression|null * * @throws InvalidArgumentException */ - public function set($model, string $key, $geometry, array $attributes): Expression|null + public function set($model, string $key, $value, array $attributes): Expression|null { - if (! $geometry) { + if (! $value) { return null; } - if (! ($geometry instanceof $this->className)) { - $geometryType = is_object($geometry) ? $geometry::class : gettype($geometry); + if (! ($value instanceof $this->className)) { + $geometryType = is_object($value) ? $value::class : gettype($value); throw new InvalidArgumentException( sprintf('Expected %s, %s given.', static::class, $geometryType) ); } - $wkt = $geometry->toWkt(withFunction: true); + $wkt = $value->toWkt(); - return DB::raw("ST_GeomFromText('{$wkt}')"); + return DB::raw("ST_GeomFromText('{$wkt}', {$value->srid})"); } private function extractWktFromExpression(Expression $expression): string { - preg_match('/ST_GeomFromText\(\'(.+)\'\)/', (string) $expression, $match); + preg_match('/ST_GeomFromText\(\'(.+)\', .+\)/', (string) $expression, $match); return $match[1]; } + + private function extractSridFromExpression(Expression $expression): int + { + preg_match('/ST_GeomFromText\(\'.+\', (.+)\)/', (string) $expression, $match); + + return (int)$match[1]; + } } diff --git a/src/Objects/Geometry.php b/src/Objects/Geometry.php index 3f9f167..b4df53e 100644 --- a/src/Objects/Geometry.php +++ b/src/Objects/Geometry.php @@ -18,6 +18,8 @@ abstract class Geometry implements Castable, Arrayable, Jsonable, JsonSerializable { + public int $srid = 0; + abstract public function toWkt(bool $withFunction = true): string; /** @@ -33,21 +35,29 @@ public function toJson($options = 0): string public function toWkb(): string { - $geoPHPGeometry = geoPHP::load($this->toWkt()); + /** @var \Point $geoPHPGeometry */ + $geoPHPGeometry = geoPHP::load($this->toJson()); + + $sridInBinary = pack('L', $this->srid); // @phpstan-ignore-next-line - return (new geoPHPWkb)->write($geoPHPGeometry, true); + return $sridInBinary . (new geoPHPWkb)->write($geoPHPGeometry); } /** * @param string $wkb + * @param int $srid * @return static * * @throws InvalidArgumentException */ public static function fromWkb(string $wkb): static { + $srid = substr($wkb, 0, 4); + $srid = unpack('L', $srid)[1]; + $geometry = Factory::parse($wkb, true); + $geometry->srid = $srid; if (! ($geometry instanceof static)) { throw new InvalidArgumentException( @@ -58,15 +68,10 @@ public static function fromWkb(string $wkb): static return $geometry; } - /** - * @param string $wkt - * @return static - * - * @throws InvalidArgumentException - */ - public static function fromWkt(string $wkt): static + public static function fromWkt(string $wkt, int $srid = 0): static { $geometry = Factory::parse($wkt, false); + $geometry->srid = $srid; if (! ($geometry instanceof static)) { throw new InvalidArgumentException( @@ -77,15 +82,10 @@ public static function fromWkt(string $wkt): static return $geometry; } - /** - * @param string $geoJson - * @return static - * - * @throws InvalidArgumentException - */ - public static function fromJson(string $geoJson): static + public static function fromJson(string $geoJson, int $srid = 0): static { $geometry = Factory::parse($geoJson, false); + $geometry->srid = $srid; if (! ($geometry instanceof static)) { throw new InvalidArgumentException( diff --git a/src/Objects/GeometryCollection.php b/src/Objects/GeometryCollection.php index a15603a..19a77bc 100644 --- a/src/Objects/GeometryCollection.php +++ b/src/Objects/GeometryCollection.php @@ -20,16 +20,18 @@ class GeometryCollection extends Geometry implements ArrayAccess /** * @param Collection|array $geometries + * @param int $srid * * @throws InvalidArgumentException */ - public function __construct(Collection|array $geometries) + public function __construct(Collection|array $geometries, int $srid = 0) { if (is_array($geometries)) { $geometries = collect($geometries); } $this->geometries = $geometries; + $this->srid = $srid; $this->validateGeometriesType(); $this->validateGeometriesCount(); @@ -154,9 +156,9 @@ protected function toCollectionWkt(bool $withFunction): string { return $this->geometries ->map(static function (Geometry $geometry) use ($withFunction): string { - return (string) $geometry->toWkt($withFunction); + return $geometry->toWkt($withFunction); }) - ->join(','); + ->join(', '); } /** diff --git a/src/Objects/MultiLineString.php b/src/Objects/MultiLineString.php index dfc3fba..6d16e49 100644 --- a/src/Objects/MultiLineString.php +++ b/src/Objects/MultiLineString.php @@ -22,13 +22,14 @@ class MultiLineString extends GeometryCollection /** * @param Collection|array $geometries + * @param int $srid * * @throws InvalidArgumentException */ - public function __construct(Collection|array $geometries) + public function __construct(Collection|array $geometries, int $srid = 0) { // @phpstan-ignore-next-line - parent::__construct($geometries); + parent::__construct($geometries, $srid); } public function toWkt(bool $withFunction = true): string diff --git a/src/Objects/MultiPolygon.php b/src/Objects/MultiPolygon.php index a038860..d86fabd 100644 --- a/src/Objects/MultiPolygon.php +++ b/src/Objects/MultiPolygon.php @@ -22,13 +22,14 @@ class MultiPolygon extends GeometryCollection /** * @param Collection|array $geometries + * @param int $srid * * @throws InvalidArgumentException */ - public function __construct(Collection|array $geometries) + public function __construct(Collection|array $geometries, int $srid = 0) { // @phpstan-ignore-next-line - parent::__construct($geometries); + parent::__construct($geometries, $srid); } public function toWkt(bool $withFunction = true): string diff --git a/src/Objects/Point.php b/src/Objects/Point.php index 15a1888..e5d65a1 100644 --- a/src/Objects/Point.php +++ b/src/Objects/Point.php @@ -10,10 +10,11 @@ class Point extends Geometry public float $longitude; - public function __construct(float $latitude, float $longitude) + public function __construct(float $latitude, float $longitude, int $srid = 0) { $this->latitude = $latitude; $this->longitude = $longitude; + $this->srid = $srid; } public function toWkt(bool $withFunction = true): string diff --git a/src/Objects/PointCollection.php b/src/Objects/PointCollection.php index f04a3f9..71a807a 100644 --- a/src/Objects/PointCollection.php +++ b/src/Objects/PointCollection.php @@ -20,12 +20,13 @@ abstract class PointCollection extends GeometryCollection /** * @param Collection|array $geometries + * @param int $srid * * @throws InvalidArgumentException */ - public function __construct(Collection|array $geometries) + public function __construct(Collection|array $geometries, int $srid = 0) { // @phpstan-ignore-next-line - parent::__construct($geometries); + parent::__construct($geometries, $srid); } } diff --git a/tests/GeometryCastTest.php b/tests/GeometryCastTest.php index 43b4d75..b1ebcf4 100644 --- a/tests/GeometryCastTest.php +++ b/tests/GeometryCastTest.php @@ -38,8 +38,8 @@ }); it('gets original geometry field', function (): void { - $point = new Point(180, 0); - $point2 = new Point(0, 0); + $point = new Point(180, 0, 4326); + $point2 = new Point(0, 0, 4326); /** @var TestPlace $testPlace */ $testPlace = TestPlace::factory()->create(['point' => $point]); diff --git a/tests/Objects/GeometryCollectionTest.php b/tests/Objects/GeometryCollectionTest.php index 22c1c2a..9ffede0 100644 --- a/tests/Objects/GeometryCollectionTest.php +++ b/tests/Objects/GeometryCollectionTest.php @@ -161,7 +161,7 @@ new Point(180, 0), ]); - $geometryCollectionFromWkt = GeometryCollection::fromWkt('GEOMETRYCOLLECTION(POLYGON((0 180,1 179,2 178,3 177,0 180)),POINT(0 180))'); + $geometryCollectionFromWkt = GeometryCollection::fromWkt('GEOMETRYCOLLECTION(POLYGON((0 180, 1 179, 2 178, 3 177, 0 180)),POINT(0 180))'); expect($geometryCollectionFromWkt)->toEqual($geometryCollection); }); @@ -180,7 +180,7 @@ new Point(180, 0), ], 4326); - $geometryCollectionFromWkt = GeometryCollection::fromWkt('GEOMETRYCOLLECTION(POLYGON((0 180,1 179,2 178,3 177,0 180)),POINT(0 180))', 4326); + $geometryCollectionFromWkt = GeometryCollection::fromWkt('GEOMETRYCOLLECTION(POLYGON((0 180, 1 179, 2 178, 3 177, 0 180)),POINT(0 180))', 4326); expect($geometryCollectionFromWkt)->toEqual($geometryCollection); }); @@ -218,7 +218,7 @@ new Point(180, 0), ], 4326); - $geometryCollectionFromWkb = GeometryCollection::fromWkb($geometryCollection->toWkb(), 4326); + $geometryCollectionFromWkb = GeometryCollection::fromWkb($geometryCollection->toWkb()); expect($geometryCollectionFromWkb)->toEqual($geometryCollection); }); diff --git a/tests/Objects/LineStringTest.php b/tests/Objects/LineStringTest.php index 46c0d1c..a0abe7b 100644 --- a/tests/Objects/LineStringTest.php +++ b/tests/Objects/LineStringTest.php @@ -85,7 +85,7 @@ new Point(179, 1), ]); - $lineStringFromWkt = LineString::fromWkt('LINESTRING(0 180,1 179)'); + $lineStringFromWkt = LineString::fromWkt('LINESTRING(0 180, 1 179)'); expect($lineStringFromWkt)->toEqual($lineString); }); @@ -96,7 +96,7 @@ new Point(179, 1), ], 4326); - $lineStringFromWkt = LineString::fromWkt('LINESTRING(0 180,1 179)', 4326); + $lineStringFromWkt = LineString::fromWkt('LINESTRING(0 180, 1 179)', 4326); expect($lineStringFromWkt)->toEqual($lineString); }); @@ -118,7 +118,7 @@ new Point(179, 1), ], 4326); - $lineStringFromWkb = LineString::fromWkb($lineString->toWkb(), 4326); + $lineStringFromWkb = LineString::fromWkb($lineString->toWkb()); expect($lineStringFromWkb)->toEqual($lineString); }); diff --git a/tests/Objects/MultiLineStringTest.php b/tests/Objects/MultiLineStringTest.php index ace012f..3e0f10b 100644 --- a/tests/Objects/MultiLineStringTest.php +++ b/tests/Objects/MultiLineStringTest.php @@ -99,7 +99,7 @@ ]), ]); - $multiLineStringFromWkt = MultiLineString::fromWkt('MULTILINESTRING((0 180,1 179))',); + $multiLineStringFromWkt = MultiLineString::fromWkt('MULTILINESTRING((0 180, 1 179))',); expect($multiLineStringFromWkt)->toEqual($multiLineString); }); @@ -112,7 +112,7 @@ ]), ], 4326); - $multiLineStringFromWkt = MultiLineString::fromWkt('MULTILINESTRING((0 180,1 179))', 4326); + $multiLineStringFromWkt = MultiLineString::fromWkt('MULTILINESTRING((0 180, 1 179))', 4326); expect($multiLineStringFromWkt)->toEqual($multiLineString); }); @@ -125,7 +125,7 @@ ]), ]); - $multiLineStringFromWkb = MultiLineString::fromWkb($multiLineString->toWkb(),); + $multiLineStringFromWkb = MultiLineString::fromWkb($multiLineString->toWkb()); expect($multiLineStringFromWkb)->toEqual($multiLineString); }); @@ -138,7 +138,7 @@ ]), ], 4326); - $multiLineStringFromWkb = MultiLineString::fromWkb($multiLineString->toWkb(), 4326); + $multiLineStringFromWkb = MultiLineString::fromWkb($multiLineString->toWkb()); expect($multiLineStringFromWkb)->toEqual($multiLineString); }); diff --git a/tests/Objects/MultiPointTest.php b/tests/Objects/MultiPointTest.php index 2afa315..04dd058 100644 --- a/tests/Objects/MultiPointTest.php +++ b/tests/Objects/MultiPointTest.php @@ -108,7 +108,7 @@ new Point(180, 0), ], 4326); - $multiPointFromWkb = MultiPoint::fromWkb($multiPoint->toWkb(), 4326); + $multiPointFromWkb = MultiPoint::fromWkb($multiPoint->toWkb()); expect($multiPointFromWkb)->toEqual($multiPoint); }); diff --git a/tests/Objects/MultiPolygonTest.php b/tests/Objects/MultiPolygonTest.php index 124b6fa..07f7f64 100644 --- a/tests/Objects/MultiPolygonTest.php +++ b/tests/Objects/MultiPolygonTest.php @@ -135,7 +135,7 @@ ]), ]); - $multiPolygonFromWkt = MultiPolygon::fromWkt('MULTIPOLYGON(((0 180,1 179,2 178,3 177,0 180)))'); + $multiPolygonFromWkt = MultiPolygon::fromWkt('MULTIPOLYGON(((0 180, 1 179, 2 178, 3 177, 0 180)))'); expect($multiPolygonFromWkt)->toEqual($multiPolygon); }); @@ -153,7 +153,7 @@ ]), ], 4326); - $multiPolygonFromWkt = MultiPolygon::fromWkt('MULTIPOLYGON(((0 180,1 179,2 178,3 177,0 180)))', 4326); + $multiPolygonFromWkt = MultiPolygon::fromWkt('MULTIPOLYGON(((0 180, 1 179, 2 178, 3 177, 0 180)))', 4326); expect($multiPolygonFromWkt)->toEqual($multiPolygon); }); @@ -171,7 +171,7 @@ ]), ]); - $multiPolygonFromWkb = MultiPolygon::fromWkt($multiPolygon->toWkb()); + $multiPolygonFromWkb = MultiPolygon::fromWkb($multiPolygon->toWkb()); expect($multiPolygonFromWkb)->toEqual($multiPolygon); }); @@ -189,7 +189,7 @@ ]), ], 4326); - $multiPolygonFromWkb = MultiPolygon::fromWkt($multiPolygon->toWkb(), 4326); + $multiPolygonFromWkb = MultiPolygon::fromWkb($multiPolygon->toWkb(), 4326); expect($multiPolygonFromWkb)->toEqual($multiPolygon); }); diff --git a/tests/Objects/PointTest.php b/tests/Objects/PointTest.php index b11f93f..d486cd4 100644 --- a/tests/Objects/PointTest.php +++ b/tests/Objects/PointTest.php @@ -83,7 +83,7 @@ it('creates point with SRID from WKB', function (): void { $point = new Point(180, 0, 4326); - $pointFromWkb = Point::fromWkb($point->toWkb(), 4326); + $pointFromWkb = Point::fromWkb($point->toWkb()); expect($pointFromWkb)->toEqual($point); }); diff --git a/tests/Objects/PolygonTest.php b/tests/Objects/PolygonTest.php index f00e4cc..9923bea 100644 --- a/tests/Objects/PolygonTest.php +++ b/tests/Objects/PolygonTest.php @@ -120,7 +120,7 @@ ]), ]); - $polygonFromWkt = Polygon::fromWkt('POLYGON((0 180,1 179,2 178,3 177,0 180))'); + $polygonFromWkt = Polygon::fromWkt('POLYGON((0 180, 1 179, 2 178, 3 177, 0 180))'); expect($polygonFromWkt)->toEqual($polygon); }); @@ -136,7 +136,7 @@ ]), ], 4326); - $polygonFromWkt = Polygon::fromWkt('POLYGON((0 180,1 179,2 178,3 177,0 180))', 4326); + $polygonFromWkt = Polygon::fromWkt('POLYGON((0 180, 1 179, 2 178, 3 177, 0 180))', 4326); expect($polygonFromWkt)->toEqual($polygon); }); @@ -168,7 +168,7 @@ ]), ], 4326); - $polygonFromWkb = Polygon::fromWkb($polygon->toWkb(), 4326); + $polygonFromWkb = Polygon::fromWkb($polygon->toWkb()); expect($polygonFromWkb)->toEqual($polygon); }); From 848dc07874f5b3b22e313eec29c469f7fb0dd3fa Mon Sep 17 00:00:00 2001 From: Matan Yadaev Date: Wed, 20 Jul 2022 00:52:58 +0300 Subject: [PATCH 12/14] fixes --- src/GeometryCast.php | 2 +- src/Objects/Geometry.php | 5 ++--- tests/Objects/MultiLineStringTest.php | 2 +- tests/Objects/MultiPolygonTest.php | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/GeometryCast.php b/src/GeometryCast.php index 6ea6508..9f665cf 100644 --- a/src/GeometryCast.php +++ b/src/GeometryCast.php @@ -85,6 +85,6 @@ private function extractSridFromExpression(Expression $expression): int { preg_match('/ST_GeomFromText\(\'.+\', (.+)\)/', (string) $expression, $match); - return (int)$match[1]; + return (int) $match[1]; } } diff --git a/src/Objects/Geometry.php b/src/Objects/Geometry.php index b4df53e..bc8a57a 100644 --- a/src/Objects/Geometry.php +++ b/src/Objects/Geometry.php @@ -35,18 +35,16 @@ public function toJson($options = 0): string public function toWkb(): string { - /** @var \Point $geoPHPGeometry */ $geoPHPGeometry = geoPHP::load($this->toJson()); $sridInBinary = pack('L', $this->srid); // @phpstan-ignore-next-line - return $sridInBinary . (new geoPHPWkb)->write($geoPHPGeometry); + return $sridInBinary.(new geoPHPWkb)->write($geoPHPGeometry); } /** * @param string $wkb - * @param int $srid * @return static * * @throws InvalidArgumentException @@ -54,6 +52,7 @@ public function toWkb(): string public static function fromWkb(string $wkb): static { $srid = substr($wkb, 0, 4); + // @phpstan-ignore-next-line $srid = unpack('L', $srid)[1]; $geometry = Factory::parse($wkb, true); diff --git a/tests/Objects/MultiLineStringTest.php b/tests/Objects/MultiLineStringTest.php index 3e0f10b..68810d3 100644 --- a/tests/Objects/MultiLineStringTest.php +++ b/tests/Objects/MultiLineStringTest.php @@ -99,7 +99,7 @@ ]), ]); - $multiLineStringFromWkt = MultiLineString::fromWkt('MULTILINESTRING((0 180, 1 179))',); + $multiLineStringFromWkt = MultiLineString::fromWkt('MULTILINESTRING((0 180, 1 179))', ); expect($multiLineStringFromWkt)->toEqual($multiLineString); }); diff --git a/tests/Objects/MultiPolygonTest.php b/tests/Objects/MultiPolygonTest.php index 07f7f64..7fc0d4c 100644 --- a/tests/Objects/MultiPolygonTest.php +++ b/tests/Objects/MultiPolygonTest.php @@ -189,7 +189,7 @@ ]), ], 4326); - $multiPolygonFromWkb = MultiPolygon::fromWkb($multiPolygon->toWkb(), 4326); + $multiPolygonFromWkb = MultiPolygon::fromWkb($multiPolygon->toWkb()); expect($multiPolygonFromWkb)->toEqual($multiPolygon); }); From 65261bdf5babc1ecb4cf7401c7fa6c5cd3465506 Mon Sep 17 00:00:00 2001 From: Matan Yadaev Date: Wed, 20 Jul 2022 23:20:44 +0300 Subject: [PATCH 13/14] Fixes --- .run/{Unnamed.run.xml => Test.run.xml} | 0 src/Factory.php | 6 +----- src/Objects/Geometry.php | 26 ++++++++++++++++++++++---- 3 files changed, 23 insertions(+), 9 deletions(-) rename .run/{Unnamed.run.xml => Test.run.xml} (100%) diff --git a/.run/Unnamed.run.xml b/.run/Test.run.xml similarity index 100% rename from .run/Unnamed.run.xml rename to .run/Test.run.xml diff --git a/src/Factory.php b/src/Factory.php index 65cd6c5..f946a03 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -25,12 +25,8 @@ class Factory { - public static function parse(string $value, bool $isWkb): Geometry + public static function parse(string $value): Geometry { - if ($isWkb) { - $value = substr($value, 4); - } - try { /** @var geoPHPGeometry|false $geoPHPGeometry */ $geoPHPGeometry = geoPHP::load($value); diff --git a/src/Objects/Geometry.php b/src/Objects/Geometry.php index bc8a57a..5434313 100644 --- a/src/Objects/Geometry.php +++ b/src/Objects/Geometry.php @@ -40,7 +40,9 @@ public function toWkb(): string $sridInBinary = pack('L', $this->srid); // @phpstan-ignore-next-line - return $sridInBinary.(new geoPHPWkb)->write($geoPHPGeometry); + $wkbWithoutSrid = (new geoPHPWkb)->write($geoPHPGeometry); + + return $sridInBinary.$wkbWithoutSrid; } /** @@ -55,7 +57,9 @@ public static function fromWkb(string $wkb): static // @phpstan-ignore-next-line $srid = unpack('L', $srid)[1]; - $geometry = Factory::parse($wkb, true); + $wkb = substr($wkb, 4); + + $geometry = Factory::parse($wkb); $geometry->srid = $srid; if (! ($geometry instanceof static)) { @@ -67,9 +71,16 @@ public static function fromWkb(string $wkb): static return $geometry; } + /** + * @param string $wkt + * @param int $srid + * @return static + * + * @throws InvalidArgumentException + */ public static function fromWkt(string $wkt, int $srid = 0): static { - $geometry = Factory::parse($wkt, false); + $geometry = Factory::parse($wkt); $geometry->srid = $srid; if (! ($geometry instanceof static)) { @@ -81,9 +92,16 @@ public static function fromWkt(string $wkt, int $srid = 0): static return $geometry; } + /** + * @param string $geoJson + * @param int $srid + * @return static + * + * @throws InvalidArgumentException + */ public static function fromJson(string $geoJson, int $srid = 0): static { - $geometry = Factory::parse($geoJson, false); + $geometry = Factory::parse($geoJson); $geometry->srid = $srid; if (! ($geometry instanceof static)) { From 84cc5383af842583c07f05c5f394f41b74f4e4a2 Mon Sep 17 00:00:00 2001 From: Matan Yadaev Date: Wed, 20 Jul 2022 23:43:23 +0300 Subject: [PATCH 14/14] update docs --- API.md | 51 +++++++++++++++++++++++++++++++++++++++------------ README.md | 26 ++++++++++++++++---------- 2 files changed, 55 insertions(+), 22 deletions(-) diff --git a/API.md b/API.md index 95c0552..c256179 100644 --- a/API.md +++ b/API.md @@ -1,23 +1,28 @@ # API -## Available spatial classes +## Available geometry classes -* `Point(float $latitude, float $longitude)` - [MySQL Point](https://dev.mysql.com/doc/refman/8.0/en/gis-class-point.html) -* `MultiPoint(Point[] | Collection)` - [MySQL MultiPoint](https://dev.mysql.com/doc/refman/8.0/en/gis-class-multipoint.html) -* `LineString(Point[] | Collection)` - [MySQL LineString](https://dev.mysql.com/doc/refman/8.0/en/gis-class-linestring.html) -* `MultiLineString(LineString[] | Collection)` - [MySQL MultiLineString](https://dev.mysql.com/doc/refman/8.0/en/gis-class-multilinestring.html) -* `Polygon(LineString[] | Collection)` - [MySQL Polygon](https://dev.mysql.com/doc/refman/8.0/en/gis-class-polygon.html) -* `MultiPolygon(Polygon[] | Collection)` - [MySQL MultiPolygon](https://dev.mysql.com/doc/refman/8.0/en/gis-class-multipolygon.html) -* `GeometryCollection(Geometry[] | Collection)` - [MySQL GeometryCollection](https://dev.mysql.com/doc/refman/8.0/en/gis-class-geometrycollection.html) +* `Point(float $latitude, float $longitude, int $srid = 0)` - [MySQL Point](https://dev.mysql.com/doc/refman/8.0/en/gis-class-point.html) +* `MultiPoint(Point[] | Collection, int $srid = 0)` - [MySQL MultiPoint](https://dev.mysql.com/doc/refman/8.0/en/gis-class-multipoint.html) +* `LineString(Point[] | Collection, int $srid = 0)` - [MySQL LineString](https://dev.mysql.com/doc/refman/8.0/en/gis-class-linestring.html) +* `MultiLineString(LineString[] | Collection, int $srid = 0)` - [MySQL MultiLineString](https://dev.mysql.com/doc/refman/8.0/en/gis-class-multilinestring.html) +* `Polygon(LineString[] | Collection, int $srid = 0)` - [MySQL Polygon](https://dev.mysql.com/doc/refman/8.0/en/gis-class-polygon.html) +* `MultiPolygon(Polygon[] | Collection, int $srid = 0)` - [MySQL MultiPolygon](https://dev.mysql.com/doc/refman/8.0/en/gis-class-multipolygon.html) +* `GeometryCollection(Geometry[] | Collection, int $srid = 0)` - [MySQL GeometryCollection](https://dev.mysql.com/doc/refman/8.0/en/gis-class-geometrycollection.html) -## Available spatial functions +Geometry classes can be also created by these static methods: -Every geometry class has these functions: +* `fromJson(string $geoJson, int $srid = 0)` - Creates a geometry object from a [GeoJSON](https://en.wikipedia.org/wiki/GeoJSON) string. +* `fromWkt(string $wkt, int $srid = 0)` - Creates a geometry object from a [WKT](https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry). +* `fromWkb(string $wkb, int $srid = 0)` - Creates a geometry object from a [WKB](https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry#Well-known_binary). + +## Available geometry class methods * `toArray()` - Serializes the geometry object into a GeoJSON associative array. * `toJson()` - Serializes the geometry object into an GeoJSON string. -* `fromJson(string $geoJson)` - Deserializes a geometry object from a GeoJSON string. (static method) * `toFeatureCollectionJson()` - Serializes the geometry object into an GeoJSON's FeatureCollection string. +* `toWkt()` - Serializes the geometry object into a WKT. +* `toWkb()` - Serializes the geometry object into a WKB. * `getCoordinates()` - Returns the coordinates of the geometry object. In addition, `GeometryCollection` also has these functions: @@ -40,7 +45,7 @@ $geometryCollection = new GeometryCollection([ ]); echo $geometryCollection->getGeometries()[1]->latitude; // 180 -// can also access as an array: +// or access as an array: echo $geometryCollection[1]->latitude; // 180 ``` @@ -59,6 +64,7 @@ echo $geometryCollection[1]->latitude; // 180 * [whereCrosses](#whereCrosses) * [whereDisjoint](#whereDisjoint) * [whereEquals](#whereEquals) +* [whereSrid](#whereSrid) ### withDistance @@ -372,3 +378,24 @@ Place::query() ``` +### whereSrid + +Filters records by the [ST_Srid](https://dev.mysql.com/doc/refman/8.0/en/gis-general-property-functions.html#function_st-srid) function. + +| parameter name | type +| ------------------ | -------------------- +| `$column` | `string` +| `$operator` | `string` +| `$value` | `int` + +
Example + +```php +Place::create(['location' => new Point(0, 0, 4326)]); + +Place::query() + ->whereSrid('location', '=', 4326) + ->exists(); // true +``` +
+ diff --git a/README.md b/README.md index 615415e..dd049ab 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,12 @@ use MatanYadaev\EloquentSpatial\Objects\Point; $londonEye = Place::create([ 'name' => 'London Eye', - 'location' => new Point(51.5032973, -0.1195537) + 'location' => new Point(51.5032973, -0.1217424), +]); + +$whiteHouse = Place::create([ + 'name' => 'White House', + 'location' => new Point(38.8976763, -77.0365298, 4326), // with SRID ]); $vaticanCity = Place::create([ @@ -119,8 +124,8 @@ $vaticanCity = Place::create([ new Point(12.457734346389769, 41.905918239316286), new Point(12.45572805404663, 41.90637337450963), new Point(12.455363273620605, 41.90746728266806), - ]) - ]) + ]), + ]), ]) ``` @@ -128,7 +133,9 @@ Retrieve a record with spatial data: ```php echo $londonEye->location->latitude; // 51.5032973 -echo $londonEye->location->longitude; // -0.1195537 +echo $londonEye->location->longitude; // -0.1217424 + +echo $whiteHouse->location->srid; // 4326 echo $vacationCity->area->toJson(); // {"type":"Polygon","coordinates":[[[41.90746728266806,12.455363273620605],[41.906636872349075,12.450309991836548],[41.90197359839437,12.445632219314575],[41.90027269624499,12.447413206100464],[41.90000118654431,12.457906007766724],[41.90281205461268,12.458517551422117],[41.903107507989986,12.457584142684937],[41.905918239316286,12.457734346389769],[41.90637337450963,12.45572805404663],[41.90746728266806,12.455363273620605]]]} ``` @@ -170,13 +177,12 @@ Place::query()->whereDistance(...); // This is IDE-friendly Place::whereDistance(...); // This is not ``` -## Tests +## Development -``` bash -composer phpunit -# or with coverage -composer phpunit-coverage -``` +* Test: `composer pest` +* Test with coverage: `composer pest-coverage` +* Type check: `composer phpstan` +* Format: `composer php-cs-fixer` ## Changelog