# HG changeset patch # User unC0Rr # Date 1541165364 -3600 # Node ID bf40b5f938b0845f838fe95a4f98585b19c41597 # Parent 5ade484f33517841e0fb5cf96bf033c62490f206 - Add methods to work with Rect as box - Refactor, tests, fixes diff -r 5ade484f3351 -r bf40b5f938b0 rust/integral-geometry/src/lib.rs --- a/rust/integral-geometry/src/lib.rs Fri Nov 02 13:30:04 2018 +0100 +++ b/rust/integral-geometry/src/lib.rs Fri Nov 02 14:29:24 2018 +0100 @@ -202,6 +202,17 @@ } } + pub fn from_box(left: i32, right: i32, top: i32, bottom: i32) -> Self { + assert!(left <= right); + assert!(top <= bottom); + + Rect::new(left, top, (right - left) as u32, (bottom - top) as u32) + } + + pub fn from_size(top_left: Point, size: Size) -> Self { + Rect::new(top_left.x, top_left.y, size.width as u32, size.height as u32) + } + #[inline] pub fn size(&self) -> Size { Size::new(self.width as usize, self.height as usize) @@ -211,6 +222,41 @@ pub fn area(&self) -> usize { self.size().area() } + + #[inline] + pub fn left(&self) -> i32 { + self.x + } + + #[inline] + pub fn top(&self) -> i32 { + self.y + } + + #[inline] + pub fn right(&self) -> i32 { + self.x + self.width as i32 + } + + #[inline] + pub fn bottom(&self) -> i32 { + self.y + self.height as i32 + } + + #[inline] + pub fn top_left(&self) -> Point { + Point::new(self.x, self.y) + } + + #[inline] + pub fn with_margin(&self, margin: i32) -> Self { + Rect::from_box( + self.left() + margin, + self.right() - margin, + self.top() + margin, + self.bottom() - margin, + ) + } } #[derive(PartialEq, Eq, Clone, Copy, Debug)] @@ -440,4 +486,12 @@ assert_eq!(l.center(), Point::new(3, 3)); } + + #[test] + fn rect() { + let r = Rect::from_box(10, 100, 0, 70); + + assert_eq!(r.top_left(), Point::new(10, 0)); + assert_eq!(r.with_margin(12), Rect::from_box(22, 88, 12, 58)); + } } diff -r 5ade484f3351 -r bf40b5f938b0 rust/land2d/src/lib.rs --- a/rust/land2d/src/lib.rs Fri Nov 02 13:30:04 2018 +0100 +++ b/rust/land2d/src/lib.rs Fri Nov 02 14:29:24 2018 +0100 @@ -3,24 +3,29 @@ use std::cmp; -use integral_geometry::{ - ArcPoints, EquidistantPoints, - Point, Size, SizeMask, Line -}; +use integral_geometry::{ArcPoints, EquidistantPoints, Line, Point, Rect, Size, SizeMask}; pub struct Land2D { pixels: vec2d::Vec2D, play_size: Size, - mask: SizeMask + play_box: Rect, + + mask: SizeMask, } impl Land2D { pub fn new(play_size: Size, fill_value: T) -> Self { let real_size = play_size.next_power_of_two(); + let top_left = Point::new( + (real_size.width - play_size.width / 2) as i32, + (real_size.height - play_size.height) as i32, + ); + let play_box = Rect::from_size(top_left, play_size); Self { play_size, + play_box, pixels: vec2d::Vec2D::new(real_size, fill_value), - mask: real_size.to_mask() + mask: real_size.to_mask(), } } @@ -55,6 +60,11 @@ } #[inline] + pub fn play_box(&self) -> Rect { + self.play_box + } + + #[inline] pub fn is_valid_x(&self, x: i32) -> bool { self.mask.contains_x(x as usize) } @@ -245,7 +255,8 @@ let from_x = cmp::max(0, center.x - offset.x) as usize; let to_x = cmp::min(self.width() - 1, (center.x + offset.x) as usize); self.pixels[row_index as usize][from_x..=to_x] - .iter_mut().for_each(|v| *v = value); + .iter_mut() + .for_each(|v| *v = value); to_x - from_x + 1 } else { 0 @@ -253,14 +264,14 @@ } pub fn fill_circle(&mut self, center: Point, radius: i32, value: T) -> usize { - let transforms = - [[0, 1, 1, 0], [0, 1, -1, 0], - [1, 0, 0, 1], [1, 0, 0, -1]]; - ArcPoints::new(radius).map(|vector| { - transforms.iter().map(|m| - self.fill_row(center, vector.transform(m), value) - ).sum::() - }).sum() + let transforms = [[0, 1, 1, 0], [0, 1, -1, 0], [1, 0, 0, 1], [1, 0, 0, -1]]; + ArcPoints::new(radius) + .map(|vector| { + transforms + .iter() + .map(|m| self.fill_row(center, vector.transform(m), value)) + .sum::() + }).sum() } pub fn draw_thick_line(&mut self, line: Line, radius: i32, value: T) -> usize { diff -r 5ade484f3351 -r bf40b5f938b0 rust/landgen/src/outline.rs --- a/rust/landgen/src/outline.rs Fri Nov 02 13:30:04 2018 +0100 +++ b/rust/landgen/src/outline.rs Fri Nov 02 14:29:24 2018 +0100 @@ -1,6 +1,6 @@ use itertools::Itertools; -use integral_geometry::{Line, Point, Size}; +use integral_geometry::{Line, Point, Rect, Size}; use land2d::Land2D; use outline_template::OutlineTemplate; @@ -9,14 +9,19 @@ pub islands: Vec>, pub fill_points: Vec, pub size: Size, + pub play_box: Rect, } impl OutlinePoints { pub fn from_outline_template>( outline_template: &OutlineTemplate, + play_box: Rect, + size: Size, random_numbers: &mut I, ) -> Self { Self { + play_box, + size, islands: outline_template .islands .iter() @@ -24,14 +29,15 @@ i.iter() .zip(random_numbers.tuples()) .map(|(rect, (rnd_a, rnd_b))| { - Point::new( - rect.x + (rnd_a % rect.width) as i32, - rect.y + (rnd_b % rect.height) as i32, - ) + rect.top_left() + + Point::new( + (rnd_a % rect.width) as i32, + (rnd_b % rect.height) as i32, + ) + + play_box.top_left() }).collect() }).collect(), fill_points: outline_template.fill_points.clone(), - size: outline_template.size, } } @@ -51,7 +57,6 @@ segment: Line, random_numbers: &mut I, ) -> Option { - None } @@ -130,18 +135,28 @@ fn next(&mut self) -> Option { if self.island < self.outline.islands.len() { - if self.index + 1 < self.outline.islands[self.index].len() { - Some(Line::new( - self.outline.islands[self.index][self.index], - self.outline.islands[self.index][self.index + 1], - )) - } else if self.index + 1 == self.outline.islands[self.index].len() { - Some(Line::new( - self.outline.islands[self.index][self.index], - self.outline.islands[self.index][0], - )) + if self.index + 1 < self.outline.islands[self.island].len() { + let result = Some(Line::new( + self.outline.islands[self.island][self.index], + self.outline.islands[self.island][self.index + 1], + )); + + self.index += 1; + + result + } else if self.index + 1 == self.outline.islands[self.island].len() { + let result = Some(Line::new( + self.outline.islands[self.island][self.index], + self.outline.islands[self.island][0], + )); + + self.island += 1; + self.index = 0; + + result } else { self.island += 1; + self.index = 0; self.next() } } else { @@ -149,3 +164,30 @@ } } } + +#[test()] +fn points_test() { + let mut points = OutlinePoints { + islands: vec![ + vec![Point::new(0, 0), Point::new(20, 0), Point::new(30, 30)], + vec![Point::new(10, 15), Point::new(15, 20), Point::new(20, 15)], + ], + fill_points: vec![Point::new(1, 1)], + play_box: Rect::from_box(0, 100, 0, 100).with_margin(10), + size: Size::square(100), + }; + + let segments: Vec = points.segments_iter().collect(); + assert_eq!( + segments.first(), + Some(&Line::new(Point::new(0, 0), Point::new(20, 0))) + ); + assert_eq!( + segments.last(), + Some(&Line::new(Point::new(20, 15), Point::new(10, 15))) + ); + + points.iter_mut().for_each(|p| p.x = 2); + assert_eq!(points.fill_points[0].x, 2); + assert_eq!(points.islands[0][0].x, 2); +} diff -r 5ade484f3351 -r bf40b5f938b0 rust/landgen/src/template_based.rs --- a/rust/landgen/src/template_based.rs Fri Nov 02 13:30:04 2018 +0100 +++ b/rust/landgen/src/template_based.rs Fri Nov 02 14:29:24 2018 +0100 @@ -23,19 +23,10 @@ parameters: LandGenerationParameters, random_numbers: &mut I, ) -> Land2D { - let mut points = - OutlinePoints::from_outline_template(&self.outline_template, random_numbers); - - let mut land = Land2D::new(points.size, parameters.basic); + let mut land = Land2D::new(self.outline_template.size, parameters.basic); - let top_left = Point::new( - (land.width() - land.play_width() / 2) as i32, - (land.height() - land.play_height()) as i32, - ); - - points.size = land.size(); - - points.iter_mut().for_each(|p| *p += top_left); + let mut points = + OutlinePoints::from_outline_template(&self.outline_template, land.play_box(), land.size(), random_numbers); // mirror if self.outline_template.can_mirror { @@ -72,15 +63,3 @@ land } } - -#[test()] -fn points_test() { - let mut points = OutlinePoints { - islands: vec![vec![]], - fill_points: vec![Point::new(1, 1)], - size: Size::square(100), - }; - - points.iter_mut().for_each(|p| p.x = 2); - assert_eq!(points.fill_points[0].x, 2); -}