Skip to content

Commit

Permalink
fix tests & unsew impls
Browse files Browse the repository at this point in the history
I might be a little challenged
  • Loading branch information
imrn99 committed Oct 30, 2024
1 parent 5964e0f commit fccadad
Show file tree
Hide file tree
Showing 3 changed files with 438 additions and 50 deletions.
381 changes: 381 additions & 0 deletions <
Original file line number Diff line number Diff line change
@@ -0,0 +1,381 @@
// ------ IMPORTS

use crate::prelude::{CMap2, CMapBuilder, Orbit2, OrbitPolicy, Vertex2};

// ------ CONTENT

// --- GENERAL

#[test]
fn example_test() {
// build a triangle
let mut map: CMap2<f64> = CMapBuilder::default().n_darts(3).build().unwrap();
map.one_link(1, 2);
map.one_link(2, 3);
map.one_link(3, 1);
map.insert_vertex(1, (0.0, 0.0));
map.insert_vertex(2, (1.0, 0.0));
map.insert_vertex(3, (0.0, 1.0));

// checks
let faces = map.fetch_faces();
assert_eq!(faces.identifiers.len(), 1);
assert_eq!(faces.identifiers[0], 1);
let mut face = Orbit2::new(&map, OrbitPolicy::Face, 1);
assert_eq!(face.next(), Some(1));
assert_eq!(face.next(), Some(2));
assert_eq!(face.next(), Some(3));
assert_eq!(face.next(), None);

// build a second triangle
map.add_free_darts(3);
map.one_link(4, 5);
map.one_link(5, 6);
map.one_link(6, 4);
map.insert_vertex(4, (0.0, 2.0));
map.insert_vertex(5, (2.0, 0.0));
map.insert_vertex(6, (1.0, 1.0));

// checks
let faces = map.fetch_faces();
assert_eq!(&faces.identifiers, &[1, 4]);
let mut face = Orbit2::new(&map, OrbitPolicy::Face, 4);
assert_eq!(face.next(), Some(4));
assert_eq!(face.next(), Some(5));
assert_eq!(face.next(), Some(6));
assert_eq!(face.next(), None);

// sew both triangles
map.two_sew(2, 4);

// checks
assert_eq!(map.beta::<2>(2), 4);
assert_eq!(map.vertex_id(2), 2);
assert_eq!(map.vertex_id(5), 2);
assert_eq!(map.vertex(2).unwrap(), Vertex2::from((1.5, 0.0)));
assert_eq!(map.vertex_id(3), 3);
assert_eq!(map.vertex_id(4), 3);
assert_eq!(map.vertex(3).unwrap(), Vertex2::from((0.0, 1.5)));
let edges = map.fetch_edges();
assert_eq!(&edges.identifiers, &[1, 2, 3, 5, 6]);

// adjust bottom-right & top-left vertex position
assert_eq!(
map.replace_vertex(2, Vertex2::from((1.0, 0.0))),
Some(Vertex2::from((1.5, 0.0)))
);
assert_eq!(map.vertex(2).unwrap(), Vertex2::from((1.0, 0.0)));
assert_eq!(
map.replace_vertex(3, Vertex2::from((0.0, 1.0))),
Some(Vertex2::from((0.0, 1.5)))
);
assert_eq!(map.vertex(3).unwrap(), Vertex2::from((0.0, 1.0)));

// separate the diagonal from the rest
map.one_unsew(1);
map.one_unsew(2);
map.one_unsew(6);
map.one_unsew(4);
// break up & remove the diagonal
map.two_unsew(2); // this makes dart 2 and 4 free
map.remove_free_dart(2);
map.remove_free_dart(4);
// sew the square back up
map.one_sew(1, 5);
map.one_sew(6, 3);

// i-cells
let faces = map.fetch_faces();
assert_eq!(&faces.identifiers, &[1]);
let edges = map.fetch_edges();
assert_eq!(&edges.identifiers, &[1, 3, 5, 6]);
let vertices = map.fetch_vertices();
assert_eq!(&vertices.identifiers, &[1, 3, 5, 6]);
assert_eq!(map.vertex(1).unwrap(), Vertex2::from((0.0, 0.0)));
assert_eq!(map.vertex(5).unwrap(), Vertex2::from((1.0, 0.0)));
assert_eq!(map.vertex(6).unwrap(), Vertex2::from((1.0, 1.0)));
assert_eq!(map.vertex(3).unwrap(), Vertex2::from((0.0, 1.0)));
// darts
assert_eq!(map.n_unused_darts(), 2); // there are unused darts since we removed the diagonal
assert_eq!(map.beta_runtime(1, 1), 5);
assert_eq!(map.beta_runtime(1, 5), 6);
assert_eq!(map.beta_runtime(1, 6), 3);
assert_eq!(map.beta_runtime(1, 3), 1);
}

#[test]
#[should_panic(expected = "called `Option::unwrap()` on a `None` value")]
fn remove_vertex_twice() {
// in its default state, all darts/vertices of a map are considered to be used
let mut map: CMap2<f64> = CMap2::new(4);
// set vertex 1 as unused
map.remove_vertex(1).unwrap();
// set vertex 1 as unused, again
map.remove_vertex(1).unwrap(); // this should panic
}

#[test]
#[should_panic(expected = "assertion failed")]
fn remove_dart_twice() {
// in its default state, all darts/vertices of a map are considered to be used
// darts are also free
let mut map: CMap2<f64> = CMap2::new(4);
// set dart 1 as unused
map.remove_free_dart(1);
// set dart 1 as unused, again
map.remove_free_dart(1); // this should panic
}

// --- (UN)SEW

#[test]
fn two_sew_complete() {
let mut map: CMap2<f64> = CMap2::new(4);
map.one_link(1, 2);
map.one_link(3, 4);
map.insert_vertex(1, (0.0, 0.0));
map.insert_vertex(2, (0.0, 1.0));
map.insert_vertex(3, (1.0, 1.0));
map.insert_vertex(4, (1.0, 0.0));
map.two_sew(1, 3);
assert_eq!(map.vertex(1).unwrap(), Vertex2::from((0.5, 0.0)));
assert_eq!(map.vertex(2).unwrap(), Vertex2::from((0.5, 1.0)));
}

#[test]
fn two_sew_incomplete() {
let mut map: CMap2<f64> = CMap2::new(3);
map.one_link(1, 2);
map.insert_vertex(1, (0.0, 0.0));
map.insert_vertex(2, (0.0, 1.0));
map.insert_vertex(3, (1.0, 1.0));
map.two_sew(1, 3);
// missing beta1 image for dart 3
assert_eq!(map.vertex(1).unwrap(), Vertex2::from((0.0, 0.0)));
assert_eq!(map.vertex(2).unwrap(), Vertex2::from((0.5, 1.0)));
map.two_unsew(1);
assert_eq!(map.add_free_dart(), 4);
map.one_link(3, 4);
map.two_sew(1, 3);
// missing vertex for dart 4
assert_eq!(map.vertex(1).unwrap(), Vertex2::from((0.0, 0.0)));
assert_eq!(map.vertex(2).unwrap(), Vertex2::from((0.5, 1.0)));
}

#[test]
fn two_sew_no_b1() {
let mut map: CMap2<f64> = CMap2::new(2);
map.insert_vertex(1, (0.0, 0.0));
map.insert_vertex(2, (1.0, 1.0));
map.two_sew(1, 2);
assert_eq!(map.vertex(1).unwrap(), Vertex2::from((0.0, 0.0)));
assert_eq!(map.vertex(2).unwrap(), Vertex2::from((1.0, 1.0)));
}

#[test]
// #[should_panic] // FIXME: find a way to test what's printed?
fn two_sew_no_attributes() {
let mut map: CMap2<f64> = CMap2::new(2);
map.two_sew(1, 2); // should panic
}

#[test]
// #[should_panic] // FIXME: find a way to test what's printed?
fn two_sew_no_attributes_bis() {
let mut map: CMap2<f64> = CMap2::new(4);
map.one_link(1, 2);
map.one_link(3, 4);
map.two_sew(1, 3); // panic
}

#[test]
#[should_panic(expected = "Dart 1 and 3 do not have consistent orientation for 2-sewing")]
fn two_sew_bad_orientation() {
let mut map: CMap2<f64> = CMap2::new(4);
map.one_link(1, 2);
map.one_link(3, 4);
map.insert_vertex(1, (0.0, 0.0));
map.insert_vertex(2, (0.0, 1.0)); // 1->2 goes up
map.insert_vertex(3, (1.0, 0.0));
map.insert_vertex(4, (1.0, 1.0)); // 3->4 also goes up
map.two_sew(1, 3); // panic
}

#[test]
fn one_sew_complete() {
let mut map: CMap2<f64> = CMap2::new(3);
map.two_link(1, 2);
map.insert_vertex(1, (0.0, 0.0));
map.insert_vertex(2, (0.0, 1.0));
map.insert_vertex(3, (0.0, 2.0));
map.one_sew(1, 3);
assert_eq!(map.vertex(2).unwrap(), Vertex2::from((0.0, 1.5)));
}

#[test]
fn one_sew_incomplete_attributes() {
let mut map: CMap2<f64> = CMap2::new(3);
map.two_link(1, 2);
map.insert_vertex(1, (0.0, 0.0));
map.insert_vertex(2, (0.0, 1.0));
map.one_sew(1, 3);
assert_eq!(map.vertex(2).unwrap(), Vertex2::from((0.0, 1.0)));
}

#[test]
fn one_sew_incomplete_beta() {
let mut map: CMap2<f64> = CMap2::new(3);
map.insert_vertex(1, (0.0, 0.0));
map.insert_vertex(2, (0.0, 1.0));
map.one_sew(1, 2);
assert_eq!(map.vertex(2).unwrap(), Vertex2::from((0.0, 1.0)));
}
#[test]
// #[should_panic] // FIXME: find a way to test what's printed?
fn one_sew_no_attributes() {
let mut map: CMap2<f64> = CMap2::new(2);
map.one_sew(1, 2); // should panic
}

#[test]
// #[should_panic] // FIXME: find a way to test what's printed?
fn one_sew_no_attributes_bis() {
let mut map: CMap2<f64> = CMap2::new(3);
map.two_link(1, 2);
map.one_sew(1, 3); // panic
}

// --- IO

#[cfg(feature = "io")]
#[test]
fn io_write() {
// build a map looking like this:
// 15
// / \
// / \
// / \
// 16 14
// | |
// 4---3---7
// | | /|
// | | / |
// | |/ |
// 1---2---6
let mut cmap: CMap2<f32> = CMap2::new(16);
// bottom left square
cmap.one_link(1, 2);
cmap.one_link(2, 3);
cmap.one_link(3, 4);
cmap.one_link(4, 1);
// bottom right triangles
cmap.one_link(5, 6);
cmap.one_link(6, 7);
cmap.one_link(7, 5);
cmap.two_link(7, 8);
cmap.one_link(8, 9);
cmap.one_link(9, 10);
cmap.one_link(10, 8);
// top polygon
cmap.one_link(11, 12);
cmap.one_link(12, 13);
cmap.one_link(13, 14);
cmap.one_link(14, 15);
cmap.one_link(15, 16);
cmap.one_link(16, 11);
// assemble
cmap.two_link(2, 10);
cmap.two_link(3, 11);
cmap.two_link(9, 12);

// insert vertices
cmap.insert_vertex(1, (0.0, 0.0));
cmap.insert_vertex(2, (1.0, 0.0));
cmap.insert_vertex(6, (2.0, 0.0));
cmap.insert_vertex(4, (0.0, 1.0));
cmap.insert_vertex(3, (1.0, 1.0));
cmap.insert_vertex(7, (2.0, 1.0));
cmap.insert_vertex(16, (0.0, 2.0));
cmap.insert_vertex(15, (1.0, 3.0));
cmap.insert_vertex(14, (2.0, 2.0));

// generate VTK data
let mut res = String::new();
cmap.to_vtk_ascii(&mut res);
println!("{res}");

// check result
assert!(res.contains("POINTS 9 float"));
assert!(res.contains("CELLS 12 44"));
assert!(res.contains("CELL_TYPES 12"));
// faces
assert!(res.contains("4 0 1 2 3"));
assert!(res.contains("3 1 4 5"));
assert!(res.contains("4 0 1 2 3"));
assert!(res.contains("4 0 1 2 3"));
// edges
assert!(res.contains("2 0 1"));
assert!(res.contains("2 3 0"));
assert!(res.contains("2 1 4"));
assert!(res.contains("2 4 5"));
assert!(res.contains("2 5 6"));
assert!(res.contains("2 6 7"));
assert!(res.contains("2 7 8"));
assert!(res.contains("2 8 3"));
}

// --- PARALLEL

#[test]
fn merge_ordering() {}

#[test]
fn split_ordering() {}

#[test]
fn sew_ordering() {
loom::model(|| {
// setup the map
let map: CMap2<f64> = CMapBuilder::default().n_darts(5).build().unwrap();
map.two_link(1, 2);
map.one_link(4, 5);
map.insert_vertex(2, Vertex2(1.0, 1.0));
map.insert_vertex(3, Vertex2(1.0, 2.0));
map.insert_vertex(5, Vertex2(2.0, 2.0));
let arc = loom::sync::Arc::new(map);
let (m1, m2) = (arc.clone(), arc.clone());

// we're going to do to sew ops:
// - 1-sew 1 to 3 (t1)
// - 2-sew 3 to 4 (t2)
// this will result in a single vertex being define, of ID 2
// depending on the order of execution of the sews, the value may change
// 1-sew before 2-sew: (1.5, 1.75)
// 2-sew before 1-sew: (1.25, 1.5)

let t1 = loom::thread::spawn(move || {
m1.one_sew(1, 3);
});

let t2 = loom::thread::spawn(move || {
m2.two_sew(3, 4);
});

t1.join().unwrap();
t2.join().unwrap();

// all path should result in the same topological result here
assert!(arc.vertex(2).is_some());
assert!(arc.vertex(3).is_none());
assert!(arc.vertex(5).is_none());
assert_eq!(Orbit2::new(arc.as_ref(), OrbitPolicy::Vertex, 2).count(), 3);

// the v2 can have two values though
let path1 = arc.vertex(2) == Some(Vertex2(1.5, 1.75));
let path2 = arc.vertex(2) == Some(Vertex2(1.25, 1.5));
assert!(path1 || path2);
});
}

#[test]
fn unsew_ordering() {}
Loading

0 comments on commit fccadad

Please sign in to comment.