surface_grid/
lib.rs

1//! A crate providing data structures for square-tiled grids wrapped around the surface of certain objects.
2//! This create was intended to be used for the creation of cellular automata on non-flat grids.
3//! The crate provides a trait `SurfaceGrid` with an associated type `Point` which can be used to traverse the grid squares.
4//! Additionally, for grids that wrap a sphere the `Point` type implements the `SpherePoint` trait providing conversions
5//! between geographic and surface grid coordinates.
6//! 
7//! ## Available Surfaces
8//! ### Spheres
9//! - `RectangleSphereGrid` - Uses an equirectangular projection to wrap a rectangle around the sphere.
10//! - `CubeSphereGrid` - Projects a cube over the sphere with each face being a square grid.
11
12use std::ops::{IndexMut, Index};
13
14use rayon::iter::ParallelIterator;
15
16pub mod sphere;
17
18/// A grid wrapped around a surface.
19pub trait SurfaceGrid<T> : IndexMut<Self::Point> + Index<Self::Point, Output = T> + IntoIterator<Item = (Self::Point, T)> {
20    /// The type of a point on this grid.
21    type Point: GridPoint + Send;
22
23    /// Creates a new surface grid by calling the specified function for each point in the grid.
24    ///
25    /// - `f` - The function to apply.
26    fn from_fn<F: FnMut(&Self::Point) -> T>(f: F) -> Self;
27
28    /// Creates a new surface grid by calling the specified function in parallel for each point in
29    /// the grid.
30    ///
31    /// - `f` - The function to apply.
32    fn from_fn_par<F: Fn(&Self::Point) -> T + Send + Sync>(f: F) -> Self where T: Send + Sync;
33
34    /// Applies a function to each cell and its direct neighbours.
35    ///
36    /// The provided function is called with the arguments: current, up, down, left, right.
37    ///
38    /// `f` - The function to apply.
39    fn map_neighbours<F: FnMut(&T, &T, &T, &T, &T) -> T>(&self, mut f: F) -> Self where Self: Sized {
40        Self::from_fn(|current| {
41            f(&self[current.clone()], &self[current.up()], &self[current.down()], &self[current.left()], &self[current.right()])
42        })
43    }
44    
45    /// Applies a function to each cell and its direct neighbours including diagonals.
46    ///
47    /// The provided function is called with the arguments: up_left, up, up_right,
48    /// left, current, right, down_left, down, down_right.
49    ///
50    /// `f` - The function to apply.
51    fn map_neighbours_diagonals<
52                F: FnMut(&T, &T, &T, &T, &T, &T, &T, &T, &T) -> T
53            >(&self, mut f: F) -> Self where Self: Sized {
54        Self::from_fn(|current| {
55            f(
56                &self[current.up().left()], &self[current.up()], &self[current.up().right()],
57                &self[current.left()], &self[current.clone()], &self[current.right()],
58                &self[current.down().left()], &self[current.down()], &self[current.down().right()]
59                )
60        })
61    }
62    
63    /// Applies a function in parallel to each cell and its direct neighbours.
64    ///
65    /// The provided function is called with the arguments: current, up, down, left, right.
66    ///
67    /// `f` - The function to apply.
68    fn map_neighbours_par<
69                F: Fn(&T, &T, &T, &T, &T) -> T + Send + Sync
70            >(&self, f: F) -> Self where Self: Sized + Sync, T: Send + Sync {
71        Self::from_fn_par(|current| {
72            f(&self[current.clone()], &self[current.up()], &self[current.down()], &self[current.left()], &self[current.right()])
73        })
74    }
75    
76    /// Applies a function in parallel to each cell and its direct neighbours including diagonals.
77    ///
78    /// The provided function is called with the arguments: up_left, up, up_right,
79    /// left, current, right, down_left, down, down_right.
80    ///
81    /// `f` - The function to apply.
82    fn map_neighbours_diagonals_par<
83                F: Fn(&T, &T, &T, &T, &T, &T, &T, &T, &T) -> T + Send + Sync
84            >(&self, f: F) -> Self where Self: Sized + Sync, T: Send + Sync {
85        Self::from_fn_par(|current| {
86            f(
87                &self[current.up().left()], &self[current.up()], &self[current.up().right()],
88                &self[current.left()], &self[current.clone()], &self[current.right()],
89                &self[current.down().left()], &self[current.down()], &self[current.down().right()]
90                )
91        })
92    }
93    
94    /// Applies a function to each cell and its direct neighbours providing the current point.
95    ///
96    /// The provided function is called with the arguments: current, position, up, down, left, right.
97    ///
98    /// `f` - The function to apply.
99    fn map_neighbours_with_position<F: FnMut(&T, &Self::Point, &T, &T, &T, &T) -> T>(&self, mut f: F) -> Self where Self: Sized {
100        Self::from_fn(|current| {
101            f(&self[current.clone()], current, &self[current.up()], &self[current.down()], &self[current.left()], &self[current.right()])
102        })
103    }
104    
105    /// Applies a function to each cell and its direct neighbours including diagonals providing the
106    /// current point.
107    ///
108    /// The provided function is called with the arguments: position
109    /// up_left, up, up_right,
110    /// left, current, right,
111    /// down_left, down, down_right.
112    ///
113    /// `f` - The function to apply.
114    fn map_neighbours_diagonals_with_position<
115                F: FnMut(&Self::Point, &T, &T, &T, &T, &T, &T, &T, &T, &T) -> T
116            >(&self, mut f: F) -> Self where Self: Sized {
117        Self::from_fn(|current| {
118            f(current,
119                &self[current.up().left()], &self[current.up()], &self[current.up().right()],
120                &self[current.left()], &self[current.clone()], &self[current.right()],
121                &self[current.down().left()], &self[current.down()], &self[current.down().right()]
122                )
123        })
124    }
125    
126    /// Applies a function in parallel to each cell and its direct neighbours providing the current
127    /// point.
128    ///
129    /// The provided function is called with the arguments: current, position, up, down, left, right.
130    ///
131    /// `f` - The function to apply.
132    fn map_neighbours_par_with_position<
133                F: Fn(&T, &Self::Point, &T, &T, &T, &T) -> T + Send + Sync
134            >(&self, f: F) -> Self where Self: Sized + Sync, T: Send + Sync {
135        Self::from_fn_par(|current| {
136            f(&self[current.clone()], current, &self[current.up()], &self[current.down()], &self[current.left()], &self[current.right()])
137        })
138    }
139    
140    /// Applies a function in parallel to each cell and its direct neighbours including diagonals
141    /// providing the current point.
142    ///
143    /// The provided function is called with the arguments: position,
144    /// up_left, up, up_right,
145    /// left, current, right, 
146    /// down_left, down, down_right.
147    ///
148    /// `f` - The function to apply.
149    fn map_neighbours_diagonals_par_with_position<
150                F: Fn(&Self::Point, &T, &T, &T, &T, &T, &T, &T, &T, &T) -> T + Send + Sync
151            >(&self, f: F) -> Self where Self: Sized + Sync, T: Send + Sync {
152        Self::from_fn_par(|current| {
153            f(current,
154                &self[current.up().left()], &self[current.up()], &self[current.up().right()],
155                &self[current.left()], &self[current.clone()], &self[current.right()],
156                &self[current.down().left()], &self[current.down()], &self[current.down().right()]
157                )
158        })
159    }
160    
161    /// Updates this surface grid by calling the specified function for each point in the grid.
162    ///
163    /// - `f` - The function to apply.
164    fn set_from_fn<F: FnMut(&Self::Point) -> T>(&mut self, f: F);
165    
166    /// Updates this surface grid by calling the specified function for each point in the grid in
167    /// parallel.
168    ///
169    /// - `f` - The function to apply.
170    fn set_from_fn_par<F: Fn(&Self::Point) -> T + Send + Sync>(&mut self, f: F) where T: Send + Sync;
171
172    /// Applies a function to each cell and its direct neighbours.
173    ///
174    /// The provided function is called with the arguments: current, up, down, left, right.
175    ///
176    /// `source` - The source grid from which to read data.
177    /// `f` - The function to apply.
178    fn set_from_neighbours<
179                U,
180                G: SurfaceGrid<U, Point = Self::Point>,
181                F: FnMut(&U, &U, &U, &U, &U) -> T
182            >(&mut self, source: &G, mut f: F) {
183        self.set_from_fn(|current| {
184            f(&source[current.clone()], &source[current.up()], &source[current.down()], &source[current.left()], &source[current.right()])
185        })
186    }
187    
188    /// Applies a function to each cell and its direct neighbours including diagonals.
189    ///
190    /// The provided function is called with the arguments: up_left, up, up_right,
191    /// left, current, right, down_left, down, down_right.
192    ///
193    /// `source` - The source grid from which to read data.
194    /// `f` - The function to apply.
195    fn set_from_neighbours_diagonals<
196                U,
197                G: SurfaceGrid<U, Point = Self::Point>,
198                F: FnMut(&U, &U, &U, &U, &U, &U, &U, &U, &U) -> T
199            >(&mut self, source: &G, mut f: F) {
200        self.set_from_fn(|current| {
201            f(
202                &source[current.up().left()], &source[current.up()], &source[current.up().right()],
203                &source[current.left()], &source[current.clone()], &source[current.right()],
204                &source[current.down().left()], &source[current.down()], &source[current.down().right()]
205                )
206        })
207    }
208    
209    /// Applies a function to each cell and its direct neighbours in parallel.
210    ///
211    /// The provided function is called with the arguments: current, up, down, left, right.
212    ///
213    /// `source` - The source grid from which to read data.
214    /// `f` - The function to apply.
215    fn set_from_neighbours_par<
216                U,
217                G: SurfaceGrid<U, Point = Self::Point> + Sync,
218                F: Fn(&U, &U, &U, &U, &U) -> T + Send + Sync
219            >(&mut self, source: &G, f: F) where T: Send + Sync {
220        self.set_from_fn(|current| {
221            f(&source[current.clone()], &source[current.up()], &source[current.down()], &source[current.left()], &source[current.right()])
222        })
223    }
224    
225    /// Applies a function to each cell and its direct neighbours including diagonals in parallel.
226    ///
227    /// The provided function is called with the arguments: up_left, up, up_right,
228    /// left, current, right, down_left, down, down_right.
229    ///
230    /// `source` - The source grid from which to read data.
231    /// `f` - The function to apply.
232    fn set_from_neighbours_diagonals_par<
233                U,
234                G: SurfaceGrid<U, Point = Self::Point> + Sync,
235                F: Fn(&U, &U, &U, &U, &U, &U, &U, &U, &U) -> T + Send + Sync
236            >(&mut self, source: &G, f: F) where T: Send + Sync {
237        self.set_from_fn(|current| {
238            f(
239                &source[current.up().left()], &source[current.up()], &source[current.up().right()],
240                &source[current.left()], &source[current.clone()], &source[current.right()],
241                &source[current.down().left()], &source[current.down()], &source[current.down().right()]
242                )
243        })
244    }
245    
246    /// Applies a function to each cell and its direct neighbours providing the position.
247    ///
248    /// The provided function is called with the arguments: current, position, up, down, left, right.
249    ///
250    /// `source` - The source grid from which to read data.
251    /// `f` - The function to apply.
252    fn set_from_neighbours_with_position<
253                U,
254                G: SurfaceGrid<U, Point = Self::Point>,
255                F: FnMut(&U, &Self::Point, &U, &U, &U, &U) -> T
256            >(&mut self, source: &G, mut f: F) {
257        self.set_from_fn(|current| {
258            f(&source[current.clone()], current, &source[current.up()], &source[current.down()], &source[current.left()], &source[current.right()])
259        })
260    }
261    
262    /// Applies a function to each cell and its direct neighbours including diagonals.
263    ///
264    /// The provided function is called with the arguments: position,
265    /// up_left, up, up_right,
266    /// left, current, right,
267    /// down_left, down, down_right.
268    ///
269    /// `source` - The source grid from which to read data.
270    /// `f` - The function to apply.
271    fn set_from_neighbours_diagonals_with_position<
272                U,
273                G: SurfaceGrid<U, Point = Self::Point>,
274                F: FnMut(&Self::Point, &U, &U, &U, &U, &U, &U, &U, &U, &U) -> T
275            >(&mut self, source: &G, mut f: F) {
276        self.set_from_fn(|current| {
277            f(current,
278                &source[current.up().left()], &source[current.up()], &source[current.up().right()],
279                &source[current.left()], &source[current.clone()], &source[current.right()],
280                &source[current.down().left()], &source[current.down()], &source[current.down().right()]
281                )
282        })
283    }
284    
285    /// Applies a function to each cell and its direct neighbours in parallel.
286    ///
287    /// The provided function is called with the arguments: current, position, up, down, left, right.
288    ///
289    /// `source` - The source grid from which to read data.
290    /// `f` - The function to apply.
291    fn set_from_neighbours_par_with_position<
292                U,
293                G: SurfaceGrid<U, Point = Self::Point> + Sync,
294                F: Fn(&U, &Self::Point, &U, &U, &U, &U) -> T + Send + Sync
295            >(&mut self, source: &G, f: F) where T: Send + Sync {
296        self.set_from_fn(|current| {
297            f(&source[current.clone()], current, &source[current.up()], &source[current.down()], &source[current.left()], &source[current.right()])
298        })
299    }
300    
301    /// Applies a function to each cell and its direct neighbours including diagonals in parallel.
302    ///
303    /// The provided function is called with the arguments: position,
304    /// up_left, up, up_right,
305    /// left, current, right,
306    /// down_left, down, down_right.
307    ///
308    /// `source` - The source grid from which to read data.
309    /// `f` - The function to apply.
310    fn set_from_neighbours_diagonals_par_with_position<
311                U,
312                G: SurfaceGrid<U, Point = Self::Point> + Sync,
313                F: Fn(&Self::Point, &U, &U, &U, &U, &U, &U, &U, &U, &U) -> T + Send + Sync
314            >(&mut self, source: &G, f: F) where T: Send + Sync {
315        self.set_from_fn(|current| {
316            f(current,
317                &source[current.up().left()], &source[current.up()], &source[current.up().right()],
318                &source[current.left()], &source[current.clone()], &source[current.right()],
319                &source[current.down().left()], &source[current.down()], &source[current.down().right()]
320                )
321        })
322    }
323
324    /// Calls a function for each element on this grid.
325    ///
326    /// - `f` - The function to apply.
327    fn for_each(&mut self, f: impl FnMut(&mut T));
328    
329    /// Calls a function for each element on this grid with the position.
330    ///
331    /// - `f` - The function to apply.
332    fn for_each_with_position(&mut self, f: impl FnMut(&Self::Point, &mut T));
333    
334    /// Calls a function for each element on this grid in parallel.
335    ///
336    /// - `f` - The function to apply.
337    fn par_for_each(&mut self, f: impl Fn(&mut T) + Sync) where T: Send + Sync;
338    
339    /// Calls a function for each element on this grid with the position in parallel.
340    ///
341    /// - `f` - The function to apply.
342    fn par_for_each_with_position(&mut self, f: impl Fn(&Self::Point, &mut T) + Sync) where T: Send + Sync;
343
344    /// Iterates over the points in this grid and their values.
345    fn iter<'a>(&'a self) -> impl Iterator<Item = (Self::Point, &'a T)> where T: 'a;
346
347    /// Iterates over the points in this grid and their values in parallel.
348    fn par_iter<'a>(&'a self) -> impl ParallelIterator<Item = (Self::Point, &'a T)> where T: 'a + Send + Sync;
349
350    /// Iterates over the points in this grid.
351    fn points(&self) -> impl Iterator<Item = Self::Point>;
352
353    /// Iterates over the points in this grid in parallel.
354    fn par_points(&self) -> impl ParallelIterator<Item = Self::Point>;
355}
356
357/// A point on a surface grid.
358/// 
359/// A type implementing this trait should ensure that the following conditions are met:
360/// - Two points are equal if they point to the same physical location on the grid.
361///
362/// A point on the grid must also be associated with some direction.
363/// For surfaces that loop this should work such that moving in the same direction will eventually
364/// result in reaching the point at which you started moving.
365pub trait GridPoint : Eq + PartialEq + Clone {
366    /// Gets the point that is immediately above this grid point.
367    fn up(&self) -> Self;
368    
369    /// Gets the point that is immediately below this grid point.
370    fn down(&self) -> Self;
371
372    /// Gets the point that is immediately to the left of this grid point.
373    fn left(&self) -> Self;
374
375    /// Gets the point that is immediately to the right of this grid point.
376    fn right(&self) -> Self;
377
378    /// Gets the position of the point in 3D space.
379    ///
380    /// - `scale` - The scale of the 3D object.
381    fn position(&self, scale: f64) -> (f64, f64, f64);
382}
383