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