Skip to content

Commit f600013

Browse files
committed
more spatial functions
1 parent 4a6851c commit f600013

File tree

2 files changed

+144
-40
lines changed

2 files changed

+144
-40
lines changed

src/Builders/SpatialBuilder.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,41 @@ public function whereTouches(string $column, Geometry | string $geometryOrColumn
8585
return $this->whereRaw("ST_TOUCHES(`{$column}`, {$geometryOrColumn})");
8686
}
8787

88+
public function whereIntersects(string $column, Geometry | string $geometryOrColumn): self
89+
{
90+
$geometryOrColumn = $this->toExpression($geometryOrColumn);
91+
92+
return $this->whereRaw("ST_INTERSECTS(`{$column}`, {$geometryOrColumn})");
93+
}
94+
95+
public function whereCrosses(string $column, Geometry | string $geometryOrColumn): self
96+
{
97+
$geometryOrColumn = $this->toExpression($geometryOrColumn);
98+
99+
return $this->whereRaw("ST_CROSSES(`{$column}`, {$geometryOrColumn})");
100+
}
101+
102+
public function whereDisjoint(string $column, Geometry | string $geometryOrColumn): self
103+
{
104+
$geometryOrColumn = $this->toExpression($geometryOrColumn);
105+
106+
return $this->whereRaw("ST_DISJOINT(`{$column}`, {$geometryOrColumn})");
107+
}
108+
109+
public function whereOverlaps(string $column, Geometry | string $geometryOrColumn): self
110+
{
111+
$geometryOrColumn = $this->toExpression($geometryOrColumn);
112+
113+
return $this->whereRaw("ST_OVERLAPS(`{$column}`, {$geometryOrColumn})");
114+
}
115+
116+
public function whereEquals(string $column, Geometry | string $geometryOrColumn): self
117+
{
118+
$geometryOrColumn = $this->toExpression($geometryOrColumn);
119+
120+
return $this->whereRaw("ST_EQUALS(`{$column}`, {$geometryOrColumn})");
121+
}
122+
88123
protected function toExpression(Geometry | string $geometryOrColumn): Expression
89124
{
90125
return $geometryOrColumn instanceof Geometry

tests/Builders/SpatialBuilderTest.php

Lines changed: 109 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
namespace MatanYadaev\EloquentSpatial\Tests\Builders;
44

55
use Illuminate\Foundation\Testing\DatabaseMigrations;
6+
use MatanYadaev\EloquentSpatial\Objects\LineString;
67
use MatanYadaev\EloquentSpatial\Objects\MultiPolygon;
78
use MatanYadaev\EloquentSpatial\Objects\Point;
9+
use MatanYadaev\EloquentSpatial\Objects\Polygon;
810
use MatanYadaev\EloquentSpatial\Tests\TestCase;
911
use MatanYadaev\EloquentSpatial\Tests\TestModels\TestPlace;
1012

@@ -16,7 +18,7 @@ class SpatialBuilderTest extends TestCase
1618
public function it_calculates_distance_between_column_and_column(): void
1719
{
1820
TestPlace::factory()->create([
19-
'point' => new Point(23.1, 55.5),
21+
'point' => new Point(0, 0),
2022
]);
2123

2224
/** @var TestPlace $testPlaceWithDistance */
@@ -31,56 +33,55 @@ public function it_calculates_distance_between_column_and_column(): void
3133
public function it_calculates_distance_between_column_and_geometry(): void
3234
{
3335
TestPlace::factory()->create([
34-
'point' => new Point(23.1, 55.5),
36+
'point' => new Point(0, 0),
3537
]);
3638

3739
/** @var TestPlace $testPlaceWithDistance */
3840
$testPlaceWithDistance = TestPlace::query()
39-
->withDistance('point', new Point(23.1, 55.6))
41+
->withDistance('point', new Point(1, 1))
4042
->firstOrFail();
4143

42-
$this->assertEquals(0.1, $testPlaceWithDistance->distance);
44+
$this->assertEquals(1.4142135623731, $testPlaceWithDistance->distance);
4345
}
4446

4547
/** @test */
4648
public function it_calculates_distance_with_defined_name(): void
4749
{
4850
TestPlace::factory()->create([
49-
'point' => new Point(23.1, 55.5),
51+
'point' => new Point(0, 0),
5052
]);
5153

5254
/** @var TestPlace $testPlaceWithDistance */
5355
$testPlaceWithDistance = TestPlace::query()
54-
->withDistance('point', new Point(23.1, 55.6), 'distance_in_meters')
56+
->withDistance('point', new Point(1, 1), 'distance_in_meters')
5557
->firstOrFail();
5658

57-
$this->assertEquals(0.1, $testPlaceWithDistance->distance_in_meters);
59+
$this->assertEquals(1.4142135623731, $testPlaceWithDistance->distance_in_meters);
5860
}
5961

6062
/** @test */
6163
public function it_filters_by_distance(): void
6264
{
6365
TestPlace::factory()->create([
64-
'point' => new Point(23.1, 55.5),
66+
'point' => new Point(0, 0),
6567
]);
6668

67-
/** @var TestPlace $testPlaceWithinDistance */
6869
$testPlaceWithinDistance = TestPlace::query()
69-
->whereDistance('point', new Point(23.1, 55.6), '<', 1)
70-
->firstOrFail();
70+
->whereDistance('point', new Point(1, 1), '<', 10)
71+
->first();
7172

7273
$this->assertNotNull($testPlaceWithinDistance);
7374
}
7475

7576
/** @test */
7677
public function it_orders_by_distance(): void
7778
{
78-
$point = new Point(23.1, 55.51);
79+
$point = new Point(0, 0);
7980
$testPlace1 = TestPlace::factory()->create([
80-
'point' => new Point(23.1, 55.5),
81+
'point' => new Point(1, 1),
8182
]);
8283
$testPlace2 = TestPlace::factory()->create([
83-
'point' => new Point(0, 0),
84+
'point' => new Point(2, 2),
8485
]);
8586

8687
/** @var TestPlace $closestTestPlace */
@@ -100,7 +101,9 @@ public function it_orders_by_distance(): void
100101
/** @test */
101102
public function it_calculates_distance_sphere_column_and_column(): void
102103
{
103-
TestPlace::factory()->create();
104+
TestPlace::factory()->create([
105+
'point' => new Point(0, 0),
106+
]);
104107

105108
/** @var TestPlace $testPlaceWithDistance */
106109
$testPlaceWithDistance = TestPlace::query()
@@ -114,56 +117,55 @@ public function it_calculates_distance_sphere_column_and_column(): void
114117
public function it_calculates_distance_sphere_column_and_geometry(): void
115118
{
116119
TestPlace::factory()->create([
117-
'point' => new Point(23.1, 55.5),
120+
'point' => new Point(0, 0),
118121
]);
119122

120123
/** @var TestPlace $testPlaceWithDistance */
121124
$testPlaceWithDistance = TestPlace::query()
122-
->withDistanceSphere('point', new Point(23.1, 55.51))
125+
->withDistanceSphere('point', new Point(1, 1))
123126
->firstOrFail();
124127

125-
$this->assertEquals(1022.7925914593363, $testPlaceWithDistance->distance);
128+
$this->assertEquals(157249.0357231545, $testPlaceWithDistance->distance);
126129
}
127130

128131
/** @test */
129132
public function it_calculates_distance_sphere_with_defined_name(): void
130133
{
131134
TestPlace::factory()->create([
132-
'point' => new Point(23.1, 55.5),
135+
'point' => new Point(0, 0),
133136
]);
134137

135138
/** @var TestPlace $testPlaceWithDistance */
136139
$testPlaceWithDistance = TestPlace::query()
137-
->withDistanceSphere('point', new Point(23.1, 55.51), 'distance_in_meters')
140+
->withDistanceSphere('point', new Point(1, 1), 'distance_in_meters')
138141
->firstOrFail();
139142

140-
$this->assertEquals(1022.7925914593363, $testPlaceWithDistance->distance_in_meters);
143+
$this->assertEquals(157249.0357231545, $testPlaceWithDistance->distance_in_meters);
141144
}
142145

143146
/** @test */
144147
public function it_filters_distance_sphere(): void
145148
{
146149
TestPlace::factory()->create([
147-
'point' => new Point(23.1, 55.5),
150+
'point' => new Point(0, 0),
148151
]);
149152

150-
/** @var TestPlace $testPlaceWithinDistanceSphere */
151153
$testPlaceWithinDistanceSphere = TestPlace::query()
152-
->whereDistanceSphere('point', new Point(23.1, 55.51), '<', 2000)
153-
->firstOrFail();
154+
->whereDistanceSphere('point', new Point(1, 1), '<', 200000)
155+
->first();
154156

155157
$this->assertNotNull($testPlaceWithinDistanceSphere);
156158
}
157159

158160
/** @test */
159161
public function it_orders_by_distance_sphere(): void
160162
{
161-
$point = new Point(23.1, 55.51);
163+
$point = new Point(0, 0);
162164
$testPlace1 = TestPlace::factory()->create([
163-
'point' => new Point(23.1, 55.5),
165+
'point' => new Point(1, 1),
164166
]);
165167
$testPlace2 = TestPlace::factory()->create([
166-
'point' => new Point(0, 0),
168+
'point' => new Point(2, 2),
167169
]);
168170

169171
/** @var TestPlace $closestTestPlace */
@@ -184,13 +186,12 @@ public function it_orders_by_distance_sphere(): void
184186
public function it_filters_by_within(): void
185187
{
186188
TestPlace::factory()->create([
187-
'point' => new Point(23.1, 55.5),
189+
'point' => new Point(0, 0),
188190
]);
189191

190-
/** @var TestPlace $testPlace */
191192
$testPlace = TestPlace::query()
192-
->whereWithin('point', MultiPolygon::fromJson('{"type":"MultiPolygon","coordinates":[[[[55.5,23.0],[55.4,23.2],[55.8,23.3],[55.5,23.0]]]]}'))
193-
->firstOrFail();
193+
->whereWithin('point', Polygon::fromJson('{"type":"Polygon","coordinates":[[[-1,-1],[1,-1],[1,1],[-1,1],[-1,-1]]]}'))
194+
->first();
194195

195196
$this->assertNotNull($testPlace);
196197
}
@@ -199,13 +200,12 @@ public function it_filters_by_within(): void
199200
public function it_filters_by_contains(): void
200201
{
201202
TestPlace::factory()->create([
202-
'multi_polygon' => MultiPolygon::fromJson('{"type":"MultiPolygon","coordinates":[[[[55.5,23.0],[55.4,23.2],[55.8,23.3],[55.5,23.0]]]]}'),
203+
'polygon' => Polygon::fromJson('{"type":"Polygon","coordinates":[[[-1,-1],[1,-1],[1,1],[-1,1],[-1,-1]]]}'),
203204
]);
204205

205-
/** @var TestPlace $testPlace */
206206
$testPlace = TestPlace::query()
207-
->whereContains('multi_polygon', new Point(23.1, 55.5))
208-
->firstOrFail();
207+
->whereContains('polygon', new Point(0, 0))
208+
->first();
209209

210210
$this->assertNotNull($testPlace);
211211
}
@@ -214,13 +214,82 @@ public function it_filters_by_contains(): void
214214
public function it_filters_by_touches(): void
215215
{
216216
TestPlace::factory()->create([
217-
'point' => new Point(23.1, 55.5),
217+
'point' => new Point(0, 0),
218+
]);
219+
220+
$testPlace = TestPlace::query()
221+
->whereTouches('point', Polygon::fromJson('{"type":"Polygon","coordinates":[[[-1,-1],[0,-1],[0,0],[-1,0],[-1,-1]]]}'))
222+
->first();
223+
224+
$this->assertNotNull($testPlace);
225+
}
226+
227+
/** @test */
228+
public function it_filters_by_intersects(): void
229+
{
230+
TestPlace::factory()->create([
231+
'point' => new Point(0, 0),
218232
]);
219233

220-
/** @var TestPlace $testPlace */
221234
$testPlace = TestPlace::query()
222-
->whereTouches('point', MultiPolygon::fromJson('{"type":"MultiPolygon","coordinates":[[[[55.5,23.1],[55.6,23.2],[55.7,23.3],[55.5,23.1]]]]}'))
223-
->firstOrFail();
235+
->whereIntersects('point', Polygon::fromJson('{"type":"Polygon","coordinates":[[[-1,-1],[1,-1],[1,1],[-1,1],[-1,-1]]]}'))
236+
->first();
237+
238+
$this->assertNotNull($testPlace);
239+
}
240+
241+
/** @test */
242+
public function it_filters_by_crosses(): void
243+
{
244+
TestPlace::factory()->create([
245+
'line_string' => LineString::fromJson('{"type":"LineString","coordinates":[[0,0],[2,0]]}'),
246+
]);
247+
248+
$testPlace = TestPlace::query()
249+
->whereCrosses('line_string', Polygon::fromJson('{"type":"Polygon","coordinates":[[[-1,-1],[1,-1],[1,1],[-1,1],[-1,-1]]]}'))
250+
->first();
251+
252+
$this->assertNotNull($testPlace);
253+
}
254+
255+
/** @test */
256+
public function it_filters_by_disjoint(): void
257+
{
258+
TestPlace::factory()->create([
259+
'point' => new Point(0, 0),
260+
]);
261+
262+
$testPlace = TestPlace::query()
263+
->whereDisjoint('point', Polygon::fromJson('{"type":"Polygon","coordinates":[[[-1,-1],[-0.5,-1],[-0.5,-0.5],[-1,-0.5],[-1,-1]]]}'))
264+
->first();
265+
266+
$this->assertNotNull($testPlace);
267+
}
268+
269+
/** @test */
270+
public function it_filters_by_overlaps(): void
271+
{
272+
TestPlace::factory()->create([
273+
'polygon' => Polygon::fromJson('{"type":"Polygon","coordinates":[[[-1,-1],[-0.5,-1],[-0.5,-0.5],[-1,-0.5],[-1,-1]]]}'),
274+
]);
275+
276+
$testPlace = TestPlace::query()
277+
->whereOverlaps('polygon', Polygon::fromJson('{"type":"Polygon","coordinates":[[[-0.75,-0.75],[1,-1],[1,1],[-1,1],[-0.75,-0.75]]]}'))
278+
->first();
279+
280+
$this->assertNotNull($testPlace);
281+
}
282+
283+
/** @test */
284+
public function it_filters_by_equals(): void
285+
{
286+
TestPlace::factory()->create([
287+
'point' => new Point(0, 0),
288+
]);
289+
290+
$testPlace = TestPlace::query()
291+
->whereEquals('point', new Point(0, 0))
292+
->first();
224293

225294
$this->assertNotNull($testPlace);
226295
}

0 commit comments

Comments
 (0)