aboutsummaryrefslogtreecommitdiff
path: root/src/bitmap.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/bitmap.rs')
-rw-r--r--src/bitmap.rs39
1 files changed, 22 insertions, 17 deletions
diff --git a/src/bitmap.rs b/src/bitmap.rs
index dc66d73..6aa6b12 100644
--- a/src/bitmap.rs
+++ b/src/bitmap.rs
@@ -1,4 +1,5 @@
1use std::{ 1use std::{
2 collections::HashSet,
2 convert::{From, Into, TryFrom}, 3 convert::{From, Into, TryFrom},
3 ops::{Add, Sub}, 4 ops::{Add, Sub},
4}; 5};
@@ -10,7 +11,7 @@ pub struct Pixmap<T> {
10 pub data: Vec<T>, 11 pub data: Vec<T>,
11} 12}
12 13
13#[derive(Copy, Clone, Debug)] 14#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
14pub struct MapPoint { 15pub struct MapPoint {
15 pub x: u32, 16 pub x: u32,
16 pub y: u32, 17 pub y: u32,
@@ -249,22 +250,26 @@ where
249 .collect() 250 .collect()
250 } 251 }
251 252
252 pub fn flood_fill( 253 pub fn flood_fill(&mut self, start: MapPoint, target: T, replacement: T) -> Vec<MapPoint> {
253 &mut self, 254 let mut queue = vec![start];
254 start: MapPoint, 255 let mut area = HashSet::new();
255 target: T, 256 loop {
256 replacement: T, 257 if queue.is_empty() {
257 pts: &mut Vec<MapPoint>, 258 break area.drain().collect();
258 ) { 259 } else {
259 if !self.contains(start) || self.get(start) != target || self.get(start) == replacement { 260 let last = queue.pop().unwrap();
260 return; 261 area.insert(last);
261 } else { 262 for (x, y) in [(1, 0), (0, 1), (-1, 0), (0, -1)].iter() {
262 pts.push(start); 263 let dir = MapPoint::try_from((last.x as i64 + x, last.y as i64 + y));
263 self.set(start, replacement); 264 if let Ok(pt) = dir {
264 for (x, y) in [(1, 0), (0, 1), (-1, 0), (0, -1)].iter() { 265 if self.contains(pt)
265 let dir = MapPoint::try_from((start.x as i64 - x, start.y as i64 + y)); 266 && self.get(pt) == target
266 if let Ok(pt) = dir { 267 && self.get(pt) != replacement
267 self.flood_fill(pt, target, replacement, pts); 268 && !area.contains(&pt)
269 {
270 queue.push(pt);
271 }
272 }
268 } 273 }
269 } 274 }
270 } 275 }