# `cell-map`: many-layer 2D cellular maps
[](https://crates.io/crates/cell-map) [](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::<MyLayer, f64>::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
});
// 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);
}
}
```