wip refactor without rc/refcell

This commit is contained in:
Jean-Gabriel Gill-Couture 2023-08-04 22:38:49 -04:00
parent 6a0f480c8a
commit 0b892980ca
3 changed files with 62 additions and 41 deletions

View File

@ -27,6 +27,15 @@ impl Attractor {
} }
} }
/// A Node of the graph that is connected to one or more other nodes
///
/// Use cases :
/// - Rendering
/// - Must be easy and fast to find connections
/// - Must know the number of descendent generations to calculate vein thickness
/// - Growing
/// - Must be easy and fast to find nodes in a cell
/// - Probably worth marking nodes as dead when no attractor is in range
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub struct Node { pub struct Node {
pub position: Point, pub position: Point,

View File

@ -1,6 +1,4 @@
use log::info; #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, PartialOrd)]
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub struct Point { pub struct Point {
pub x: i32, pub x: i32,
pub y: i32, pub y: i32,
@ -46,6 +44,25 @@ impl Point {
} }
} }
impl Ord for Point {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
if self.x > other.x {
return std::cmp::Ordering::Greater;
}
if self.x < other.x {
return std::cmp::Ordering::Less;
}
if self.y > other.y {
return std::cmp::Ordering::Greater;
}
if self.y < other.y {
return std::cmp::Ordering::Less;
}
std::cmp::Ordering::Equal
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::Point; use super::Point;
@ -164,28 +181,35 @@ mod tests {
} }
#[test] #[test]
fn scale_does_nothing_when_right_length() { fn movement_does_nothing_when_right_length() {
let root = Point::new((0,0)); let root = Point::new((0,0));
let node = Point::new((0,1)); let node = Point::new((0,1));
assert_eq!(root.movement(node.clone(), 1), node); assert_eq!(root.movement(node.clone(), 1), node);
} }
#[test] #[test]
fn scale_adjusts_to_asked_length() { fn movement_does_not_overlap() {
let root = Point::new((0,1));
let node = Point::new((0,0));
assert_eq!(root.movement(node.clone(), 2), node);
}
#[test]
fn movement_adjusts_to_asked_length() {
let root = Point::new((0,0)); let root = Point::new((0,0));
let node = Point::new((0,1)); let node = Point::new((0,1));
assert_eq!(root.movement(node, 10), Point::new((0,10))); assert_eq!(root.movement(node, 10), Point::new((0,10)));
} }
#[test] #[test]
fn scale_works_away_from_origin() { fn movement_works_away_from_origin() {
let root = Point::new((10,10)); let root = Point::new((10,10));
let node = Point::new((10,11)); let node = Point::new((10,11));
assert_eq!(root.movement(node, 10), Point::new((10,20))); assert_eq!(root.movement(node, 10), Point::new((10,20)));
} }
#[test] #[test]
fn scale_works_in_two_dimension() { fn movement_works_in_two_dimension() {
let root = Point::new((10,10)); let root = Point::new((10,10));
let node = Point::new((40,50)); let node = Point::new((40,50));
assert_eq!(root.movement(node, 50), Point::new((40,50))); assert_eq!(root.movement(node, 50), Point::new((40,50)));
@ -196,7 +220,7 @@ mod tests {
} }
#[test] #[test]
fn scale_works_in_all_directions() { fn movement_works_in_all_directions() {
let root = Point::new((40,50)); let root = Point::new((40,50));
let node = Point::new((10,10)); let node = Point::new((10,10));
assert_eq!(root.movement(node, 5), Point::new((37,46))); assert_eq!(root.movement(node, 5), Point::new((37,46)));

View File

@ -102,7 +102,7 @@ impl SpaceColonization {
F: Copy + Fn(&Node, &Node), F: Copy + Fn(&Node, &Node),
{ {
info!("Rendering {} nodes", self.nodes.len()); info!("Rendering {} nodes", self.nodes.len());
for n in self.nodes_tree.iter() { for n in self.nodes.iter() {
n.render(render_id, render_fn); n.render(render_id, render_fn);
} }
} }
@ -221,8 +221,25 @@ impl SpaceColonization {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use std::cell::RefCell;
use super::*; use super::*;
fn assert_nodes(sc: &SpaceColonization, expected_nodes: Vec<(Point, Point)>) {
let rendered_nodes = RefCell::new(Vec::new());
sc.render_nodes(0.0, |n1, n2| {
rendered_nodes.borrow_mut().push((n1.position, n2.position));
});
rendered_nodes.borrow_mut().sort_by(|line1, line2| {
if line1.0 != line2.0 {
return line1.0.cmp(&line2.0);
}
return line1.1.cmp(&line2.1);
})
}
#[test] #[test]
fn grow_should_reach_single_attractor_and_die() { fn grow_should_reach_single_attractor_and_die() {
let mut nodes = Vec::new(); let mut nodes = Vec::new();
@ -232,62 +249,33 @@ mod test {
let sc = SpaceColonization::new_for_tests(100, 100, nodes, attractors); let sc = SpaceColonization::new_for_tests(100, 100, nodes, attractors);
assert_nodes(&sc, Vec::from([(Point::new((0,0)), Point::new((10,0)))]));
assert_eq!(sc.attractors.len(), 1); assert_eq!(sc.attractors.len(), 1);
assert!(sc assert!(sc
.attractors .attractors
.iter() .iter()
.find(|a| a.dead == true) .find(|a| a.dead == true)
.is_none()); .is_none());
assert_eq!(sc.nodes_tree[0].children.len(), 0);
sc.grow(); sc.grow();
assert_eq!(sc.new_nodes.len(), 0); assert_eq!(sc.new_nodes.len(), 0);
assert_eq!(sc.nodes_tree.[0].children.len(), 1);
assert!(sc assert!(sc
.attractors .attractors
.iter() .iter()
.find(|a| a.dead == true) .find(|a| a.dead == true)
.is_none()); .is_none());
assert_eq!( // TODO assert point 3,0
sc.nodes_tree.[0].children.[0].position,
Point::new((3, 0))
);
assert_eq!(
sc.nodes_tree[0].children.len(),
1,
);
assert_eq!(
sc.nodes_tree.len(),
1,
);
println!("root node direct children iteration 1 {:?}", sc.nodes_tree.[0].children);
sc.grow(); sc.grow();
assert_eq!(
sc.nodes_tree.len(),
1,
);
assert_eq!(sc assert_eq!(sc
.attractors .attractors
.iter() .iter()
.filter(|a| a.dead == true) .filter(|a| a.dead == true)
.collect::<Vec<&Attractor>>().len(), 1); .collect::<Vec<&Attractor>>().len(), 1);
println!("root node direct children iteration 2 {:?}", sc.nodes_tree.[0].children); // TODO assert nodes 3,0 and 6,0
assert_eq!(
sc.nodes_tree[0].children.len(),
1,
);
assert_eq!(
sc.nodes_tree[0].children[0].position,
Point::new((3, 0))
);
assert_eq!(
sc.nodes_tree[0].children[0].children[0].position,
Point::new((6, 0))
);
assert_eq!(sc.nodes.len(), 3); assert_eq!(sc.nodes.len(), 3);
} }
} }