rust/landgen/src/outline.rs
changeset 14105 4d22be35cfa2
parent 14102 400864ecb954
child 14108 8556937ae338
equal deleted inserted replaced
14104:7845beb87cb5 14105:4d22be35cfa2
    44 
    44 
    45     pub fn total_len(&self) -> usize {
    45     pub fn total_len(&self) -> usize {
    46         self.islands.iter().map(|i| i.len()).sum::<usize>() + self.fill_points.len()
    46         self.islands.iter().map(|i| i.len()).sum::<usize>() + self.fill_points.len()
    47     }
    47     }
    48 
    48 
       
    49     pub fn iter(&self) -> impl Iterator<Item = &Point> {
       
    50         self.islands
       
    51             .iter()
       
    52             .flat_map(|i| i.iter())
       
    53             .chain(self.fill_points.iter())
       
    54     }
       
    55 
    49     pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Point> {
    56     pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Point> {
    50         self.islands
    57         self.islands
    51             .iter_mut()
    58             .iter_mut()
    52             .flat_map(|i| i.iter_mut())
    59             .flat_map(|i| i.iter_mut())
    53             .chain(self.fill_points.iter_mut())
    60             .chain(self.fill_points.iter_mut())
    54     }
    61     }
    55 
    62 
    56     fn divide_edge<I: Iterator<Item = u32>>(
    63     fn divide_edge<I: Iterator<Item = u32>>(
    57         &self,
    64         &self,
    58         segment: Line,
    65         segment: Line,
       
    66         distance_divisor: u32,
    59         random_numbers: &mut I,
    67         random_numbers: &mut I,
    60     ) -> Option<Point> {
    68     ) -> Option<Point> {
       
    69         #[inline]
       
    70         fn intersect(p: &Point, m: &Point, p1: &Point, p2: &Point) -> bool {
       
    71             let t1 = (m.x - p1.x) * p.y - p.x * (m.y - p1.y);
       
    72             let t2 = (m.x - p2.x) * p.y - p.x * (m.y - p2.y);
       
    73 
       
    74             (t1 > 0) != (t2 > 0)
       
    75         }
       
    76 
       
    77         #[inline]
       
    78         fn solve_intersection(p: &Point, m: &Point, s: &Point, e: &Point) -> Option<(i32, u32)> {
       
    79             let f = *e - *s;
       
    80             let aqpb = (p.x * f.y - f.x * p.y) as i64;
       
    81 
       
    82             if aqpb != 0 {
       
    83                 let iy = ((((s.x - m.x) as i64 * p.y as i64 + m.y as i64 * p.x as i64)
       
    84                     * f.y as i64
       
    85                     - s.y as i64 * f.x as i64 * p.y as i64)
       
    86                     / aqpb) as i32;
       
    87                 let ix = if p.y.abs() > f.y.abs() {
       
    88                     (iy - m.y) * p.x / p.y + m.x
       
    89                 } else {
       
    90                     (iy - s.y) * f.x / f.y + s.x
       
    91                 };
       
    92 
       
    93                 let intersection_point = Point::new(ix, iy);
       
    94                 let diff_point = *m - intersection_point;
       
    95                 let d = diff_point.integral_norm();
       
    96                 let t = p.y * diff_point.y + p.x * diff_point.x;
       
    97 
       
    98                 Some((t, d))
       
    99             } else {
       
   100                 None
       
   101             }
       
   102         }
       
   103 
    61         let min_distance = 40;
   104         let min_distance = 40;
    62         // new point should fall inside this box
   105         // new point should fall inside this box
    63         let map_box = self.play_box.with_margin(min_distance);
   106         let map_box = self.play_box.with_margin(min_distance);
    64 
   107 
    65         let p = Point::new(
   108         let p = Point::new(
   123                 dist_left = min(dist_left, dr);
   166                 dist_left = min(dist_left, dr);
   124             }
   167             }
   125         }
   168         }
   126 
   169 
   127         // now go through all other segments
   170         // now go through all other segments
   128 
   171         for s in self.segments_iter() {
   129         None
   172             if s != segment {
   130     }
   173                 if intersect(&p, &mid_point, &s.start, &s.end) {
   131 
   174                     if let Some((t, d)) = solve_intersection(&p, &mid_point, &s.start, &s.end) {
   132     fn divide_edges<I: Iterator<Item = u32>>(&mut self, random_numbers: &mut I) {
   175                         if t > 0 {
       
   176                             dist_left = min(d, dist_left);
       
   177                         } else {
       
   178                             dist_right = min(d, dist_right);
       
   179                         }
       
   180                     }
       
   181                 }
       
   182             }
       
   183         }
       
   184 
       
   185         // go through all points, including fill points
       
   186         for pi in self.iter() {
       
   187             if *pi != segment.start && *pi != segment.end {
       
   188                 if intersect(&p, &pi, &segment.start, &segment.end) {
       
   189                     // ray from segment.start
       
   190                     if let Some((t, d)) = solve_intersection(&p, &mid_point, &segment.start, &pi) {
       
   191                         if t > 0 {
       
   192                             dist_left = min(d, dist_left);
       
   193                         } else {
       
   194                             dist_right = min(d, dist_right);
       
   195                         }
       
   196                     }
       
   197 
       
   198                     // ray from segment.end
       
   199                     if let Some((t, d)) = solve_intersection(&p, &mid_point, &segment.end, &pi) {
       
   200                         if t > 0 {
       
   201                             dist_left = min(d, dist_left);
       
   202                         } else {
       
   203                             dist_right = min(d, dist_right);
       
   204                         }
       
   205                     }
       
   206                 }
       
   207             }
       
   208         }
       
   209 
       
   210         let max_dist = p.integral_norm() * 100 / distance_divisor;
       
   211         dist_left = min(dist_left, max_dist);
       
   212         dist_right = min(dist_right, max_dist);
       
   213 
       
   214         if dist_right + dist_left < min_distance as u32 * 2 + 10 {
       
   215             // limits are too narrow, just divide
       
   216             Some(mid_point)
       
   217         } else {
       
   218             // select distance within [-dist_left; dist_right], keeping min_distance in mind
       
   219             let d = -(dist_left as i32)
       
   220                 + min_distance
       
   221                 + random_numbers.next().unwrap() as i32
       
   222                     % (dist_right as i32 + dist_left as i32 - min_distance * 2);
       
   223 
       
   224             Some(Point::new(
       
   225                 mid_point.x + p.x * d / distance_divisor as i32,
       
   226                 mid_point.y + p.y * d / distance_divisor as i32,
       
   227             ))
       
   228         }
       
   229     }
       
   230 
       
   231     fn divide_edges<I: Iterator<Item = u32>>(
       
   232         &mut self,
       
   233         distance_divisor: u32,
       
   234         random_numbers: &mut I,
       
   235     ) {
   133         for is in 0..self.islands.len() {
   236         for is in 0..self.islands.len() {
   134             let mut i = 0;
   237             let mut i = 0;
   135             let mut segment;
   238             let mut segment;
   136 
   239 
   137             loop {
   240             loop {
   149                     }
   252                     }
   150 
   253 
   151                     segment = Line::new(island[i], end_point);
   254                     segment = Line::new(island[i], end_point);
   152                 }
   255                 }
   153 
   256 
   154                 if let Some(new_point) = self.divide_edge(segment, random_numbers) {
   257                 if let Some(new_point) = self.divide_edge(segment, distance_divisor, random_numbers)
       
   258                 {
   155                     self.islands[is].insert(i + 1, new_point);
   259                     self.islands[is].insert(i + 1, new_point);
   156                     i += 2;
   260                     i += 2;
   157                 } else {
   261                 } else {
   158                     i += 1;
   262                     i += 1;
   159                 }
   263                 }
   160             }
   264             }
   161         }
   265         }
   162     }
   266     }
   163 
   267 
   164     pub fn bezierize(&mut self) {
   268     pub fn bezierize(&mut self) {}
   165         unimplemented!()
   269 
   166     }
   270     pub fn distort<I: Iterator<Item = u32>>(
   167 
   271         &mut self,
   168     pub fn distort<I: Iterator<Item = u32>>(&mut self, random_numbers: &mut I) {
   272         distance_divisor: u32,
       
   273         random_numbers: &mut I,
       
   274     ) {
   169         loop {
   275         loop {
   170             let old_len = self.total_len();
   276             let old_len = self.total_len();
   171             self.divide_edges(random_numbers);
   277             self.divide_edges(distance_divisor, random_numbers);
   172 
   278 
   173             if self.total_len() == old_len {
   279             if self.total_len() == old_len {
   174                 break;
   280                 break;
   175             }
   281             }
   176         }
   282         }
   191             index: 0,
   297             index: 0,
   192         }
   298         }
   193     }
   299     }
   194 
   300 
   195     pub fn mirror(&mut self) {
   301     pub fn mirror(&mut self) {
   196         let width = self.size.width as i32;
   302         let r = self.size.width as i32 - 1;
   197         self.iter_mut()
   303 
   198             .for_each(|p| p.x = width - 1 - p.x);
   304         self.iter_mut().for_each(|p| p.x = r - p.x);
   199     }
   305     }
   200 
   306 
   201     pub fn flip(&mut self) {
   307     pub fn flip(&mut self) {
   202         let height = self.size.height as i32;
   308         let t = self.size.height as i32 - 1;
   203         self.iter_mut()
   309 
   204             .for_each(|p| p.y = height - 1 - p.y);
   310         self.iter_mut().for_each(|p| p.y = t - p.y);
   205     }
   311     }
   206 }
   312 }
   207 
   313 
   208 struct OutlineSegmentsIterator<'a> {
   314 struct OutlineSegmentsIterator<'a> {
   209     outline: &'a OutlinePoints,
   315     outline: &'a OutlinePoints,