162 lines
4.2 KiB
Rust
162 lines
4.2 KiB
Rust
use std::{
|
|
sync::{Arc, RwLock},
|
|
thread,
|
|
};
|
|
|
|
#[derive(Debug, Default, Clone, Copy, PartialEq, PartialOrd)]
|
|
pub struct Point2d {
|
|
pub x: f64,
|
|
pub y: f64,
|
|
}
|
|
|
|
#[derive(Debug, Default, Clone, Copy)]
|
|
pub struct PVal {
|
|
point_index: usize,
|
|
val: f64,
|
|
}
|
|
|
|
impl PartialEq for PVal {
|
|
fn eq(&self, other: &Self) -> bool {
|
|
self.val == other.val
|
|
}
|
|
}
|
|
|
|
impl Eq for PVal {}
|
|
|
|
impl PartialOrd for PVal {
|
|
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
|
Some(self.cmp(other))
|
|
}
|
|
}
|
|
|
|
impl Ord for PVal {
|
|
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
|
self.val
|
|
.partial_cmp(&other.val)
|
|
.unwrap_or(std::cmp::Ordering::Equal)
|
|
}
|
|
}
|
|
|
|
impl PVal {
|
|
pub fn new(point: usize, val: f64) -> Self {
|
|
Self {
|
|
point_index: point,
|
|
val,
|
|
}
|
|
}
|
|
|
|
pub fn point_index(&self) -> usize {
|
|
self.point_index
|
|
}
|
|
|
|
pub fn val(&self) -> f64 {
|
|
self.val
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Default, Clone)]
|
|
pub struct Spindex2d {
|
|
pub xpoints: Arc<RwLock<Vec<usize>>>,
|
|
pub ypoints: Arc<RwLock<Vec<usize>>>,
|
|
pub xs: Arc<RwLock<Vec<PVal>>>,
|
|
pub ys: Arc<RwLock<Vec<PVal>>>,
|
|
}
|
|
|
|
impl Spindex2d {
|
|
pub fn new(points: &[Point2d]) -> Self {
|
|
let mut xpoints = Vec::with_capacity(points.len());
|
|
let mut xs = Vec::with_capacity(points.len());
|
|
|
|
let mut ypoints = Vec::with_capacity(points.len());
|
|
let mut ys = Vec::with_capacity(points.len());
|
|
|
|
thread::scope(|s| {
|
|
s.spawn(|| {
|
|
for (i, point) in points.iter().enumerate() {
|
|
let x = PVal::new(i, point.x);
|
|
xs.push(x);
|
|
xpoints.push(i);
|
|
}
|
|
});
|
|
|
|
s.spawn(|| {
|
|
for (i, point) in points.iter().enumerate() {
|
|
let y = PVal::new(i, point.y);
|
|
ys.push(y);
|
|
ypoints.push(i);
|
|
}
|
|
});
|
|
});
|
|
|
|
let index = Self {
|
|
xpoints: Arc::new(RwLock::new(xpoints)),
|
|
ypoints: Arc::new(RwLock::new(ypoints)),
|
|
xs: Arc::new(RwLock::new(xs)),
|
|
ys: Arc::new(RwLock::new(ys)),
|
|
};
|
|
|
|
index.sort();
|
|
|
|
index
|
|
}
|
|
|
|
/// This method assumes that the points have the same cardinality and order as the points used
|
|
/// when constructing this index. May panic if the updated points argument is longer than the
|
|
/// original points.
|
|
pub fn update(&self, points: &[Point2d]) {
|
|
thread::scope(|s| {
|
|
s.spawn(|| {
|
|
let mut xs = self.xs.write().unwrap();
|
|
let xpoints = self.xpoints.read().unwrap();
|
|
|
|
for (i, point) in points.iter().enumerate() {
|
|
let xi = xpoints[i];
|
|
let x = PVal::new(i, point.x);
|
|
xs[xi] = x;
|
|
}
|
|
});
|
|
|
|
s.spawn(|| {
|
|
let mut ys = self.ys.write().unwrap();
|
|
let ypoints = self.ypoints.read().unwrap();
|
|
|
|
for (i, point) in points.iter().enumerate() {
|
|
let yi = ypoints[i];
|
|
let y = PVal::new(i, point.y);
|
|
ys[yi] = y;
|
|
}
|
|
});
|
|
});
|
|
|
|
self.sort();
|
|
}
|
|
|
|
fn sort(&self) {
|
|
let xs = self.xs.clone();
|
|
let points = self.xpoints.clone();
|
|
let xhandle = thread::spawn(move || {
|
|
let mut xs = xs.write().unwrap();
|
|
xs.sort_unstable();
|
|
let mut points = points.write().unwrap();
|
|
for (i, x) in xs.iter().enumerate() {
|
|
let p = x.point_index;
|
|
points[p] = i;
|
|
}
|
|
});
|
|
|
|
let ys = self.ys.clone();
|
|
let points = self.ypoints.clone();
|
|
let yhandle = thread::spawn(move || {
|
|
let mut ys = ys.write().unwrap();
|
|
ys.sort_unstable();
|
|
let mut points = points.write().unwrap();
|
|
for (i, y) in ys.iter().enumerate() {
|
|
let p = y.point_index;
|
|
points[p] = i;
|
|
}
|
|
});
|
|
|
|
xhandle.join().unwrap();
|
|
yhandle.join().unwrap();
|
|
}
|
|
}
|