--- 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));
+ }
}
--- 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<T> {
pixels: vec2d::Vec2D<T>,
play_size: Size,
- mask: SizeMask
+ play_box: Rect,
+
+ mask: SizeMask,
}
impl<T: Copy + PartialEq> Land2D<T> {
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::<usize>()
- }).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::<usize>()
+ }).sum()
}
pub fn draw_thick_line(&mut self, line: Line, radius: i32, value: T) -> usize {
--- 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<Vec<Point>>,
pub fill_points: Vec<Point>,
pub size: Size,
+ pub play_box: Rect,
}
impl OutlinePoints {
pub fn from_outline_template<I: Iterator<Item = u32>>(
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<Point> {
-
None
}
@@ -130,18 +135,28 @@
fn next(&mut self) -> Option<Self::Item> {
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<Line> = 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);
+}
--- 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<T>,
random_numbers: &mut I,
) -> Land2D<T> {
- 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);
-}