added formulas

This commit is contained in:
2026-06-26 12:23:46 +03:00
parent 4df70fa270
commit 83ca6bc12c
8 changed files with 456 additions and 23 deletions
+96 -7
View File
@@ -3,9 +3,12 @@ from __future__ import annotations
from pathlib import Path
import pytest
import rasterio
from app.core import coverage as coverage_core
from app.core.antenna import AntennaPattern, gain
from app.core.coverage import compute_coverage
from app.core.surface import SurfaceProfile, SurfaceSample
from app.core.vegetation import WORLDCOVER_P833, p833_coefficients_for_class
from app.models.coverage import CoverageRequest
from app.services import jobs
@@ -22,7 +25,94 @@ def test_jobs_store_roundtrip() -> None:
def test_coverage_fspl_geojson() -> None:
request = CoverageRequest(
request = _coverage_request(format="geojson", radius_m=5000, range_step_m=500)
result = compute_coverage(request)
assert result["type"] == "FeatureCollection"
assert len(result["features"]) >= 1
def test_coverage_geotiff_export(tmp_path: Path) -> None:
request = _coverage_request(format="geotiff")
result = compute_coverage(request, output_dir=tmp_path)
path = Path(result["uri"])
assert path.exists()
assert result["kind"] == "coverage_raster"
assert result["format"] == "geotiff"
assert result["metadata"]["value_units"] == "dBm"
assert result["metadata"]["valid_pixels"] > 0
with rasterio.open(path) as dataset:
assert dataset.driver == "GTiff"
assert dataset.count == 1
assert dataset.crs is not None
assert dataset.nodata == -9999.0
data = dataset.read(1)
assert data.shape == (2, 2)
assert (data != -9999.0).any()
def test_coverage_png_export(tmp_path: Path) -> None:
request = _coverage_request(format="png")
result = compute_coverage(request, output_dir=tmp_path)
path = Path(result["uri"])
assert path.exists()
assert result["kind"] == "coverage_raster"
assert result["format"] == "png"
assert result["metadata"]["png_min_dbm"] is not None
with rasterio.open(path) as dataset:
assert dataset.driver == "PNG"
assert dataset.count == 1
assert dataset.read(1).shape == (2, 2)
def test_coverage_surface_obstruction_reduces_rx_power(monkeypatch) -> None:
def fake_surface_profile(points, *, include_buildings, include_canopy, db=None):
midpoint = len(points) // 2
samples = [
SurfaceSample(
i=index,
lat=point.lat,
lon=point.lon,
distance_m=point.distance_m,
ground_m=0.0,
building_m=0.0,
canopy_m=80.0 if include_canopy and index == midpoint else 0.0,
surface_m=80.0 if include_canopy and index == midpoint else 0.0,
)
for index, point in enumerate(points)
]
return SurfaceProfile(distance_m=points[-1].distance_m, samples=samples)
monkeypatch.setattr(coverage_core, "surface_profile_from_points", fake_surface_profile)
obstructed = _coverage_request(
format="geojson",
include_buildings=False,
include_canopy=True,
)
clear = _coverage_request(
format="geojson",
include_buildings=False,
include_canopy=False,
)
obstructed_power = coverage_core._rx_power_dbm(obstructed, 1.0, 90.0)
clear_power = coverage_core._rx_power_dbm(clear, 1.0, 90.0)
assert obstructed_power < clear_power
def _coverage_request(
*,
format: str,
radius_m: float = 1000,
range_step_m: float = 1000,
include_buildings: bool = False,
include_canopy: bool = False,
) -> CoverageRequest:
return CoverageRequest(
tx={
"lat": 59.935,
"lon": 30.305,
@@ -33,16 +123,15 @@ def test_coverage_fspl_geojson() -> None:
antenna={"pattern": "omni", "gain_dbi": 8},
rx={"height_agl": 2, "sensitivity_dbm": -110, "gain_dbi": 2},
model="fspl",
radius_m=5000,
radius_m=radius_m,
azimuth_step_deg=90,
range_step_m=500,
range_step_m=range_step_m,
include_buildings=include_buildings,
include_canopy=include_canopy,
include_vegetation=False,
levels_dbm=[-90],
format="geojson",
format=format,
)
result = compute_coverage(request)
assert result["type"] == "FeatureCollection"
assert len(result["features"]) >= 1
def test_worldcover_p833_mapping() -> None: