Redo a whole bunch of shit now with adjacency graphs

This commit is contained in:
Emi Simpson 2021-11-14 16:22:04 -05:00
parent 3be8db1fdc
commit 24c147f47d
Signed by: Emi
GPG Key ID: A12F2C2FFDC3D847
2 changed files with 436 additions and 100 deletions

View File

@ -1,4 +1,10 @@
use std::collections::HashSet;
pub mod util;
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 macroquad::prelude::mouse_position;
@ -30,48 +36,103 @@ async fn main() {
if is_mouse_button_pressed(MouseButton::Left) {
dd.click(mouse_position().into())
}
dd.update();
dd.draw();
next_frame().await;
}
}
pub struct DelaunayDemo {
pub nodes: Vec<Arc<Node>>,
pub nodes: Vec<NodeRef>,
pub triangles: Vec<Triangle>,
pub edges: Vec<Edge>,
adjacency: HashMap<Edge, (NeighborOne, NeighborTwo)>,
poisoned: bool,
random_state: u128
}
enum NeighborOne {
Occupant(Triangle),
Border,
}
enum NeighborTwo {
Friend(Triangle),
Hole,
}
use NeighborOne::*;
use NeighborTwo::*;
impl From<Triangle> for NeighborOne {
fn from(triangle: Triangle) -> NeighborOne {
Occupant(triangle)
}
}
impl From<&Triangle> for NeighborOne {
fn from(triangle: &Triangle) -> NeighborOne {
triangle.clone().into()
}
}
impl From<Triangle> for NeighborTwo {
fn from(triangle: Triangle) -> NeighborTwo {
Friend(triangle)
}
}
impl From<&Triangle> for NeighborTwo {
fn from(triangle: &Triangle) -> NeighborTwo {
triangle.clone().into()
}
}
impl NeighborTwo {
fn unwrap_mut(&mut self) -> &mut Triangle {
if let Friend(triangle) = self {
triangle
} else {
panic!("Tried to unwrap a neighbor that wasn't a friend");
}
}
}
impl Default for DelaunayDemo {
fn default() -> Self {
let nodes: Vec<Arc<Node>> = vec![
Arc::new((0.0, 0.0).into()),
Arc::new((0.0, screen_height()).into()),
Arc::new((screen_width(), 0.0).into()),
Arc::new((screen_width(), screen_height()).into()),
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())),
];
let edges = vec![
let edges = (
Edge(nodes[2].clone(), nodes[0].clone()),
Edge(nodes[0].clone(), nodes[1].clone()),
Edge(nodes[1].clone(), nodes[2].clone()),
Edge(nodes[2].clone(), nodes[3].clone()),
Edge(nodes[3].clone(), nodes[1].clone()),
];
);
let triangles = vec![
Triangle::new(
[edges[0].clone(), edges[1].clone(), edges[2].clone()],
[edges.0.clone(), edges.1.clone(), edges.2.clone()],
),
Triangle::new(
[edges[2].clone(), edges[3].clone(), edges[4].clone()],
[edges.2.clone(), edges.3.clone(), edges.4.clone()],
),
];
let adjacency = [
(edges.0, (Border, (&triangles[0]).into())),
(edges.1, (Border, (&triangles[0]).into())),
(edges.2, ((&triangles[0]).into(), (&triangles[1]).into())),
(edges.3, (Border, (&triangles[1]).into())),
(edges.4, (Border, (&triangles[1]).into())),
].into();
DelaunayDemo {
nodes, edges, triangles,
nodes, adjacency, triangles, random_state: 1312_1312_1312, poisoned: false,
}
}
}
#[derive(Copy, Clone, Debug)]
pub struct Node(Vec2);
pub struct Node(Vec2, Vec2);
impl Deref for Node {
type Target = Vec2;
@ -89,12 +150,14 @@ impl DerefMut for Node {
impl From<(f32, f32)> for Node {
fn from((x, y): (f32, f32)) -> Node {
Node(Vec2::new(x, y))
Node(Vec2::new(x, y), Vec2::ZERO)
}
}
#[derive(Clone, Debug)]
pub struct Edge(Arc<Node>, Arc<Node>);
type NodeRef = Arc<Cell<Node>>;
#[derive(Clone)]
pub struct Edge(NodeRef, NodeRef);
impl PartialEq for Edge {
fn eq(&self, other: &Edge) -> bool {
@ -126,11 +189,22 @@ impl Hash for Edge {
}
}
impl fmt::Debug for Edge {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f,
"Edge({},{} -> {},{})",
self.0.get().x,
self.0.get().y,
self.1.get().x,
self.1.get().y,
)
}
}
#[derive(Clone)]
pub struct Triangle {
nodes: [Arc<Node>; 3],
nodes: [NodeRef; 3],
edges: [Edge; 3],
circumcenter: Vec2,
radius: f32,
}
impl Triangle {
@ -144,131 +218,308 @@ impl Triangle {
edges[1].0.clone()
}
];
let circumcenter = Self::circumcenter(**nodes[0], **nodes[1], **nodes[2]);
let radius = circumcenter.distance(**nodes[0]);
Triangle {
nodes,
edges,
circumcenter,
radius,
}
}
fn circumcenter(a: Vec2, b: Vec2, c: Vec2) -> Vec2 {
let len_a = b.distance(c);
let len_b = c.distance(a);
let len_c = a.distance(b);
pub fn new_from_points(nodes: [NodeRef; 3]) -> Triangle {
let edges = [
Edge(nodes[0].clone(), nodes[1].clone()),
Edge(nodes[1].clone(), nodes[2].clone()),
Edge(nodes[2].clone(), nodes[0].clone()),
];
Triangle {
nodes,
edges,
}
}
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 );
pub fn circumcenter(&self) -> (Vec2, f32) {
Self::calc_circumcenter(*self.nodes[0].get(), *self.nodes[1].get(), *self.nodes[2].get())
}
let ang_a = f32::acos(cos_a);
let ang_b = f32::acos(cos_b);
let ang_c = PI - ang_a - ang_b;
fn calc_circumcenter(a: Vec2, b: Vec2, c: Vec2) -> (Vec2, f32) {
let len_a = b.distance(c);
let len_b = c.distance(a);
let len_c = a.distance(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 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 );
Vec2::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),
)
}
let ang_a = f32::acos(cos_a);
let ang_b = f32::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 circumcenter = Vec2::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),
);
let radius = circumcenter.distance(a);
(circumcenter, radius)
}
pub fn invalidated_by_point(&self, point: Vec2) -> bool {
self.circumcenter.distance(point) < self.radius
let (c, r) = self.circumcenter();
c.distance(point) < r
}
}
impl PartialEq for Triangle {
fn eq(&self, other: &Triangle) -> bool {
let mut our_ptrs = [
Arc::as_ptr(&self.nodes[0]),
Arc::as_ptr(&self.nodes[1]),
Arc::as_ptr(&self.nodes[2]),
];
let mut other_ptrs = [
Arc::as_ptr(&other.nodes[0]),
Arc::as_ptr(&other.nodes[1]),
Arc::as_ptr(&other.nodes[2]),
];
our_ptrs.sort_unstable();
other_ptrs.sort_unstable();
our_ptrs[0] == other_ptrs[0] &&
our_ptrs[1] == other_ptrs[1] &&
our_ptrs[2] == other_ptrs[2]
}
}
impl Eq for Triangle {}
impl Hash for Triangle {
fn hash<H: Hasher>(&self, state: &mut H) {
let mut ptrs = [
Arc::as_ptr(&self.nodes[0]),
Arc::as_ptr(&self.nodes[1]),
Arc::as_ptr(&self.nodes[2]),
];
ptrs.sort_unstable();
ptrs.hash(state);
}
}
impl fmt::Debug for Triangle {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let coords: Vec<_> = self.nodes.iter()
.flat_map(|n| [n.get().x, n.get().y])
.collect();
write!(
f,
"Triangle[({}, {}), ({}, {}), ({}, {}))",
coords[0],
coords[1],
coords[2],
coords[3],
coords[4],
coords[5],
)
}
}
impl DelaunayDemo {
fn draw(&self) {
clear_background(BG);
let mut danger_lines = Vec::with_capacity(3);
for triangle in &self.triangles {
let c = triangle.circumcenter;
let color = if c.distance(mouse_position().into()) < triangle.radius {
danger_lines.extend(&triangle.edges);
DIM_FG //HIL_FG
} else {
DIM_FG
};
draw_circle_lines(c.x, c.y, triangle.radius, 1.0, color);
let (c, r) = triangle.circumcenter();
draw_circle_lines(c.x, c.y, r, 1.0, DIM_FG);
}
for edge in &self.edges {
let color = if danger_lines.contains(&edge) {
FG //HIL_FG
} else {
FG
};
draw_line(edge.0.x, edge.0.y, edge.1.x, edge.1.y, 3.0, color);
for edge in self.adjacency.keys() {
draw_line(
edge.0.get().x,
edge.0.get().y,
edge.1.get().x,
edge.1.get().y,
3.0, FG
);
}
for node in &self.nodes {
draw_circle(node.x, node.y, 10.0, FG);
draw_circle(node.get().x, node.get().y, 10.0, FG);
}
}
fn update(&mut self) {
for node in self.nodes.clone() {
if node.get().1 != Vec2::ZERO {
self.move_point(node);
}
}
}
fn click(&mut self, pos: Vec2) {
self.add_point(Node(pos));
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,
);
if let Err(msg) = self.add_point(Node(pos, direction * 2.0)) {
self.poisoned = true;
eprintln!("{}", msg);
}
}
fn add_point(&mut self, node: Node) {
fn add_point(&mut self, node: Node) -> Result<(), String> {
println!("Adding point {:?}", node);
// Remove invalid triangles and coalesce their edges
let mut bad_triangle_sides: Vec<_> = Vec::with_capacity(self.triangles.len() * 3);
let mut orphaned_edges: Vec<_> = Vec::with_capacity(self.triangles.len() * 3);
let mut i = 0;
while i < self.triangles.len() {
let triangle = &self.triangles[i];
if triangle.invalidated_by_point(*node) {
bad_triangle_sides.extend(
self.triangles.remove(i).edges
orphaned_edges.extend(
self.remove_triangle(i)?.edges
);
} else {
i = i + 1;
}
}
orphaned_edges.retain(|e| self.adjacency.contains_key(e));
println!("Orphaned Edges: {:?}", orphaned_edges);
// For every edge
// If it has a duplicate later in the list
// Remove the edge from existance
// Otherwise
// Form a new triangle with that edge and this point
let node = Arc::new(node);
let mut new_edges = HashSet::with_capacity(bad_triangle_sides.len());
i = 0;
while i < bad_triangle_sides.len() {
let edge = &bad_triangle_sides[i];
let other_edge_i = bad_triangle_sides[(i + 1)..].iter()
.position(|other_edge| edge == other_edge);
if let Some(other_edge_i) = other_edge_i {
bad_triangle_sides.remove(other_edge_i + i + 1);
i = i + 1;
} else {
let edge = bad_triangle_sides.remove(i);
let new_edge_a = Edge(edge.0.clone(), node.clone());
let new_edge_b = Edge(edge.1.clone(), node.clone());
self.triangles.push(Triangle::new([
edge,
new_edge_a.clone(),
new_edge_b.clone(),
]));
new_edges.extend([new_edge_a, new_edge_b]);
}
// For every edge form a new triangle with that edge and this point
let node = Arc::new(Cell::new(node));
for edge in orphaned_edges {
println!("Creating triangle with: {:?}", edge);
self.create_triangle([
Edge(edge.0.clone(), node.clone()),
Edge(edge.1.clone(), node.clone()),
edge,
])?;
}
self.edges.retain(|e| !bad_triangle_sides.iter().any(|bad_e| e == bad_e));
self.edges.extend(new_edges);
self.nodes.push(node);
Ok(())
}
/*fn move_point(&mut self, node: Arc<Node>) {
fn remove_triangle(&mut self, index: usize) -> Result<Triangle, String> {
let triangle = self.triangles.remove(index);
for edge in &triangle.edges {
match self.adjacency.get_mut(edge) {
Some((Occupant(side1), side2 @ Friend(_))) => {
let side2_inner = side2.unwrap_mut();
if side1 == &triangle {
swap(side1, side2_inner);
} else if side2_inner != &triangle {
return Err(format!(
"{:?} does not contain triangle \
{:?}, but this triangle's list of edges includes this \
edge. Triangle was in the triangle index until now.",
edge, triangle
));
}
*side2 = Hole;
},
Some((Occupant(our_side), Hole)) => {
if our_side != &triangle {
return Err(format!(
"{:?} does not contain triangle \
{:?}, but this triangle's list of edges includes this \
edge. Triangle was in the triangle index until now.",
edge, triangle
));
}
self.adjacency.remove(&edge);
},
Some((Border, our_side @ Friend(_))) => {
*our_side = Hole;
},
Some((Border, Hole)) => {
return Err(format!(
"{:?} removed from graph, but it's edge {:?} is \
already marked as a border-hole edge", triangle, edge
));
}
None => {
return Err(format!(
"{:?} removed from graph, but it's edge {:?} was \
missing from adjacency graph", triangle, edge
));
},
}
}
Ok(triangle)
}
fn create_triangle(&mut self, edges: [Edge; 3]) -> Result<&Triangle, String> {
let triangle = Triangle::new(edges.clone());
for edge in edges {
match self.adjacency.entry(edge) {
Entry::Occupied(mut entry) => {
match entry.get_mut() {
(Occupant(tri1), Friend(tri2)) => {
let (tri1, tri2) = (tri1.clone(), tri2.clone());
return Err(format!(
"Tried to create a triangle with edge {:?}, \
but this edge is already in use by triangles {:?} and \
{:?}.",
entry.key(), tri1, tri2
));
},
(Border, Friend(tri)) => {
let tri = tri.clone();
return Err(format!(
"Tried to create a triangle with edge {:?}, \
but this edge is already in use by triangle {:?} and \
is a border.",
entry.key(), tri
));
},
(Occupant(_) | Border, new_home @ Hole) => {
*new_home = Friend(triangle.clone());
},
}
},
Entry::Vacant(entry) => {
entry.insert(((&triangle).into(), Hole));
}
}
}
self.triangles.push(triangle);
Ok(self.triangles.last().unwrap())
}
fn move_point(&mut self, node: NodeRef) {
if self.poisoned {
return
}
/*
// Update position
let mut node_inner = node.get();
node_inner.0 = node_inner.0 + node_inner.1;
// Check for a bounce
if node_inner.0.y > screen_height() {
node_inner.0.y = 2.0 * screen_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;
node_inner.1.x = -node_inner.1.x;
}
if node_inner.0.x < 0.0 {
node_inner.0.x = -node_inner.0.x;
node_inner.1.x = -node_inner.1.x;
}
node.set(node_inner);
*/
// Check for broken triangles
@ -279,5 +530,77 @@ impl DelaunayDemo {
// Form triangle consisting of common point A + self + opposite
// Form triangle consisting of common point B + self + opposite
}*/
/*
let mut i = 0;
let mut needs_rerun = false;
while i < self.triangles.len() {
if i == 0 {
needs_rerun = false;
}
let triangle = &self.triangles[i];
if !triangle.nodes.iter().any(|n| Arc::ptr_eq(n, &node)) &&
triangle.invalidated_by_point(*node_inner)
{
println!("{:?} invalidated by {:?}", triangle, node_inner);
let pair_triangle_i = self.triangles.iter()
.position(|t| {
t.nodes.iter()
.filter(|n| triangle.nodes
.iter()
.any(|n2| Arc::ptr_eq(n, n2))
)
.count() == 2
});
let pair_triangle_i = if let Some(i) = pair_triangle_i {
i
} else {
i = (i + 1) % self.triangles.len();
needs_rerun = true;
continue
};
// .expect("Invariant violated: All triangles invalidated by a moved \
// point have a pair triangle");
let pair_triangle = self.triangles.remove(pair_triangle_i);
let triangle = self.triangles.remove(i);
let common_edge = pair_triangle.edges.iter()
.filter(|e|
!Arc::ptr_eq(&e.0, &node) &&
!Arc::ptr_eq(&e.1, &node)
)
.next()
.expect("Invariant violated: Triangles must be a closed polygon");
let opposite_point = triangle.nodes.into_iter()
.filter(|n|
!Arc::ptr_eq(&common_edge.0, n) &&
!Arc::ptr_eq(&common_edge.1, n)
)
.next()
.expect("Invariant violated: Triangles must have three unique points");
let new_common_edge = Edge(node.clone(), opposite_point.clone());
self.edges.push(new_common_edge);
let common_edge_i = self.edges.iter()
.position(|e| e == common_edge)
.expect("Invariant violated: Triangle edges must all be in the \
master database");
let common_edge = self.edges.remove(common_edge_i);
self.triangles.extend([
Triangle::new_from_points([node.clone(), opposite_point.clone(), common_edge.0]),
Triangle::new_from_points([node.clone(), opposite_point, common_edge.1]),
]);
} else {
if needs_rerun {
i = (i + 1) % self.triangles.len();
} else {
i = (i + 1);
}
}
}
*/
}
}

View File

@ -0,0 +1,13 @@
pub fn pcg64(state: &mut u128) -> u64 {
let mut x = *state;
pcg64_iterstate(state);
let count = (x >> (128 - 6)) as u32; // Highest 6 bits
x ^= x >> 35;
((x >> 58) as u64).rotate_right(count)
}
fn pcg64_iterstate(state: &mut u128) {
const MULTIPLIER: u128 = 0xde92a69f6e2f9f25fd0d90f576075fbd;
const INCREMENT: u128 = 621;
*state = state.wrapping_mul(MULTIPLIER).wrapping_add(INCREMENT);
}