conspire 0.7.0

The Rust interface to conspire.
Documentation
use crate::geometry::{
    grid::{Pixels, Voxels},
    ntree::{Octree, Quadtree},
};

fn octree_leaves(octree: &Octree<u16, usize, u8>) -> usize {
    octree.iter().filter(|node| node.is_leaf()).count()
}

fn quadtree_leaves(quadtree: &Quadtree<u16, usize, u8>) -> usize {
    quadtree.iter().filter(|node| node.is_leaf()).count()
}

#[test]
fn octree_homogeneous_stays_root() {
    let octree = Octree::<u16, usize, u8>::from(Voxels::new(vec![1u8; 8], [2, 2, 2]));
    assert_eq!(octree.len(), 1);
    assert_eq!(octree_leaves(&octree), 1);
}

#[test]
fn octree_heterogeneous_subdivides_once() {
    let mut data = vec![1u8; 8];
    data[7] = 2;
    let octree = Octree::<u16, usize, u8>::from(Voxels::new(data, [2, 2, 2]));
    assert_eq!(octree.len(), 9);
    assert_eq!(octree_leaves(&octree), 8);
}

#[test]
fn octree_non_power_of_two_pads() {
    let octree = Octree::<u16, usize, u8>::from(Voxels::new(vec![1u8; 27], [3, 3, 3]));
    assert_eq!(octree.rescale().center, [2.0; 3]);
    assert!(octree_leaves(&octree) > 1);
}

#[test]
fn quadtree_homogeneous_stays_root() {
    let quadtree = Quadtree::<u16, usize, u8>::from(Pixels::new(vec![1u8; 4], [2, 2]));
    assert_eq!(quadtree.len(), 1);
    assert_eq!(quadtree_leaves(&quadtree), 1);
}

#[test]
fn quadtree_heterogeneous_subdivides_once() {
    let mut data = vec![1u8; 4];
    data[3] = 2;
    let quadtree = Quadtree::<u16, usize, u8>::from(Pixels::new(data, [2, 2]));
    assert_eq!(quadtree.len(), 5);
    assert_eq!(quadtree_leaves(&quadtree), 4);
}

#[test]
fn quadtree_non_power_of_two_pads() {
    let quadtree = Quadtree::<u16, usize, u8>::from(Pixels::new(vec![1u8; 9], [3, 3]));
    assert_eq!(quadtree.rescale().center, [2.0; 2]);
    assert!(quadtree_leaves(&quadtree) > 1);
}

#[test]
fn octree_round_trip() {
    let data: Vec<u8> = (1..=8).collect();
    let octree = Octree::<u16, usize, u8>::from(Voxels::new(data.clone(), [2, 2, 2]));
    let back = Voxels::<u8>::from(&octree);
    assert_eq!(*back.nel(), [2, 2, 2]);
    assert_eq!(back.data(), data);
}

#[test]
fn octree_round_trip_non_power_of_two() {
    let data: Vec<u8> = (0..27).collect();
    let octree = Octree::<u16, usize, u8>::from(Voxels::new(data.clone(), [3, 3, 3]));
    let back = Voxels::<u8>::from(&octree);
    assert_eq!(*back.nel(), [3, 3, 3]);
    assert_eq!(back.data(), data);
}

#[test]
fn refining_a_valued_leaf_inherits_and_clears_parent() {
    let mut octree = Octree::<u16, usize, u8>::from(Voxels::new(vec![7u8; 8], [2, 2, 2]));
    assert_eq!(octree.nodes[0].value, Some(7));
    octree.subdivide(0).unwrap();
    assert_eq!(octree.nodes[0].value, None);
    let children = *octree.nodes[0].orthants().unwrap();
    assert!(children.iter().all(|&c| octree.nodes[c].value == Some(7)));
    let back = Voxels::<u8>::from(&octree);
    assert_eq!(*back.nel(), [2, 2, 2]);
    assert_eq!(back.data(), [7; 8]);
}

#[test]
fn quadtree_round_trip_non_power_of_two() {
    let data: Vec<u8> = (0..6).collect();
    let quadtree = Quadtree::<u16, usize, u8>::from(Pixels::new(data.clone(), [3, 2]));
    let back = Pixels::<u8>::from(&quadtree);
    assert_eq!(*back.nel(), [3, 2]);
    assert_eq!(back.data(), data);
}