73 lines
1.7 KiB
Python
73 lines
1.7 KiB
Python
from typing import Literal
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
from app.models.common import AntennaPoint, GeoJSON, Point, SurfaceKind
|
|
|
|
|
|
class ElevationResponse(Point):
|
|
elevation_m: float
|
|
surface: SurfaceKind
|
|
|
|
|
|
class TerrainProfileRequest(BaseModel):
|
|
start: Point
|
|
end: Point
|
|
samples: int = Field(default=512, ge=2, le=10000)
|
|
include_buildings: bool = True
|
|
include_canopy: bool = True
|
|
k_factor: float = Field(default=1.333, gt=0)
|
|
|
|
|
|
class ProfileSample(BaseModel):
|
|
i: int
|
|
lat: float
|
|
lon: float
|
|
distance_m: float
|
|
ground_m: float
|
|
building_m: float
|
|
canopy_m: float
|
|
surface_m: float
|
|
curvature_corr_m: float
|
|
|
|
|
|
class TerrainProfileResponse(BaseModel):
|
|
distance_m: float
|
|
samples: list[ProfileSample]
|
|
path_geojson: GeoJSON
|
|
|
|
|
|
class LosRequest(BaseModel):
|
|
tx: AntennaPoint
|
|
rx: AntennaPoint
|
|
frequency_mhz: float = Field(gt=0)
|
|
fresnel_clearance: float = Field(default=0.6, ge=0)
|
|
include_buildings: bool = True
|
|
include_canopy: bool = True
|
|
include_vegetation: bool = True
|
|
k_factor: float = Field(default=1.333, gt=0)
|
|
samples: int = Field(default=512, ge=2, le=10000)
|
|
|
|
|
|
class Obstruction(BaseModel):
|
|
distance_m: float
|
|
clearance_m: float
|
|
fresnel_radius_m: float
|
|
required_clearance_m: float
|
|
type: Literal["terrain", "building", "canopy"]
|
|
|
|
|
|
class LosResponse(BaseModel):
|
|
los_clear: bool
|
|
geometric_los: bool
|
|
first_fresnel_clearance_pct: float
|
|
worst_obstruction: Obstruction | None
|
|
obstructions: list[Obstruction]
|
|
geometric_obstructions: list[Obstruction]
|
|
fresnel_violations_count: int
|
|
geometric_obstructions_count: int
|
|
building_obstructions_count: int
|
|
diffraction_loss_db: float
|
|
vegetation_loss_db: float
|
|
profile_ref: str
|