Grid

Struct Grid 

Source
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,

Source

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);
Source

pub fn init(rows: usize, cols: usize, data: T) -> Grid<T>

Init a grid of size rows x columns with the given data element.

Source

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?
examples/bezier.rs (line 31)
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
Hide additional examples
examples/bspline.rs (line 33)
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}
Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub fn rows(&self) -> usize

Returns the number of rows of the grid.

Source

pub fn cols(&self) -> usize

Returns the number of columns of the grid.

Source

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());
Source

pub fn clear(&mut self)

Clears the grid.

Source

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);
Source

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;
Source

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.

Source

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.

Source

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.

Source

pub fn iter_row_mut(&mut self, row: usize) -> IterMut<'_, T>

Returns a mutable iterator over a row.

§Examples
use grid::*;
let mut grid: Grid<u8> = grid![[1, 2, 3][3, 4, 5]];
let mut col_iter = grid.iter_row_mut(1);
let next = col_iter.next();
*next.unwrap() = 10;
assert_eq!(grid[1][0], 10);
§Panics

Panics if the row index is out of bounds.

Source

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().

Source

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().

Source

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];
Source

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];
Source

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))
Source

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))
Source

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]);
Source

pub fn into_vec(self) -> Vec<T>

Converts self into a vector without clones or allocation.

Trait Implementations§

Source§

impl<T> Clone for Grid<T>
where T: Clone,

Source§

fn clone(&self) -> Grid<T>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T> Debug for Grid<T>
where T: Debug,

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl From<Grid<DVec3>> for TriangleMesh

Source§

fn from(grid: Grid<Point3>) -> TriangleMesh

Converts to this type from the input type.
Source§

impl<T> Index<usize> for Grid<T>
where T: Clone,

Source§

type Output = [T]

The returned type after indexing.
Source§

fn index(&self, idx: usize) -> &<Grid<T> as Index<usize>>::Output

Performs the indexing (container[index]) operation. Read more
Source§

impl<T> IndexMut<usize> for Grid<T>
where T: Clone,

Source§

fn index_mut(&mut self, idx: usize) -> &mut <Grid<T> as Index<usize>>::Output

Performs the mutable indexing (container[index]) operation. Read more
Source§

impl<T> PartialEq for Grid<T>
where T: Eq,

Source§

fn eq(&self, other: &Grid<T>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

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> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert 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>

Convert 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)

Convert &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)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.