Retab
This commit is contained in:
parent
0226922ebf
commit
3e15269afb
364
src/main.rs
364
src/main.rs
|
@ -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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue