use super::wire::{PackedSint64Iter, WireDenseNodes};
pub(crate) struct DenseNodeColumns {
pub ids: Vec<i64>,
pub lats: Vec<i32>,
pub lons: Vec<i32>,
}
impl DenseNodeColumns {
pub fn new() -> Self {
Self {
ids: Vec::new(),
lats: Vec::new(),
lons: Vec::new(),
}
}
#[inline]
pub fn len(&self) -> usize {
self.ids.len()
}
pub fn clear(&mut self) {
self.ids.clear();
self.lats.clear();
self.lons.clear();
}
#[allow(clippy::cast_possible_truncation)]
pub fn decode_append(
&mut self,
dense: &WireDenseNodes<'_>,
granularity: i32,
lat_offset: i64,
lon_offset: i64,
) {
let gran = i64::from(granularity);
let mut cumulative_id: i64 = 0;
for delta in PackedSint64Iter::new(dense.id_data) {
cumulative_id += delta;
self.ids.push(cumulative_id);
}
if granularity == 100 && lat_offset % 100 == 0 && lon_offset % 100 == 0 {
#[allow(clippy::cast_possible_wrap)]
let lat_off_e7 = (lat_offset / 100) as i32;
#[allow(clippy::cast_possible_wrap)]
let lon_off_e7 = (lon_offset / 100) as i32;
let mut cumulative_lat: i64 = 0;
for delta in PackedSint64Iter::new(dense.lat_data) {
cumulative_lat += delta;
self.lats.push(cumulative_lat as i32 + lat_off_e7);
}
let mut cumulative_lon: i64 = 0;
for delta in PackedSint64Iter::new(dense.lon_data) {
cumulative_lon += delta;
self.lons.push(cumulative_lon as i32 + lon_off_e7);
}
} else {
let mut cumulative_lat: i64 = 0;
for delta in PackedSint64Iter::new(dense.lat_data) {
cumulative_lat += delta;
let nano = lat_offset + gran * cumulative_lat;
self.lats.push((nano / 100) as i32);
}
let mut cumulative_lon: i64 = 0;
for delta in PackedSint64Iter::new(dense.lon_data) {
cumulative_lon += delta;
let nano = lon_offset + gran * cumulative_lon;
self.lons.push((nano / 100) as i32);
}
}
}
#[inline]
pub fn collect_matching_ids_multi_bbox(
&self,
bboxes: &[(i32, i32, i32, i32)],
out: &mut [Vec<i64>],
) {
let n = self.len();
let lats = &self.lats;
let lons = &self.lons;
let ids = &self.ids;
for i in 0..n {
let lat = lats[i];
let lon = lons[i];
let id = ids[i];
for (j, &(min_lat, max_lat, min_lon, max_lon)) in bboxes.iter().enumerate() {
let hit = (lat >= min_lat) as u8
& (lat <= max_lat) as u8
& (lon >= min_lon) as u8
& (lon <= max_lon) as u8;
if hit != 0 {
out[j].push(id);
}
}
}
}
#[inline]
pub fn collect_matching_ids_bbox(
&self,
min_lat: i32,
max_lat: i32,
min_lon: i32,
max_lon: i32,
out: &mut Vec<i64>,
) {
let n = self.len();
let lats = &self.lats;
let lons = &self.lons;
let ids = &self.ids;
for i in 0..n {
let hit = (lats[i] >= min_lat) as u8
& (lats[i] <= max_lat) as u8
& (lons[i] >= min_lon) as u8
& (lons[i] <= max_lon) as u8;
if hit != 0 {
out.push(ids[i]);
}
}
}
}