use simple_accumulator::SimpleAccumulator;
use std::cell::Cell;
use std::collections::{HashMap, HashSet};
use std::fmt;
use std::hash::{Hash, Hasher};
#[derive(Debug, Copy, Clone)]
pub struct Point {
x: f64,
y: f64,
}
impl Point {
pub fn new(x: f64, y: f64) -> Self {
Point {
x: f64::trunc(x * 1000.0) / 1000.0,
y: f64::trunc(y * 1000.0) / 1000.0,
}
}
}
impl fmt::Display for Point {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:5} {:5}", self.x, self.y)
}
}
#[derive(Debug, Clone)]
pub struct Connection(String, String, Cell<usize>);
impl Eq for Connection {}
impl PartialEq for Connection {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0 && self.1 == other.1
}
}
impl PartialEq<String> for Connection {
fn eq(&self, other: &String) -> bool {
self.0 == *other || self.1 == *other
}
}
impl Hash for Connection {
fn hash<H: Hasher>(&self, hasher: &mut H) {
self.0.hash(hasher);
self.1.hash(hasher);
}
}
#[derive(Debug, Clone)]
pub struct Graph(HashSet<Connection>);
impl Graph {
pub fn push(&mut self, connection: &Connection) {
self.0.insert(connection.clone());
if let Some(x) = self.0.get(connection) {
let val = x.2.get();
x.2.set(val + 1);
}
}
}
#[derive(Debug, Clone)]
pub struct PointPlane {
pub points: HashMap<String, u32>,
pub graph: Graph,
pub accumulate_xaxis: SimpleAccumulator,
pub accumulate_yaxis: SimpleAccumulator,
capacity: usize,
}
impl PointPlane {
pub fn new(points: Vec<Point>, capacity: usize) -> Self {
let mut graph = Graph(HashSet::<Connection>::with_capacity(100));
let mut frequencies: HashMap<String, u32> = HashMap::with_capacity(100);
let mut x = Vec::with_capacity(capacity);
let mut y = Vec::with_capacity(capacity);
*frequencies.entry(points[0].to_string()).or_insert(0) += 1;
x.push(points[0].x);
y.push(points[0].y);
for k in 1..points.len() {
x.push(points[k].x);
y.push(points[k].y);
graph.push(&Connection(
(points[k - 1].x).to_string() + "-" + &*(points[k - 1].y).to_string(),
(points[k].x).to_string() + "-" + &*(points[k].y).to_string(),
Cell::new(0),
));
*frequencies.entry(points[k].to_string()).or_insert(0) += 1;
}
PointPlane {
points: frequencies,
graph,
accumulate_xaxis: SimpleAccumulator::with_fixed_capacity(&x, capacity, true),
accumulate_yaxis: SimpleAccumulator::with_fixed_capacity(&y, capacity, true),
capacity,
}
}
}