This commit is contained in:
Emi Simpson 2021-11-16 23:05:35 -05:00
parent 0226922ebf
commit 3e15269afb
Signed by: Emi
GPG Key ID: A12F2C2FFDC3D847
1 changed files with 182 additions and 182 deletions

View File

@ -27,14 +27,14 @@ use macroquad::prelude::Color;
use macroquad::input::MouseButton; use macroquad::input::MouseButton;
use std::sync::Arc; use std::sync::Arc;
const BG: Color = Color::new(0.16863, 0.23922, 0.21176, 1.0); const BG: Color = Color::new(0.16863, 0.23922, 0.21176, 1.0);
const FG: Color = Color::new(0.91569, 0.71765, 0.00000, 1.0); 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.1; const SPEED: f64 = 0.1;
const BOING_RADIUS: f64 = 30.0; const BOING_RADIUS: f64 = 30.0;
const HILITE: bool = false; const HILITE: bool = false;
#[macroquad::main("BasicShapes")] #[macroquad::main("BasicShapes")]
async fn main() { async fn main() {
@ -343,72 +343,72 @@ impl Triangle {
c.distance(point) < r c.distance(point) < r
} }
pub fn common_edge(&self, other: &Triangle) -> Result<&Edge, String> { pub fn common_edge(&self, other: &Triangle) -> Result<&Edge, String> {
let common_edge = self.edges.iter() let common_edge = self.edges.iter()
.filter(|e| other.edges.contains(e)) .filter(|e| other.edges.contains(e))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
if common_edge.len() > 1 { if common_edge.len() > 1 {
Err(format!( Err(format!(
"Tried to call common_edge on two triangles which share more \ "Tried to call common_edge on two triangles which share more \
than one common edge?: {:?} and {:?}.", than one common edge?: {:?} and {:?}.",
self, other self, other
)) ))
} else if let Some(common_edge) = common_edge.first() { } else if let Some(common_edge) = common_edge.first() {
Ok(common_edge) Ok(common_edge)
} else { } else {
Err(format!( Err(format!(
"Tried to call common_edge on two triangles which don't \ "Tried to call common_edge on two triangles which don't \
share a common edges: {:?} and {:?}.", share a common edges: {:?} and {:?}.",
self, other self, other
)) ))
} }
} }
pub fn point_not_on(&self, edge: &Edge) -> Result<&NodeRef, String> { pub fn point_not_on(&self, edge: &Edge) -> Result<&NodeRef, String> {
self.nodes.iter() self.nodes.iter()
.filter(|n| .filter(|n|
!Arc::ptr_eq(n, &edge.0) && !Arc::ptr_eq(n, &edge.0) &&
!Arc::ptr_eq(n, &edge.1) !Arc::ptr_eq(n, &edge.1)
) )
.next() .next()
.ok_or_else(||format!( .ok_or_else(||format!(
".point_not_on called on {:?} with edge {:?}, but no points were found \ ".point_not_on called on {:?} with edge {:?}, but no points were found \
not on this edge", not on this edge",
self, edge self, edge
)) ))
} }
pub fn invalidated_by_neighbor(&self, other: &Triangle) -> Result<bool, String> { pub fn invalidated_by_neighbor(&self, other: &Triangle) -> Result<bool, String> {
let common_edge = self.common_edge(other)?; let common_edge = self.common_edge(other)?;
let self_point = self.point_not_on(common_edge)?; let self_point = self.point_not_on(common_edge)?;
let othr_point = other.point_not_on(common_edge)?; let othr_point = other.point_not_on(common_edge)?;
let common_distance = common_edge.0.get().distance(*common_edge.1.get()); let common_distance = common_edge.0.get().distance(*common_edge.1.get());
let self_sidea = common_edge.0.get().distance(*self_point.get()); let self_sidea = common_edge.0.get().distance(*self_point.get());
let self_sideb = common_edge.1.get().distance(*self_point.get()); let self_sideb = common_edge.1.get().distance(*self_point.get());
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 = f64::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 = f64::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)
- common_distance.powf(2.0) - common_distance.powf(2.0)
) / (2.0 * othr_sidea * othr_sideb) ) / (2.0 * othr_sidea * othr_sideb)
); );
return Ok(self_angle + othr_angle > PI) return Ok(self_angle + othr_angle > PI)
} }
} }
impl PartialEq for Triangle { impl PartialEq for Triangle {
@ -577,10 +577,10 @@ impl DelaunayDemo {
self.move_point(node); self.move_point(node);
} }
} }
if let Err(msg) = self.re_delaunize() { if let Err(msg) = self.re_delaunize() {
eprintln!("POISONED: {}", msg); eprintln!("POISONED: {}", msg);
self.poisoned = true; self.poisoned = true;
} }
} }
fn click(&mut self, pos: Vec2) { fn click(&mut self, pos: Vec2) {
@ -773,139 +773,139 @@ impl DelaunayDemo {
new_pos.1.x = -new_pos.1.x; new_pos.1.x = -new_pos.1.x;
} }
node.set(node_inner); node.set(new_pos);
} }
fn get_neighbors(&self, triangle: &Triangle) -> Result<Vec<&Triangle>, String> { fn get_neighbors(&self, triangle: &Triangle) -> Result<Vec<&Triangle>, String> {
triangle.edges.iter() triangle.edges.iter()
.filter_map(|e| .filter_map(|e|
match self.adjacency.get(e) { match self.adjacency.get(e) {
Some((Occupant(a), Friend(b))) => { Some((Occupant(a), Friend(b))) => {
if a != triangle && b == triangle { if a != triangle && b == triangle {
Some(Ok(a)) Some(Ok(a))
} else if a == triangle && b != triangle { } else if a == triangle && b != triangle {
Some(Ok(b)) Some(Ok(b))
} else if a == triangle && b == triangle { } else if a == triangle && b == triangle {
Some(Err(format!( Some(Err(format!(
"{:?} has {:?} in adjacency graph which lists itself as \ "{:?} has {:?} in adjacency graph which lists itself as \
its own neighbor", its own neighbor",
triangle, e triangle, e
))) )))
} else { } else {
Some(Err(format!( Some(Err(format!(
"{:?} has {:?}, but the adjacency graph reports that the \ "{:?} has {:?}, but the adjacency graph reports that the \
triangles next to this edge are {:?} and {:?}", triangles next to this edge are {:?} and {:?}",
triangle, e, a, b triangle, e, a, b
))) )))
} }
}, },
Some((Border, Friend(tri))) => { Some((Border, Friend(tri))) => {
if tri == triangle { if tri == triangle {
None None
} else { } else {
Some(Err(format!( Some(Err(format!(
"{:?} has {:?}, but the adjacency graph reports that \ "{:?} has {:?}, but the adjacency graph reports that \
this edge is an edge between the graph hull and {:?}", this edge is an edge between the graph hull and {:?}",
triangle, e, tri triangle, e, tri
))) )))
} }
}, },
Some((Occupant(tri), Hole)) => { Some((Occupant(tri), Hole)) => {
if tri == triangle { if tri == triangle {
None None
} else { } else {
Some(Err(format!( Some(Err(format!(
"{:?} has {:?}, but the adjacency graph reports that \ "{:?} has {:?}, but the adjacency graph reports that \
this edge is an edge between a polygonal hole and {:?}", this edge is an edge between a polygonal hole and {:?}",
triangle, e, tri triangle, e, tri
))) )))
} }
}, },
Some((Border, Hole)) => { Some((Border, Hole)) => {
Some(Err(format!( Some(Err(format!(
"{:?} has {:?}, but the adjacency graph lists this edge as \ "{:?} has {:?}, but the adjacency graph lists this edge as \
being between the graph hull and a polygonal hole (aka, it \ being between the graph hull and a polygonal hole (aka, it \
has no neighbors", has no neighbors",
triangle, e triangle, e
))) )))
}, },
None => { None => {
Some(Err(format!( Some(Err(format!(
"get_neighbors called on {:?}, but its edge {:?} is not \ "get_neighbors called on {:?}, but its edge {:?} is not \
present in the adjacency graph.", present in the adjacency graph.",
triangle, e triangle, e
))) )))
}, },
} }
) )
.collect() .collect()
} }
fn flip_triangles( fn flip_triangles(
&mut self, &mut self,
tri1: &Triangle, tri1: &Triangle,
tri2: &Triangle tri2: &Triangle
) -> Result<(Triangle, &Triangle), String> { ) -> Result<(Triangle, &Triangle), String> {
let mut indices = self.triangles.iter() let mut indices = self.triangles.iter()
.enumerate() .enumerate()
.filter(|(_, t)| t == &tri1 || t == &tri2) .filter(|(_, t)| t == &tri1 || t == &tri2)
.map(|(i, _)| i); .map(|(i, _)| i);
let err = || format!( let err = || format!(
"flip_triangles called on {:?} and {:?}, but not both of these were found in \ "flip_triangles called on {:?} and {:?}, but not both of these were found in \
the list of triangles", the list of triangles",
tri1, tri2 tri1, tri2
); );
let mut indices = [ let mut indices = [
indices.next().ok_or_else(err)?, indices.next().ok_or_else(err)?,
indices.next().ok_or_else(err)?, indices.next().ok_or_else(err)?,
]; ];
indices.sort_unstable(); indices.sort_unstable();
let tri1 = self.remove_triangle(indices[1])?; let tri1 = self.remove_triangle(indices[1])?;
let tri2 = self.remove_triangle(indices[0])?; let tri2 = self.remove_triangle(indices[0])?;
let common_edge = tri1.common_edge(&tri2)?; let common_edge = tri1.common_edge(&tri2)?;
let tri1_point = tri1.point_not_on(common_edge)?; let tri1_point = tri1.point_not_on(common_edge)?;
let tri2_point = tri2.point_not_on(common_edge)?; let tri2_point = tri2.point_not_on(common_edge)?;
Ok(( Ok((
self.create_triangle([ self.create_triangle([
Edge(tri1_point.clone(), common_edge.0.clone()), Edge(tri1_point.clone(), common_edge.0.clone()),
Edge(tri2_point.clone(), common_edge.0.clone()), Edge(tri2_point.clone(), common_edge.0.clone()),
Edge(tri1_point.clone(), tri2_point.clone()), Edge(tri1_point.clone(), tri2_point.clone()),
])?.clone(), ])?.clone(),
self.create_triangle([ self.create_triangle([
Edge(tri1_point.clone(), common_edge.1.clone()), Edge(tri1_point.clone(), common_edge.1.clone()),
Edge(tri2_point.clone(), common_edge.1.clone()), Edge(tri2_point.clone(), common_edge.1.clone()),
Edge(tri1_point.clone(), tri2_point.clone()), Edge(tri1_point.clone(), tri2_point.clone()),
])?, ])?,
)) ))
} }
fn re_delaunize(&mut self) -> Result<(), String> { fn re_delaunize(&mut self) -> Result<(), String> {
let mut i = 0; let mut i = 0;
while i < self.triangles.len() { while i < self.triangles.len() {
let triangle = &self.triangles[i]; let triangle = &self.triangles[i];
let neighbors: Vec<_> = self.get_neighbors(triangle)? let neighbors: Vec<_> = self.get_neighbors(triangle)?
.into_iter() .into_iter()
.cloned() .cloned()
.collect(); .collect();
let mut flipped = false; let mut flipped = false;
for neighbor in neighbors { for neighbor in neighbors {
if triangle.invalidated_by_neighbor(&neighbor)? { if triangle.invalidated_by_neighbor(&neighbor)? {
let triangle = triangle.clone(); let triangle = triangle.clone();
self.flip_triangles(&triangle, &neighbor)?; self.flip_triangles(&triangle, &neighbor)?;
i = 0; i = 0;
flipped = true; flipped = true;
break; break;
} }
} }
if !flipped { if !flipped {
i = i + 1; i = i + 1;
} }
} }
Ok(()) Ok(())
} }
} }