1#![doc = include_str!("../README.md")]
2
3mod next_after;
4
5use crate::next_after::NextAfter;
6
7#[derive(Copy, Clone, Debug)]
8pub struct Point {
9 pub x: f64,
10 pub y: f64,
11}
12
13#[derive(Copy, Clone, Debug)]
14pub struct Rect {
15 pub min: Point,
16 pub max: Point,
17}
18
19impl Rect {
20 pub fn contains_point(&self, p: Point) -> bool {
21 return p.x >= self.min.x && p.x <= self.max.x && p.y >= self.min.y && p.y <= self.max.y;
22 }
23
24 pub fn intersects_rect(&self, other: Rect) -> bool {
25 if self.min.y > other.max.y || self.max.y < other.min.y {
26 return false;
27 }
28 if self.min.x > other.max.x || self.max.x < other.min.x {
29 return false;
30 }
31 return true;
32 }
33
34 pub fn nw(&self) -> Point {
35 Point {
36 x: self.min.x,
37 y: self.max.y,
38 }
39 }
40
41 pub fn sw(&self) -> Point {
42 Point {
43 x: self.min.x,
44 y: self.min.y,
45 }
46 }
47
48 pub fn se(&self) -> Point {
49 Point {
50 x: self.max.x,
51 y: self.min.y,
52 }
53 }
54
55 pub fn ne(&self) -> Point {
56 Point {
57 x: self.max.x,
58 y: self.max.y,
59 }
60 }
61
62 pub fn south(&self) -> Segment {
63 Segment {
64 a: self.sw(),
65 b: self.se(),
66 }
67 }
68
69 pub fn east(&self) -> Segment {
70 Segment {
71 a: self.se(),
72 b: self.ne(),
73 }
74 }
75
76 pub fn north(&self) -> Segment {
77 Segment {
78 a: self.ne(),
79 b: self.nw(),
80 }
81 }
82
83 pub fn west(&self) -> Segment {
84 Segment {
85 a: self.nw(),
86 b: self.sw(),
87 }
88 }
89
90 pub fn segment_at(&self, index: i64) -> Segment {
91 match index {
92 0 => return self.south(),
93 1 => return self.east(),
94 2 => return self.north(),
95 3 => return self.west(),
96 _ => return self.south(), }
98 }
99}
100
101fn segment_at_for_vec_point(exterior: &Vec<Point>, index: i64) -> Segment {
102 let seg_a: Point = exterior[index as usize];
103 let mut seg_b_index = index;
104 if seg_b_index == (exterior.len() - 1) as i64 {
105 seg_b_index = 0
106 } else {
107 seg_b_index += 1
108 }
109 let seg_b: Point = exterior[seg_b_index as usize];
110 return Segment { a: seg_a, b: seg_b };
111}
112
113fn rings_contains_point(ring: &Vec<Point>, point: Point, allow_on_edge: bool) -> bool {
114 let rect = Rect {
115 min: Point {
116 x: std::f64::NEG_INFINITY,
117 y: point.y,
118 },
119 max: Point {
120 x: std::f64::INFINITY,
121 y: point.y,
122 },
123 };
124 let mut inside: bool = false;
125 let n: i64 = (ring.len() - 1) as i64;
126 for i in 0..n {
127 let seg: Segment = segment_at_for_vec_point(&ring, i);
128
129 if seg.rect().intersects_rect(rect) {
130 let res: RaycastResult = raycast(&seg, point);
131 if res.on {
133 inside = allow_on_edge;
134 break;
135 }
136 if res.inside {
137 inside = !inside;
138 }
139 }
140 }
141 return inside;
142}
143
144pub struct Polygon {
145 pub exterior: Vec<Point>,
146 pub holes: Vec<Vec<Point>>,
147 pub rect: Rect,
148}
149
150impl Polygon {
151 fn contains_point_normal(&self, p: Point) -> bool {
156 if !rings_contains_point(&self.exterior, p, false) {
157 return false;
158 }
159 let mut contains: bool = true;
160 for hole in self.holes.iter() {
161 if rings_contains_point(&hole, p, false) {
162 contains = false;
163 break;
164 }
165 }
166 return contains;
167 }
168
169 pub fn contains_point(&self, p: Point) -> bool {
171 if !self.rect.contains_point(p) {
172 return false;
173 }
174
175 return self.contains_point_normal(p);
176 }
177
178 pub fn new(exterior: Vec<Point>, holes: Vec<Vec<Point>>) -> Polygon {
225 return Polygon::default_new(exterior, holes);
226 }
227
228 fn default_new(exterior: Vec<Point>, holes: Vec<Vec<Point>>) -> Polygon {
229 let mut minx: f64 = exterior.get(0).unwrap().x;
230 let mut miny: f64 = exterior.get(0).unwrap().y;
231 let mut maxx: f64 = exterior.get(0).unwrap().x;
232 let mut maxy: f64 = exterior.get(0).unwrap().y;
233
234 for i in 0..exterior.len() - 1 {
236 let p = exterior[i];
237 if p.x < minx {
238 minx = p.x;
239 }
240 if p.y < miny {
241 miny = p.y;
242 }
243 if p.x > maxx {
244 maxx = p.x;
245 }
246 if p.y > maxy {
247 maxy = p.y;
248 }
249 }
250
251 let rect = Rect {
252 min: Point { x: minx, y: miny },
253 max: Point { x: maxx, y: maxy },
254 };
255
256 return Polygon {
257 exterior,
258 holes,
259 rect,
260 };
261 }
262}
263
264#[derive(Copy, Clone, Debug)]
265pub struct Segment {
266 pub a: Point,
267 pub b: Point,
268}
269
270impl Segment {
271 pub fn rect(&self) -> Rect {
272 let mut min_x: f64 = self.a.x;
273 let mut min_y: f64 = self.a.y;
274 let mut max_x: f64 = self.b.x;
275 let mut max_y: f64 = self.b.y;
276
277 if min_x > max_x {
278 let actual_min_x = max_x;
279 let actual_max_x = min_x;
280 min_x = actual_min_x;
281 max_x = actual_max_x;
282 }
283
284 if min_y > max_y {
285 let actual_min_y = max_y;
286 let actual_max_y = min_y;
287 min_y = actual_min_y;
288 max_y = actual_max_y;
289 }
290
291 return Rect {
292 min: Point { x: min_x, y: min_y },
293 max: Point { x: max_x, y: max_y },
294 };
295 }
296}
297
298pub struct RaycastResult {
299 inside: bool, on: bool, }
302
303pub fn raycast(seg: &Segment, point: Point) -> RaycastResult {
304 let mut p = point;
305 let a = seg.a;
306 let b = seg.b;
307
308 if a.y < b.y && (p.y < a.y || p.y > b.y) {
310 return RaycastResult {
311 inside: false,
312 on: false,
313 };
314 } else if a.y > b.y && (p.y < b.y || p.y > a.y) {
315 return RaycastResult {
316 inside: false,
317 on: false,
318 };
319 }
320
321 if a.y == b.y {
323 if a.x == b.x {
324 if p.x == a.x && p.y == a.y {
325 return RaycastResult {
326 inside: false,
327 on: true,
328 };
329 }
330 return RaycastResult {
331 inside: false,
332 on: false,
333 };
334 }
335 if p.y == b.y {
336 if a.x < b.x {
339 if p.x >= a.x && p.x <= b.x {
340 return RaycastResult {
341 inside: false,
342 on: true,
343 };
344 }
345 } else {
346 if p.x >= b.x && p.x <= a.x {
347 return RaycastResult {
348 inside: false,
349 on: true,
350 };
351 }
352 }
353 }
354 }
355 if a.x == b.x && p.x == b.x {
356 if a.y < b.y {
359 if p.y >= a.y && p.y <= b.y {
360 return RaycastResult {
361 inside: false,
362 on: true,
363 };
364 }
365 } else {
366 if p.y >= b.y && p.y <= a.y {
367 return RaycastResult {
368 inside: false,
369 on: true,
370 };
371 }
372 }
373 }
374 if (p.x - a.x) / (b.x - a.x) == (p.y - a.y) / (b.y - a.y) {
375 return RaycastResult {
376 inside: false,
377 on: true,
378 };
379 }
380
381 while p.y == a.y || p.y == b.y {
383 p.y = p.y.next_after(std::f64::INFINITY);
386 }
387
388 if a.y < b.y {
389 if p.y < a.y || p.y > b.y {
390 return RaycastResult {
391 inside: false,
392 on: false,
393 };
394 }
395 } else {
396 if p.y < b.y || p.y > a.y {
397 return RaycastResult {
398 inside: false,
399 on: false,
400 };
401 }
402 }
403 if a.x > b.x {
404 if p.x >= a.x {
405 return RaycastResult {
406 inside: false,
407 on: false,
408 };
409 }
410 if p.x <= b.x {
411 return RaycastResult {
412 inside: true,
413 on: false,
414 };
415 }
416 } else {
417 if p.x >= b.x {
418 return RaycastResult {
419 inside: false,
420 on: false,
421 };
422 }
423 if p.x <= a.x {
424 return RaycastResult {
425 inside: true,
426 on: false,
427 };
428 }
429 }
430 if a.y < b.y {
431 if (p.y - a.y) / (p.x - a.x) >= (b.y - a.y) / (b.x - a.x) {
432 return RaycastResult {
433 inside: true,
434 on: false,
435 };
436 }
437 } else {
438 if (p.y - b.y) / (p.x - b.x) >= (a.y - b.y) / (a.x - b.x) {
439 return RaycastResult {
440 inside: true,
441 on: false,
442 };
443 }
444 }
445 return RaycastResult {
446 inside: false,
447 on: false,
448 };
449}