Add some adjustments to reduce crash frequency

This commit is contained in:
Emi Simpson 2021-11-16 17:47:29 -05:00
parent 4a480d9680
commit f1a90f0d9a
Signed by: Emi
GPG Key ID: A12F2C2FFDC3D847
1 changed files with 125 additions and 40 deletions

View File

@ -1,12 +1,15 @@
pub mod util; pub mod util;
use macroquad::prelude::DVec2;
use macroquad::prelude::Rect;
use macroquad::prelude::Camera2D;
use core::mem::swap; use core::mem::swap;
use std::collections::HashMap; use std::collections::HashMap;
use core::fmt; use core::fmt;
use core::cell::Cell; use core::cell::Cell;
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
use core::f32::consts::PI;
use macroquad::prelude::draw_circle_lines; use macroquad::prelude::draw_circle_lines;
use core::f64::consts::PI;
use macroquad::prelude::mouse_position; use macroquad::prelude::mouse_position;
use macroquad::prelude::is_mouse_button_pressed; use macroquad::prelude::is_mouse_button_pressed;
use macroquad::prelude::Vec2; 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 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 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")] #[macroquad::main("BasicShapes")]
async fn main() { async fn main() {
let mut dd = DelaunayDemo::default(); let mut dd = DelaunayDemo::default();
@ -36,6 +43,22 @@ async fn main() {
if is_mouse_button_pressed(MouseButton::Left) { if is_mouse_button_pressed(MouseButton::Left) {
dd.click(mouse_position().into()) 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.update();
dd.draw(); dd.draw();
next_frame().await; next_frame().await;
@ -50,10 +73,12 @@ pub struct DelaunayDemo {
random_state: u128 random_state: u128
} }
#[derive(Debug)]
enum NeighborOne { enum NeighborOne {
Occupant(Triangle), Occupant(Triangle),
Border, Border,
} }
#[derive(Debug)]
enum NeighborTwo { enum NeighborTwo {
Friend(Triangle), Friend(Triangle),
Hole, Hole,
@ -97,11 +122,13 @@ impl NeighborTwo {
impl Default for DelaunayDemo { impl Default for DelaunayDemo {
fn default() -> Self { fn default() -> Self {
let height = screen_height() as f64;
let width = screen_width() as f64;
let nodes: Vec<NodeRef> = vec![ let nodes: Vec<NodeRef> = vec![
Arc::new(Cell::new((0.0, 0.0).into())), Arc::new(Cell::new((-5.0 - BOING_RADIUS, 0.0 - BOING_RADIUS).into())),
Arc::new(Cell::new((0.0, screen_height()).into())), Arc::new(Cell::new((0.0 - BOING_RADIUS, height + BOING_RADIUS).into())),
Arc::new(Cell::new((screen_width(), 0.0).into())), Arc::new(Cell::new((width + BOING_RADIUS, 0.0 - BOING_RADIUS).into())),
Arc::new(Cell::new((screen_width(), screen_height()).into())), Arc::new(Cell::new((width + BOING_RADIUS, height + BOING_RADIUS).into())),
]; ];
let edges = ( let edges = (
Edge(nodes[2].clone(), nodes[0].clone()), Edge(nodes[2].clone(), nodes[0].clone()),
@ -125,32 +152,55 @@ impl Default for DelaunayDemo {
(edges.3, (Border, (&triangles[1]).into())), (edges.3, (Border, (&triangles[1]).into())),
(edges.4, (Border, (&triangles[1]).into())), (edges.4, (Border, (&triangles[1]).into())),
].into(); ].into();
DelaunayDemo { let mut dd = DelaunayDemo {
nodes, adjacency, triangles, random_state: 1312_1312_1312, poisoned: false, 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)] #[derive(Copy, Clone, Debug)]
pub struct Node(Vec2, Vec2); pub struct Node(DVec2, DVec2);
impl Deref for Node { impl Deref for Node {
type Target = Vec2; type Target = DVec2;
fn deref(&self) -> &Vec2 { fn deref(&self) -> &DVec2 {
&self.0 &self.0
} }
} }
impl DerefMut for Node { impl DerefMut for Node {
fn deref_mut(&mut self) -> &mut Vec2 { fn deref_mut(&mut self) -> &mut DVec2 {
&mut self.0 &mut self.0
} }
} }
impl From<(f32, f32)> for Node { impl From<(f64, f64)> for Node {
fn from((x, y): (f32, f32)) -> Node { fn from((x, y): (f64, f64)) -> Node {
Node(Vec2::new(x, y), Vec2::ZERO) 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()) 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_a = b.distance(c);
let len_b = c.distance(a); let len_b = c.distance(a);
let len_c = a.distance(b); 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_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 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_a = f64::acos(cos_a);
let ang_b = f32::acos(cos_b); let ang_b = f64::acos(cos_b);
let ang_c = PI - ang_a - ang_b; let ang_c = PI - ang_a - ang_b;
let sin_2a = f32::sin(2.0 * ang_a); let sin_2a = f64::sin(2.0 * ang_a);
let sin_2b = f32::sin(2.0 * ang_b); let sin_2b = f64::sin(2.0 * ang_b);
let sin_2c = f32::sin(2.0 * ang_c); 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.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), (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) (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(); let (c, r) = self.circumcenter();
c.distance(point) < r c.distance(point) < r
} }
@ -319,14 +369,14 @@ impl Triangle {
let othr_sidea = common_edge.0.get().distance(*othr_point.get()); let othr_sidea = common_edge.0.get().distance(*othr_point.get());
let othr_sideb = common_edge.1.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_sidea.powf(2.0)
+ self_sideb.powf(2.0) + self_sideb.powf(2.0)
- common_distance.powf(2.0) - common_distance.powf(2.0)
) / (2.0 * self_sidea * self_sideb) ) / (2.0 * self_sidea * self_sideb)
); );
let othr_angle = f32::acos( let othr_angle = f64::acos(
( (
othr_sidea.powf(2.0) othr_sidea.powf(2.0)
+ othr_sideb.powf(2.0) + othr_sideb.powf(2.0)
@ -394,21 +444,37 @@ impl fmt::Debug for Triangle {
impl DelaunayDemo { impl DelaunayDemo {
fn draw(&self) { fn draw(&self) {
clear_background(BG); clear_background(BG);
let mut highlight_segments = Vec::new();
for triangle in &self.triangles { for triangle in &self.triangles {
let (c, r) = triangle.circumcenter(); 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() { 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( draw_line(
edge.0.get().x, edge_0.x,
edge.0.get().y, edge_0.y,
edge.1.get().x, edge_1.x,
edge.1.get().y, edge_1.y,
3.0, FG 3.0, color
); );
} }
for node in &self.nodes { 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 return
} }
for node in self.nodes.clone() { for node in self.nodes.clone() {
if node.get().1 != Vec2::ZERO { if node.get().1 != DVec2::ZERO {
self.move_point(node); self.move_point(node);
} }
} }
@ -430,11 +496,11 @@ impl DelaunayDemo {
fn click(&mut self, pos: Vec2) { fn click(&mut self, pos: Vec2) {
let random = util::pcg64(&mut self.random_state); let random = util::pcg64(&mut self.random_state);
let angle = (random as f64) / (u64::MAX as f64) * (2.0 * std::f64::consts::PI); let angle = (random as f64) / (u64::MAX as f64) * (2.0 * std::f64::consts::PI);
let direction = Vec2::new( let direction = DVec2::new(
f64::cos(angle) as f32, f64::cos(angle),
f64::sin(angle) as f32, 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; self.poisoned = true;
eprintln!("POISONED: {}", msg); eprintln!("POISONED: {}", msg);
} }
@ -566,17 +632,36 @@ impl DelaunayDemo {
let mut node_inner = node.get(); let mut node_inner = node.get();
node_inner.0 = node_inner.0 + node_inner.1; 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 // Check for a bounce
if node_inner.0.y > screen_height() { let height = screen_height() as f64;
node_inner.0.y = 2.0 * screen_height() - node_inner.0.y; 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; node_inner.1.y = -node_inner.1.y;
} }
if node_inner.0.y < 0.0 { if node_inner.0.y < 0.0 {
node_inner.0.y = -node_inner.0.y; node_inner.0.y = -node_inner.0.y;
node_inner.1.y = -node_inner.1.y; node_inner.1.y = -node_inner.1.y;
} }
if node_inner.0.x > screen_width() { if node_inner.0.x > width {
node_inner.0.x = 2.0 * screen_width() - node_inner.0.x; node_inner.0.x = 2.0 * width - node_inner.0.x;
node_inner.1.x = -node_inner.1.x; node_inner.1.x = -node_inner.1.x;
} }
if node_inner.0.x < 0.0 { if node_inner.0.x < 0.0 {