added vegetation

This commit is contained in:
2026-06-23 13:22:07 +03:00
parent cfbfcb52d3
commit 1867018672
10 changed files with 145 additions and 27 deletions
Binary file not shown.
Binary file not shown.
+29 -2
View File
@@ -1,19 +1,44 @@
from sqlalchemy.orm import Session
from app.core.diffraction import deygout
from app.core.fresnel import los_analysis
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.terrain import surface_profile_from_points
from app.services.vegetation import vegetation_loss_along
def link_budget(request: LinkBudgetRequest) -> LinkBudgetResponse:
def link_budget(request: LinkBudgetRequest, db: Session | None = None) -> 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)
freq_hz = request.frequency_mhz * 1_000_000
surface_profile = surface_profile_from_points(
points,
include_buildings=request.include_buildings,
include_canopy=False,
db=db,
)
los_result = los_analysis(
surface_profile,
tx_height_agl=request.tx.height_agl,
rx_height_agl=request.rx.height_agl,
freq_hz=freq_hz,
k=request.k_factor,
)
diffraction_db = deygout(
surface_profile,
tx_height_agl=request.tx.height_agl,
rx_height_agl=request.rx.height_agl,
freq_hz=freq_hz,
)
vegetation_db = vegetation_loss_along(
points,
freq_hz=request.frequency_mhz * 1_000_000,
freq_hz=freq_hz,
include_vegetation=request.include_vegetation,
)
budget = manual_link_budget(
@@ -24,6 +49,8 @@ def link_budget(request: LinkBudgetRequest) -> LinkBudgetResponse:
rx_gain_dbi=request.rx.gain_dbi,
sensitivity_dbm=request.rx.sensitivity_dbm,
frequency_mhz=request.frequency_mhz,
diffraction_db=diffraction_db,
vegetation_db=vegetation_db,
fresnel_clear=los_result.los_clear,
)
return LinkBudgetResponse(**budget.__dict__)
+26 -19
View File
@@ -9,7 +9,7 @@ from app.core import dem
from app.core.diffraction import deygout
from app.core.fresnel import LosSample, los_analysis
from app.core.geo import GeoPoint, PathPoint, linestring_geojson, sample_path
from app.core.surface import build_surface_profile
from app.core.surface import SurfaceProfile, build_surface_profile
from app.models.terrain import (
ElevationResponse,
LosRequest,
@@ -38,18 +38,11 @@ def terrain_profile(
GeoPoint(lat=request.end.lat, lon=request.end.lon),
request.samples,
)
try:
ground_elevations = dem.elevations_along(points, dem_path=get_settings().dem_path).tolist()
except dem.DemNotConfiguredError:
ground_elevations = np.zeros(len(points), dtype=float).tolist()
building_heights = _building_heights(points, request.include_buildings, db)
profile = build_surface_profile(
profile = surface_profile_from_points(
points,
ground_elevations=ground_elevations,
building_heights=building_heights,
include_buildings=request.include_buildings,
include_canopy=request.include_canopy,
db=db,
)
return TerrainProfileResponse(
distance_m=profile.distance_m,
@@ -75,18 +68,11 @@ def los(
GeoPoint(lat=request.rx.lat, lon=request.rx.lon),
request.samples,
)
try:
ground_elevations = dem.elevations_along(points, dem_path=get_settings().dem_path).tolist()
except dem.DemNotConfiguredError:
ground_elevations = np.zeros(len(points), dtype=float).tolist()
building_heights = _building_heights(points, request.include_buildings, db)
surface_profile = build_surface_profile(
surface_profile = surface_profile_from_points(
points,
ground_elevations=ground_elevations,
building_heights=building_heights,
include_buildings=request.include_buildings,
include_canopy=request.include_canopy,
db=db,
)
result = los_analysis(
surface_profile,
@@ -153,3 +139,24 @@ def _building_heights(
return buildings_service.building_heights_along(points, db)
except SQLAlchemyError:
return None
def surface_profile_from_points(
points: list[PathPoint],
include_buildings: bool,
include_canopy: bool,
db: Session | None = None,
) -> SurfaceProfile:
try:
ground_elevations = dem.elevations_along(points, dem_path=get_settings().dem_path).tolist()
except dem.DemNotConfiguredError:
ground_elevations = np.zeros(len(points), dtype=float).tolist()
building_heights = _building_heights(points, include_buildings, db)
return build_surface_profile(
points,
ground_elevations=ground_elevations,
building_heights=building_heights,
include_buildings=include_buildings,
include_canopy=include_canopy,
)