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