90 lines
2.8 KiB
TypeScript
90 lines
2.8 KiB
TypeScript
/**
|
||
* Terrain Service – Phase 4 stub.
|
||
*
|
||
* Provides elevation queries that future phases will use for:
|
||
* - Line-of-sight (LOS) / non-LOS classification
|
||
* - Diffraction loss (knife-edge / Bullington)
|
||
* - Terrain-aware heatmaps
|
||
*
|
||
* For now we expose the interface and a flat-terrain mock.
|
||
* Switch to BackendTerrainService once the FastAPI `/api/terrain/*`
|
||
* endpoints are ready with real SRTM / DEM data.
|
||
*/
|
||
|
||
export interface TerrainService {
|
||
/** Return ground elevation (metres above sea level) at a point. */
|
||
getElevation(lat: number, lon: number): Promise<number>;
|
||
|
||
/**
|
||
* Return an elevation profile between two points.
|
||
* @param samples Number of equidistant samples along the path.
|
||
* @returns Array of elevations (metres) from start to end.
|
||
*/
|
||
getElevationProfile(
|
||
lat1: number,
|
||
lon1: number,
|
||
lat2: number,
|
||
lon2: number,
|
||
samples: number,
|
||
): Promise<number[]>;
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Mock – flat terrain (elevation 0 everywhere)
|
||
// ---------------------------------------------------------------------------
|
||
export class MockTerrainService implements TerrainService {
|
||
async getElevation(_lat: number, _lon: number): Promise<number> {
|
||
return 0;
|
||
}
|
||
|
||
async getElevationProfile(
|
||
_lat1: number,
|
||
_lon1: number,
|
||
_lat2: number,
|
||
_lon2: number,
|
||
samples: number,
|
||
): Promise<number[]> {
|
||
return Array(samples).fill(0);
|
||
}
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Backend – calls FastAPI terrain endpoints (Phase 4+)
|
||
// ---------------------------------------------------------------------------
|
||
export class BackendTerrainService implements TerrainService {
|
||
private apiUrl: string;
|
||
|
||
constructor(apiUrl: string) {
|
||
this.apiUrl = apiUrl;
|
||
}
|
||
|
||
async getElevation(lat: number, lon: number): Promise<number> {
|
||
const response = await fetch(
|
||
`${this.apiUrl}/api/terrain/elevation?lat=${lat}&lon=${lon}`,
|
||
);
|
||
if (!response.ok) throw new Error(`Terrain API error: ${response.status}`);
|
||
const data = await response.json();
|
||
return data.elevation;
|
||
}
|
||
|
||
async getElevationProfile(
|
||
lat1: number,
|
||
lon1: number,
|
||
lat2: number,
|
||
lon2: number,
|
||
samples: number,
|
||
): Promise<number[]> {
|
||
const response = await fetch(
|
||
`${this.apiUrl}/api/terrain/profile?lat1=${lat1}&lon1=${lon1}&lat2=${lat2}&lon2=${lon2}&samples=${samples}`,
|
||
);
|
||
if (!response.ok) throw new Error(`Terrain API error: ${response.status}`);
|
||
const data = await response.json();
|
||
return data.profile;
|
||
}
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Default export – use Mock until backend is ready
|
||
// ---------------------------------------------------------------------------
|
||
export const terrainService: TerrainService = new MockTerrainService();
|