Files
rfcp/backend/app/core/grid.py
mytec defa3ad440 @mytec: feat: Phase 3.0 Architecture Refactor
Major refactoring of RFCP backend:
- Modular propagation models (8 models)
- SharedMemoryManager for terrain data
- ProcessPoolExecutor parallel processing
- WebSocket progress streaming
- Building filtering pipeline (351k → 15k)
- 82 unit tests

Performance: Standard preset 38s → 5s (7.6x speedup)

Known issue: Detailed preset timeout (fix in 3.1.0)
2026-02-01 23:12:26 +02:00

84 lines
2.4 KiB
Python

"""
Grid generation for coverage calculations.
"""
import numpy as np
from dataclasses import dataclass
from typing import List, Tuple
from app.geometry.haversine import haversine_distance
@dataclass
class BoundingBox:
min_lat: float
min_lon: float
max_lat: float
max_lon: float
@dataclass
class Grid:
points: List[Tuple[float, float]]
bounding_box: BoundingBox
resolution: float
radius: float
class GridService:
"""Generate coverage grid points."""
@staticmethod
def generate(
center_lat: float,
center_lon: float,
radius: float,
resolution: float,
) -> Grid:
points = []
lat_step = resolution / 111000
lon_step = resolution / (111000 * np.cos(np.radians(center_lat)))
lat_delta = radius / 111000
lon_delta = radius / (111000 * np.cos(np.radians(center_lat)))
bbox = BoundingBox(
min_lat=center_lat - lat_delta,
min_lon=center_lon - lon_delta,
max_lat=center_lat + lat_delta,
max_lon=center_lon + lon_delta,
)
lat = center_lat - lat_delta
while lat <= center_lat + lat_delta:
lon = center_lon - lon_delta
while lon <= center_lon + lon_delta:
dist = haversine_distance(center_lat, center_lon, lat, lon)
if dist <= radius:
points.append((lat, lon))
lon += lon_step
lat += lat_step
return Grid(points=points, bounding_box=bbox, resolution=resolution, radius=radius)
@staticmethod
def generate_multi_site(sites: list, radius: float, resolution: float) -> Grid:
all_points = set()
min_lat = min_lon = float("inf")
max_lat = max_lon = float("-inf")
for site in sites:
grid = GridService.generate(site.lat, site.lon, radius, resolution)
for p in grid.points:
all_points.add((round(p[0], 7), round(p[1], 7)))
min_lat = min(min_lat, grid.bounding_box.min_lat)
min_lon = min(min_lon, grid.bounding_box.min_lon)
max_lat = max(max_lat, grid.bounding_box.max_lat)
max_lon = max(max_lon, grid.bounding_box.max_lon)
return Grid(
points=list(all_points),
bounding_box=BoundingBox(min_lat, min_lon, max_lat, max_lon),
resolution=resolution, radius=radius,
)