Support outcode & gps search

This commit is contained in:
Andras Schmelczer 2026-04-04 09:58:58 +01:00
parent 23d128ff63
commit 3853b5dce7
6 changed files with 188 additions and 3 deletions

View file

@ -28,6 +28,12 @@ pub struct PostcodesResponse {
features: Vec<Map<String, Value>>,
}
#[derive(Deserialize)]
pub struct NearestPostcodeParams {
lat: f64,
lng: f64,
}
#[derive(Deserialize)]
pub struct PostcodeParams {
bounds: Option<String>,
@ -311,6 +317,45 @@ pub async fn get_postcodes(
Ok(Json(response))
}
/// Find the nearest postcode to a given lat/lng coordinate.
pub async fn get_nearest_postcode(
State(shared): State<Arc<SharedState>>,
Query(params): Query<NearestPostcodeParams>,
) -> Result<Json<Value>, StatusCode> {
let state = shared.load_state();
let postcode_data = &state.postcode_data;
let query_lat = params.lat as f32;
let query_lng = params.lng as f32;
let cos_lat = (query_lat as f64).to_radians().cos() as f32;
let mut best_idx: Option<usize> = None;
let mut best_dist_sq = f32::MAX;
for (idx, &(pc_lat, pc_lon)) in postcode_data.centroids.iter().enumerate() {
let dlat = pc_lat - query_lat;
let dlon = (pc_lon - query_lng) * cos_lat;
let dist_sq = dlat * dlat + dlon * dlon;
if dist_sq < best_dist_sq {
best_dist_sq = dist_sq;
best_idx = Some(idx);
}
}
let idx = best_idx.ok_or(StatusCode::NOT_FOUND)?;
let (lat, lon) = postcode_data.centroids[idx];
let geometry = postcode_data.geometries[idx].clone();
let postcode = &postcode_data.postcodes[idx];
info!(postcode = %postcode, "GET /api/nearest-postcode");
Ok(Json(serde_json::json!({
"postcode": postcode,
"latitude": lat as f64,
"longitude": lon as f64,
"geometry": geometry,
})))
}
/// Look up a single postcode and return its centroid coordinates and geometry.
pub async fn get_postcode_lookup(
State(shared): State<Arc<SharedState>>,