Skip to content

Commit

Permalink
[TM-1523] improve validation (#592)
Browse files Browse the repository at this point in the history
* [TM-1460] add migration to add index

* [TM-1460] add index to polygon geometry and validate overlapping with bbox

* [TM-1460] lint

* [TM-1460] add overlap check with bboxes

* [TM-1523] finish bbox precalculus for overlapping check

* [TM-1523] add index to sitepolygon

* [TM-1523] add initial factory with non empty geometry,for index
  • Loading branch information
egrojMonroy authored Nov 29, 2024
1 parent 9bb6341 commit 9fa19bf
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 25 deletions.
43 changes: 22 additions & 21 deletions app/Validators/Extensions/Polygons/NotOverlapping.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,21 @@ public static function passes($attribute, $value, $parameters, $validator): bool
public static function getIntersectionData(string $polygonUuid): array
{
$sitePolygon = SitePolygon::forPolygonGeometry($polygonUuid)->first();
if ($sitePolygon === null) {
return [
'valid' => false,
'error' => 'Site polygon not found for the given polygon ID',
'status' => 404,
];
if (! $sitePolygon) {
return ['valid' => false, 'error' => 'Site polygon not found', 'status' => 404];
}

$relatedPolyIds = $sitePolygon->project->sitePolygons()
->where('poly_id', '!=', $polygonUuid)
->pluck('poly_id');
$intersects = PolygonGeometry::join('site_polygon', 'polygon_geometry.uuid', '=', 'site_polygon.poly_id')

$bboxFilteredPolyIds = PolygonGeometry::join('site_polygon', 'polygon_geometry.uuid', '=', 'site_polygon.poly_id')
->whereIn('polygon_geometry.uuid', $relatedPolyIds)
->whereRaw('ST_Intersects(ST_Envelope(polygon_geometry.geom), (SELECT ST_Envelope(geom) FROM polygon_geometry WHERE uuid = ?))', [$polygonUuid])
->pluck('polygon_geometry.uuid');

$intersects = PolygonGeometry::join('site_polygon', 'polygon_geometry.uuid', '=', 'site_polygon.poly_id')
->whereIn('polygon_geometry.uuid', $bboxFilteredPolyIds)
->select([
'polygon_geometry.uuid',
'site_polygon.poly_name',
Expand All @@ -50,28 +52,27 @@ public static function getIntersectionData(string $polygonUuid): array

$mainPolygonArea = PolygonGeometry::where('uuid', $polygonUuid)
->value(DB::raw('ST_Area(geom)'));
$extra_info = [];
foreach ($intersects as $intersect) {
if ($intersect->intersects) {

$extra_info = $intersects
->filter(fn ($intersect) => $intersect->intersects)
->map(function ($intersect) use ($mainPolygonArea) {
$minArea = min($mainPolygonArea, $intersect->area);
if ($minArea > 0) {
$percentage = ($intersect->intersection_area / $minArea) * 100;
$percentage = round($percentage, 2);
} else {
$percentage = 100;
}
$extra_info[] = [
$percentage = $minArea > 0
? round(($intersect->intersection_area / $minArea) * 100, 2)
: 100;

return [
'poly_uuid' => $intersect->uuid,
'poly_name' => $intersect->poly_name,
'percentage' => $percentage,
'intersectSmaller' => ($intersect->area < $mainPolygonArea),
];
}
}

})
->values()
->toArray();

return [
'valid' => ! $intersects->contains('intersects', 1),
'valid' => empty($extra_info),
'uuid' => $polygonUuid,
'project_id' => $sitePolygon->project_id,
'extra_info' => $extra_info,
Expand Down
9 changes: 6 additions & 3 deletions database/factories/V2/PolygonGeometryFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,14 @@ public function definition()

public function geojson(string|array $geojson)
{
$geom = DB::raw("ST_GeomFromGeoJSON('$geojson')");
if (is_array($geojson)) {
$geojson = json_encode($geojson);
}
$geomExpression = DB::raw("ST_GeomFromGeoJSON('$geojson')");

return $this->state(function (array $attributes) use ($geom) {
return $this->state(function (array $attributes) use ($geomExpression) {
return [
'geom' => $geom,
'geom' => $geomExpression,
];
});
}
Expand Down
18 changes: 17 additions & 1 deletion database/factories/V2/Sites/SitePolygonFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,24 @@ class SitePolygonFactory extends Factory
{
public function definition()
{
$geojson = [
'type' => 'Polygon',
'coordinates' => [
[
[0, 0],
[1, 0],
[1, 1],
[0, 1],
[0, 0],
],
],
];

return [
'poly_id' => PolygonGeometry::factory()->create()->uuid,
'poly_id' => PolygonGeometry::factory()
->geojson($geojson)
->create()
->uuid,
'site_id' => Site::factory()->create()->uuid,
'calc_area' => $this->faker->numberBetween(2.0, 50.0),
];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

class AddSpatialIndexToPolygonGeometry extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('polygon_geometry', function (Blueprint $table) {
DB::statement('ALTER TABLE polygon_geometry MODIFY COLUMN geom GEOMETRY NOT NULL');
DB::statement('CREATE SPATIAL INDEX polygon_geometry_geom_spatial_idx ON polygon_geometry (geom)');
});
}

public function down()
{
Schema::table('polygon_geometry', function (Blueprint $table) {
DB::statement('DROP INDEX polygon_geometry_geom_spatial_idx ON polygon_geometry');
DB::statement('ALTER TABLE polygon_geometry MODIFY COLUMN geom GEOMETRY NULL');
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration {
public function up(): void
{
Schema::table('site_polygon', function (Blueprint $table) {
$table->index('poly_id', 'idx_site_polygon_poly_id');
});
}

public function down(): void
{
Schema::table('site_polygon', function (Blueprint $table) {
$table->dropIndex('idx_site_polygon_poly_id');
});
}
};

0 comments on commit 9fa19bf

Please sign in to comment.