Add some adjustments to reduce crash frequency
This commit is contained in:
parent
4a480d9680
commit
f1a90f0d9a
165
src/main.rs
165
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<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 {
|
||||
|
|
Loading…
Reference in New Issue