Skip to main content

wfc_tiled/
forbid_corner.rs

1extern crate wfc;
2extern crate coord_2d;
3
4use std::collections::HashSet;
5
6use rand::Rng;
7use coord_2d::Coord;
8
9use wfc::{ForbidPattern, Wrap, PatternId, ForbidInterface};
10
11use crate::tile_pattern::TilePattern;
12
13/// Used to prevent wrapping on the edges in the result
14/// 
15/// 
16/// # Examples
17/// A fully functional example can be found under `examples/anchor.rs`
18/// ```
19/// let pattern = TilePattern::from_csv(input_path, 
20///     NonZeroU32::new(pattern_size).unwrap(), 
21///     &[Orientation::Original]).expect("Error while creating pattern");
22/// 
23/// let forbid = ForceBorderForbid::new(&pattern, pattern_size);
24/// let grid = pattern.run_collapse(output_size, attempts,
25///  WrapXY, forbid, &mut rand::thread_rng()).expect("Error in WFC");
26/// ```
27pub struct ForceBorderForbid {
28    pattern_ids: HashSet<PatternId>,
29    offset: i32,
30}
31
32impl ForbidPattern for ForceBorderForbid {
33    fn forbid<W: Wrap, R: Rng>(&mut self, fi: &mut ForbidInterface<W>, rng: &mut R) {
34        let output_size = fi.wave_size();
35        (0..(output_size.width() as i32))
36            .map(|x| Coord::new(x, output_size.height() as i32 - self.offset as i32))
37            .chain(
38                (0..(output_size.width() as i32)).map(|y| {
39                    Coord::new(output_size.width() as i32 - self.offset as i32, y)
40                }),
41            )
42            .for_each(|coord| {
43                self.pattern_ids.iter().for_each(|&pattern_id| {
44                    fi.forbid_all_patterns_except(coord, pattern_id, rng)
45                        .unwrap();
46                });
47            });
48    }
49}
50impl ForceBorderForbid {
51    pub fn new(pattern: &TilePattern, pattern_size: u32) -> ForceBorderForbid{
52        let input_size = pattern.overlapping_patterns.grid().size();
53        let bottom_right_offset = pattern_size - (pattern_size / 2);
54        let id_grid = pattern.overlapping_patterns.id_grid();
55        let bottom_right_coord = Coord::new(
56            input_size.width() as i32 - bottom_right_offset as i32,
57            input_size.height() as i32 - bottom_right_offset as i32,
58        );
59        let bottom_right_ids = id_grid
60            .get_checked(bottom_right_coord)
61            .iter()
62            .cloned()
63            .collect::<HashSet<_>>();
64        return ForceBorderForbid {
65            pattern_ids: bottom_right_ids,
66            offset: bottom_right_offset as i32,
67        };
68    }
69}