added land

This commit is contained in:
2026-06-23 13:14:27 +03:00
parent 11a172ef3d
commit cfbfcb52d3
15 changed files with 106 additions and 4 deletions
Binary file not shown.
Binary file not shown.
+13 -3
View File
@@ -1,19 +1,29 @@
from app.core.geo import GeoPoint
from app.core.geo import GeoPoint, sample_path
from app.core.propagation import manual_link_budget
from app.models.link import LinkBudgetRequest, LinkBudgetResponse
from app.services.vegetation import vegetation_loss_along
def link_budget(request: LinkBudgetRequest) -> LinkBudgetResponse:
if request.model != "manual":
raise NotImplementedError(f"{request.model} link model is implemented in a later stage")
tx = GeoPoint(lat=request.tx.lat, lon=request.tx.lon)
rx = GeoPoint(lat=request.rx.lat, lon=request.rx.lon)
points = sample_path(tx, rx, 256)
vegetation_db = vegetation_loss_along(
points,
freq_hz=request.frequency_mhz * 1_000_000,
include_vegetation=request.include_vegetation,
)
budget = manual_link_budget(
tx=GeoPoint(lat=request.tx.lat, lon=request.tx.lon),
rx=GeoPoint(lat=request.rx.lat, lon=request.rx.lon),
tx=tx,
rx=rx,
tx_power_dbm=request.tx.power_dbm,
tx_gain_dbi=request.tx.gain_dbi,
rx_gain_dbi=request.rx.gain_dbi,
sensitivity_dbm=request.rx.sensitivity_dbm,
frequency_mhz=request.frequency_mhz,
vegetation_db=vegetation_db,
)
return LinkBudgetResponse(**budget.__dict__)
+7
View File
@@ -20,6 +20,7 @@ from app.models.terrain import (
TerrainProfileResponse,
)
from app.services import buildings as buildings_service
from app.services.vegetation import vegetation_loss_along
def elevation_at(lat: float, lon: float, surface: str) -> ElevationResponse:
@@ -101,6 +102,11 @@ def los(
request.rx.height_agl,
request.frequency_mhz * 1_000_000,
)
vegetation_loss = vegetation_loss_along(
points,
freq_hz=request.frequency_mhz * 1_000_000,
include_vegetation=request.include_vegetation,
)
def convert(sample: LosSample) -> Obstruction:
return Obstruction(
@@ -131,6 +137,7 @@ def los(
geometric_obstructions_count=len(geometric_obstructions),
building_obstructions_count=len(building_obstructions),
diffraction_loss_db=diffraction_loss,
vegetation_loss_db=vegetation_loss,
profile_ref=f"inline:{profile_request.samples}",
)
+39
View File
@@ -0,0 +1,39 @@
from __future__ import annotations
from pathlib import Path
from app.config import get_settings
from app.core.geo import PathPoint
from app.core.landcover import LandcoverNotConfiguredError, landcover_path
from app.core.vegetation import P833Coefficients, p833_attenuation
def vegetation_loss_along(
points: list[PathPoint],
freq_hz: float,
include_vegetation: bool,
landcover_path_dir: str | Path | None = None,
canopy_path_dir: str | Path | None = None,
) -> float:
if not include_vegetation:
return 0.0
settings = get_settings()
landcover_dir = landcover_path_dir or settings.landcover_path
canopy_dir = canopy_path_dir or settings.canopy_path
try:
path = landcover_path(points, landcover_dir, canopy_dir)
except LandcoverNotConfiguredError:
return 0.0
coefficients = P833Coefficients(
gamma_db_per_m=settings.p833_gamma_db_per_m,
max_attenuation_db=settings.p833_max_attenuation_db,
)
return p833_attenuation(
depth_m=path.vegetation_depth_m,
freq_hz=freq_hz,
forest_type="unknown",
coefficients=coefficients,
)