From 3f76a787662b817d7c6541fb180c1dcbd8a38f85 Mon Sep 17 00:00:00 2001
From: Dane Johnson <daneallenjohnson@protonmail.com>
Date: Thu, 28 Apr 2022 16:14:34 -0500
Subject: [PATCH] Remove nodes with right click

---
 src/main.rs | 62 +++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 55 insertions(+), 7 deletions(-)

diff --git a/src/main.rs b/src/main.rs
index ebc46f4..354220f 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -9,6 +9,8 @@ extern crate image;
 use image::io::Reader as ImageReader;
 use image::{ DynamicImage };
 
+use std::collections::{HashMap, HashSet};
+
 use std::cell::RefCell;
 use std::rc::Rc;
 
@@ -21,26 +23,61 @@ struct Node {
     pub y: f32,
 
     pub name: String,
-    pub edges: Vec<usize>,
+    pub edges: HashSet<usize>,
 }
 #[derive(Serialize, Deserialize, Debug)]
 struct Board {
-    nodes: Vec<Node>,
+    nodes: HashMap<usize, Node>,
 }
 impl Board {
     pub fn new() -> Self {
-	let nodes = Vec::new();
+	let nodes = HashMap::new();
 	Board { nodes }
     }
 
     pub fn add_node(&mut self, x: f32, y: f32) {
-	self.nodes.push(Node {
+	self.nodes.insert(self.next_id(), Node {
 	    x,
 	    y,
 	    name: "Canada".to_string(),
-	    edges: vec![],
+	    edges: HashSet::new(),
 	});   
     }
+
+    pub fn remove_node(&mut self, id: usize) {
+	self.nodes.remove(&id);
+	for (_, node) in &mut self.nodes {
+	    node.edges.remove(&id);
+	}
+    }
+
+    pub fn nearest_node(&self, x: f32, y: f32) -> Option<usize> {
+	let f = |n: &Node| dist_sq((n.x, n.y), (x, y));
+	let mut iter = self.nodes.iter();
+	if let Some((id, node)) = iter.next() {
+	    let mut min = *id;
+	    let mut min_val = f(node);
+	    for (id, node) in iter {
+		let val = f(node);
+		if val < min_val {
+		    min = *id;
+		    min_val = val;
+		}
+	    }
+	    Some(min)
+	} else {
+	    None
+	}
+    }
+
+    fn next_id(&self) -> usize {
+	for i in 0 .. {
+	    if !self.nodes.contains_key(&i) {
+		return i;
+	    }
+	}
+	unreachable!();
+    }
 }
 
 struct AppState {
@@ -84,6 +121,10 @@ fn inv_lerp(v0: f32, v1: f32, a: f32) -> f32 {
     (a - v0) / (v1 - v0)
 }
 
+fn dist_sq((x0, y0): (f32, f32), (x1, y1): (f32, f32)) -> f32 {
+    (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)
+}
+
 trait CoordTransformer {
     fn to_coords(&self, x: i32, y: i32) -> (f32, f32);
     fn from_coords(&self, x: f32, y: f32) -> (i32, i32);
@@ -200,7 +241,7 @@ fn main() {
 	    image.draw(f.x(), f.y(), f.w(), f.h());
 	}
 	let board = &state.board;
-	for node in &board.nodes {
+	for (_, node) in &board.nodes {
 	    let (x, y) = f.from_coords(node.x, node.y);
 	    draw_text(&node.name, x, y);
 	}
@@ -211,7 +252,14 @@ fn main() {
 	    Event::Push => {
 		let mut state = state_clone.borrow_mut();
 		let (pos_x, pos_y) = f.to_coords(app::event_x(), app::event_y());
-		state.board.add_node(pos_x, pos_y);
+		if app::event_button() == 1 {
+		    state.board.add_node(pos_x, pos_y);
+		} else if app::event_button() == 3 {
+		    let id = state.board.nearest_node(pos_x, pos_y);
+		    if let Some(id) = id {
+			state.board.remove_node(id);
+		    }
+		}
 		app::redraw();
 		true
 	    }