pub struct Grid<T> { /* private fields */ }Expand description
Stores elements of a certain type in a 2D grid structure.
Uses a rust Vec<T> type to reference the grid data on the heap.
Also the number of rows and columns are stored in the grid data structure.
The grid data is stored in a row-major memory layout.
Implementations§
Source§impl<T> Grid<T>where
T: Clone,
impl<T> Grid<T>where
T: Clone,
Sourcepub fn new(rows: usize, cols: usize) -> Grid<T>where
T: Default,
pub fn new(rows: usize, cols: usize) -> Grid<T>where
T: Default,
Init a grid of size rows x columns with default values of the given type. For example this will generate a 2x3 grid of zeros:
use grid::Grid;
let grid : Grid<u8> = Grid::new(2,2);
assert_eq!(grid[0][0], 0);Sourcepub fn init(rows: usize, cols: usize, data: T) -> Grid<T>
pub fn init(rows: usize, cols: usize, data: T) -> Grid<T>
Init a grid of size rows x columns with the given data element.
Sourcepub fn from_vec(vec: Vec<T>, cols: usize) -> Grid<T>
pub fn from_vec(vec: Vec<T>, cols: usize) -> Grid<T>
Returns a grid from a vector with a given column length.
The length of vec must be a multiple of cols.
For example:
use grid::Grid;
let grid = Grid::from_vec(vec![1,2,3,4,5,6], 3);
assert_eq!(grid.size(), (2, 3));will create a grid with the following layout: [1,2,3] [4,5,6]
This example will fail, because vec.len() is not a multiple of cols:
use grid::Grid;
Grid::from_vec(vec![1,2,3,4,5], 3);Examples found in repository?
6fn load_teapot(
7 division: (usize, usize),
8) -> std::io::Result<Model<SurfacePatch<BezierSurface<Point3>>>> {
9 use std::fs::File;
10 use std::io::{BufRead, BufReader};
11 use std::path::Path;
12 use std::str::FromStr;
13
14 let file = Path::new(&std::env::var("CARGO_MANIFEST_DIR").unwrap()).join("assets/teapot.bpt");
15 let reader = BufReader::new(File::open(file)?);
16
17 let mut model = Model::new();
18 let mut points = Vec::new();
19 let mut current_cols = 0;
20
21 for line in reader.lines() {
22 let numbers = line?;
23 let items = numbers.split_whitespace().collect::<Vec<_>>();
24 if items.len() == 1 {
25 model
26 .faces
27 .reserve_exact(usize::from_str(items[0]).unwrap());
28 } else if items.len() == 2 {
29 if points.len() > 0 {
30 let surface = SurfacePatch {
31 surface: BezierSurface::new(Grid::from_vec(points, current_cols)),
32 parameter_range: ((0.0, 1.0), (0.0, 1.0)),
33 parameter_division: division,
34 };
35 model.add_face(surface);
36 }
37 let m = usize::from_str(items[0]).unwrap();
38 let n = usize::from_str(items[1]).unwrap();
39 points = Vec::with_capacity((m + 1) * (n + 1));
40 current_cols = n + 1;
41 } else if items.len() == 3 {
42 let point = Point3::new(
43 Float::from_str(items[0]).unwrap(),
44 Float::from_str(items[1]).unwrap(),
45 Float::from_str(items[2]).unwrap(),
46 );
47 points.push(point);
48 }
49 }
50 // add last surface
51 let surface = SurfacePatch {
52 surface: BezierSurface::new(Grid::from_vec(points, current_cols)),
53 parameter_range: ((0.0, 1.0), (0.0, 1.0)),
54 parameter_division: division,
55 };
56 model.add_face(surface);
57 Ok(model)
58}More examples
6fn load_teapot(
7 degree: (usize, usize),
8 division: (usize, usize),
9) -> std::io::Result<Model<SurfacePatch<BSplineSurface<Point3>>>> {
10 use std::fs::File;
11 use std::io::{BufRead, BufReader};
12 use std::path::Path;
13 use std::str::FromStr;
14
15 let file = Path::new(&std::env::var("CARGO_MANIFEST_DIR").unwrap()).join("assets/teapot.bpt");
16 let reader = BufReader::new(File::open(file)?);
17
18 let mut model = Model::new();
19 let mut points = Vec::new();
20 let mut current_cols = 0;
21
22 for line in reader.lines() {
23 let numbers = line?;
24 let items = numbers.split_whitespace().collect::<Vec<_>>();
25 if items.len() == 1 {
26 model
27 .faces
28 .reserve_exact(usize::from_str(items[0]).unwrap());
29 } else if items.len() == 2 {
30 if points.len() > 0 {
31 let surface = SurfacePatch {
32 surface: BSplineSurface::uniform_clamped(
33 Grid::from_vec(points, current_cols),
34 degree,
35 ),
36 parameter_range: ((0.0, 1.0), (0.0, 1.0)),
37 parameter_division: division,
38 };
39 model.add_face(surface);
40 }
41 let m = usize::from_str(items[0]).unwrap();
42 let n = usize::from_str(items[1]).unwrap();
43 points = Vec::with_capacity((m + 1) * (n + 1));
44 current_cols = n + 1;
45 } else if items.len() == 3 {
46 let point = Point3::new(
47 Float::from_str(items[0]).unwrap(),
48 Float::from_str(items[1]).unwrap(),
49 Float::from_str(items[2]).unwrap(),
50 );
51 points.push(point);
52 }
53 }
54 // add last surface
55 let surface = SurfacePatch {
56 surface: BSplineSurface::uniform_clamped(Grid::from_vec(points, current_cols), degree),
57 parameter_range: ((0.0, 1.0), (0.0, 1.0)),
58 parameter_division: division,
59 };
60 model.add_face(surface);
61 Ok(model)
62}Sourcepub unsafe fn get_unchecked(&self, row: usize, col: usize) -> &T
pub unsafe fn get_unchecked(&self, row: usize, col: usize) -> &T
Returns a reference to an element, without performing bound checks. Generally not recommended, use with caution! Calling this method with an out-of-bounds index is undefined behavior even if the resulting reference is not used.
Sourcepub unsafe fn get_unchecked_mut(&mut self, row: usize, col: usize) -> &mut T
pub unsafe fn get_unchecked_mut(&mut self, row: usize, col: usize) -> &mut T
Returns a mutable reference to an element, without performing bound checks. Generally not recommended, use with caution! Calling this method with an out-of-bounds index is undefined behavior even if the resulting reference is not used.
Sourcepub fn get(&self, row: usize, col: usize) -> Option<&T>
pub fn get(&self, row: usize, col: usize) -> Option<&T>
Access a certain element in the grid. Returns None if an element beyond the grid bounds is tried to be accessed.
Sourcepub fn get_mut(&mut self, row: usize, col: usize) -> Option<&mut T>
pub fn get_mut(&mut self, row: usize, col: usize) -> Option<&mut T>
Mutable access to a certain element in the grid. Returns None if an element beyond the grid bounds is tried to be accessed.
Sourcepub fn size(&self) -> (usize, usize)
pub fn size(&self) -> (usize, usize)
Returns the size of the gird as a two element tuple. First element are the number of rows and the second the columns.
Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Returns true if the grid contains no elements. For example:
use grid::*;
let grid : Grid<u8> = grid![];
assert!(grid.is_empty());Sourcepub fn iter(&self) -> Iter<'_, T>
pub fn iter(&self) -> Iter<'_, T>
Returns an iterator over the whole grid, starting from the first row and column.
use grid::*;
let grid: Grid<u8> = grid![[1,2][3,4]];
let mut iter = grid.iter();
assert_eq!(iter.next(), Some(&1));
assert_eq!(iter.next(), Some(&2));
assert_eq!(iter.next(), Some(&3));
assert_eq!(iter.next(), Some(&4));
assert_eq!(iter.next(), None);Sourcepub fn iter_mut(&mut self) -> IterMut<'_, T>
pub fn iter_mut(&mut self) -> IterMut<'_, T>
Returns an mutable iterator over the whole grid that allows modifying each value.
use grid::*;
let mut grid: Grid<u8> = grid![[1,2][3,4]];
let mut iter = grid.iter_mut();
let next = iter.next();
assert_eq!(next, Some(&mut 1));
*next.unwrap() = 10;Sourcepub fn iter_col(&self, col: usize) -> StepBy<Iter<'_, T>>
pub fn iter_col(&self, col: usize) -> StepBy<Iter<'_, T>>
Returns an iterator over a column.
§Examples
use grid::*;
let grid: Grid<u8> = grid![[1, 2, 3][3, 4, 5]];
let mut col_iter = grid.iter_col(1);
assert_eq!(col_iter.next(), Some(&2));
assert_eq!(col_iter.next(), Some(&4));
assert_eq!(col_iter.next(), None);§Panics
Panics if the col index is out of bounds.
Sourcepub fn iter_col_mut(&mut self, col: usize) -> StepBy<IterMut<'_, T>>
pub fn iter_col_mut(&mut self, col: usize) -> StepBy<IterMut<'_, T>>
Returns a mutable iterator over a column.
§Examples
use grid::*;
let mut grid: Grid<u8> = grid![[1, 2, 3][3, 4, 5]];
let mut col_iter = grid.iter_col_mut(1);
let next = col_iter.next();
assert_eq!(next, Some(&mut 2));
*next.unwrap() = 10;
assert_eq!(grid[0][1], 10);§Panics
Panics if the col index is out of bounds.
Sourcepub fn iter_row(&self, row: usize) -> Iter<'_, T>
pub fn iter_row(&self, row: usize) -> Iter<'_, T>
Returns an iterator over a row.
§Examples
use grid::*;
let grid: Grid<u8> = grid![[1, 2, 3][3, 4, 5]];
let mut col_iter = grid.iter_row(1);
assert_eq!(col_iter.next(), Some(&3));
assert_eq!(col_iter.next(), Some(&4));
assert_eq!(col_iter.next(), Some(&5));
assert_eq!(col_iter.next(), None);§Panics
Panics if the row index is out of bounds.
Sourcepub fn iter_row_mut(&mut self, row: usize) -> IterMut<'_, T>
pub fn iter_row_mut(&mut self, row: usize) -> IterMut<'_, T>
Sourcepub fn push_row(&mut self, row: Vec<T>)
pub fn push_row(&mut self, row: Vec<T>)
Add a new row to the grid.
§Examples
use grid::*;
let mut grid: Grid<u8> = grid![[1, 2, 3][3, 4, 5]];
let row = vec![6,7,8];
grid.push_row(row);
assert_eq!(grid.rows(), 3);
assert_eq!(grid[2][0], 6);
assert_eq!(grid[2][1], 7);
assert_eq!(grid[2][2], 8);Can also be used to init an empty grid:
use grid::*;
let mut grid: Grid<u8> = grid![];
let row = vec![1,2,3];
grid.push_row(row);
assert_eq!(grid.size(), (1, 3));§Panics
Panics if the grid is not empty and row.len() != grid.cols().
Sourcepub fn push_col(&mut self, col: Vec<T>)
pub fn push_col(&mut self, col: Vec<T>)
Add a new column to the grid.
Important:
Please note that Grid uses a Row-Major memory layout. Therefore, the push_col()
operation requires quite a lot of memory shifting and will be significantly slower compared
to a push_row() operation.
§Examples
use grid::*;
let mut grid: Grid<u8> = grid![[1, 2, 3][3, 4, 5]];
let col = vec![4,6];
grid.push_col(col);
assert_eq!(grid.cols(), 4);
assert_eq!(grid[0][3], 4);
assert_eq!(grid[1][3], 6);Can also be used to init an empty grid:
use grid::*;
let mut grid: Grid<u8> = grid![];
let col = vec![1,2,3];
grid.push_col(col);
assert_eq!(grid.size(), (3, 1));§Panics
Panics if the grid is not empty and col.len() != grid.rows().
Sourcepub fn pop_row(&mut self) -> Option<Vec<T>>
pub fn pop_row(&mut self) -> Option<Vec<T>>
Removes the last row from a grid and returns it, or None if it is empty.
§Examples
use grid::*;
let mut grid = grid![[1,2,3][4,5,6]];
assert_eq![grid.pop_row(), Some(vec![4,5,6])];
assert_eq![grid.pop_row(), Some(vec![1,2,3])];
assert_eq![grid.pop_row(), None];Sourcepub fn pop_col(&mut self) -> Option<Vec<T>>
pub fn pop_col(&mut self) -> Option<Vec<T>>
Removes the last column from a grid and returns it, or None if it is empty.
Note that this operation is much slower than the pop_row() because the memory layout
of Grid is row-major and removing a column requires a lot of move operations.
§Examples
use grid::*;
let mut grid = grid![[1,2,3][4,5,6]];
assert_eq![grid.pop_col(), Some(vec![3,6])];
assert_eq![grid.pop_col(), Some(vec![2,5])];
assert_eq![grid.pop_col(), Some(vec![1,4])];
assert_eq![grid.pop_col(), None];Sourcepub fn insert_row(&mut self, index: usize, row: Vec<T>)
pub fn insert_row(&mut self, index: usize, row: Vec<T>)
Insert a new row at the index and shifts all rows after down.
§Examples
use grid::*;
let mut grid = grid![[1,2,3][4,5,6]];
grid.insert_row(1, vec![7,8,9]);
assert_eq!(grid[0], [1,2,3]);
assert_eq!(grid[1], [7,8,9]);
assert_eq!(grid[2], [4,5,6]);
assert_eq!(grid.size(), (3,3))Sourcepub fn insert_col(&mut self, index: usize, col: Vec<T>)
pub fn insert_col(&mut self, index: usize, col: Vec<T>)
Insert a new column at the index.
Important! Insertion of columns is a lot slower than the lines insertion. This is because of the memory layout of the grid data structure.
§Examples
use grid::*;
let mut grid = grid![[1,2,3][4,5,6]];
grid.insert_col(1, vec![9,9]);
assert_eq!(grid[0], [1,9,2,3]);
assert_eq!(grid[1], [4,9,5,6]);
assert_eq!(grid.size(), (2,4))Sourcepub fn flatten(&self) -> &Vec<T>
pub fn flatten(&self) -> &Vec<T>
Returns a reference to the internal data structure of the grid.
Grid uses a row major layout. All rows are placed right after each other in the vector data structure.
§Examples
use grid::*;
let grid = grid![[1,2,3][4,5,6]];
let flat = grid.flatten();
assert_eq!(flat, &vec![1,2,3,4,5,6]);Trait Implementations§
impl<T> Eq for Grid<T>where
T: Eq,
Auto Trait Implementations§
impl<T> Freeze for Grid<T>
impl<T> RefUnwindSafe for Grid<T>where
T: RefUnwindSafe,
impl<T> Send for Grid<T>where
T: Send,
impl<T> Sync for Grid<T>where
T: Sync,
impl<T> Unpin for Grid<T>where
T: Unpin,
impl<T> UnwindSafe for Grid<T>where
T: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.