File size: 2,405 Bytes
ee194aa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e6ce7f9
ee194aa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e6ce7f9
 
 
 
ee194aa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
from shapely.geometry import Point
from shapely.ops import transform
from pyproj import Transformer
from typing import List, Set
import math
import asyncio


class GetNearbyParcelsBySamplingUseCase:
    def __init__(self, parcel_repository, buffer_radius_m: float, step_m: float = 100):
        self.repo = parcel_repository
        self.radius = buffer_radius_m
        self.step = step_m  # espacement des points (densité)
        self.to_projected = Transformer.from_crs("EPSG:4326", "EPSG:3857", always_xy=True).transform
        self.to_geographic = Transformer.from_crs("EPSG:3857", "EPSG:4326", always_xy=True).transform

    async def __call__(self, lat: float, lon: float) -> dict:
        center = transform(self.to_projected, Point(lon, lat))

        sampled_points = self._generate_sampling_points(center)

        seen_ids: Set[str] = set()
        nearby_parcels: List[dict] = []

        # Traitement asynchrone en lot pour optimiser les performances
        tasks = []
        for pt in sampled_points:
            lon_, lat_ = transform(self.to_geographic, pt).coords[0]
            tasks.append(self.repo.get_parcel_from_point(lat_, lon_))
        
        print(f"len(tasks): {len(tasks)}")

        # Exécution parallèle des requêtes
        parcel_results = await asyncio.gather(*tasks, return_exceptions=True)
        
        for parcel in parcel_results:
            if isinstance(parcel, Exception):
                continue  # Ignorer les erreurs et continuer
                
            if parcel:
                parcel_id = parcel.get("cadastre", {}).get("id", {}).get("value")
                if parcel_id not in seen_ids:
                    nearby_parcels.append(parcel)
                    seen_ids.add(parcel_id)

        return {
            "parcels": nearby_parcels,
            "number_of_points": len(sampled_points)
        }

    def _generate_sampling_points(self, center: Point) -> List[Point]:
        points = []
        step = self.step
        radius = self.radius

        min_x, min_y = center.x - radius, center.y - radius
        max_x, max_y = center.x + radius, center.y + radius

        for x in range(int(min_x), int(max_x), int(step)):
            for y in range(int(min_y), int(max_y), int(step)):
                pt = Point(x, y)
                if pt.distance(center) <= radius:
                    points.append(pt)
        return points