# HG changeset patch # User unC0Rr # Date 1676282412 -3600 # Node ID 5f00829c55ec601f547aca92e9f9b3fd295cd024 # Parent 168f44ef9b671c580c73f9d63f13ac7c62860d71 Refactor landgen package structure diff -r 168f44ef9b67 -r 5f00829c55ec rust/landgen/src/lib.rs --- a/rust/landgen/src/lib.rs Mon Feb 13 10:39:37 2023 +0100 +++ b/rust/landgen/src/lib.rs Mon Feb 13 11:00:12 2023 +0100 @@ -1,6 +1,4 @@ -mod outline; -pub mod outline_template; -pub mod template_based; +pub mod outline_template_based; pub mod wavefront_collapse; #[derive(Clone, Copy)] diff -r 168f44ef9b67 -r 5f00829c55ec rust/landgen/src/outline.rs --- a/rust/landgen/src/outline.rs Mon Feb 13 10:39:37 2023 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,341 +0,0 @@ -use itertools::Itertools; -use std::cmp::min; - -use integral_geometry::{Line, Point, Polygon, Ray, Rect, Size}; -use land2d::Land2D; - -use crate::outline_template::OutlineTemplate; - -pub struct OutlinePoints { - pub islands: Vec, - pub fill_points: Vec, - pub size: Size, - pub play_box: Rect, - intersections_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() - .map(|i| { - i.iter() - .zip(random_numbers.tuples()) - .map(|(rect, (rnd_a, rnd_b))| { - play_box.top_left() + rect.quotient(rnd_a as usize, rnd_b as usize) - }) - .collect::>() - .into() - }) - .collect(), - fill_points: outline_template.fill_points.clone(), - intersections_box: Rect::at_origin(size) - .with_margin(size.to_square().width as i32 * -2), - } - } - - pub fn total_len(&self) -> usize { - self.islands.iter().map(|i| i.edges_count()).sum::() + self.fill_points.len() - } - - pub fn iter(&self) -> impl Iterator { - self.islands - .iter() - .flat_map(|p| p.iter()) - .chain(self.fill_points.iter()) - } - - pub fn iter_mut(&mut self) -> impl Iterator { - self.islands - .iter_mut() - .flat_map(|i| i.iter_mut()) - .chain(self.fill_points.iter_mut()) - } - - fn divide_edge>( - &self, - segment: Line, - distance_divisor: u32, - random_numbers: &mut I, - ) -> Option { - #[inline] - fn intersects(ray: &Ray, edge: &Line) -> bool { - ray.orientation(edge.start) != ray.orientation(edge.end) - } - - #[inline] - fn solve_intersection( - intersections_box: &Rect, - ray: &Ray, - edge: &Line, - ) -> Option<(i32, u32)> { - let edge_dir = edge.scaled_direction(); - let aqpb = ray.direction.cross(edge_dir) as i64; - - if aqpb != 0 { - let mut iy = ((((edge.start.x - ray.start.x) as i64 * ray.direction.y as i64 - + ray.start.y as i64 * ray.direction.x as i64) - * edge_dir.y as i64 - - edge.start.y as i64 * edge_dir.x as i64 * ray.direction.y as i64) - / aqpb) as i32; - - // is there better way to do it? - if iy < intersections_box.top() { - iy = intersections_box.top(); - } else if iy > intersections_box.bottom() { - iy = intersections_box.bottom(); - } - - let ix = if ray.direction.y.abs() > edge_dir.y.abs() { - ray.start.x + ray.direction.cotangent_mul(iy - ray.start.y) - } else { - edge.start.x + edge_dir.cotangent_mul(iy - edge.start.y) - }; - - let intersection_point = Point::new(ix, iy).clamp(intersections_box); - let diff_point = ray.start - intersection_point; - let t = ray.direction.dot(diff_point); - - if diff_point.max_norm() >= std::i16::MAX as i32 { - Some((t, std::i32::MAX as u32)) - } else { - let d = diff_point.integral_norm(); - - Some((t, d)) - } - } else { - None - } - } - - let min_distance = 40; - // new point should fall inside this box - let map_box = self.play_box.with_margin(min_distance); - - let normal = segment.scaled_normal(); - let normal_len = normal.integral_norm(); - let mid_point = segment.center(); - - if (normal_len < min_distance as u32 * 3) || !map_box.contains_inside(mid_point) { - return None; - } - - let normal_ray = Ray::new(mid_point, normal); - let mut dist_left = (self.size.width + self.size.height) as u32; - let mut dist_right = dist_left; - - // find distances to map borders - if normal.x != 0 { - // where the normal line intersects the left map border - let left_intersection = Point::new( - map_box.left(), - mid_point.y + normal.tangent_mul(map_box.left() - mid_point.x), - ); - dist_left = (mid_point - left_intersection).integral_norm(); - - // same for the right border - let right_intersection = Point::new( - map_box.right(), - mid_point.y + normal.tangent_mul(map_box.right() - mid_point.x), - ); - dist_right = (mid_point - right_intersection).integral_norm(); - - if normal.x > 0 { - std::mem::swap(&mut dist_left, &mut dist_right); - } - } - - if normal.y != 0 { - // where the normal line intersects the top map border - let top_intersection = Point::new( - mid_point.x + normal.cotangent_mul(map_box.top() - mid_point.y), - map_box.top(), - ); - let dl = (mid_point - top_intersection).integral_norm(); - - // same for the bottom border - let bottom_intersection = Point::new( - mid_point.x + normal.cotangent_mul(map_box.bottom() - mid_point.y), - map_box.bottom(), - ); - let dr = (mid_point - bottom_intersection).integral_norm(); - - if normal.y < 0 { - dist_left = min(dist_left, dl); - dist_right = min(dist_right, dr); - } else { - dist_left = min(dist_left, dr); - dist_right = min(dist_right, dl); - } - } - - // now go through all other segments - for s in self.segments_iter() { - if s != segment { - if intersects(&normal_ray, &s) { - if let Some((t, d)) = - solve_intersection(&self.intersections_box, &normal_ray, &s) - { - if t > 0 { - dist_right = min(dist_right, d); - } else { - dist_left = min(dist_left, d); - } - } - } - } - } - - // go through all points, including fill points - for pi in self.iter().cloned() { - if pi != segment.start && pi != segment.end { - if intersects(&pi.ray_with_dir(normal), &segment) { - // ray from segment.start - if let Some((t, d)) = solve_intersection( - &self.intersections_box, - &normal_ray, - &segment.start.line_to(pi), - ) { - if t > 0 { - dist_right = min(dist_right, d); - } else { - dist_left = min(dist_left, d); - } - } - - // ray from segment.end - if let Some((t, d)) = solve_intersection( - &self.intersections_box, - &normal_ray, - &segment.end.line_to(pi), - ) { - if t > 0 { - dist_right = min(dist_right, d); - } else { - dist_left = min(dist_left, d); - } - } - } - } - } - - let max_dist = normal_len * 100 / distance_divisor; - dist_left = min(dist_left, max_dist); - dist_right = min(dist_right, max_dist); - - if dist_right + dist_left < min_distance as u32 * 2 + 10 { - // limits are too narrow, just divide - Some(mid_point) - } else { - // select distance within [-dist_right; dist_left], keeping min_distance in mind - let d = -(dist_right as i32) - + min_distance - + random_numbers.next().unwrap() as i32 - % (dist_right as i32 + dist_left as i32 - min_distance * 2); - - Some(mid_point + normal * d / normal_len as i32) - } - } - - fn divide_edges>( - &mut self, - distance_divisor: u32, - random_numbers: &mut I, - ) { - for is in 0..self.islands.len() { - let mut i = 0; - while i < self.islands[is].edges_count() { - let segment = self.islands[is].get_edge(i); - if let Some(new_point) = self.divide_edge(segment, distance_divisor, random_numbers) - { - self.islands[is].split_edge(i, new_point); - i += 2; - } else { - i += 1; - } - } - } - } - - pub fn bezierize(&mut self, segments_number: u32) { - for island in &mut self.islands { - island.bezierize(segments_number); - } - } - - pub fn distort>( - &mut self, - distance_divisor: u32, - random_numbers: &mut I, - ) { - loop { - let old_len = self.total_len(); - self.divide_edges(distance_divisor, random_numbers); - - if self.total_len() == old_len { - break; - } - } - } - - pub fn draw(&self, land: &mut Land2D, value: T) { - for segment in self.segments_iter() { - land.draw_line(segment, value); - } - } - - fn segments_iter<'a>(&'a self) -> impl Iterator + 'a { - self.islands.iter().flat_map(|p| p.iter_edges()) - } - - pub fn mirror(&mut self) { - let r = self.size.width as i32 - 1; - - self.iter_mut().for_each(|p| p.x = r - p.x); - } - - pub fn flip(&mut self) { - let t = self.size.height as i32 - 1; - - self.iter_mut().for_each(|p| p.y = t - p.y); - } -} - -#[test] -fn points_test() { - let size = Size::square(100); - let mut points = OutlinePoints { - islands: vec![ - Polygon::new(&[Point::new(0, 0), Point::new(20, 0), Point::new(30, 30)]), - Polygon::new(&[Point::new(10, 15), Point::new(15, 20), Point::new(20, 15)]), - ], - fill_points: vec![Point::new(1, 1)], - play_box: Rect::at_origin(size).with_margin(10), - size: Size::square(100), - intersections_box: Rect::at_origin(size), - }; - - 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].get_edge(0).start.x, 2); -} diff -r 168f44ef9b67 -r 5f00829c55ec rust/landgen/src/outline_template.rs --- a/rust/landgen/src/outline_template.rs Mon Feb 13 10:39:37 2023 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -use integral_geometry::{Point, Rect, Size}; - -#[derive(Clone, Debug)] -pub struct OutlineTemplate { - pub islands: Vec>, - pub fill_points: Vec, - pub size: Size, - pub can_flip: bool, - pub can_invert: bool, - pub can_mirror: bool, - pub is_negative: bool, -} - -impl OutlineTemplate { - pub fn new(size: Size) -> Self { - OutlineTemplate { - size, - islands: Vec::new(), - fill_points: Vec::new(), - can_flip: false, - can_invert: false, - can_mirror: false, - is_negative: false, - } - } - - pub fn flippable(self) -> Self { - Self { - can_flip: true, - ..self - } - } - - pub fn mirrorable(self) -> Self { - Self { - can_mirror: true, - ..self - } - } - - pub fn invertable(self) -> Self { - Self { - can_invert: true, - ..self - } - } - - pub fn negative(self) -> Self { - Self { - is_negative: true, - ..self - } - } - - pub fn with_fill_points(self, fill_points: Vec) -> Self { - Self { - fill_points, - ..self - } - } - - pub fn with_islands(self, islands: Vec>) -> Self { - Self { islands, ..self } - } - - pub fn add_fill_points(mut self, points: &[Point]) -> Self { - self.fill_points.extend_from_slice(points); - self - } - - pub fn add_island(mut self, island: &[Rect]) -> Self { - self.islands.push(island.into()); - self - } -} diff -r 168f44ef9b67 -r 5f00829c55ec rust/landgen/src/outline_template_based/mod.rs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rust/landgen/src/outline_template_based/mod.rs Mon Feb 13 11:00:12 2023 +0100 @@ -0,0 +1,3 @@ +mod outline; +pub mod outline_template; +pub mod template_based; \ No newline at end of file diff -r 168f44ef9b67 -r 5f00829c55ec rust/landgen/src/outline_template_based/outline.rs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rust/landgen/src/outline_template_based/outline.rs Mon Feb 13 11:00:12 2023 +0100 @@ -0,0 +1,341 @@ +use itertools::Itertools; +use std::cmp::min; + +use integral_geometry::{Line, Point, Polygon, Ray, Rect, Size}; +use land2d::Land2D; + +use super::outline_template::OutlineTemplate; + +pub struct OutlinePoints { + pub islands: Vec, + pub fill_points: Vec, + pub size: Size, + pub play_box: Rect, + intersections_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() + .map(|i| { + i.iter() + .zip(random_numbers.tuples()) + .map(|(rect, (rnd_a, rnd_b))| { + play_box.top_left() + rect.quotient(rnd_a as usize, rnd_b as usize) + }) + .collect::>() + .into() + }) + .collect(), + fill_points: outline_template.fill_points.clone(), + intersections_box: Rect::at_origin(size) + .with_margin(size.to_square().width as i32 * -2), + } + } + + pub fn total_len(&self) -> usize { + self.islands.iter().map(|i| i.edges_count()).sum::() + self.fill_points.len() + } + + pub fn iter(&self) -> impl Iterator { + self.islands + .iter() + .flat_map(|p| p.iter()) + .chain(self.fill_points.iter()) + } + + pub fn iter_mut(&mut self) -> impl Iterator { + self.islands + .iter_mut() + .flat_map(|i| i.iter_mut()) + .chain(self.fill_points.iter_mut()) + } + + fn divide_edge>( + &self, + segment: Line, + distance_divisor: u32, + random_numbers: &mut I, + ) -> Option { + #[inline] + fn intersects(ray: &Ray, edge: &Line) -> bool { + ray.orientation(edge.start) != ray.orientation(edge.end) + } + + #[inline] + fn solve_intersection( + intersections_box: &Rect, + ray: &Ray, + edge: &Line, + ) -> Option<(i32, u32)> { + let edge_dir = edge.scaled_direction(); + let aqpb = ray.direction.cross(edge_dir) as i64; + + if aqpb != 0 { + let mut iy = ((((edge.start.x - ray.start.x) as i64 * ray.direction.y as i64 + + ray.start.y as i64 * ray.direction.x as i64) + * edge_dir.y as i64 + - edge.start.y as i64 * edge_dir.x as i64 * ray.direction.y as i64) + / aqpb) as i32; + + // is there better way to do it? + if iy < intersections_box.top() { + iy = intersections_box.top(); + } else if iy > intersections_box.bottom() { + iy = intersections_box.bottom(); + } + + let ix = if ray.direction.y.abs() > edge_dir.y.abs() { + ray.start.x + ray.direction.cotangent_mul(iy - ray.start.y) + } else { + edge.start.x + edge_dir.cotangent_mul(iy - edge.start.y) + }; + + let intersection_point = Point::new(ix, iy).clamp(intersections_box); + let diff_point = ray.start - intersection_point; + let t = ray.direction.dot(diff_point); + + if diff_point.max_norm() >= std::i16::MAX as i32 { + Some((t, std::i32::MAX as u32)) + } else { + let d = diff_point.integral_norm(); + + Some((t, d)) + } + } else { + None + } + } + + let min_distance = 40; + // new point should fall inside this box + let map_box = self.play_box.with_margin(min_distance); + + let normal = segment.scaled_normal(); + let normal_len = normal.integral_norm(); + let mid_point = segment.center(); + + if (normal_len < min_distance as u32 * 3) || !map_box.contains_inside(mid_point) { + return None; + } + + let normal_ray = Ray::new(mid_point, normal); + let mut dist_left = (self.size.width + self.size.height) as u32; + let mut dist_right = dist_left; + + // find distances to map borders + if normal.x != 0 { + // where the normal line intersects the left map border + let left_intersection = Point::new( + map_box.left(), + mid_point.y + normal.tangent_mul(map_box.left() - mid_point.x), + ); + dist_left = (mid_point - left_intersection).integral_norm(); + + // same for the right border + let right_intersection = Point::new( + map_box.right(), + mid_point.y + normal.tangent_mul(map_box.right() - mid_point.x), + ); + dist_right = (mid_point - right_intersection).integral_norm(); + + if normal.x > 0 { + std::mem::swap(&mut dist_left, &mut dist_right); + } + } + + if normal.y != 0 { + // where the normal line intersects the top map border + let top_intersection = Point::new( + mid_point.x + normal.cotangent_mul(map_box.top() - mid_point.y), + map_box.top(), + ); + let dl = (mid_point - top_intersection).integral_norm(); + + // same for the bottom border + let bottom_intersection = Point::new( + mid_point.x + normal.cotangent_mul(map_box.bottom() - mid_point.y), + map_box.bottom(), + ); + let dr = (mid_point - bottom_intersection).integral_norm(); + + if normal.y < 0 { + dist_left = min(dist_left, dl); + dist_right = min(dist_right, dr); + } else { + dist_left = min(dist_left, dr); + dist_right = min(dist_right, dl); + } + } + + // now go through all other segments + for s in self.segments_iter() { + if s != segment { + if intersects(&normal_ray, &s) { + if let Some((t, d)) = + solve_intersection(&self.intersections_box, &normal_ray, &s) + { + if t > 0 { + dist_right = min(dist_right, d); + } else { + dist_left = min(dist_left, d); + } + } + } + } + } + + // go through all points, including fill points + for pi in self.iter().cloned() { + if pi != segment.start && pi != segment.end { + if intersects(&pi.ray_with_dir(normal), &segment) { + // ray from segment.start + if let Some((t, d)) = solve_intersection( + &self.intersections_box, + &normal_ray, + &segment.start.line_to(pi), + ) { + if t > 0 { + dist_right = min(dist_right, d); + } else { + dist_left = min(dist_left, d); + } + } + + // ray from segment.end + if let Some((t, d)) = solve_intersection( + &self.intersections_box, + &normal_ray, + &segment.end.line_to(pi), + ) { + if t > 0 { + dist_right = min(dist_right, d); + } else { + dist_left = min(dist_left, d); + } + } + } + } + } + + let max_dist = normal_len * 100 / distance_divisor; + dist_left = min(dist_left, max_dist); + dist_right = min(dist_right, max_dist); + + if dist_right + dist_left < min_distance as u32 * 2 + 10 { + // limits are too narrow, just divide + Some(mid_point) + } else { + // select distance within [-dist_right; dist_left], keeping min_distance in mind + let d = -(dist_right as i32) + + min_distance + + random_numbers.next().unwrap() as i32 + % (dist_right as i32 + dist_left as i32 - min_distance * 2); + + Some(mid_point + normal * d / normal_len as i32) + } + } + + fn divide_edges>( + &mut self, + distance_divisor: u32, + random_numbers: &mut I, + ) { + for is in 0..self.islands.len() { + let mut i = 0; + while i < self.islands[is].edges_count() { + let segment = self.islands[is].get_edge(i); + if let Some(new_point) = self.divide_edge(segment, distance_divisor, random_numbers) + { + self.islands[is].split_edge(i, new_point); + i += 2; + } else { + i += 1; + } + } + } + } + + pub fn bezierize(&mut self, segments_number: u32) { + for island in &mut self.islands { + island.bezierize(segments_number); + } + } + + pub fn distort>( + &mut self, + distance_divisor: u32, + random_numbers: &mut I, + ) { + loop { + let old_len = self.total_len(); + self.divide_edges(distance_divisor, random_numbers); + + if self.total_len() == old_len { + break; + } + } + } + + pub fn draw(&self, land: &mut Land2D, value: T) { + for segment in self.segments_iter() { + land.draw_line(segment, value); + } + } + + fn segments_iter<'a>(&'a self) -> impl Iterator + 'a { + self.islands.iter().flat_map(|p| p.iter_edges()) + } + + pub fn mirror(&mut self) { + let r = self.size.width as i32 - 1; + + self.iter_mut().for_each(|p| p.x = r - p.x); + } + + pub fn flip(&mut self) { + let t = self.size.height as i32 - 1; + + self.iter_mut().for_each(|p| p.y = t - p.y); + } +} + +#[test] +fn points_test() { + let size = Size::square(100); + let mut points = OutlinePoints { + islands: vec![ + Polygon::new(&[Point::new(0, 0), Point::new(20, 0), Point::new(30, 30)]), + Polygon::new(&[Point::new(10, 15), Point::new(15, 20), Point::new(20, 15)]), + ], + fill_points: vec![Point::new(1, 1)], + play_box: Rect::at_origin(size).with_margin(10), + size: Size::square(100), + intersections_box: Rect::at_origin(size), + }; + + 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].get_edge(0).start.x, 2); +} diff -r 168f44ef9b67 -r 5f00829c55ec rust/landgen/src/outline_template_based/outline_template.rs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rust/landgen/src/outline_template_based/outline_template.rs Mon Feb 13 11:00:12 2023 +0100 @@ -0,0 +1,75 @@ +use integral_geometry::{Point, Rect, Size}; + +#[derive(Clone, Debug)] +pub struct OutlineTemplate { + pub islands: Vec>, + pub fill_points: Vec, + pub size: Size, + pub can_flip: bool, + pub can_invert: bool, + pub can_mirror: bool, + pub is_negative: bool, +} + +impl OutlineTemplate { + pub fn new(size: Size) -> Self { + OutlineTemplate { + size, + islands: Vec::new(), + fill_points: Vec::new(), + can_flip: false, + can_invert: false, + can_mirror: false, + is_negative: false, + } + } + + pub fn flippable(self) -> Self { + Self { + can_flip: true, + ..self + } + } + + pub fn mirrorable(self) -> Self { + Self { + can_mirror: true, + ..self + } + } + + pub fn invertable(self) -> Self { + Self { + can_invert: true, + ..self + } + } + + pub fn negative(self) -> Self { + Self { + is_negative: true, + ..self + } + } + + pub fn with_fill_points(self, fill_points: Vec) -> Self { + Self { + fill_points, + ..self + } + } + + pub fn with_islands(self, islands: Vec>) -> Self { + Self { islands, ..self } + } + + pub fn add_fill_points(mut self, points: &[Point]) -> Self { + self.fill_points.extend_from_slice(points); + self + } + + pub fn add_island(mut self, island: &[Rect]) -> Self { + self.islands.push(island.into()); + self + } +} diff -r 168f44ef9b67 -r 5f00829c55ec rust/landgen/src/outline_template_based/template_based.rs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rust/landgen/src/outline_template_based/template_based.rs Mon Feb 13 11:00:12 2023 +0100 @@ -0,0 +1,69 @@ +use super::{ + outline::OutlinePoints, outline_template::OutlineTemplate}; +use crate::{LandGenerationParameters, + LandGenerator, +}; +use land2d::Land2D; + +pub struct TemplatedLandGenerator { + outline_template: OutlineTemplate, +} + +impl TemplatedLandGenerator { + pub fn new(outline_template: OutlineTemplate) -> Self { + Self { outline_template } + } +} + +impl LandGenerator for TemplatedLandGenerator { + fn generate_land>( + &self, + parameters: &LandGenerationParameters, + random_numbers: &mut I, + ) -> Land2D { + let mut land = Land2D::new(&self.outline_template.size, parameters.basic); + + let mut points = OutlinePoints::from_outline_template( + &self.outline_template, + land.play_box(), + land.size().size(), + random_numbers, + ); + + // mirror + if self.outline_template.can_mirror { + if let Some(b) = random_numbers.next() { + if b & 1 != 0 { + points.mirror(); + } + } + } + + // flip + if self.outline_template.can_flip { + if let Some(b) = random_numbers.next() { + if b & 1 != 0 { + points.flip(); + } + } + } + + if !parameters.skip_distort { + points.distort(parameters.distance_divisor, random_numbers); + } + + if !parameters.skip_bezier { + points.bezierize(5); + } + + points.draw(&mut land, parameters.zero); + + for p in &points.fill_points { + land.fill(*p, parameters.zero, parameters.zero) + } + + points.draw(&mut land, parameters.basic); + + land + } +} diff -r 168f44ef9b67 -r 5f00829c55ec rust/landgen/src/template_based.rs --- a/rust/landgen/src/template_based.rs Mon Feb 13 10:39:37 2023 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -use crate::{ - outline::OutlinePoints, outline_template::OutlineTemplate, LandGenerationParameters, - LandGenerator, -}; -use land2d::Land2D; - -pub struct TemplatedLandGenerator { - outline_template: OutlineTemplate, -} - -impl TemplatedLandGenerator { - pub fn new(outline_template: OutlineTemplate) -> Self { - Self { outline_template } - } -} - -impl LandGenerator for TemplatedLandGenerator { - fn generate_land>( - &self, - parameters: &LandGenerationParameters, - random_numbers: &mut I, - ) -> Land2D { - let mut land = Land2D::new(&self.outline_template.size, parameters.basic); - - let mut points = OutlinePoints::from_outline_template( - &self.outline_template, - land.play_box(), - land.size().size(), - random_numbers, - ); - - // mirror - if self.outline_template.can_mirror { - if let Some(b) = random_numbers.next() { - if b & 1 != 0 { - points.mirror(); - } - } - } - - // flip - if self.outline_template.can_flip { - if let Some(b) = random_numbers.next() { - if b & 1 != 0 { - points.flip(); - } - } - } - - if !parameters.skip_distort { - points.distort(parameters.distance_divisor, random_numbers); - } - - if !parameters.skip_bezier { - points.bezierize(5); - } - - points.draw(&mut land, parameters.zero); - - for p in &points.fill_points { - land.fill(*p, parameters.zero, parameters.zero) - } - - points.draw(&mut land, parameters.basic); - - land - } -} diff -r 168f44ef9b67 -r 5f00829c55ec rust/landgen/src/wavefront_collapse/tile_image.rs --- a/rust/landgen/src/wavefront_collapse/tile_image.rs Mon Feb 13 10:39:37 2023 +0100 +++ b/rust/landgen/src/wavefront_collapse/tile_image.rs Mon Feb 13 11:00:12 2023 +0100 @@ -23,7 +23,7 @@ Self { id: self.id.clone(), symmetrical: self.symmetrical, - reverse: !self.reverse, + reverse: !self.symmetrical && !self.reverse, } } diff -r 168f44ef9b67 -r 5f00829c55ec rust/lib-hwengine-future/src/lib.rs --- a/rust/lib-hwengine-future/src/lib.rs Mon Feb 13 10:39:37 2023 +0100 +++ b/rust/lib-hwengine-future/src/lib.rs Mon Feb 13 11:00:12 2023 +0100 @@ -1,6 +1,6 @@ use integral_geometry::{Point, Size}; use land2d; -use landgen::{template_based::TemplatedLandGenerator, LandGenerationParameters, LandGenerator}; +use landgen::{outline_template_based::template_based::TemplatedLandGenerator, LandGenerationParameters, LandGenerator}; use lfprng::LaggedFibonacciPRNG; use mapgen::{theme::Theme, MapGenerator}; use std::fs; diff -r 168f44ef9b67 -r 5f00829c55ec rust/mapgen/src/lib.rs --- a/rust/mapgen/src/lib.rs Mon Feb 13 10:39:37 2023 +0100 +++ b/rust/mapgen/src/lib.rs Mon Feb 13 11:00:12 2023 +0100 @@ -3,7 +3,7 @@ use self::theme::Theme; use integral_geometry::{Point, Rect, Size}; use land2d::Land2D; -use landgen::{outline_template::OutlineTemplate, LandGenerationParameters}; +use landgen::{outline_template_based::outline_template::OutlineTemplate, LandGenerationParameters}; use serde_derive::Deserialize; use serde_yaml; use std::{borrow::Borrow, collections::hash_map::HashMap, mem::replace};