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;
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<NodeRef> = 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 {