rust/landgen/src/outline.rs
author Wuzzy <Wuzzy2@mail.ru>
Thu, 25 Apr 2019 23:01:05 +0200
changeset 14844 e239378a9400
parent 14212 bb2f301d4fe0
permissions -rw-r--r--
Prevent entering “/”, “\” and “:” in team and scheme names. The name of teams and schems is saved in the file name itself, so these characters would cause trouble as they are used in path names in Linux and Windows.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
14074
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
     1
use itertools::Itertools;
14086
5d42204ac35e Start convertion of FindPoint()
unC0Rr
parents: 14083
diff changeset
     2
use std::cmp::min;
14074
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
     3
14142
3119d665d3c6 collapse rectangle types back together with consistent usage of size
alfadur
parents: 14140
diff changeset
     4
use integral_geometry::{Line, Ray, Point, Polygon, Rect, Size};
14074
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
     5
use land2d::Land2D;
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
     6
14212
bb2f301d4fe0 2018ize everything
alfadur
parents: 14147
diff changeset
     7
use crate::outline_template::OutlineTemplate;
14074
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
     8
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
     9
pub struct OutlinePoints {
14129
6e0be42d0a8f polygonize OutlinePoints
alfadur
parents: 14127
diff changeset
    10
    pub islands: Vec<Polygon>,
14074
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
    11
    pub fill_points: Vec<Point>,
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
    12
    pub size: Size,
14142
3119d665d3c6 collapse rectangle types back together with consistent usage of size
alfadur
parents: 14140
diff changeset
    13
    pub play_box: Rect,
3119d665d3c6 collapse rectangle types back together with consistent usage of size
alfadur
parents: 14140
diff changeset
    14
    intersections_box: Rect,
14074
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
    15
}
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
    16
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
    17
impl OutlinePoints {
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
    18
    pub fn from_outline_template<I: Iterator<Item = u32>>(
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
    19
        outline_template: &OutlineTemplate,
14142
3119d665d3c6 collapse rectangle types back together with consistent usage of size
alfadur
parents: 14140
diff changeset
    20
        play_box: Rect,
14083
bf40b5f938b0 - Add methods to work with Rect as box
unC0Rr
parents: 14082
diff changeset
    21
        size: Size,
14074
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
    22
        random_numbers: &mut I,
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
    23
    ) -> Self {
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
    24
        Self {
14083
bf40b5f938b0 - Add methods to work with Rect as box
unC0Rr
parents: 14082
diff changeset
    25
            play_box,
bf40b5f938b0 - Add methods to work with Rect as box
unC0Rr
parents: 14082
diff changeset
    26
            size,
14074
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
    27
            islands: outline_template
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
    28
                .islands
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
    29
                .iter()
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
    30
                .map(|i| {
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
    31
                    i.iter()
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
    32
                        .zip(random_numbers.tuples())
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
    33
                        .map(|(rect, (rnd_a, rnd_b))| {
14142
3119d665d3c6 collapse rectangle types back together with consistent usage of size
alfadur
parents: 14140
diff changeset
    34
                            play_box.top_left() + rect.quotient(rnd_a as usize, rnd_b as usize)
14127
c27461e6a9eb Implement non-overflowing calculations for high values
unc0rr
parents: 14126
diff changeset
    35
                        })
14130
376a0551b00a - Add distance-divider option to land_dump
unc0rr
parents: 14129
diff changeset
    36
                        .collect::<Vec<_>>()
376a0551b00a - Add distance-divider option to land_dump
unc0rr
parents: 14129
diff changeset
    37
                        .into()
14127
c27461e6a9eb Implement non-overflowing calculations for high values
unc0rr
parents: 14126
diff changeset
    38
                })
c27461e6a9eb Implement non-overflowing calculations for high values
unc0rr
parents: 14126
diff changeset
    39
                .collect(),
14074
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
    40
            fill_points: outline_template.fill_points.clone(),
14142
3119d665d3c6 collapse rectangle types back together with consistent usage of size
alfadur
parents: 14140
diff changeset
    41
            intersections_box: Rect::at_origin(size)
14130
376a0551b00a - Add distance-divider option to land_dump
unc0rr
parents: 14129
diff changeset
    42
                .with_margin(size.to_square().width as i32 * -2),
14074
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
    43
        }
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
    44
    }
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
    45
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
    46
    pub fn total_len(&self) -> usize {
14129
6e0be42d0a8f polygonize OutlinePoints
alfadur
parents: 14127
diff changeset
    47
        self.islands.iter().map(|i| i.edges_count()).sum::<usize>() + self.fill_points.len()
14074
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
    48
    }
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
    49
14105
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
    50
    pub fn iter(&self) -> impl Iterator<Item = &Point> {
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
    51
        self.islands
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
    52
            .iter()
14129
6e0be42d0a8f polygonize OutlinePoints
alfadur
parents: 14127
diff changeset
    53
            .flat_map(|p| p.iter())
14105
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
    54
            .chain(self.fill_points.iter())
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
    55
    }
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
    56
14139
09f62bb046ef actually there is a way to preserve mutable polygon iterator
alfadur
parents: 14138
diff changeset
    57
    pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Point> {
09f62bb046ef actually there is a way to preserve mutable polygon iterator
alfadur
parents: 14138
diff changeset
    58
        self.islands
09f62bb046ef actually there is a way to preserve mutable polygon iterator
alfadur
parents: 14138
diff changeset
    59
            .iter_mut()
09f62bb046ef actually there is a way to preserve mutable polygon iterator
alfadur
parents: 14138
diff changeset
    60
            .flat_map(|i| i.iter_mut())
09f62bb046ef actually there is a way to preserve mutable polygon iterator
alfadur
parents: 14138
diff changeset
    61
            .chain(self.fill_points.iter_mut())
14074
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
    62
    }
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
    63
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
    64
    fn divide_edge<I: Iterator<Item = u32>>(
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
    65
        &self,
14081
e5904ead4864 Introduce OutlineSegmentsIterator, some refactoring
unC0Rr
parents: 14074
diff changeset
    66
        segment: Line,
14105
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
    67
        distance_divisor: u32,
14074
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
    68
        random_numbers: &mut I,
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
    69
    ) -> Option<Point> {
14105
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
    70
        #[inline]
14136
c416d32764b7 organize landgen a bit more
alfadur
parents: 14131
diff changeset
    71
        fn intersects(ray: &Ray, edge: &Line) -> bool {
c416d32764b7 organize landgen a bit more
alfadur
parents: 14131
diff changeset
    72
            ray.orientation(edge.start) != ray.orientation(edge.end)
14105
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
    73
        }
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
    74
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
    75
        #[inline]
14140
7f5a591e1c43 separate rectangle types based on right/bottom edge inclusivity
alfadur
parents: 14139
diff changeset
    76
        fn solve_intersection(
14142
3119d665d3c6 collapse rectangle types back together with consistent usage of size
alfadur
parents: 14140
diff changeset
    77
            intersections_box: &Rect,
14140
7f5a591e1c43 separate rectangle types based on right/bottom edge inclusivity
alfadur
parents: 14139
diff changeset
    78
            ray: &Ray,
7f5a591e1c43 separate rectangle types based on right/bottom edge inclusivity
alfadur
parents: 14139
diff changeset
    79
            edge: &Line
7f5a591e1c43 separate rectangle types based on right/bottom edge inclusivity
alfadur
parents: 14139
diff changeset
    80
        ) -> Option<(i32, u32)>
14136
c416d32764b7 organize landgen a bit more
alfadur
parents: 14131
diff changeset
    81
        {
c416d32764b7 organize landgen a bit more
alfadur
parents: 14131
diff changeset
    82
            let edge_dir = edge.scaled_direction();
c416d32764b7 organize landgen a bit more
alfadur
parents: 14131
diff changeset
    83
            let aqpb = ray.direction.cross(edge_dir) as i64;
14105
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
    84
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
    85
            if aqpb != 0 {
14136
c416d32764b7 organize landgen a bit more
alfadur
parents: 14131
diff changeset
    86
                let mut iy =
c416d32764b7 organize landgen a bit more
alfadur
parents: 14131
diff changeset
    87
                    ((((edge.start.x - ray.start.x) as i64 * ray.direction.y as i64
c416d32764b7 organize landgen a bit more
alfadur
parents: 14131
diff changeset
    88
                        + ray.start.y as i64 * ray.direction.x as i64)
c416d32764b7 organize landgen a bit more
alfadur
parents: 14131
diff changeset
    89
                    * edge_dir.y as i64
c416d32764b7 organize landgen a bit more
alfadur
parents: 14131
diff changeset
    90
                    - edge.start.y as i64 * edge_dir.x as i64 * ray.direction.y as i64)
14105
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
    91
                    / aqpb) as i32;
14130
376a0551b00a - Add distance-divider option to land_dump
unc0rr
parents: 14129
diff changeset
    92
376a0551b00a - Add distance-divider option to land_dump
unc0rr
parents: 14129
diff changeset
    93
                // is there better way to do it?
376a0551b00a - Add distance-divider option to land_dump
unc0rr
parents: 14129
diff changeset
    94
                if iy < intersections_box.top() {
376a0551b00a - Add distance-divider option to land_dump
unc0rr
parents: 14129
diff changeset
    95
                    iy = intersections_box.top();
376a0551b00a - Add distance-divider option to land_dump
unc0rr
parents: 14129
diff changeset
    96
                } else if iy > intersections_box.bottom() {
376a0551b00a - Add distance-divider option to land_dump
unc0rr
parents: 14129
diff changeset
    97
                    iy = intersections_box.bottom();
376a0551b00a - Add distance-divider option to land_dump
unc0rr
parents: 14129
diff changeset
    98
                }
376a0551b00a - Add distance-divider option to land_dump
unc0rr
parents: 14129
diff changeset
    99
14136
c416d32764b7 organize landgen a bit more
alfadur
parents: 14131
diff changeset
   100
                let ix = if ray.direction.y.abs() > edge_dir.y.abs() {
14147
11202097584f fix tangents
alfadur
parents: 14146
diff changeset
   101
                    ray.start.x + ray.direction.cotangent_mul(iy - ray.start.y)
14105
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   102
                } else {
14147
11202097584f fix tangents
alfadur
parents: 14146
diff changeset
   103
                    edge.start.x + edge_dir.cotangent_mul(iy - edge.start.y)
14105
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   104
                };
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   105
14137
alfadur
parents: 14136 14135
diff changeset
   106
                let intersection_point = Point::new(ix, iy).clamp(intersections_box);
14136
c416d32764b7 organize landgen a bit more
alfadur
parents: 14131
diff changeset
   107
                let diff_point = ray.start - intersection_point;
c416d32764b7 organize landgen a bit more
alfadur
parents: 14131
diff changeset
   108
                let t = ray.direction.dot(diff_point);
14137
alfadur
parents: 14136 14135
diff changeset
   109
14127
c27461e6a9eb Implement non-overflowing calculations for high values
unc0rr
parents: 14126
diff changeset
   110
                if diff_point.max_norm() >= std::i16::MAX as i32 {
c27461e6a9eb Implement non-overflowing calculations for high values
unc0rr
parents: 14126
diff changeset
   111
                    Some((t, std::i32::MAX as u32))
c27461e6a9eb Implement non-overflowing calculations for high values
unc0rr
parents: 14126
diff changeset
   112
                } else {
c27461e6a9eb Implement non-overflowing calculations for high values
unc0rr
parents: 14126
diff changeset
   113
                    let d = diff_point.integral_norm();
14105
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   114
14127
c27461e6a9eb Implement non-overflowing calculations for high values
unc0rr
parents: 14126
diff changeset
   115
                    Some((t, d))
c27461e6a9eb Implement non-overflowing calculations for high values
unc0rr
parents: 14126
diff changeset
   116
                }
14105
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   117
            } else {
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   118
                None
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   119
            }
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   120
        }
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   121
14086
5d42204ac35e Start convertion of FindPoint()
unC0Rr
parents: 14083
diff changeset
   122
        let min_distance = 40;
5d42204ac35e Start convertion of FindPoint()
unC0Rr
parents: 14083
diff changeset
   123
        // new point should fall inside this box
5d42204ac35e Start convertion of FindPoint()
unC0Rr
parents: 14083
diff changeset
   124
        let map_box = self.play_box.with_margin(min_distance);
5d42204ac35e Start convertion of FindPoint()
unC0Rr
parents: 14083
diff changeset
   125
14136
c416d32764b7 organize landgen a bit more
alfadur
parents: 14131
diff changeset
   126
        let normal = segment.scaled_normal();
c416d32764b7 organize landgen a bit more
alfadur
parents: 14131
diff changeset
   127
        let normal_len = normal.integral_norm();
14086
5d42204ac35e Start convertion of FindPoint()
unC0Rr
parents: 14083
diff changeset
   128
        let mid_point = segment.center();
5d42204ac35e Start convertion of FindPoint()
unC0Rr
parents: 14083
diff changeset
   129
14136
c416d32764b7 organize landgen a bit more
alfadur
parents: 14131
diff changeset
   130
        if (normal_len < min_distance as u32 * 3) || !map_box.contains_inside(mid_point) {
14086
5d42204ac35e Start convertion of FindPoint()
unC0Rr
parents: 14083
diff changeset
   131
            return None;
5d42204ac35e Start convertion of FindPoint()
unC0Rr
parents: 14083
diff changeset
   132
        }
5d42204ac35e Start convertion of FindPoint()
unC0Rr
parents: 14083
diff changeset
   133
14136
c416d32764b7 organize landgen a bit more
alfadur
parents: 14131
diff changeset
   134
        let normal_ray = Ray::new(mid_point, normal);
14086
5d42204ac35e Start convertion of FindPoint()
unC0Rr
parents: 14083
diff changeset
   135
        let mut dist_left = (self.size.width + self.size.height) as u32;
5d42204ac35e Start convertion of FindPoint()
unC0Rr
parents: 14083
diff changeset
   136
        let mut dist_right = dist_left;
5d42204ac35e Start convertion of FindPoint()
unC0Rr
parents: 14083
diff changeset
   137
5d42204ac35e Start convertion of FindPoint()
unC0Rr
parents: 14083
diff changeset
   138
        // find distances to map borders
14136
c416d32764b7 organize landgen a bit more
alfadur
parents: 14131
diff changeset
   139
        if normal.x != 0 {
14115
21642eb0ff29 import some clarity into border distance computation
alfadur
parents: 14114
diff changeset
   140
            // where the normal line intersects the left map border
21642eb0ff29 import some clarity into border distance computation
alfadur
parents: 14114
diff changeset
   141
            let left_intersection = Point::new(
21642eb0ff29 import some clarity into border distance computation
alfadur
parents: 14114
diff changeset
   142
                map_box.left(),
14147
11202097584f fix tangents
alfadur
parents: 14146
diff changeset
   143
                mid_point.y + normal.tangent_mul(map_box.left() - mid_point.x),
14127
c27461e6a9eb Implement non-overflowing calculations for high values
unc0rr
parents: 14126
diff changeset
   144
            );
14115
21642eb0ff29 import some clarity into border distance computation
alfadur
parents: 14114
diff changeset
   145
            dist_left = (mid_point - left_intersection).integral_norm();
14086
5d42204ac35e Start convertion of FindPoint()
unC0Rr
parents: 14083
diff changeset
   146
14115
21642eb0ff29 import some clarity into border distance computation
alfadur
parents: 14114
diff changeset
   147
            // same for the right border
21642eb0ff29 import some clarity into border distance computation
alfadur
parents: 14114
diff changeset
   148
            let right_intersection = Point::new(
21642eb0ff29 import some clarity into border distance computation
alfadur
parents: 14114
diff changeset
   149
                map_box.right(),
14147
11202097584f fix tangents
alfadur
parents: 14146
diff changeset
   150
                mid_point.y + normal.tangent_mul(map_box.right() - mid_point.x)  ,
14127
c27461e6a9eb Implement non-overflowing calculations for high values
unc0rr
parents: 14126
diff changeset
   151
            );
14115
21642eb0ff29 import some clarity into border distance computation
alfadur
parents: 14114
diff changeset
   152
            dist_right = (mid_point - right_intersection).integral_norm();
14086
5d42204ac35e Start convertion of FindPoint()
unC0Rr
parents: 14083
diff changeset
   153
14136
c416d32764b7 organize landgen a bit more
alfadur
parents: 14131
diff changeset
   154
            if normal.x > 0 {
14115
21642eb0ff29 import some clarity into border distance computation
alfadur
parents: 14114
diff changeset
   155
                std::mem::swap(&mut dist_left, &mut dist_right);
14086
5d42204ac35e Start convertion of FindPoint()
unC0Rr
parents: 14083
diff changeset
   156
            }
5d42204ac35e Start convertion of FindPoint()
unC0Rr
parents: 14083
diff changeset
   157
        }
5d42204ac35e Start convertion of FindPoint()
unC0Rr
parents: 14083
diff changeset
   158
14136
c416d32764b7 organize landgen a bit more
alfadur
parents: 14131
diff changeset
   159
        if normal.y != 0 {
14115
21642eb0ff29 import some clarity into border distance computation
alfadur
parents: 14114
diff changeset
   160
            // where the normal line intersects the top map border
21642eb0ff29 import some clarity into border distance computation
alfadur
parents: 14114
diff changeset
   161
            let top_intersection = Point::new(
14147
11202097584f fix tangents
alfadur
parents: 14146
diff changeset
   162
                mid_point.x + normal.cotangent_mul(map_box.top() - mid_point.y),
14127
c27461e6a9eb Implement non-overflowing calculations for high values
unc0rr
parents: 14126
diff changeset
   163
                map_box.top(),
c27461e6a9eb Implement non-overflowing calculations for high values
unc0rr
parents: 14126
diff changeset
   164
            );
14115
21642eb0ff29 import some clarity into border distance computation
alfadur
parents: 14114
diff changeset
   165
            let dl = (mid_point - top_intersection).integral_norm();
14086
5d42204ac35e Start convertion of FindPoint()
unC0Rr
parents: 14083
diff changeset
   166
14115
21642eb0ff29 import some clarity into border distance computation
alfadur
parents: 14114
diff changeset
   167
            // same for the bottom border
21642eb0ff29 import some clarity into border distance computation
alfadur
parents: 14114
diff changeset
   168
            let bottom_intersection = Point::new(
14147
11202097584f fix tangents
alfadur
parents: 14146
diff changeset
   169
                mid_point.x + normal.cotangent_mul(map_box.bottom() - mid_point.y),
14127
c27461e6a9eb Implement non-overflowing calculations for high values
unc0rr
parents: 14126
diff changeset
   170
                map_box.bottom(),
c27461e6a9eb Implement non-overflowing calculations for high values
unc0rr
parents: 14126
diff changeset
   171
            );
14115
21642eb0ff29 import some clarity into border distance computation
alfadur
parents: 14114
diff changeset
   172
            let dr = (mid_point - bottom_intersection).integral_norm();
21642eb0ff29 import some clarity into border distance computation
alfadur
parents: 14114
diff changeset
   173
14136
c416d32764b7 organize landgen a bit more
alfadur
parents: 14131
diff changeset
   174
            if normal.y < 0 {
14086
5d42204ac35e Start convertion of FindPoint()
unC0Rr
parents: 14083
diff changeset
   175
                dist_left = min(dist_left, dl);
5d42204ac35e Start convertion of FindPoint()
unC0Rr
parents: 14083
diff changeset
   176
                dist_right = min(dist_right, dr);
5d42204ac35e Start convertion of FindPoint()
unC0Rr
parents: 14083
diff changeset
   177
            } else {
5d42204ac35e Start convertion of FindPoint()
unC0Rr
parents: 14083
diff changeset
   178
                dist_left = min(dist_left, dr);
14115
21642eb0ff29 import some clarity into border distance computation
alfadur
parents: 14114
diff changeset
   179
                dist_right = min(dist_right, dl);
14086
5d42204ac35e Start convertion of FindPoint()
unC0Rr
parents: 14083
diff changeset
   180
            }
5d42204ac35e Start convertion of FindPoint()
unC0Rr
parents: 14083
diff changeset
   181
        }
5d42204ac35e Start convertion of FindPoint()
unC0Rr
parents: 14083
diff changeset
   182
5d42204ac35e Start convertion of FindPoint()
unC0Rr
parents: 14083
diff changeset
   183
        // now go through all other segments
14105
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   184
        for s in self.segments_iter() {
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   185
            if s != segment {
14136
c416d32764b7 organize landgen a bit more
alfadur
parents: 14131
diff changeset
   186
                if intersects(&normal_ray, &s) {
c416d32764b7 organize landgen a bit more
alfadur
parents: 14131
diff changeset
   187
                    if let Some((t, d)) =
c416d32764b7 organize landgen a bit more
alfadur
parents: 14131
diff changeset
   188
                        solve_intersection(&self.intersections_box, &normal_ray, &s)
c416d32764b7 organize landgen a bit more
alfadur
parents: 14131
diff changeset
   189
                    {
14105
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   190
                        if t > 0 {
14118
be4419243735 fix normal offset for split points and make directions more consistent
alfadur
parents: 14116
diff changeset
   191
                            dist_right = min(dist_right, d);
14105
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   192
                        } else {
14118
be4419243735 fix normal offset for split points and make directions more consistent
alfadur
parents: 14116
diff changeset
   193
                            dist_left = min(dist_left, d);
14105
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   194
                        }
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   195
                    }
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   196
                }
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   197
            }
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   198
        }
14086
5d42204ac35e Start convertion of FindPoint()
unC0Rr
parents: 14083
diff changeset
   199
14105
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   200
        // go through all points, including fill points
14131
32383b888309 resolve some clippy complaints
alfadur
parents: 14130
diff changeset
   201
        for pi in self.iter().cloned() {
32383b888309 resolve some clippy complaints
alfadur
parents: 14130
diff changeset
   202
            if pi != segment.start && pi != segment.end {
14146
477faa7b8a48 fix ray construction
alfadur
parents: 14145
diff changeset
   203
                if intersects(&pi.ray_with_dir(normal), &segment) {
14105
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   204
                    // ray from segment.start
14130
376a0551b00a - Add distance-divider option to land_dump
unc0rr
parents: 14129
diff changeset
   205
                    if let Some((t, d)) = solve_intersection(
14136
c416d32764b7 organize landgen a bit more
alfadur
parents: 14131
diff changeset
   206
                        &self.intersections_box, &normal_ray, &segment.start.line_to(pi),
14130
376a0551b00a - Add distance-divider option to land_dump
unc0rr
parents: 14129
diff changeset
   207
                    ) {
14105
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   208
                        if t > 0 {
14118
be4419243735 fix normal offset for split points and make directions more consistent
alfadur
parents: 14116
diff changeset
   209
                            dist_right = min(dist_right, d);
14105
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   210
                        } else {
14118
be4419243735 fix normal offset for split points and make directions more consistent
alfadur
parents: 14116
diff changeset
   211
                            dist_left = min(dist_left, d);
14105
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   212
                        }
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   213
                    }
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   214
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   215
                    // ray from segment.end
14130
376a0551b00a - Add distance-divider option to land_dump
unc0rr
parents: 14129
diff changeset
   216
                    if let Some((t, d)) = solve_intersection(
14136
c416d32764b7 organize landgen a bit more
alfadur
parents: 14131
diff changeset
   217
                        &self.intersections_box, &normal_ray, &segment.end.line_to(pi)
14130
376a0551b00a - Add distance-divider option to land_dump
unc0rr
parents: 14129
diff changeset
   218
                    ) {
14105
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   219
                        if t > 0 {
14118
be4419243735 fix normal offset for split points and make directions more consistent
alfadur
parents: 14116
diff changeset
   220
                            dist_right = min(dist_right, d);
14105
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   221
                        } else {
14118
be4419243735 fix normal offset for split points and make directions more consistent
alfadur
parents: 14116
diff changeset
   222
                            dist_left = min(dist_left, d);
14105
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   223
                        }
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   224
                    }
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   225
                }
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   226
            }
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   227
        }
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   228
14136
c416d32764b7 organize landgen a bit more
alfadur
parents: 14131
diff changeset
   229
        let max_dist = normal_len * 100 / distance_divisor;
14105
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   230
        dist_left = min(dist_left, max_dist);
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   231
        dist_right = min(dist_right, max_dist);
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   232
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   233
        if dist_right + dist_left < min_distance as u32 * 2 + 10 {
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   234
            // limits are too narrow, just divide
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   235
            Some(mid_point)
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   236
        } else {
14118
be4419243735 fix normal offset for split points and make directions more consistent
alfadur
parents: 14116
diff changeset
   237
            // select distance within [-dist_right; dist_left], keeping min_distance in mind
be4419243735 fix normal offset for split points and make directions more consistent
alfadur
parents: 14116
diff changeset
   238
            let d = -(dist_right as i32)
14105
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   239
                + min_distance
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   240
                + random_numbers.next().unwrap() as i32
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   241
                    % (dist_right as i32 + dist_left as i32 - min_distance * 2);
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   242
14136
c416d32764b7 organize landgen a bit more
alfadur
parents: 14131
diff changeset
   243
            Some(mid_point + normal * d / normal_len as i32)
14105
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   244
        }
14074
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
   245
    }
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
   246
14105
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   247
    fn divide_edges<I: Iterator<Item = u32>>(
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   248
        &mut self,
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   249
        distance_divisor: u32,
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   250
        random_numbers: &mut I,
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   251
    ) {
14074
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
   252
        for is in 0..self.islands.len() {
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
   253
            let mut i = 0;
14129
6e0be42d0a8f polygonize OutlinePoints
alfadur
parents: 14127
diff changeset
   254
            while i < self.islands[is].edges_count() {
6e0be42d0a8f polygonize OutlinePoints
alfadur
parents: 14127
diff changeset
   255
                let segment = self.islands[is].get_edge(i);
14130
376a0551b00a - Add distance-divider option to land_dump
unc0rr
parents: 14129
diff changeset
   256
                if let Some(new_point) = self.divide_edge(segment, distance_divisor, random_numbers)
376a0551b00a - Add distance-divider option to land_dump
unc0rr
parents: 14129
diff changeset
   257
                {
14129
6e0be42d0a8f polygonize OutlinePoints
alfadur
parents: 14127
diff changeset
   258
                    self.islands[is].split_edge(i, new_point);
14074
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
   259
                    i += 2;
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
   260
                } else {
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
   261
                    i += 1;
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
   262
                }
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
   263
            }
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
   264
        }
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
   265
    }
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
   266
14145
3078123e84ea Bezierize land outline
unc0rr
parents: 14142
diff changeset
   267
    pub fn bezierize(&mut self, segments_number: u32) {
3078123e84ea Bezierize land outline
unc0rr
parents: 14142
diff changeset
   268
        for island in &mut self.islands {
3078123e84ea Bezierize land outline
unc0rr
parents: 14142
diff changeset
   269
            island.bezierize(segments_number);
3078123e84ea Bezierize land outline
unc0rr
parents: 14142
diff changeset
   270
        }
3078123e84ea Bezierize land outline
unc0rr
parents: 14142
diff changeset
   271
    }
14074
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
   272
14105
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   273
    pub fn distort<I: Iterator<Item = u32>>(
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   274
        &mut self,
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   275
        distance_divisor: u32,
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   276
        random_numbers: &mut I,
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   277
    ) {
14074
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
   278
        loop {
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
   279
            let old_len = self.total_len();
14105
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   280
            self.divide_edges(distance_divisor, random_numbers);
14074
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
   281
14098
dbaa125a0fe9 fix infinite loop in landgen
alfadur
parents: 14086
diff changeset
   282
            if self.total_len() == old_len {
14074
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
   283
                break;
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
   284
            }
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
   285
        }
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
   286
    }
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
   287
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
   288
    pub fn draw<T: Copy + PartialEq>(&self, land: &mut Land2D<T>, value: T) {
14081
e5904ead4864 Introduce OutlineSegmentsIterator, some refactoring
unC0Rr
parents: 14074
diff changeset
   289
        for segment in self.segments_iter() {
e5904ead4864 Introduce OutlineSegmentsIterator, some refactoring
unC0Rr
parents: 14074
diff changeset
   290
            land.draw_line(segment, value);
e5904ead4864 Introduce OutlineSegmentsIterator, some refactoring
unC0Rr
parents: 14074
diff changeset
   291
        }
e5904ead4864 Introduce OutlineSegmentsIterator, some refactoring
unC0Rr
parents: 14074
diff changeset
   292
    }
e5904ead4864 Introduce OutlineSegmentsIterator, some refactoring
unC0Rr
parents: 14074
diff changeset
   293
14129
6e0be42d0a8f polygonize OutlinePoints
alfadur
parents: 14127
diff changeset
   294
    fn segments_iter<'a>(&'a self) -> impl Iterator<Item = Line> + 'a {
6e0be42d0a8f polygonize OutlinePoints
alfadur
parents: 14127
diff changeset
   295
        self.islands.iter().flat_map(|p| p.iter_edges())
14074
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
   296
    }
14100
b2feb190e4bc Move flip and mirror to outline methods
unc0rr
parents: 14098
diff changeset
   297
b2feb190e4bc Move flip and mirror to outline methods
unc0rr
parents: 14098
diff changeset
   298
    pub fn mirror(&mut self) {
14105
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   299
        let r = self.size.width as i32 - 1;
14139
09f62bb046ef actually there is a way to preserve mutable polygon iterator
alfadur
parents: 14138
diff changeset
   300
09f62bb046ef actually there is a way to preserve mutable polygon iterator
alfadur
parents: 14138
diff changeset
   301
        self.iter_mut().for_each(|p| p.x = r - p.x);
14100
b2feb190e4bc Move flip and mirror to outline methods
unc0rr
parents: 14098
diff changeset
   302
    }
b2feb190e4bc Move flip and mirror to outline methods
unc0rr
parents: 14098
diff changeset
   303
b2feb190e4bc Move flip and mirror to outline methods
unc0rr
parents: 14098
diff changeset
   304
    pub fn flip(&mut self) {
14105
4d22be35cfa2 Finish porting FindPoint()
unc0rr
parents: 14102
diff changeset
   305
        let t = self.size.height as i32 - 1;
14139
09f62bb046ef actually there is a way to preserve mutable polygon iterator
alfadur
parents: 14138
diff changeset
   306
09f62bb046ef actually there is a way to preserve mutable polygon iterator
alfadur
parents: 14138
diff changeset
   307
        self.iter_mut().for_each(|p| p.y = t - p.y);
14100
b2feb190e4bc Move flip and mirror to outline methods
unc0rr
parents: 14098
diff changeset
   308
    }
14074
abb42ba345b6 Rework lib structure, no code changes
unC0Rr
parents:
diff changeset
   309
}
14081
e5904ead4864 Introduce OutlineSegmentsIterator, some refactoring
unC0Rr
parents: 14074
diff changeset
   310
14083
bf40b5f938b0 - Add methods to work with Rect as box
unC0Rr
parents: 14082
diff changeset
   311
#[test()]
bf40b5f938b0 - Add methods to work with Rect as box
unC0Rr
parents: 14082
diff changeset
   312
fn points_test() {
14140
7f5a591e1c43 separate rectangle types based on right/bottom edge inclusivity
alfadur
parents: 14139
diff changeset
   313
    let size = Size::square(100);
14083
bf40b5f938b0 - Add methods to work with Rect as box
unC0Rr
parents: 14082
diff changeset
   314
    let mut points = OutlinePoints {
bf40b5f938b0 - Add methods to work with Rect as box
unC0Rr
parents: 14082
diff changeset
   315
        islands: vec![
14129
6e0be42d0a8f polygonize OutlinePoints
alfadur
parents: 14127
diff changeset
   316
            Polygon::new(&[Point::new(0, 0), Point::new(20, 0), Point::new(30, 30)]),
6e0be42d0a8f polygonize OutlinePoints
alfadur
parents: 14127
diff changeset
   317
            Polygon::new(&[Point::new(10, 15), Point::new(15, 20), Point::new(20, 15)]),
14083
bf40b5f938b0 - Add methods to work with Rect as box
unC0Rr
parents: 14082
diff changeset
   318
        ],
bf40b5f938b0 - Add methods to work with Rect as box
unC0Rr
parents: 14082
diff changeset
   319
        fill_points: vec![Point::new(1, 1)],
14142
3119d665d3c6 collapse rectangle types back together with consistent usage of size
alfadur
parents: 14140
diff changeset
   320
        play_box: Rect::at_origin(size).with_margin(10),
14083
bf40b5f938b0 - Add methods to work with Rect as box
unC0Rr
parents: 14082
diff changeset
   321
        size: Size::square(100),
14142
3119d665d3c6 collapse rectangle types back together with consistent usage of size
alfadur
parents: 14140
diff changeset
   322
        intersections_box: Rect::at_origin(size),
14083
bf40b5f938b0 - Add methods to work with Rect as box
unC0Rr
parents: 14082
diff changeset
   323
    };
bf40b5f938b0 - Add methods to work with Rect as box
unC0Rr
parents: 14082
diff changeset
   324
bf40b5f938b0 - Add methods to work with Rect as box
unC0Rr
parents: 14082
diff changeset
   325
    let segments: Vec<Line> = points.segments_iter().collect();
bf40b5f938b0 - Add methods to work with Rect as box
unC0Rr
parents: 14082
diff changeset
   326
    assert_eq!(
bf40b5f938b0 - Add methods to work with Rect as box
unC0Rr
parents: 14082
diff changeset
   327
        segments.first(),
bf40b5f938b0 - Add methods to work with Rect as box
unC0Rr
parents: 14082
diff changeset
   328
        Some(&Line::new(Point::new(0, 0), Point::new(20, 0)))
bf40b5f938b0 - Add methods to work with Rect as box
unC0Rr
parents: 14082
diff changeset
   329
    );
bf40b5f938b0 - Add methods to work with Rect as box
unC0Rr
parents: 14082
diff changeset
   330
    assert_eq!(
bf40b5f938b0 - Add methods to work with Rect as box
unC0Rr
parents: 14082
diff changeset
   331
        segments.last(),
bf40b5f938b0 - Add methods to work with Rect as box
unC0Rr
parents: 14082
diff changeset
   332
        Some(&Line::new(Point::new(20, 15), Point::new(10, 15)))
bf40b5f938b0 - Add methods to work with Rect as box
unC0Rr
parents: 14082
diff changeset
   333
    );
bf40b5f938b0 - Add methods to work with Rect as box
unC0Rr
parents: 14082
diff changeset
   334
14139
09f62bb046ef actually there is a way to preserve mutable polygon iterator
alfadur
parents: 14138
diff changeset
   335
    points.iter_mut().for_each(|p| p.x = 2);
14130
376a0551b00a - Add distance-divider option to land_dump
unc0rr
parents: 14129
diff changeset
   336
14083
bf40b5f938b0 - Add methods to work with Rect as box
unC0Rr
parents: 14082
diff changeset
   337
    assert_eq!(points.fill_points[0].x, 2);
14129
6e0be42d0a8f polygonize OutlinePoints
alfadur
parents: 14127
diff changeset
   338
    assert_eq!(points.islands[0].get_edge(0).start.x, 2);
14083
bf40b5f938b0 - Add methods to work with Rect as box
unC0Rr
parents: 14082
diff changeset
   339
}