# `cell-map`: many-layer 2D cellular maps [![Crates.io](https://img.shields.io/crates/v/cell-map?style=for-the-badge)](https://crates.io/crates/cell-map) [![docs.rs](https://img.shields.io/docsrs/cell-map?style=for-the-badge)](https://docs.rs/cell-map/) This crate provides the `CellMap` type, a 2D map with many layers comprised of cells that can store arbitrary data. It is based on [ANYbotics/grid_map](https://github.com/ANYbotics/grid_map), a C++ ROS package which provides the same type of data structre. `CellMap` uses `ndarray::Array2` to store its data in an efficient and scalable format. It also uses `nalgebra` types for expressing vectors and points. ## Getting Started ### Layers Each layer of the cell map is represented by its own `ndarray::Array2` array. The map indexes each layer by an enum implementing the `Layer` trait. A derive macro is provided to simplify this, for example: ```rust use cell_map::Layer; #[derive(Layer, Clone, Debug)] enum MyLayer { Height, Gradient, Roughness } ``` The `Layer` trait is required to be `Clone`, and is recommended to be `Debug`. ### Creating a `CellMap` To create a new map: ```rust use cell_map::{CellMap, CellMapParams, Layer}; use nalgebra::Vector2; // Creates a new 5x5 map where each cell is 1.0 units wide, which is centred on (0, 0), with // all elements initialised to 1.0. let my_map = CellMap::::new_from_elem( CellMapParams { cell_size: Vector2::new(1.0, 1.0), cell_bounds: Bounds::new((0, 5), (0, 5)).unwrap(), centre: Vector2::new(0.0, 0.0), }, 1.0, ); ``` ### Iterating Over Cells `CellMap` provides methods to produce iterators over its data: - `CellMap::iter()` gives an iterator over all cells in every layer of the map - `CellMap::window_iter()` gives an iterator over rectangular windows into the map. - `CellMap::line_iter()` gives an iterator of cells between two world points All iterators also provide a mutable variant, and more iterators are planned in the future! You can modify iterators so they produce their indexes, as well as controlling which layers the data comes from. See `iterators` for more information. ```rust // Check all the cells in our map are 1, this will be true assert!(my_map.iter().all(|&v| v == 1.0)); // Use a window iterator to change all cells not on the border of the map to 2 my_map.window_iter_mut(Vector2::new(1, 1)).unwrap().for_each(|mut v| { v[(1, 1)] = 2.0; }); // Overwrite all values on the Roughness layer to be zero my_map.iter_mut().layer(MyLayer::Roughness).for_each(|v| *v = 0.0); // Check that our map is how we expect it for ((layer, cell), &value) in my_map.iter().indexed() { if matches!(layer, MyLayer::Roughness) { assert_eq!(value, 0.0); } else if cell.x == 0 || cell.x == 4 || cell.y == 0 || cell.y == 4 { assert_eq!(value, 1.0); } else { assert_eq!(value, 2.0); } } ```