Added movement but it's very crashy
This commit is contained in:
parent
94556f71dc
commit
4a480d9680
297
src/main.rs
297
src/main.rs
|
@ -269,6 +269,73 @@ impl Triangle {
|
|||
let (c, r) = self.circumcenter();
|
||||
c.distance(point) < r
|
||||
}
|
||||
|
||||
pub fn common_edge(&self, other: &Triangle) -> Result<&Edge, String> {
|
||||
let common_edge = self.edges.iter()
|
||||
.filter(|e| other.edges.contains(e))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if common_edge.len() > 1 {
|
||||
Err(format!(
|
||||
"Tried to call common_edge on two triangles which share more \
|
||||
than one common edge?: {:?} and {:?}.",
|
||||
self, other
|
||||
))
|
||||
} else if let Some(common_edge) = common_edge.first() {
|
||||
Ok(common_edge)
|
||||
} else {
|
||||
Err(format!(
|
||||
"Tried to call common_edge on two triangles which don't \
|
||||
share a common edges: {:?} and {:?}.",
|
||||
self, other
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn point_not_on(&self, edge: &Edge) -> Result<&NodeRef, String> {
|
||||
self.nodes.iter()
|
||||
.filter(|n|
|
||||
!Arc::ptr_eq(n, &edge.0) &&
|
||||
!Arc::ptr_eq(n, &edge.1)
|
||||
)
|
||||
.next()
|
||||
.ok_or_else(||format!(
|
||||
".point_not_on called on {:?} with edge {:?}, but no points were found \
|
||||
not on this edge",
|
||||
self, edge
|
||||
))
|
||||
}
|
||||
|
||||
pub fn invalidated_by_neighbor(&self, other: &Triangle) -> Result<bool, String> {
|
||||
|
||||
let common_edge = self.common_edge(other)?;
|
||||
|
||||
let self_point = self.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 self_sidea = common_edge.0.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_sideb = common_edge.1.get().distance(*othr_point.get());
|
||||
|
||||
let self_angle = f32::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(
|
||||
(
|
||||
othr_sidea.powf(2.0)
|
||||
+ othr_sideb.powf(2.0)
|
||||
- common_distance.powf(2.0)
|
||||
) / (2.0 * othr_sidea * othr_sideb)
|
||||
);
|
||||
|
||||
return Ok(self_angle + othr_angle > PI)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Triangle {
|
||||
|
@ -346,11 +413,18 @@ impl DelaunayDemo {
|
|||
}
|
||||
|
||||
fn update(&mut self) {
|
||||
if self.poisoned {
|
||||
return
|
||||
}
|
||||
for node in self.nodes.clone() {
|
||||
if node.get().1 != Vec2::ZERO {
|
||||
self.move_point(node);
|
||||
}
|
||||
}
|
||||
if let Err(msg) = self.re_delaunize() {
|
||||
eprintln!("POISONED: {}", msg);
|
||||
self.poisoned = true;
|
||||
}
|
||||
}
|
||||
|
||||
fn click(&mut self, pos: Vec2) {
|
||||
|
@ -362,7 +436,7 @@ impl DelaunayDemo {
|
|||
);
|
||||
if let Err(msg) = self.add_point(Node(pos, direction * 2.0)) {
|
||||
self.poisoned = true;
|
||||
eprintln!("{}", msg);
|
||||
eprintln!("POISONED: {}", msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -488,11 +562,6 @@ impl DelaunayDemo {
|
|||
|
||||
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;
|
||||
|
@ -516,88 +585,138 @@ impl DelaunayDemo {
|
|||
}
|
||||
|
||||
node.set(node_inner);
|
||||
*/
|
||||
|
||||
// Check for broken triangles
|
||||
|
||||
// Remove triange
|
||||
|
||||
// Remove triangle consisting of common points + self
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
fn get_neighbors(&self, triangle: &Triangle) -> Result<Vec<&Triangle>, String> {
|
||||
triangle.edges.iter()
|
||||
.filter_map(|e|
|
||||
match self.adjacency.get(e) {
|
||||
Some((Occupant(a), Friend(b))) => {
|
||||
if a != triangle && b == triangle {
|
||||
Some(Ok(a))
|
||||
} else if a == triangle && b != triangle {
|
||||
Some(Ok(b))
|
||||
} else if a == triangle && b == triangle {
|
||||
Some(Err(format!(
|
||||
"{:?} has {:?} in adjacency graph which lists itself as \
|
||||
its own neighbor",
|
||||
triangle, e
|
||||
)))
|
||||
} else {
|
||||
Some(Err(format!(
|
||||
"{:?} has {:?}, but the adjacency graph reports that the \
|
||||
triangles next to this edge are {:?} and {:?}",
|
||||
triangle, e, a, b
|
||||
)))
|
||||
}
|
||||
},
|
||||
Some((Border, Friend(tri))) => {
|
||||
if tri == triangle {
|
||||
None
|
||||
} else {
|
||||
Some(Err(format!(
|
||||
"{:?} has {:?}, but the adjacency graph reports that \
|
||||
this edge is an edge between the graph hull and {:?}",
|
||||
triangle, e, tri
|
||||
)))
|
||||
}
|
||||
},
|
||||
Some((Occupant(tri), Hole)) => {
|
||||
if tri == triangle {
|
||||
None
|
||||
} else {
|
||||
Some(Err(format!(
|
||||
"{:?} has {:?}, but the adjacency graph reports that \
|
||||
this edge is an edge between a polygonal hole and {:?}",
|
||||
triangle, e, tri
|
||||
)))
|
||||
}
|
||||
},
|
||||
Some((Border, Hole)) => {
|
||||
Some(Err(format!(
|
||||
"{:?} has {:?}, but the adjacency graph lists this edge as \
|
||||
being between the graph hull and a polygonal hole (aka, it \
|
||||
has no neighbors",
|
||||
triangle, e
|
||||
)))
|
||||
},
|
||||
None => {
|
||||
Some(Err(format!(
|
||||
"get_neighbors called on {:?}, but its edge {:?} is not \
|
||||
present in the adjacency graph.",
|
||||
triangle, e
|
||||
)))
|
||||
},
|
||||
}
|
||||
)
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn flip_triangles(
|
||||
&mut self,
|
||||
tri1: &Triangle,
|
||||
tri2: &Triangle
|
||||
) -> Result<(Triangle, &Triangle), String> {
|
||||
let mut indices = self.triangles.iter()
|
||||
.enumerate()
|
||||
.filter(|(_, t)| t == &tri1 || t == &tri2)
|
||||
.map(|(i, _)| i);
|
||||
let err = || format!(
|
||||
"flip_triangles called on {:?} and {:?}, but not both of these were found in \
|
||||
the list of triangles",
|
||||
tri1, tri2
|
||||
);
|
||||
|
||||
let mut indices = [
|
||||
indices.next().ok_or_else(err)?,
|
||||
indices.next().ok_or_else(err)?,
|
||||
];
|
||||
indices.sort_unstable();
|
||||
|
||||
let tri1 = self.remove_triangle(indices[1])?;
|
||||
let tri2 = self.remove_triangle(indices[0])?;
|
||||
|
||||
let common_edge = tri1.common_edge(&tri2)?;
|
||||
|
||||
let tri1_point = tri1.point_not_on(common_edge)?;
|
||||
let tri2_point = tri2.point_not_on(common_edge)?;
|
||||
|
||||
Ok((
|
||||
self.create_triangle([
|
||||
Edge(tri1_point.clone(), common_edge.0.clone()),
|
||||
Edge(tri2_point.clone(), common_edge.0.clone()),
|
||||
Edge(tri1_point.clone(), tri2_point.clone()),
|
||||
])?.clone(),
|
||||
self.create_triangle([
|
||||
Edge(tri1_point.clone(), common_edge.1.clone()),
|
||||
Edge(tri2_point.clone(), common_edge.1.clone()),
|
||||
Edge(tri1_point.clone(), tri2_point.clone()),
|
||||
])?,
|
||||
))
|
||||
}
|
||||
|
||||
fn re_delaunize(&mut self) -> Result<(), String> {
|
||||
let mut i = 0;
|
||||
while i < self.triangles.len() {
|
||||
let triangle = &self.triangles[i];
|
||||
let neighbors: Vec<_> = self.get_neighbors(triangle)?
|
||||
.into_iter()
|
||||
.cloned()
|
||||
.collect();
|
||||
let mut flipped = false;
|
||||
for neighbor in neighbors {
|
||||
if triangle.invalidated_by_neighbor(&neighbor)? {
|
||||
let triangle = triangle.clone();
|
||||
self.flip_triangles(&triangle, &neighbor)?;
|
||||
i = 0;
|
||||
flipped = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if !flipped {
|
||||
i = i + 1;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue