--- a/rust/integral-geometry/src/lib.rs Wed Oct 31 22:41:05 2018 +0300
+++ b/rust/integral-geometry/src/lib.rs Thu Nov 01 02:55:22 2018 +0300
@@ -78,6 +78,14 @@
}
#[inline]
+ pub fn next_power_of_two(&self) -> Self {
+ Self {
+ width: self.width.next_power_of_two(),
+ height: self.height.next_power_of_two()
+ }
+ }
+
+ #[inline]
pub fn to_mask(&self) -> SizeMask {
SizeMask::new(*self)
}
@@ -146,6 +154,22 @@
bin_assign_op_impl!(MulAssign, mul_assign);
bin_assign_op_impl!(DivAssign, div_assign);
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+pub struct Rect {
+ pub x: i32,
+ pub y: i32,
+ pub width: u32,
+ pub height: u32,
+}
+
+impl Rect {
+ #[inline]
+ pub fn new(x: i32, y: i32, width: u32, height: u32) -> Self {
+ Self { x, y, width, height }
+ }
+}
+
+
pub struct LinePoints {
accumulator: Point,
direction: Point,
--- a/rust/land2d/src/lib.rs Wed Oct 31 22:41:05 2018 +0300
+++ b/rust/land2d/src/lib.rs Thu Nov 01 02:55:22 2018 +0300
@@ -2,7 +2,6 @@
extern crate vec2d;
use std::cmp;
-use std::ops;
use integral_geometry::{
ArcPoints, EquidistantPoints, LinePoints,
@@ -11,14 +10,17 @@
pub struct Land2D<T> {
pixels: vec2d::Vec2D<T>,
+ play_size: Size,
mask: SizeMask
}
impl<T: Copy + PartialEq> Land2D<T> {
- pub fn new(size: Size, fill_value: T) -> Self {
+ pub fn new(play_size: Size, fill_value: T) -> Self {
+ let real_size = play_size.next_power_of_two();
Self {
- pixels: vec2d::Vec2D::new(size, fill_value),
- mask: size.to_mask()
+ play_size,
+ pixels: vec2d::Vec2D::new(real_size, fill_value),
+ mask: real_size.to_mask()
}
}
@@ -33,6 +35,26 @@
}
#[inline]
+ pub fn size(&self) -> Size {
+ self.pixels.size()
+ }
+
+ #[inline]
+ pub fn play_width(&self) -> usize {
+ self.play_size.width
+ }
+
+ #[inline]
+ pub fn play_height(&self) -> usize {
+ self.play_size.height
+ }
+
+ #[inline]
+ pub fn play_size(&self) -> Size {
+ self.play_size
+ }
+
+ #[inline]
pub fn is_valid_x(&self, x: i32) -> bool {
self.mask.contains_x(x as usize)
}
@@ -267,7 +289,12 @@
#[test]
fn basics() {
- let l: Land2D<u8> = Land2D::new(Size::new(32, 64), 0);
+ let l: Land2D<u8> = Land2D::new(Size::new(30, 50), 0);
+
+ assert_eq!(l.play_width(), 30);
+ assert_eq!(l.play_height(), 50);
+ assert_eq!(l.width(), 32);
+ assert_eq!(l.height(), 64);
assert!(l.is_valid_coordinate(0, 0));
assert!(!l.is_valid_coordinate(-1, -1));
--- a/rust/landgen/Cargo.toml Wed Oct 31 22:41:05 2018 +0300
+++ b/rust/landgen/Cargo.toml Thu Nov 01 02:55:22 2018 +0300
@@ -6,3 +6,4 @@
[dependencies]
integral-geometry = { path = "../integral-geometry" }
land2d = { path = "../land2d" }
+itertools = "0.7.8"
--- a/rust/landgen/src/lib.rs Wed Oct 31 22:41:05 2018 +0300
+++ b/rust/landgen/src/lib.rs Thu Nov 01 02:55:22 2018 +0300
@@ -2,6 +2,7 @@
extern crate integral_geometry;
extern crate land2d;
+extern crate itertools;
pub struct LandGenerationParameters<T> {
zero: T,
--- a/rust/landgen/src/template_based.rs Wed Oct 31 22:41:05 2018 +0300
+++ b/rust/landgen/src/template_based.rs Thu Nov 01 02:55:22 2018 +0300
@@ -1,10 +1,53 @@
-use integral_geometry::{Point, Size};
+use itertools::Itertools;
+
+use integral_geometry::{Point, Size, Rect};
use land2d::Land2D;
use LandGenerationParameters;
use LandGenerator;
+struct OutlinePoints {
+ islands: Vec<Vec<Point>>,
+ fill_points: Vec<Point>,
+ size: Size,
+}
+
+impl OutlinePoints {
+ fn from_outline_template<I: Iterator<Item = u32>>(
+ outline_template: &OutlineTemplate,
+ random_numbers: &mut I,
+ ) -> Self {
+ Self {
+ islands: outline_template
+ .islands
+ .iter()
+ .map(|i| {
+ 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,
+ )
+ }).collect()
+ }).collect(),
+ fill_points: outline_template.fill_points.clone(),
+ size: outline_template.size
+ }
+ }
+
+ fn iter_mut(&mut self) -> impl Iterator<Item = &mut Point> {
+ self.islands.iter_mut()
+ .flat_map(|i| i.iter_mut())
+ .chain(self.fill_points.iter_mut())
+ }
+
+ fn distort<I: Iterator<Item = u32>>(&mut self, random_numbers: &mut I) {
+ unimplemented!()
+ }
+}
+
struct OutlineTemplate {
- islands: Vec<Vec<Point>>,
+ islands: Vec<Vec<Rect>>,
fill_points: Vec<Point>,
size: Size,
can_flip: bool,
@@ -17,10 +60,8 @@
outline_template: OutlineTemplate,
}
-impl OutlineTemplate {}
-
impl TemplatedLandGenerator {
- fn new(outline_template: OutlineTemplate) -> Self {
+ pub fn new(outline_template: OutlineTemplate) -> Self {
Self { outline_template }
}
}
@@ -31,23 +72,61 @@
parameters: LandGenerationParameters<T>,
random_numbers: &mut I,
) -> Land2D<T> {
- let mut pa = Vec::new();
+ let mut points =
+ OutlinePoints::from_outline_template(&self.outline_template, random_numbers);
+
+ let mut land = Land2D::new(points.size, parameters.basic);
- for island in &self.outline_template.islands {
- let mut island_points = Vec::new();
+ let top_left = Point::new(
+ (land.width() - land.play_width() / 2) as i32,
+ (land.height() - land.play_height()) as i32,
+ );
- for p in island {
- island_points.push(p);
+ points.size = land.size();
+
+ points.iter_mut().for_each(|p| *p += top_left);
+
+ // mirror
+ if self.outline_template.can_mirror {
+ if let Some(b) = random_numbers.next() {
+ if b & 1 != 0 {
+ points.iter_mut().for_each(|p| p.x = land.width() as i32 - 1 - p.x);
+ }
}
-
- pa.push(island_points);
}
- let mut land = Land2D::new(
- self.outline_template.size,
- parameters.basic,
- );
+ // flip
+ if self.outline_template.can_flip {
+ if let Some(b) = random_numbers.next() {
+ if b & 1 != 0 {
+ points.iter_mut().for_each(|p|
+ p.y = land.height() as i32 - 1 - p.y);
+ }
+ }
+ }
+
+ points.distort(random_numbers);
+
+ // draw_edge(points, land, parameters.zero)
+
+ for p in points.fill_points {
+ land.fill(p, parameters.zero, parameters.zero)
+ }
+
+ // draw_edge(points, land, parameters.basic)
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);
+}