115 lines
3.1 KiB
Python
115 lines
3.1 KiB
Python
from typing import Literal
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
from app.models.common import AntennaPoint, DataSources, GeoJSON, Point, SurfaceKind
|
|
|
|
|
|
class ElevationResponse(Point):
|
|
elevation_m: float
|
|
surface: SurfaceKind
|
|
data_sources: DataSources = Field(default_factory=DataSources)
|
|
|
|
|
|
class TerrainProfileRequest(BaseModel):
|
|
start: Point
|
|
end: Point
|
|
samples: int = Field(default=512, ge=2, le=2048)
|
|
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
|
|
data_sources: DataSources = Field(default_factory=DataSources)
|
|
|
|
|
|
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=2048)
|
|
|
|
|
|
class FresnelSliceRequest(BaseModel):
|
|
tx: AntennaPoint
|
|
rx: AntennaPoint
|
|
frequency_mhz: float = Field(gt=0)
|
|
fresnel_fraction: float = Field(default=0.6, ge=0)
|
|
include_buildings: bool = True
|
|
include_canopy: bool = True
|
|
k_factor: float = Field(default=1.333, gt=0)
|
|
samples: int = Field(default=512, ge=2, le=2048)
|
|
building_limit: int = Field(default=5000, gt=0)
|
|
|
|
|
|
class Obstruction(BaseModel):
|
|
distance_m: float
|
|
clearance_m: float
|
|
fresnel_radius_m: float
|
|
required_clearance_m: float
|
|
type: Literal["terrain", "building", "canopy"]
|
|
|
|
|
|
class FresnelProfileSample(BaseModel):
|
|
i: int
|
|
lat: float
|
|
lon: float
|
|
distance_m: float
|
|
surface_m: float
|
|
path_height_m: float
|
|
obstacle_height_m: float
|
|
clearance_m: float
|
|
fresnel_radius_m: float
|
|
required_clearance_m: float
|
|
fresnel_upper_60pct_m: float
|
|
fresnel_upper_100pct_m: float
|
|
fresnel_lower_60pct_m: float
|
|
fresnel_lower_100pct_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_profile: list[FresnelProfileSample]
|
|
fresnel_violations_count: int
|
|
geometric_obstructions_count: int
|
|
building_obstructions_count: int
|
|
diffraction_loss_db: float
|
|
vegetation_loss_db: float
|
|
data_sources: DataSources = Field(default_factory=DataSources)
|
|
profile_ref: str
|
|
|
|
|
|
class FresnelSliceResponse(BaseModel):
|
|
path_geojson: GeoJSON
|
|
fresnel_geojson: GeoJSON
|
|
buildings_geojson: GeoJSON
|
|
profile: list[FresnelProfileSample]
|
|
data_sources: DataSources = Field(default_factory=DataSources)
|