rust/landgen/src/outline.rs
changeset 14145 6e0be42d0a8f
parent 14143 c27461e6a9eb
child 14146 376a0551b00a
equal deleted inserted replaced
14144:59ec51b78737 14145:6e0be42d0a8f
     1 use itertools::Itertools;
     1 use itertools::Itertools;
     2 use std::cmp::min;
     2 use std::cmp::min;
     3 
     3 
     4 use integral_geometry::{Line, Point, Rect, Size};
     4 use integral_geometry::{
       
     5     Line, Point, Rect, Size, Polygon
       
     6 };
     5 use land2d::Land2D;
     7 use land2d::Land2D;
     6 
     8 
     7 use outline_template::OutlineTemplate;
     9 use outline_template::OutlineTemplate;
     8 
    10 
     9 pub struct OutlinePoints {
    11 pub struct OutlinePoints {
    10     pub islands: Vec<Vec<Point>>,
    12     pub islands: Vec<Polygon>,
    11     pub fill_points: Vec<Point>,
    13     pub fill_points: Vec<Point>,
    12     pub size: Size,
    14     pub size: Size,
    13     pub play_box: Rect,
    15     pub play_box: Rect,
    14 }
    16 }
    15 
    17 
    35                                     (rnd_a % rect.width) as i32,
    37                                     (rnd_a % rect.width) as i32,
    36                                     (rnd_b % rect.height) as i32,
    38                                     (rnd_b % rect.height) as i32,
    37                                 )
    39                                 )
    38                                 + play_box.top_left()
    40                                 + play_box.top_left()
    39                         })
    41                         })
    40                         .collect()
    42                         .collect::<Vec<_>>().into()
    41                 })
    43                 })
    42                 .collect(),
    44                 .collect(),
    43             fill_points: outline_template.fill_points.clone(),
    45             fill_points: outline_template.fill_points.clone(),
    44         }
    46         }
    45     }
    47     }
    46 
    48 
    47     pub fn total_len(&self) -> usize {
    49     pub fn total_len(&self) -> usize {
    48         self.islands.iter().map(|i| i.len()).sum::<usize>() + self.fill_points.len()
    50         self.islands.iter().map(|i| i.edges_count()).sum::<usize>() + self.fill_points.len()
    49     }
    51     }
    50 
    52 
    51     pub fn iter(&self) -> impl Iterator<Item = &Point> {
    53     pub fn iter(&self) -> impl Iterator<Item = &Point> {
    52         self.islands
    54         self.islands
    53             .iter()
    55             .iter()
    54             .flat_map(|i| i.iter())
    56             .flat_map(|p| p.iter())
    55             .chain(self.fill_points.iter())
    57             .chain(self.fill_points.iter())
    56     }
    58     }
    57 
    59 
    58     pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Point> {
    60     pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Point> {
    59         self.islands
    61         self.islands
   233         distance_divisor: u32,
   235         distance_divisor: u32,
   234         random_numbers: &mut I,
   236         random_numbers: &mut I,
   235     ) {
   237     ) {
   236         for is in 0..self.islands.len() {
   238         for is in 0..self.islands.len() {
   237             let mut i = 0;
   239             let mut i = 0;
   238             let mut segment;
   240             while i < self.islands[is].edges_count() {
   239 
   241                 let segment = self.islands[is].get_edge(i);
   240             loop {
   242                 if let Some(new_point) = self.divide_edge(segment, distance_divisor, random_numbers) {
   241                 {
   243                     self.islands[is].split_edge(i, new_point);
   242                     let island = &self.islands[is];
       
   243                     let mut end_point;
       
   244                     if i < island.len() {
       
   245                         end_point = if i + 1 < island.len() {
       
   246                             island[i + 1]
       
   247                         } else {
       
   248                             island[0]
       
   249                         };
       
   250                     } else {
       
   251                         break;
       
   252                     }
       
   253 
       
   254                     segment = Line::new(island[i], end_point);
       
   255                 }
       
   256 
       
   257                 if let Some(new_point) = self.divide_edge(segment, distance_divisor, random_numbers)
       
   258                 {
       
   259                     self.islands[is].insert(i + 1, new_point);
       
   260                     i += 2;
   244                     i += 2;
   261                 } else {
   245                 } else {
   262                     i += 1;
   246                     i += 1;
   263                 }
   247                 }
   264             }
   248             }
   286         for segment in self.segments_iter() {
   270         for segment in self.segments_iter() {
   287             land.draw_line(segment, value);
   271             land.draw_line(segment, value);
   288         }
   272         }
   289     }
   273     }
   290 
   274 
   291     fn segments_iter(&self) -> OutlineSegmentsIterator {
   275     fn segments_iter<'a>(&'a self) -> impl Iterator<Item = Line> + 'a {
   292         OutlineSegmentsIterator {
   276         self.islands.iter().flat_map(|p| p.iter_edges())
   293             outline: self,
       
   294             island: 0,
       
   295             index: 0,
       
   296         }
       
   297     }
   277     }
   298 
   278 
   299     pub fn mirror(&mut self) {
   279     pub fn mirror(&mut self) {
   300         let r = self.size.width as i32 - 1;
   280         let r = self.size.width as i32 - 1;
   301 
   281 
   307 
   287 
   308         self.iter_mut().for_each(|p| p.y = t - p.y);
   288         self.iter_mut().for_each(|p| p.y = t - p.y);
   309     }
   289     }
   310 }
   290 }
   311 
   291 
   312 struct OutlineSegmentsIterator<'a> {
       
   313     outline: &'a OutlinePoints,
       
   314     island: usize,
       
   315     index: usize,
       
   316 }
       
   317 
       
   318 impl<'a> Iterator for OutlineSegmentsIterator<'a> {
       
   319     type Item = Line;
       
   320 
       
   321     fn next(&mut self) -> Option<Self::Item> {
       
   322         if self.island < self.outline.islands.len() {
       
   323             if self.index + 1 < self.outline.islands[self.island].len() {
       
   324                 let result = Some(Line::new(
       
   325                     self.outline.islands[self.island][self.index],
       
   326                     self.outline.islands[self.island][self.index + 1],
       
   327                 ));
       
   328 
       
   329                 self.index += 1;
       
   330 
       
   331                 result
       
   332             } else if self.index + 1 == self.outline.islands[self.island].len() {
       
   333                 let result = Some(Line::new(
       
   334                     self.outline.islands[self.island][self.index],
       
   335                     self.outline.islands[self.island][0],
       
   336                 ));
       
   337 
       
   338                 self.island += 1;
       
   339                 self.index = 0;
       
   340 
       
   341                 result
       
   342             } else {
       
   343                 self.island += 1;
       
   344                 self.index = 0;
       
   345                 self.next()
       
   346             }
       
   347         } else {
       
   348             None
       
   349         }
       
   350     }
       
   351 }
       
   352 
       
   353 #[test()]
   292 #[test()]
   354 fn points_test() {
   293 fn points_test() {
       
   294     ;
   355     let mut points = OutlinePoints {
   295     let mut points = OutlinePoints {
       
   296 
   356         islands: vec![
   297         islands: vec![
   357             vec![Point::new(0, 0), Point::new(20, 0), Point::new(30, 30)],
   298             Polygon::new(&[Point::new(0, 0), Point::new(20, 0), Point::new(30, 30)]),
   358             vec![Point::new(10, 15), Point::new(15, 20), Point::new(20, 15)],
   299             Polygon::new(&[Point::new(10, 15), Point::new(15, 20), Point::new(20, 15)]),
   359         ],
   300         ],
   360         fill_points: vec![Point::new(1, 1)],
   301         fill_points: vec![Point::new(1, 1)],
   361         play_box: Rect::from_box(0, 100, 0, 100).with_margin(10),
   302         play_box: Rect::from_box(0, 100, 0, 100).with_margin(10),
   362         size: Size::square(100),
   303         size: Size::square(100),
   363     };
   304     };
   372         Some(&Line::new(Point::new(20, 15), Point::new(10, 15)))
   313         Some(&Line::new(Point::new(20, 15), Point::new(10, 15)))
   373     );
   314     );
   374 
   315 
   375     points.iter_mut().for_each(|p| p.x = 2);
   316     points.iter_mut().for_each(|p| p.x = 2);
   376     assert_eq!(points.fill_points[0].x, 2);
   317     assert_eq!(points.fill_points[0].x, 2);
   377     assert_eq!(points.islands[0][0].x, 2);
   318     assert_eq!(points.islands[0].get_edge(0).start.x, 2);
   378 }
   319 }