--- a/rust/integral-geometry/src/lib.rs Fri Nov 02 14:08:45 2018 +0100
+++ b/rust/integral-geometry/src/lib.rs Fri Nov 02 13:17:46 2018 +0100
@@ -1,4 +1,3 @@
-use std::cmp;
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
@@ -40,8 +39,10 @@
#[inline]
pub fn transform(self, matrix: &[i32; 4]) -> Self {
- Point::new(matrix[0] * self.x + matrix[1] * self.y,
- matrix[2] * self.x + matrix[3] * self.y)
+ Point::new(
+ matrix[0] * self.x + matrix[1] * self.y,
+ matrix[2] * self.x + matrix[3] * self.y,
+ )
}
}
@@ -59,7 +60,10 @@
#[inline]
pub fn square(size: usize) -> Self {
- Size { width: size, height: size }
+ Size {
+ width: size,
+ height: size,
+ }
}
#[inline]
@@ -81,7 +85,7 @@
pub fn next_power_of_two(&self) -> Self {
Self {
width: self.width.next_power_of_two(),
- height: self.height.next_power_of_two()
+ height: self.height.next_power_of_two(),
}
}
@@ -95,7 +99,9 @@
}
}
-pub struct SizeMask{ size: Size }
+pub struct SizeMask {
+ size: Size,
+}
impl SizeMask {
#[inline]
@@ -103,7 +109,7 @@
assert!(size.is_power_of_two());
let size = Size {
width: !(size.width - 1),
- height: !(size.height - 1)
+ height: !(size.height - 1),
};
Self { size }
}
@@ -124,19 +130,22 @@
}
}
-pub struct GridIndex{ shift: Point }
+pub struct GridIndex {
+ shift: Point,
+}
impl GridIndex {
pub fn new(size: Size) -> Self {
assert!(size.is_power_of_two());
- let shift = Point::new(size.width.trailing_zeros() as i32,
- size.height.trailing_zeros() as i32);
+ let shift = Point::new(
+ size.width.trailing_zeros() as i32,
+ size.height.trailing_zeros() as i32,
+ );
Self { shift }
}
pub fn map(&self, position: Point) -> Point {
- Point::new(position.x >> self.shift.x,
- position.y >> self.shift.y)
+ Point::new(position.x >> self.shift.x, position.y >> self.shift.y)
}
}
@@ -185,7 +194,12 @@
impl Rect {
#[inline]
pub fn new(x: i32, y: i32, width: u32, height: u32) -> Self {
- Self { x, y, width, height }
+ Self {
+ x,
+ y,
+ width,
+ height,
+ }
}
#[inline]
@@ -199,6 +213,32 @@
}
}
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+pub struct Line {
+ pub start: Point,
+ pub end: Point,
+}
+
+impl Line {
+ #[inline]
+ pub fn new(start: Point, end: Point) -> Self {
+ Self { start, end }
+ }
+
+ #[inline]
+ pub fn zero() -> Self {
+ Self::new(Point::zero(), Point::zero())
+ }
+}
+
+impl IntoIterator for Line {
+ type Item = Point;
+ type IntoIter = LinePoints;
+
+ fn into_iter(self) -> Self::IntoIter {
+ LinePoints::new(self)
+ }
+}
pub struct LinePoints {
accumulator: Point,
@@ -210,14 +250,14 @@
}
impl LinePoints {
- pub fn new(from: Point, to: Point) -> Self {
- let dir = to - from;
+ pub fn new(line: Line) -> Self {
+ let dir = line.end - line.start;
Self {
accumulator: Point::zero(),
direction: dir.abs(),
sign: dir.signum(),
- current: from,
+ current: line.start,
total_steps: dir.max_norm(),
step: 0,
}
@@ -337,7 +377,7 @@
#[test]
fn line_basic() {
- let line = LinePoints::new(Point::new(0, 0), Point::new(3, 3));
+ let line = Line::new(Point::new(0, 0), Point::new(3, 3)).into_iter();
let v = get_points(&[(0, 0), (1, 1), (2, 2), (3, 3), (123, 456)]);
for (&a, b) in v.iter().zip(line) {
@@ -347,7 +387,7 @@
#[test]
fn line_skewed() {
- let line = LinePoints::new(Point::new(0, 0), Point::new(5, -7));
+ let line = Line::new(Point::new(0, 0), Point::new(5, -7)).into_iter();
let v = get_points(&[
(0, 0),
(1, -1),
--- a/rust/land2d/src/lib.rs Fri Nov 02 14:08:45 2018 +0100
+++ b/rust/land2d/src/lib.rs Fri Nov 02 13:17:46 2018 +0100
@@ -4,8 +4,8 @@
use std::cmp;
use integral_geometry::{
- ArcPoints, EquidistantPoints, LinePoints,
- Point, Size, SizeMask
+ ArcPoints, EquidistantPoints,
+ Point, Size, SizeMask, Line
};
pub struct Land2D<T> {
@@ -103,8 +103,8 @@
}).count()
}
- pub fn draw_line(&mut self, from: Point, to: Point, value: T) -> usize {
- self.fill_from_iter(LinePoints::new(from, to), value)
+ pub fn draw_line(&mut self, line: Line, value: T) -> usize {
+ self.fill_from_iter(line.into_iter(), value)
}
pub fn fill(&mut self, start_point: Point, border_value: T, fill_value: T) {
@@ -263,12 +263,12 @@
}).sum()
}
- pub fn draw_thick_line(&mut self, from: Point, to: Point, radius: i32, value: T) -> usize {
+ pub fn draw_thick_line(&mut self, line: Line, radius: i32, value: T) -> usize {
let mut result = 0;
for vector in ArcPoints::new(radius) {
for delta in EquidistantPoints::new(vector) {
- for point in LinePoints::new(from, to) {
+ for point in line.into_iter() {
self.map_point(point + delta, |p| {
if *p != value {
*p = value;
@@ -308,13 +308,13 @@
fn fill() {
let mut l: Land2D<u8> = Land2D::new(Size::square(128), 0);
- l.draw_line(Point::new(0, 0), Point::new(32, 96), 1);
- l.draw_line(Point::new(32, 96), Point::new(64, 32), 1);
- l.draw_line(Point::new(64, 32), Point::new(96, 80), 1);
- l.draw_line(Point::new(96, 80), Point::new(128, 0), 1);
+ l.draw_line(Line::new(Point::new(0, 0), Point::new(32, 96)), 1);
+ l.draw_line(Line::new(Point::new(32, 96), Point::new(64, 32)), 1);
+ l.draw_line(Line::new(Point::new(64, 32), Point::new(96, 80)), 1);
+ l.draw_line(Line::new(Point::new(96, 80), Point::new(128, 0)), 1);
- l.draw_line(Point::new(0, 128), Point::new(64, 96), 1);
- l.draw_line(Point::new(128, 128), Point::new(64, 96), 1);
+ l.draw_line(Line::new(Point::new(0, 128), Point::new(64, 96)), 1);
+ l.draw_line(Line::new(Point::new(128, 128), Point::new(64, 96)), 1);
l.fill(Point::new(32, 32), 1, 2);
l.fill(Point::new(16, 96), 1, 3);
--- a/rust/landgen/src/outline.rs Fri Nov 02 14:08:45 2018 +0100
+++ b/rust/landgen/src/outline.rs Fri Nov 02 13:17:46 2018 +0100
@@ -1,6 +1,6 @@
use itertools::Itertools;
-use integral_geometry::{Point, Size};
+use integral_geometry::{Line, Point, Size};
use land2d::Land2D;
use outline_template::OutlineTemplate;
@@ -48,8 +48,7 @@
fn divide_edge<I: Iterator<Item = u32>>(
&self,
- start_point: Point,
- end_point: Point,
+ segment: Line,
random_numbers: &mut I,
) -> Option<Point> {
None
@@ -58,25 +57,26 @@
fn divide_edges<I: Iterator<Item = u32>>(&mut self, random_numbers: &mut I) {
for is in 0..self.islands.len() {
let mut i = 0;
- let mut start_point = Point::zero();
- let mut end_point = Point::zero();
+ let mut segment;
loop {
{
let island = &self.islands[is];
+ let mut end_point;
if i < island.len() {
- start_point = island[i];
end_point = if i + 1 < island.len() {
island[i + 1]
} else {
island[0]
};
} else {
- break
+ break;
}
+
+ segment = Line::new(island[i], end_point);
}
- if let Some(new_point) = self.divide_edge(start_point, end_point, random_numbers) {
+ if let Some(new_point) = self.divide_edge(segment, random_numbers) {
self.islands[is].insert(i + 1, new_point);
i += 2;
} else {
@@ -104,13 +104,47 @@
}
pub fn draw<T: Copy + PartialEq>(&self, land: &mut Land2D<T>, value: T) {
- for island in &self.islands {
- if island.len() > 1 {
- for i in 0..island.len() - 1 {
- land.draw_line(island[i], island[i + 1], value);
- }
- land.draw_line(island[island.len() - 1], island[0], value);
- }
+ for segment in self.segments_iter() {
+ land.draw_line(segment, value);
+ }
+ }
+
+ fn segments_iter(&self) -> OutlineSegmentsIterator {
+ OutlineSegmentsIterator {
+ outline: self,
+ island: 0,
+ index: 0,
}
}
}
+
+struct OutlineSegmentsIterator<'a> {
+ outline: &'a OutlinePoints,
+ island: usize,
+ index: usize,
+}
+
+impl<'a> Iterator for OutlineSegmentsIterator<'a> {
+ type Item = Line;
+
+ 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],
+ ))
+ } else {
+ self.island += 1;
+ self.next()
+ }
+ } else {
+ None
+ }
+ }
+}