From f1a90f0d9ae206615dfd6379728cbdc7c84b0998 Mon Sep 17 00:00:00 2001 From: Emi Simpson Date: Tue, 16 Nov 2021 17:47:29 -0500 Subject: [PATCH] Add some adjustments to reduce crash frequency --- src/main.rs | 165 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 125 insertions(+), 40 deletions(-) diff --git a/src/main.rs b/src/main.rs index 88424ec..1359506 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,12 +1,15 @@ pub mod util; +use macroquad::prelude::DVec2; +use macroquad::prelude::Rect; +use macroquad::prelude::Camera2D; use core::mem::swap; use std::collections::HashMap; use core::fmt; use core::cell::Cell; use std::collections::hash_map::Entry; -use core::f32::consts::PI; use macroquad::prelude::draw_circle_lines; +use core::f64::consts::PI; use macroquad::prelude::mouse_position; use macroquad::prelude::is_mouse_button_pressed; use macroquad::prelude::Vec2; @@ -29,6 +32,10 @@ const FG: Color = Color::new(0.91569, 0.71765, 0.00000, 1.0); const DIM_FG: Color = Color::new(0.29412, 0.27451, 0.13333, 1.0); const HIL_FG: Color = Color::new(0.25806, 0.61290, 1.09032, 1.0); +const SPEED: f64 = 0.8; +const BOING_RADIUS: f64 = 30.0; +const HILITE: bool = false; + #[macroquad::main("BasicShapes")] async fn main() { let mut dd = DelaunayDemo::default(); @@ -36,6 +43,22 @@ async fn main() { if is_mouse_button_pressed(MouseButton::Left) { dd.click(mouse_position().into()) } + if is_mouse_button_pressed(MouseButton::Right) { + let mouse_position = camera.screen_to_world(mouse_position().into()); + + println!("{}", mouse_position); + + for triangle in &dd.triangles { + if triangle.invalidated_by_point(mouse_position.as_f64()) { + println!( + "{:?} has center {} with r={}", + triangle, + triangle.circumcenter().0, + triangle.circumcenter().1, + ); + } + } + } dd.update(); dd.draw(); next_frame().await; @@ -50,10 +73,12 @@ pub struct DelaunayDemo { random_state: u128 } +#[derive(Debug)] enum NeighborOne { Occupant(Triangle), Border, } +#[derive(Debug)] enum NeighborTwo { Friend(Triangle), Hole, @@ -97,11 +122,13 @@ impl NeighborTwo { impl Default for DelaunayDemo { fn default() -> Self { + let height = screen_height() as f64; + let width = screen_width() as f64; let nodes: Vec = vec![ - Arc::new(Cell::new((0.0, 0.0).into())), - Arc::new(Cell::new((0.0, screen_height()).into())), - Arc::new(Cell::new((screen_width(), 0.0).into())), - Arc::new(Cell::new((screen_width(), screen_height()).into())), + Arc::new(Cell::new((-5.0 - BOING_RADIUS, 0.0 - BOING_RADIUS).into())), + Arc::new(Cell::new((0.0 - BOING_RADIUS, height + BOING_RADIUS).into())), + Arc::new(Cell::new((width + BOING_RADIUS, 0.0 - BOING_RADIUS).into())), + Arc::new(Cell::new((width + BOING_RADIUS, height + BOING_RADIUS).into())), ]; let edges = ( Edge(nodes[2].clone(), nodes[0].clone()), @@ -125,32 +152,55 @@ impl Default for DelaunayDemo { (edges.3, (Border, (&triangles[1]).into())), (edges.4, (Border, (&triangles[1]).into())), ].into(); - DelaunayDemo { + let mut dd = DelaunayDemo { nodes, adjacency, triangles, random_state: 1312_1312_1312, poisoned: false, + }; + + /*let n_v_nodes = ((height / 50.0) - 1.0).round(); + let v_inc = height / n_v_nodes; + for i in 0..(n_v_nodes as usize) { + println!("A"); + let random = util::pcg64(&mut dd.random_state); + let offset = (random as f64) / (u64::MAX as f64) * 10.0; + dd.add_point((offset, (i + 1) as f64 * v_inc).into()).unwrap(); + println!("B"); + dd.add_point((width - offset, (i + 1) as f64 * v_inc).into()).unwrap(); } + let n_h_nodes = ((width / 50.0) - 1.0).round(); + let h_inc = width / n_h_nodes; + for i in 0..(n_h_nodes as usize) { + println!("C"); + let random = util::pcg64(&mut dd.random_state); + let offset = (random as f64) / (u64::MAX as f64) * 10.0; + dd.add_point(((i + 1) as f64 * h_inc, offset).into()).unwrap(); + println!("D"); + dd.add_point(((i + 1) as f64 * h_inc, height - offset).into()).unwrap(); + }*/ + + dd } } #[derive(Copy, Clone, Debug)] -pub struct Node(Vec2, Vec2); +pub struct Node(DVec2, DVec2); impl Deref for Node { - type Target = Vec2; + type Target = DVec2; - fn deref(&self) -> &Vec2 { + fn deref(&self) -> &DVec2 { &self.0 } } impl DerefMut for Node { - fn deref_mut(&mut self) -> &mut Vec2 { + fn deref_mut(&mut self) -> &mut DVec2 { &mut self.0 } } -impl From<(f32, f32)> for Node { - fn from((x, y): (f32, f32)) -> Node { - Node(Vec2::new(x, y), Vec2::ZERO) +impl From<(f64, f64)> for Node { + fn from((x, y): (f64, f64)) -> Node { + Node(DVec2::new(x, y), DVec2::ZERO) } } @@ -236,11 +286,11 @@ impl Triangle { } } - pub fn circumcenter(&self) -> (Vec2, f32) { + pub fn circumcenter(&self) -> (DVec2, f64) { Self::calc_circumcenter(*self.nodes[0].get(), *self.nodes[1].get(), *self.nodes[2].get()) } - fn calc_circumcenter(a: Vec2, b: Vec2, c: Vec2) -> (Vec2, f32) { + fn calc_circumcenter(a: DVec2, b: DVec2, c: DVec2) -> (DVec2, f64) { let len_a = b.distance(c); let len_b = c.distance(a); let len_c = a.distance(b); @@ -248,15 +298,15 @@ impl Triangle { let cos_a = (len_b.powf(2.0) + len_c.powf(2.0) - len_a.powf(2.0)) / (2.0 * len_b * len_c ); let cos_b = (len_c.powf(2.0) + len_a.powf(2.0) - len_b.powf(2.0)) / (2.0 * len_c * len_a ); - let ang_a = f32::acos(cos_a); - let ang_b = f32::acos(cos_b); + let ang_a = f64::acos(cos_a); + let ang_b = f64::acos(cos_b); let ang_c = PI - ang_a - ang_b; - let sin_2a = f32::sin(2.0 * ang_a); - let sin_2b = f32::sin(2.0 * ang_b); - let sin_2c = f32::sin(2.0 * ang_c); + let sin_2a = f64::sin(2.0 * ang_a); + let sin_2b = f64::sin(2.0 * ang_b); + let sin_2c = f64::sin(2.0 * ang_c); - let circumcenter = Vec2::new( + let circumcenter = DVec2::new( (a.x * sin_2a + b.x * sin_2b + c.x * sin_2c) / (sin_2a + sin_2b + sin_2c), (a.y * sin_2a + b.y * sin_2b + c.y * sin_2c) / (sin_2a + sin_2b + sin_2c), ); @@ -265,7 +315,7 @@ impl Triangle { (circumcenter, radius) } - pub fn invalidated_by_point(&self, point: Vec2) -> bool { + pub fn invalidated_by_point(&self, point: DVec2) -> bool { let (c, r) = self.circumcenter(); c.distance(point) < r } @@ -319,14 +369,14 @@ impl Triangle { let othr_sidea = common_edge.0.get().distance(*othr_point.get()); let othr_sideb = common_edge.1.get().distance(*othr_point.get()); - let self_angle = f32::acos( + let self_angle = f64::acos( ( self_sidea.powf(2.0) + self_sideb.powf(2.0) - common_distance.powf(2.0) ) / (2.0 * self_sidea * self_sideb) ); - let othr_angle = f32::acos( + let othr_angle = f64::acos( ( othr_sidea.powf(2.0) + othr_sideb.powf(2.0) @@ -394,21 +444,37 @@ impl fmt::Debug for Triangle { impl DelaunayDemo { fn draw(&self) { clear_background(BG); + let mut highlight_segments = Vec::new(); for triangle in &self.triangles { let (c, r) = triangle.circumcenter(); - draw_circle_lines(c.x, c.y, r, 1.0, DIM_FG); + let mpos: Vec2 = mouse_position().into(); + let color = if c.distance(mpos.as_f64()) < r && HILITE { + highlight_segments.extend(&triangle.edges); + HIL_FG + } else { + DIM_FG + }; + draw_circle_lines(c.x as f32, c.y as f32, r as f32, 1.0, color); } for edge in self.adjacency.keys() { + let color = if highlight_segments.contains(&edge) { + HIL_FG + } else { + FG + }; + let edge_0 = edge.0.get().as_f32(); + let edge_1 = edge.1.get().as_f32(); draw_line( - edge.0.get().x, - edge.0.get().y, - edge.1.get().x, - edge.1.get().y, - 3.0, FG + edge_0.x, + edge_0.y, + edge_1.x, + edge_1.y, + 3.0, color ); } for node in &self.nodes { - draw_circle(node.get().x, node.get().y, 10.0, FG); + let pos = node.get().as_f32(); + draw_circle(pos.x, pos.y, 10.0, FG); } } @@ -417,7 +483,7 @@ impl DelaunayDemo { return } for node in self.nodes.clone() { - if node.get().1 != Vec2::ZERO { + if node.get().1 != DVec2::ZERO { self.move_point(node); } } @@ -430,11 +496,11 @@ impl DelaunayDemo { fn click(&mut self, pos: Vec2) { let random = util::pcg64(&mut self.random_state); let angle = (random as f64) / (u64::MAX as f64) * (2.0 * std::f64::consts::PI); - let direction = Vec2::new( - f64::cos(angle) as f32, - f64::sin(angle) as f32, + let direction = DVec2::new( + f64::cos(angle), + f64::sin(angle), ); - if let Err(msg) = self.add_point(Node(pos, direction * 2.0)) { + if let Err(msg) = self.add_point(Node(pos.as_f64(), direction * SPEED)) { self.poisoned = true; eprintln!("POISONED: {}", msg); } @@ -566,17 +632,36 @@ impl DelaunayDemo { let mut node_inner = node.get(); node_inner.0 = node_inner.0 + node_inner.1; + // Check if it is going to hit another point + for other in &self.nodes { + if + !Arc::ptr_eq(other, &node) + && node_inner.distance(other.get().0) < BOING_RADIUS + { + let mut node_inner = node.get(); + let mut other_inner = other.get(); + + swap(&mut other_inner.1, &mut node_inner.1); + + other.set(other_inner); + node.set(node_inner); + return; + } + } + // Check for a bounce - if node_inner.0.y > screen_height() { - node_inner.0.y = 2.0 * screen_height() - node_inner.0.y; + let height = screen_height() as f64; + let width = screen_width() as f64; + if node_inner.0.y > height { + node_inner.0.y = 2.0 * height - node_inner.0.y; node_inner.1.y = -node_inner.1.y; } if node_inner.0.y < 0.0 { node_inner.0.y = -node_inner.0.y; node_inner.1.y = -node_inner.1.y; } - if node_inner.0.x > screen_width() { - node_inner.0.x = 2.0 * screen_width() - node_inner.0.x; + if node_inner.0.x > width { + node_inner.0.x = 2.0 * width - node_inner.0.x; node_inner.1.x = -node_inner.1.x; } if node_inner.0.x < 0.0 {