Optimise
This commit is contained in:
parent
9179acd4cd
commit
2c613dc0d1
14 changed files with 376 additions and 188 deletions
|
|
@ -1,15 +1,20 @@
|
|||
/// Grid-based spatial index for fast rectangle queries over property rows.
|
||||
///
|
||||
/// Divides the UK bounding box into cells of ~0.01 degrees (~1km),
|
||||
/// each storing indices of rows whose lat/lon falls within that cell.
|
||||
/// Divides the bounding box into cells of ~0.01 degrees (~1km).
|
||||
/// Uses a Compressed Sparse Row (CSR) layout: a single flat `values` array
|
||||
/// plus an `offsets` array so that cell `i` owns `values[offsets[i]..offsets[i+1]]`.
|
||||
/// This eliminates per-cell Vec overhead (24 bytes each for ptr+len+cap).
|
||||
pub struct GridIndex {
|
||||
min_lat: f32,
|
||||
min_lon: f32,
|
||||
cell_size: f32,
|
||||
cols: usize,
|
||||
rows: usize,
|
||||
/// cells[row * cols + col] = vec of row indices
|
||||
cells: Vec<Vec<u32>>,
|
||||
/// Flat array of row indices, grouped by cell.
|
||||
values: Vec<u32>,
|
||||
/// offsets[i] is the start index in `values` for cell i.
|
||||
/// offsets[num_cells] is values.len() (sentinel).
|
||||
offsets: Vec<u32>,
|
||||
}
|
||||
|
||||
impl GridIndex {
|
||||
|
|
@ -41,25 +46,47 @@ impl GridIndex {
|
|||
|
||||
let rows = ((max_lat - min_lat) / cell_size).ceil() as usize + 1;
|
||||
let cols = ((max_lon - min_lon) / cell_size).ceil() as usize + 1;
|
||||
let num_cells = rows * cols;
|
||||
|
||||
tracing::debug!(
|
||||
rows_grid = rows,
|
||||
cols_grid = cols,
|
||||
total_cells = rows * cols,
|
||||
total_cells = num_cells,
|
||||
cell_size,
|
||||
"Building grid index"
|
||||
"Building grid index (CSR)"
|
||||
);
|
||||
|
||||
let mut cells: Vec<Vec<u32>> = vec![Vec::new(); rows * cols];
|
||||
// First pass: count items per cell
|
||||
let mut counts = vec![0u32; num_cells];
|
||||
for index in 0..lat.len() {
|
||||
let grid_row = ((lat[index] - min_lat) / cell_size) as usize;
|
||||
let grid_col = ((lon[index] - min_lon) / cell_size) as usize;
|
||||
counts[grid_row * cols + grid_col] += 1;
|
||||
}
|
||||
|
||||
// Build offsets from counts (prefix sum)
|
||||
let mut offsets = Vec::with_capacity(num_cells + 1);
|
||||
let mut running = 0u32;
|
||||
for &count in &counts {
|
||||
offsets.push(running);
|
||||
running += count;
|
||||
}
|
||||
offsets.push(running);
|
||||
let total = running as usize;
|
||||
|
||||
// Second pass: fill values using write cursors
|
||||
let mut cursors = offsets[..num_cells].to_vec();
|
||||
let mut values = vec![0u32; total];
|
||||
for index in 0..lat.len() {
|
||||
let grid_row = ((lat[index] - min_lat) / cell_size) as usize;
|
||||
let grid_col = ((lon[index] - min_lon) / cell_size) as usize;
|
||||
let cell_index = grid_row * cols + grid_col;
|
||||
cells[cell_index].push(index as u32);
|
||||
let pos = cursors[cell_index] as usize;
|
||||
values[pos] = index as u32;
|
||||
cursors[cell_index] += 1;
|
||||
}
|
||||
|
||||
tracing::debug!("Grid index built");
|
||||
tracing::debug!("Grid index built (CSR)");
|
||||
|
||||
GridIndex {
|
||||
min_lat,
|
||||
|
|
@ -67,7 +94,8 @@ impl GridIndex {
|
|||
cell_size,
|
||||
cols,
|
||||
rows,
|
||||
cells,
|
||||
values,
|
||||
offsets,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -83,7 +111,10 @@ impl GridIndex {
|
|||
for row in row_min..=row_max {
|
||||
let row_start = row * self.cols;
|
||||
for col in col_min..=col_max {
|
||||
result.extend_from_slice(&self.cells[row_start + col]);
|
||||
let cell_idx = row_start + col;
|
||||
let start = self.offsets[cell_idx] as usize;
|
||||
let end = self.offsets[cell_idx + 1] as usize;
|
||||
result.extend_from_slice(&self.values[start..end]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -108,7 +139,10 @@ impl GridIndex {
|
|||
for row in row_min..=row_max {
|
||||
let row_start = row * self.cols;
|
||||
for col in col_min..=col_max {
|
||||
for &row_idx in &self.cells[row_start + col] {
|
||||
let cell_idx = row_start + col;
|
||||
let start = self.offsets[cell_idx] as usize;
|
||||
let end = self.offsets[cell_idx + 1] as usize;
|
||||
for &row_idx in &self.values[start..end] {
|
||||
callback(row_idx);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue