Skip to content

Commit 49b9c36

Browse files
committed
Support ST_CENTROID spatial function
1 parent 10848af commit 49b9c36

File tree

4 files changed

+73
-36
lines changed

4 files changed

+73
-36
lines changed

src/AxisOrder.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010

1111
class AxisOrder
1212
{
13-
public function __construct() {}
13+
public function __construct()
14+
{
15+
}
1416

1517
public function supported(ConnectionInterface $connection): bool
1618
{
@@ -30,7 +32,8 @@ public function supported(ConnectionInterface $connection): bool
3032
return true;
3133
}
3234

33-
private function isMariaDb(MySqlConnection $connection): bool {
35+
private function isMariaDb(MySqlConnection $connection): bool
36+
{
3437
return $connection->isMaria();
3538
}
3639

src/SpatialBuilder.php

Lines changed: 32 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ public function withDistance(
2222
ExpressionContract|Geometry|string $column,
2323
ExpressionContract|Geometry|string $geometryOrColumn,
2424
string $alias = 'distance'
25-
): self
26-
{
25+
): self {
2726
if (! $this->getQuery()->columns) {
2827
$this->select('*');
2928
}
@@ -45,8 +44,7 @@ public function whereDistance(
4544
ExpressionContract|Geometry|string $geometryOrColumn,
4645
string $operator,
4746
int|float $value
48-
): self
49-
{
47+
): self {
5048
$this->whereRaw(
5149
sprintf(
5250
'ST_DISTANCE(%s, %s) %s ?',
@@ -64,8 +62,7 @@ public function orderByDistance(
6462
ExpressionContract|Geometry|string $column,
6563
ExpressionContract|Geometry|string $geometryOrColumn,
6664
string $direction = 'asc'
67-
): self
68-
{
65+
): self {
6966
$this->orderByRaw(
7067
sprintf(
7168
'ST_DISTANCE(%s, %s) %s',
@@ -82,8 +79,7 @@ public function withDistanceSphere(
8279
ExpressionContract|Geometry|string $column,
8380
ExpressionContract|Geometry|string $geometryOrColumn,
8481
string $alias = 'distance'
85-
): self
86-
{
82+
): self {
8783
if (! $this->getQuery()->columns) {
8884
$this->select('*');
8985
}
@@ -105,8 +101,7 @@ public function whereDistanceSphere(
105101
ExpressionContract|Geometry|string $geometryOrColumn,
106102
string $operator,
107103
int|float $value
108-
): self
109-
{
104+
): self {
110105
$this->whereRaw(
111106
sprintf(
112107
'ST_DISTANCE_SPHERE(%s, %s) %s ?',
@@ -124,8 +119,7 @@ public function orderByDistanceSphere(
124119
ExpressionContract|Geometry|string $column,
125120
ExpressionContract|Geometry|string $geometryOrColumn,
126121
string $direction = 'asc'
127-
): self
128-
{
122+
): self {
129123
$this->orderByRaw(
130124
sprintf(
131125
'ST_DISTANCE_SPHERE(%s, %s) %s',
@@ -141,8 +135,7 @@ public function orderByDistanceSphere(
141135
public function whereWithin(
142136
ExpressionContract|Geometry|string $column,
143137
ExpressionContract|Geometry|string $geometryOrColumn,
144-
): self
145-
{
138+
): self {
146139
$this->whereRaw(
147140
sprintf(
148141
'ST_WITHIN(%s, %s)',
@@ -157,8 +150,7 @@ public function whereWithin(
157150
public function whereNotWithin(
158151
ExpressionContract|Geometry|string $column,
159152
ExpressionContract|Geometry|string $geometryOrColumn,
160-
): self
161-
{
153+
): self {
162154
$this->whereRaw(
163155
sprintf(
164156
'ST_WITHIN(%s, %s) = 0',
@@ -173,8 +165,7 @@ public function whereNotWithin(
173165
public function whereContains(
174166
ExpressionContract|Geometry|string $column,
175167
ExpressionContract|Geometry|string $geometryOrColumn,
176-
): self
177-
{
168+
): self {
178169
$this->whereRaw(
179170
sprintf(
180171
'ST_CONTAINS(%s, %s)',
@@ -189,8 +180,7 @@ public function whereContains(
189180
public function whereNotContains(
190181
ExpressionContract|Geometry|string $column,
191182
ExpressionContract|Geometry|string $geometryOrColumn,
192-
): self
193-
{
183+
): self {
194184
$this->whereRaw(
195185
sprintf(
196186
'ST_CONTAINS(%s, %s) = 0',
@@ -205,8 +195,7 @@ public function whereNotContains(
205195
public function whereTouches(
206196
ExpressionContract|Geometry|string $column,
207197
ExpressionContract|Geometry|string $geometryOrColumn,
208-
): self
209-
{
198+
): self {
210199
$this->whereRaw(
211200
sprintf(
212201
'ST_TOUCHES(%s, %s)',
@@ -221,8 +210,7 @@ public function whereTouches(
221210
public function whereIntersects(
222211
ExpressionContract|Geometry|string $column,
223212
ExpressionContract|Geometry|string $geometryOrColumn,
224-
): self
225-
{
213+
): self {
226214
$this->whereRaw(
227215
sprintf(
228216
'ST_INTERSECTS(%s, %s)',
@@ -237,8 +225,7 @@ public function whereIntersects(
237225
public function whereCrosses(
238226
ExpressionContract|Geometry|string $column,
239227
ExpressionContract|Geometry|string $geometryOrColumn,
240-
): self
241-
{
228+
): self {
242229
$this->whereRaw(
243230
sprintf(
244231
'ST_CROSSES(%s, %s)',
@@ -253,8 +240,7 @@ public function whereCrosses(
253240
public function whereDisjoint(
254241
ExpressionContract|Geometry|string $column,
255242
ExpressionContract|Geometry|string $geometryOrColumn,
256-
): self
257-
{
243+
): self {
258244
$this->whereRaw(
259245
sprintf(
260246
'ST_DISJOINT(%s, %s)',
@@ -269,8 +255,7 @@ public function whereDisjoint(
269255
public function whereOverlaps(
270256
ExpressionContract|Geometry|string $column,
271257
ExpressionContract|Geometry|string $geometryOrColumn,
272-
): self
273-
{
258+
): self {
274259
$this->whereRaw(
275260
sprintf(
276261
'ST_OVERLAPS(%s, %s)',
@@ -285,8 +270,7 @@ public function whereOverlaps(
285270
public function whereEquals(
286271
ExpressionContract|Geometry|string $column,
287272
ExpressionContract|Geometry|string $geometryOrColumn,
288-
): self
289-
{
273+
): self {
290274
$this->whereRaw(
291275
sprintf(
292276
'ST_EQUALS(%s, %s)',
@@ -302,8 +286,7 @@ public function whereSrid(
302286
ExpressionContract|Geometry|string $column,
303287
string $operator,
304288
int|float $value
305-
): self
306-
{
289+
): self {
307290
$this->whereRaw(
308291
sprintf(
309292
'ST_SRID(%s) %s ?',
@@ -316,6 +299,21 @@ public function whereSrid(
316299
return $this;
317300
}
318301

302+
public function withCentroid(
303+
ExpressionContract|Geometry|string $column,
304+
string $alias = 'centroid',
305+
): self {
306+
$this->selectRaw(
307+
sprintf(
308+
'ST_CENTROID(%s) AS %s',
309+
$this->toExpressionString($column),
310+
$this->getGrammar()->wrap($alias),
311+
)
312+
);
313+
314+
return $this;
315+
}
316+
319317
protected function toExpressionString(ExpressionContract|Geometry|string $geometryOrColumnOrExpression): string
320318
{
321319
$grammar = $this->getGrammar();

tests/SpatialBuilderTest.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,40 @@
372372
expect($testPlaces[0]->point)->toEqual($point1);
373373
});
374374

375+
it('calculates geometry centroid', function (): void {
376+
// Arrange
377+
$polygon = Polygon::fromJson('{"type":"Polygon","coordinates":[[[-1,-1],[1,-1],[1,1],[-1,1],[-1,-1]]]}');
378+
TestPlace::factory()->create(['polygon' => $polygon]);
379+
380+
// Act
381+
/** @var TestPlace $testPlace */
382+
$testPlace = TestPlace::query()
383+
->withCentroid('polygon')
384+
->withCasts(['centroid' => Point::class])
385+
->firstOrFail();
386+
387+
// Assert
388+
$expectedCentroid = new Point(0, 0);
389+
expect($testPlace->centroid)->toEqual($expectedCentroid);
390+
});
391+
392+
it('calculates geometry centroid with alias', function (): void {
393+
// Arrange
394+
$polygon = Polygon::fromJson('{"type":"Polygon","coordinates":[[[-1,-1],[1,-1],[1,1],[-1,1],[-1,-1]]]}');
395+
TestPlace::factory()->create(['polygon' => $polygon]);
396+
397+
// Act
398+
/** @var TestPlace $testPlace */
399+
$testPlace = TestPlace::query()
400+
->withCentroid('polygon', 'centroid_alias')
401+
->withCasts(['centroid_alias' => Point::class])
402+
->firstOrFail();
403+
404+
// Assert
405+
$expectedCentroid = new Point(0, 0);
406+
expect($testPlace->centroid_alias)->toEqual($expectedCentroid);
407+
});
408+
375409
it('uses spatial function with column', function (): void {
376410
TestPlace::factory()->create(['point' => new Point(0, 0, Srid::WGS84->value)]);
377411

tests/TestModels/TestPlace.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
* @property GeometryCollection $geometry_collection
2626
* @property float|null $distance
2727
* @property float|null $distance_in_meters
28+
* @property Point|null $centroid
29+
* @property Point|null $centroid_alias
2830
* @mixin Model
2931
*
3032
* @method static SpatialBuilder<TestPlace> query()

0 commit comments

Comments
 (0)