1 use itertools::Itertools; |
1 use itertools::Itertools; |
2 use std::cmp::min; |
2 use std::cmp::min; |
3 |
3 |
4 use integral_geometry::{Line, Ray, Point, Polygon, Rect, Size}; |
4 use integral_geometry::{Line, Point, Polygon, Ray, Rect, Size}; |
5 use land2d::Land2D; |
5 use land2d::Land2D; |
6 |
6 |
7 use crate::outline_template::OutlineTemplate; |
7 use crate::outline_template::OutlineTemplate; |
8 |
8 |
9 pub struct OutlinePoints { |
9 pub struct OutlinePoints { |
74 |
74 |
75 #[inline] |
75 #[inline] |
76 fn solve_intersection( |
76 fn solve_intersection( |
77 intersections_box: &Rect, |
77 intersections_box: &Rect, |
78 ray: &Ray, |
78 ray: &Ray, |
79 edge: &Line |
79 edge: &Line, |
80 ) -> Option<(i32, u32)> |
80 ) -> Option<(i32, u32)> { |
81 { |
|
82 let edge_dir = edge.scaled_direction(); |
81 let edge_dir = edge.scaled_direction(); |
83 let aqpb = ray.direction.cross(edge_dir) as i64; |
82 let aqpb = ray.direction.cross(edge_dir) as i64; |
84 |
83 |
85 if aqpb != 0 { |
84 if aqpb != 0 { |
86 let mut iy = |
85 let mut iy = ((((edge.start.x - ray.start.x) as i64 * ray.direction.y as i64 |
87 ((((edge.start.x - ray.start.x) as i64 * ray.direction.y as i64 |
86 + ray.start.y as i64 * ray.direction.x as i64) |
88 + ray.start.y as i64 * ray.direction.x as i64) |
|
89 * edge_dir.y as i64 |
87 * edge_dir.y as i64 |
90 - edge.start.y as i64 * edge_dir.x as i64 * ray.direction.y as i64) |
88 - edge.start.y as i64 * edge_dir.x as i64 * ray.direction.y as i64) |
91 / aqpb) as i32; |
89 / aqpb) as i32; |
92 |
90 |
93 // is there better way to do it? |
91 // is there better way to do it? |
145 dist_left = (mid_point - left_intersection).integral_norm(); |
143 dist_left = (mid_point - left_intersection).integral_norm(); |
146 |
144 |
147 // same for the right border |
145 // same for the right border |
148 let right_intersection = Point::new( |
146 let right_intersection = Point::new( |
149 map_box.right(), |
147 map_box.right(), |
150 mid_point.y + normal.tangent_mul(map_box.right() - mid_point.x) , |
148 mid_point.y + normal.tangent_mul(map_box.right() - mid_point.x), |
151 ); |
149 ); |
152 dist_right = (mid_point - right_intersection).integral_norm(); |
150 dist_right = (mid_point - right_intersection).integral_norm(); |
153 |
151 |
154 if normal.x > 0 { |
152 if normal.x > 0 { |
155 std::mem::swap(&mut dist_left, &mut dist_right); |
153 std::mem::swap(&mut dist_left, &mut dist_right); |
201 for pi in self.iter().cloned() { |
199 for pi in self.iter().cloned() { |
202 if pi != segment.start && pi != segment.end { |
200 if pi != segment.start && pi != segment.end { |
203 if intersects(&pi.ray_with_dir(normal), &segment) { |
201 if intersects(&pi.ray_with_dir(normal), &segment) { |
204 // ray from segment.start |
202 // ray from segment.start |
205 if let Some((t, d)) = solve_intersection( |
203 if let Some((t, d)) = solve_intersection( |
206 &self.intersections_box, &normal_ray, &segment.start.line_to(pi), |
204 &self.intersections_box, |
|
205 &normal_ray, |
|
206 &segment.start.line_to(pi), |
207 ) { |
207 ) { |
208 if t > 0 { |
208 if t > 0 { |
209 dist_right = min(dist_right, d); |
209 dist_right = min(dist_right, d); |
210 } else { |
210 } else { |
211 dist_left = min(dist_left, d); |
211 dist_left = min(dist_left, d); |
212 } |
212 } |
213 } |
213 } |
214 |
214 |
215 // ray from segment.end |
215 // ray from segment.end |
216 if let Some((t, d)) = solve_intersection( |
216 if let Some((t, d)) = solve_intersection( |
217 &self.intersections_box, &normal_ray, &segment.end.line_to(pi) |
217 &self.intersections_box, |
|
218 &normal_ray, |
|
219 &segment.end.line_to(pi), |
218 ) { |
220 ) { |
219 if t > 0 { |
221 if t > 0 { |
220 dist_right = min(dist_right, d); |
222 dist_right = min(dist_right, d); |
221 } else { |
223 } else { |
222 dist_left = min(dist_left, d); |
224 dist_left = min(dist_left, d); |