1use crate::core::*;
8
9struct OutPt2 {
17 pt: Point64,
18 owner_idx: usize,
19 edge_idx: Option<usize>,
21 next: usize,
23 prev: usize,
25}
26
27impl OutPt2 {
28 fn new(pt: Point64) -> Self {
29 Self {
30 pt,
31 owner_idx: 0,
32 edge_idx: None,
33 next: 0,
34 prev: 0,
35 }
36 }
37}
38
39fn path1_contains_path2(path1: &Path64, path2: &Path64) -> bool {
47 let mut io_count = 0i32;
48 for pt in path2 {
49 let pip = point_in_polygon(*pt, path1);
50 match pip {
51 PointInPolygonResult::IsOutside => io_count += 1,
52 PointInPolygonResult::IsInside => io_count -= 1,
53 _ => continue,
54 }
55 if io_count.abs() > 1 {
56 break;
57 }
58 }
59 io_count <= 0
60}
61
62fn get_segment_intersection(
65 p1: Point64,
66 p2: Point64,
67 p3: Point64,
68 p4: Point64,
69 ip: &mut Point64,
70) -> bool {
71 let res1 = cross_product_three_points(p1, p3, p4);
72 let res2 = cross_product_three_points(p2, p3, p4);
73 if res1 == 0.0 {
74 *ip = p1;
75 if res2 == 0.0 {
76 return false; } else if p1 == p3 || p1 == p4 {
78 return true;
79 } else if is_horizontal(&p3, &p4) {
80 return (p1.x > p3.x) == (p1.x < p4.x);
81 } else {
82 return (p1.y > p3.y) == (p1.y < p4.y);
83 }
84 } else if res2 == 0.0 {
85 *ip = p2;
86 if p2 == p3 || p2 == p4 {
87 return true;
88 } else if is_horizontal(&p3, &p4) {
89 return (p2.x > p3.x) == (p2.x < p4.x);
90 } else {
91 return (p2.y > p3.y) == (p2.y < p4.y);
92 }
93 }
94 if (res1 > 0.0) == (res2 > 0.0) {
95 return false;
96 }
97
98 let res3 = cross_product_three_points(p3, p1, p2);
99 let res4 = cross_product_three_points(p4, p1, p2);
100 if res3 == 0.0 {
101 *ip = p3;
102 if p3 == p1 || p3 == p2 {
103 return true;
104 } else if is_horizontal(&p1, &p2) {
105 return (p3.x > p1.x) == (p3.x < p2.x);
106 } else {
107 return (p3.y > p1.y) == (p3.y < p2.y);
108 }
109 } else if res4 == 0.0 {
110 *ip = p4;
111 if p4 == p1 || p4 == p2 {
112 return true;
113 } else if is_horizontal(&p1, &p2) {
114 return (p4.x > p1.x) == (p4.x < p2.x);
115 } else {
116 return (p4.y > p1.y) == (p4.y < p2.y);
117 }
118 }
119 if (res3 > 0.0) == (res4 > 0.0) {
120 return false;
121 }
122
123 get_segment_intersect_pt(p1, p2, p3, p4, ip)
125}
126
127fn get_intersection(
130 rect_path: &Path64,
131 p: Point64,
132 p2: Point64,
133 loc: &mut Location,
134 ip: &mut Point64,
135) -> bool {
136 match *loc {
137 Location::Left => {
138 if get_segment_intersection(p, p2, rect_path[0], rect_path[3], ip) {
139 return true;
140 } else if p.y < rect_path[0].y
141 && get_segment_intersection(p, p2, rect_path[0], rect_path[1], ip)
142 {
143 *loc = Location::Top;
144 return true;
145 } else if get_segment_intersection(p, p2, rect_path[2], rect_path[3], ip) {
146 *loc = Location::Bottom;
147 return true;
148 }
149 false
150 }
151 Location::Top => {
152 if get_segment_intersection(p, p2, rect_path[0], rect_path[1], ip) {
153 return true;
154 } else if p.x < rect_path[0].x
155 && get_segment_intersection(p, p2, rect_path[0], rect_path[3], ip)
156 {
157 *loc = Location::Left;
158 return true;
159 } else if get_segment_intersection(p, p2, rect_path[1], rect_path[2], ip) {
160 *loc = Location::Right;
161 return true;
162 }
163 false
164 }
165 Location::Right => {
166 if get_segment_intersection(p, p2, rect_path[1], rect_path[2], ip) {
167 return true;
168 } else if p.y < rect_path[1].y
169 && get_segment_intersection(p, p2, rect_path[0], rect_path[1], ip)
170 {
171 *loc = Location::Top;
172 return true;
173 } else if get_segment_intersection(p, p2, rect_path[2], rect_path[3], ip) {
174 *loc = Location::Bottom;
175 return true;
176 }
177 false
178 }
179 Location::Bottom => {
180 if get_segment_intersection(p, p2, rect_path[2], rect_path[3], ip) {
181 return true;
182 } else if p.x < rect_path[3].x
183 && get_segment_intersection(p, p2, rect_path[0], rect_path[3], ip)
184 {
185 *loc = Location::Left;
186 return true;
187 } else if get_segment_intersection(p, p2, rect_path[1], rect_path[2], ip) {
188 *loc = Location::Right;
189 return true;
190 }
191 false
192 }
193 Location::Inside => {
194 if get_segment_intersection(p, p2, rect_path[0], rect_path[3], ip) {
195 *loc = Location::Left;
196 return true;
197 } else if get_segment_intersection(p, p2, rect_path[0], rect_path[1], ip) {
198 *loc = Location::Top;
199 return true;
200 } else if get_segment_intersection(p, p2, rect_path[1], rect_path[2], ip) {
201 *loc = Location::Right;
202 return true;
203 } else if get_segment_intersection(p, p2, rect_path[2], rect_path[3], ip) {
204 *loc = Location::Bottom;
205 return true;
206 }
207 false
208 }
209 }
210}
211
212#[inline]
215fn get_adjacent_location(loc: Location, is_clockwise: bool) -> Location {
216 let delta = if is_clockwise { 1 } else { 3 };
217 let idx = (loc as i32 + delta) % 4;
218 match idx {
219 0 => Location::Left,
220 1 => Location::Top,
221 2 => Location::Right,
222 3 => Location::Bottom,
223 _ => unreachable!(),
224 }
225}
226
227#[inline]
230fn heading_clockwise(prev: Location, curr: Location) -> bool {
231 (prev as i32 + 1) % 4 == curr as i32
232}
233
234#[inline]
237fn are_opposites(prev: Location, curr: Location) -> bool {
238 (prev as i32 - curr as i32).abs() == 2
239}
240
241#[inline]
244fn is_clockwise_dir(
245 prev: Location,
246 curr: Location,
247 prev_pt: &Point64,
248 curr_pt: &Point64,
249 rect_mp: &Point64,
250) -> bool {
251 if are_opposites(prev, curr) {
252 cross_product_three_points(*prev_pt, *rect_mp, *curr_pt) < 0.0
253 } else {
254 heading_clockwise(prev, curr)
255 }
256}
257
258#[inline]
261fn get_edges_for_pt(pt: &Point64, rec: &Rect64) -> u32 {
262 let mut result = 0u32;
263 if pt.x == rec.left {
264 result = 1;
265 } else if pt.x == rec.right {
266 result = 4;
267 }
268 if pt.y == rec.top {
269 result += 2;
270 } else if pt.y == rec.bottom {
271 result += 8;
272 }
273 result
274}
275
276#[inline]
279fn is_heading_clockwise(pt1: &Point64, pt2: &Point64, edge_idx: i32) -> bool {
280 match edge_idx {
281 0 => pt2.y < pt1.y,
282 1 => pt2.x > pt1.x,
283 2 => pt2.y > pt1.y,
284 _ => pt2.x < pt1.x,
285 }
286}
287
288#[inline]
291fn has_horz_overlap(left1: &Point64, right1: &Point64, left2: &Point64, right2: &Point64) -> bool {
292 (left1.x < right2.x) && (right1.x > left2.x)
293}
294
295#[inline]
298fn has_vert_overlap(top1: &Point64, bottom1: &Point64, top2: &Point64, bottom2: &Point64) -> bool {
299 (top1.y < bottom2.y) && (bottom1.y > top2.y)
300}
301
302fn start_locs_are_clockwise(start_locs: &[Location]) -> bool {
305 let mut result = 0i32;
306 for i in 1..start_locs.len() {
307 let d = start_locs[i] as i32 - start_locs[i - 1] as i32;
308 match d {
309 -1 => result -= 1,
310 1 => result += 1,
311 -3 => result += 1,
312 3 => result -= 1,
313 _ => {}
314 }
315 }
316 result > 0
317}
318
319pub struct RectClip64 {
327 rect: Rect64,
328 rect_as_path: Path64,
329 rect_mp: Point64,
330 path_bounds: Rect64,
331 arena: Vec<OutPt2>,
332 results: Vec<Option<usize>>,
333 edges: [Vec<Option<usize>>; 8],
334 start_locs: Vec<Location>,
335}
336
337impl RectClip64 {
338 pub fn new(rect: Rect64) -> Self {
341 let rect_as_path = rect.as_path();
342 let rect_mp = rect.mid_point();
343 Self {
344 rect,
345 rect_as_path,
346 rect_mp,
347 path_bounds: Rect64::new(0, 0, 0, 0),
348 arena: Vec::new(),
349 results: Vec::new(),
350 edges: Default::default(),
351 start_locs: Vec::new(),
352 }
353 }
354
355 fn clear(&mut self) {
357 self.arena.clear();
358 self.results.clear();
359 for edge in &mut self.edges {
360 edge.clear();
361 }
362 self.start_locs.clear();
363 }
364
365 fn add(&mut self, pt: Point64, start_new: bool) -> usize {
368 let curr_idx = self.results.len();
369 if curr_idx == 0 || start_new {
370 let new_idx = self.arena.len();
371 let mut op = OutPt2::new(pt);
372 op.next = new_idx;
373 op.prev = new_idx;
374 self.arena.push(op);
375 self.results.push(Some(new_idx));
376 new_idx
377 } else {
378 let result_idx = curr_idx - 1;
379 let prev_op_idx = self.results[result_idx].unwrap();
380 if self.arena[prev_op_idx].pt == pt {
381 return prev_op_idx;
382 }
383 let new_idx = self.arena.len();
384 let mut op = OutPt2::new(pt);
385 op.owner_idx = result_idx;
386
387 let prev_next = self.arena[prev_op_idx].next;
389 op.next = prev_next;
390 op.prev = prev_op_idx;
391 self.arena.push(op);
392
393 self.arena[prev_next].prev = new_idx;
394 self.arena[prev_op_idx].next = new_idx;
395
396 self.results[result_idx] = Some(new_idx);
397 new_idx
398 }
399 }
400
401 fn add_corner_prev_curr(&mut self, prev: Location, curr: Location) {
404 if heading_clockwise(prev, curr) {
405 self.add(self.rect_as_path[prev as usize], false);
406 } else {
407 self.add(self.rect_as_path[curr as usize], false);
408 }
409 }
410
411 fn add_corner_loc(&mut self, loc: &mut Location, is_clockwise: bool) {
414 if is_clockwise {
415 let pt = self.rect_as_path[*loc as usize];
416 self.add(pt, false);
417 *loc = get_adjacent_location(*loc, true);
418 } else {
419 *loc = get_adjacent_location(*loc, false);
420 let pt = self.rect_as_path[*loc as usize];
421 self.add(pt, false);
422 }
423 }
424
425 fn get_next_location(
428 &mut self,
429 path: &Path64,
430 loc: &mut Location,
431 i: &mut usize,
432 high_i: usize,
433 ) {
434 match *loc {
435 Location::Left => {
436 while *i <= high_i && path[*i].x <= self.rect.left {
437 *i += 1;
438 }
439 if *i > high_i {
440 return;
441 }
442 if path[*i].x >= self.rect.right {
443 *loc = Location::Right;
444 } else if path[*i].y <= self.rect.top {
445 *loc = Location::Top;
446 } else if path[*i].y >= self.rect.bottom {
447 *loc = Location::Bottom;
448 } else {
449 *loc = Location::Inside;
450 }
451 }
452 Location::Top => {
453 while *i <= high_i && path[*i].y <= self.rect.top {
454 *i += 1;
455 }
456 if *i > high_i {
457 return;
458 }
459 if path[*i].y >= self.rect.bottom {
460 *loc = Location::Bottom;
461 } else if path[*i].x <= self.rect.left {
462 *loc = Location::Left;
463 } else if path[*i].x >= self.rect.right {
464 *loc = Location::Right;
465 } else {
466 *loc = Location::Inside;
467 }
468 }
469 Location::Right => {
470 while *i <= high_i && path[*i].x >= self.rect.right {
471 *i += 1;
472 }
473 if *i > high_i {
474 return;
475 }
476 if path[*i].x <= self.rect.left {
477 *loc = Location::Left;
478 } else if path[*i].y <= self.rect.top {
479 *loc = Location::Top;
480 } else if path[*i].y >= self.rect.bottom {
481 *loc = Location::Bottom;
482 } else {
483 *loc = Location::Inside;
484 }
485 }
486 Location::Bottom => {
487 while *i <= high_i && path[*i].y >= self.rect.bottom {
488 *i += 1;
489 }
490 if *i > high_i {
491 return;
492 }
493 if path[*i].y <= self.rect.top {
494 *loc = Location::Top;
495 } else if path[*i].x <= self.rect.left {
496 *loc = Location::Left;
497 } else if path[*i].x >= self.rect.right {
498 *loc = Location::Right;
499 } else {
500 *loc = Location::Inside;
501 }
502 }
503 Location::Inside => {
504 while *i <= high_i {
505 if path[*i].x < self.rect.left {
506 *loc = Location::Left;
507 } else if path[*i].x > self.rect.right {
508 *loc = Location::Right;
509 } else if path[*i].y > self.rect.bottom {
510 *loc = Location::Bottom;
511 } else if path[*i].y < self.rect.top {
512 *loc = Location::Top;
513 } else {
514 let pt = path[*i];
515 self.add(pt, false);
516 *i += 1;
517 continue;
518 }
519 break;
520 }
521 }
522 }
523 }
524
525 fn unlink_op(&mut self, op_idx: usize) -> Option<usize> {
528 let next = self.arena[op_idx].next;
529 if next == op_idx {
530 return None;
531 }
532 let prev = self.arena[op_idx].prev;
533 self.arena[prev].next = next;
534 self.arena[next].prev = prev;
535 Some(next)
536 }
537
538 fn unlink_op_back(&mut self, op_idx: usize) -> Option<usize> {
541 let next = self.arena[op_idx].next;
542 if next == op_idx {
543 return None;
544 }
545 let prev = self.arena[op_idx].prev;
546 self.arena[prev].next = next;
547 self.arena[next].prev = prev;
548 Some(prev)
549 }
550
551 fn add_to_edge(&mut self, edge_idx: usize, op_idx: usize) {
554 if self.arena[op_idx].edge_idx.is_some() {
555 return;
556 }
557 self.arena[op_idx].edge_idx = Some(edge_idx);
558 self.edges[edge_idx].push(Some(op_idx));
559 }
560
561 fn uncouple_edge(&mut self, op_idx: usize) {
564 let edge_idx = match self.arena[op_idx].edge_idx {
565 Some(idx) => idx,
566 None => return,
567 };
568 for i in 0..self.edges[edge_idx].len() {
569 if self.edges[edge_idx][i] == Some(op_idx) {
570 self.edges[edge_idx][i] = None;
571 break;
572 }
573 }
574 self.arena[op_idx].edge_idx = None;
575 }
576
577 fn set_new_owner(&mut self, op_idx: usize, new_idx: usize) {
580 self.arena[op_idx].owner_idx = new_idx;
581 let mut op2 = self.arena[op_idx].next;
582 while op2 != op_idx {
583 self.arena[op2].owner_idx = new_idx;
584 op2 = self.arena[op2].next;
585 }
586 }
587
588 fn execute_internal(&mut self, path: &Path64) {
591 if path.is_empty() {
592 return;
593 }
594
595 let high_i = path.len() - 1;
596 let mut prev = Location::Inside;
597 let mut loc = Location::Inside;
598 let mut crossing_loc = Location::Inside;
599 let mut first_cross = Location::Inside;
600
601 if !get_location(&self.rect, &path[high_i], &mut loc) {
602 let mut i = high_i;
603 while i > 0 && !get_location(&self.rect, &path[i - 1], &mut prev) {
604 i -= 1;
605 }
606 if i == 0 {
607 for pt in path {
609 self.add(*pt, false);
610 }
611 return;
612 }
613 if prev == Location::Inside {
614 loc = Location::Inside;
615 }
616 }
617 let starting_loc = loc;
618
619 let mut i = 0usize;
620 while i <= high_i {
621 prev = loc;
622 let crossing_prev = crossing_loc;
623
624 self.get_next_location(path, &mut loc, &mut i, high_i);
625
626 if i > high_i {
627 break;
628 }
629 let mut ip = Point64::new(0, 0);
630 let mut ip2 = Point64::new(0, 0);
631 let prev_pt = if i > 0 { path[i - 1] } else { path[high_i] };
632
633 crossing_loc = loc;
634 if !get_intersection(
635 &self.rect_as_path.clone(),
636 path[i],
637 prev_pt,
638 &mut crossing_loc,
639 &mut ip,
640 ) {
641 if crossing_prev == Location::Inside {
643 let is_clockw = is_clockwise_dir(prev, loc, &prev_pt, &path[i], &self.rect_mp);
644 let mut p = prev;
645 loop {
646 self.start_locs.push(p);
647 p = get_adjacent_location(p, is_clockw);
648 if p == loc {
649 break;
650 }
651 }
652 crossing_loc = crossing_prev; } else if prev != Location::Inside && prev != loc {
654 let is_clockw = is_clockwise_dir(prev, loc, &prev_pt, &path[i], &self.rect_mp);
655 let mut p = prev;
656 loop {
657 self.add_corner_loc(&mut p, is_clockw);
658 if p == loc {
659 break;
660 }
661 }
662 }
663 i += 1;
664 continue;
665 }
666
667 if loc == Location::Inside {
670 if first_cross == Location::Inside {
672 first_cross = crossing_loc;
673 self.start_locs.push(prev);
674 } else if prev != crossing_loc {
675 let is_clockw =
676 is_clockwise_dir(prev, crossing_loc, &prev_pt, &path[i], &self.rect_mp);
677 let mut p = prev;
678 loop {
679 self.add_corner_loc(&mut p, is_clockw);
680 if p == crossing_loc {
681 break;
682 }
683 }
684 }
685 } else if prev != Location::Inside {
686 loc = prev;
688 let rect_as_path = self.rect_as_path.clone();
689 get_intersection(&rect_as_path, prev_pt, path[i], &mut loc, &mut ip2);
690
691 if crossing_prev != Location::Inside && crossing_prev != loc {
692 self.add_corner_prev_curr(crossing_prev, loc);
693 }
694
695 if first_cross == Location::Inside {
696 first_cross = loc;
697 self.start_locs.push(prev);
698 }
699
700 loc = crossing_loc;
701 self.add(ip2, false);
702 if ip == ip2 {
703 get_location(&self.rect, &path[i], &mut loc);
705 self.add_corner_prev_curr(crossing_loc, loc);
706 crossing_loc = loc;
707 continue;
708 }
709 } else {
710 loc = crossing_loc;
712 if first_cross == Location::Inside {
713 first_cross = crossing_loc;
714 }
715 }
716
717 self.add(ip, false);
718 } if first_cross == Location::Inside {
721 if starting_loc != Location::Inside {
723 if self.path_bounds.contains_point(&self.rect_mp)
725 && path1_contains_path2(path, &self.rect_as_path)
726 {
727 let is_clockwise_path = start_locs_are_clockwise(&self.start_locs);
728 for j in 0..4usize {
729 let k = if is_clockwise_path { j } else { 3 - j };
730 let pt = self.rect_as_path[k];
731 self.add(pt, false);
732 let results_0 = self.results[0].unwrap();
733 self.add_to_edge(k * 2, results_0);
734 }
735 }
736 }
737 } else if loc != Location::Inside && (loc != first_cross || self.start_locs.len() > 2) {
738 if !self.start_locs.is_empty() {
739 let mut p = loc;
740 let start_locs_clone = self.start_locs.clone();
741 for &loc2 in &start_locs_clone {
742 if p == loc2 {
743 continue;
744 }
745 let hcw = heading_clockwise(p, loc2);
748 self.add_corner_loc(&mut p, hcw);
749 p = loc2;
750 }
751 loc = p;
752 }
753 if loc != first_cross {
754 let hcw = heading_clockwise(loc, first_cross);
757 self.add_corner_loc(&mut loc, hcw);
758 }
759 }
760 }
761
762 fn check_edges(&mut self) {
765 for i in 0..self.results.len() {
766 let mut op_idx = match self.results[i] {
767 Some(idx) => idx,
768 None => continue,
769 };
770
771 let mut op2_idx = op_idx;
773 loop {
774 let prev_idx = self.arena[op2_idx].prev;
775 let next_idx = self.arena[op2_idx].next;
776 let prev_pt = self.arena[prev_idx].pt;
777 let op2_pt = self.arena[op2_idx].pt;
778 let next_pt = self.arena[next_idx].pt;
779
780 if is_collinear(prev_pt, op2_pt, next_pt) {
781 if op2_idx == op_idx {
782 match self.unlink_op_back(op2_idx) {
783 Some(new_idx) => {
784 op2_idx = new_idx;
785 op_idx = self.arena[op2_idx].prev;
786 }
787 None => {
788 op2_idx = usize::MAX; break;
790 }
791 }
792 } else {
793 match self.unlink_op_back(op2_idx) {
794 Some(new_idx) => op2_idx = new_idx,
795 None => {
796 op2_idx = usize::MAX;
797 break;
798 }
799 }
800 }
801 } else {
802 op2_idx = self.arena[op2_idx].next;
803 }
804
805 if op2_idx == op_idx {
806 break;
807 }
808 }
809
810 if op2_idx == usize::MAX {
811 self.results[i] = None;
812 continue;
813 }
814 self.results[i] = Some(op_idx);
815
816 let prev_idx = self.arena[op_idx].prev;
818 let mut edge_set1 = get_edges_for_pt(&self.arena[prev_idx].pt, &self.rect);
819 let mut op2_idx = op_idx;
820 loop {
821 let edge_set2 = get_edges_for_pt(&self.arena[op2_idx].pt, &self.rect);
822 if edge_set2 != 0 && self.arena[op2_idx].edge_idx.is_none() {
823 let combined_set = edge_set1 & edge_set2;
824 for j in 0..4i32 {
825 if combined_set & (1 << j) != 0 {
826 let prev_idx = self.arena[op2_idx].prev;
827 let prev_pt = self.arena[prev_idx].pt;
828 let op2_pt = self.arena[op2_idx].pt;
829 if is_heading_clockwise(&prev_pt, &op2_pt, j) {
830 self.add_to_edge(j as usize * 2, op2_idx);
831 } else {
832 self.add_to_edge(j as usize * 2 + 1, op2_idx);
833 }
834 }
835 }
836 }
837 edge_set1 = edge_set2;
838 op2_idx = self.arena[op2_idx].next;
839
840 if op2_idx == op_idx {
841 break;
842 }
843 }
844 }
845 }
846
847 fn tidy_edges(&mut self, idx: usize, cw_idx: usize, ccw_idx: usize) {
850 if self.edges[ccw_idx].is_empty() {
851 return;
852 }
853
854 let is_horz = idx == 1 || idx == 3;
855 let cw_is_toward_larger = idx == 1 || idx == 2;
856 let mut i = 0usize;
857 let mut j = 0usize;
858
859 while i < self.edges[cw_idx].len() {
860 let p1_root = match self.edges[cw_idx][i] {
861 Some(idx) => idx,
862 None => {
863 i += 1;
864 j = 0;
865 continue;
866 }
867 };
868
869 if self.arena[p1_root].next == self.arena[p1_root].prev {
871 self.edges[cw_idx][i] = None;
872 i += 1;
873 j = 0;
874 continue;
875 }
876
877 let j_lim = self.edges[ccw_idx].len();
878 while j < j_lim {
879 match self.edges[ccw_idx][j] {
880 Some(idx) if self.arena[idx].next != self.arena[idx].prev => break,
881 _ => j += 1,
882 }
883 }
884
885 if j == j_lim {
886 i += 1;
887 j = 0;
888 continue;
889 }
890
891 let p2_root = self.edges[ccw_idx][j].unwrap();
892
893 let (p1, p1a, p2, p2a);
894 if cw_is_toward_larger {
895 p1 = self.arena[p1_root].prev;
896 p1a = p1_root;
897 p2 = p2_root;
898 p2a = self.arena[p2_root].prev;
899 } else {
900 p1 = p1_root;
901 p1a = self.arena[p1_root].prev;
902 p2 = self.arena[p2_root].prev;
903 p2a = p2_root;
904 }
905
906 let p1_pt = self.arena[p1].pt;
907 let p1a_pt = self.arena[p1a].pt;
908 let p2_pt = self.arena[p2].pt;
909 let p2a_pt = self.arena[p2a].pt;
910
911 if (is_horz && !has_horz_overlap(&p1_pt, &p1a_pt, &p2_pt, &p2a_pt))
912 || (!is_horz && !has_vert_overlap(&p1_pt, &p1a_pt, &p2_pt, &p2a_pt))
913 {
914 j += 1;
915 continue;
916 }
917
918 let is_rejoining = self.arena[p1_root].owner_idx != self.arena[p2_root].owner_idx;
920
921 if is_rejoining {
922 let p2_owner = self.arena[p2].owner_idx;
923 let p1_owner = self.arena[p1].owner_idx;
924 self.results[p2_owner] = None;
925 self.set_new_owner(p2, p1_owner);
926 }
927
928 if cw_is_toward_larger {
930 self.arena[p1].next = p2;
931 self.arena[p2].prev = p1;
932 self.arena[p1a].prev = p2a;
933 self.arena[p2a].next = p1a;
934 } else {
935 self.arena[p1].prev = p2;
936 self.arena[p2].next = p1;
937 self.arena[p1a].next = p2a;
938 self.arena[p2a].prev = p1a;
939 }
940
941 if !is_rejoining {
942 let new_idx = self.results.len();
943 self.results.push(Some(p1a));
944 self.set_new_owner(p1a, new_idx);
945 }
946
947 let (op, op2);
948 if cw_is_toward_larger {
949 op = p2;
950 op2 = p1a;
951 } else {
952 op = p1;
953 op2 = p2a;
954 }
955
956 let op_owner = self.arena[op].owner_idx;
957 let op2_owner = self.arena[op2].owner_idx;
958 self.results[op_owner] = Some(op);
959 self.results[op2_owner] = Some(op2);
960
961 let op_is_larger;
963 let op2_is_larger;
964 if is_horz {
965 let op_prev = self.arena[op].prev;
966 let op2_prev = self.arena[op2].prev;
967 op_is_larger = self.arena[op].pt.x > self.arena[op_prev].pt.x;
968 op2_is_larger = self.arena[op2].pt.x > self.arena[op2_prev].pt.x;
969 } else {
970 let op_prev = self.arena[op].prev;
971 let op2_prev = self.arena[op2].prev;
972 op_is_larger = self.arena[op].pt.y > self.arena[op_prev].pt.y;
973 op2_is_larger = self.arena[op2].pt.y > self.arena[op2_prev].pt.y;
974 }
975
976 let op_next = self.arena[op].next;
977 let op_prev = self.arena[op].prev;
978 let op2_next = self.arena[op2].next;
979 let op2_prev = self.arena[op2].prev;
980
981 if (op_next == op_prev) || (self.arena[op].pt == self.arena[op_prev].pt) {
982 if op2_is_larger == cw_is_toward_larger {
983 self.edges[cw_idx][i] = Some(op2);
984 self.edges[ccw_idx][j] = None;
985 j += 1;
986 } else {
987 self.edges[ccw_idx][j] = Some(op2);
988 self.edges[cw_idx][i] = None;
989 i += 1;
990 }
991 } else if (op2_next == op2_prev) || (self.arena[op2].pt == self.arena[op2_prev].pt) {
992 if op_is_larger == cw_is_toward_larger {
993 self.edges[cw_idx][i] = Some(op);
994 self.edges[ccw_idx][j] = None;
995 j += 1;
996 } else {
997 self.edges[ccw_idx][j] = Some(op);
998 self.edges[cw_idx][i] = None;
999 i += 1;
1000 }
1001 } else if op_is_larger == op2_is_larger {
1002 if op_is_larger == cw_is_toward_larger {
1003 self.edges[cw_idx][i] = Some(op);
1004 self.uncouple_edge(op2);
1005 self.add_to_edge(cw_idx, op2);
1006 self.edges[ccw_idx][j] = None;
1007 j += 1;
1008 } else {
1009 self.edges[cw_idx][i] = None;
1010 i += 1;
1011 self.edges[ccw_idx][j] = Some(op2);
1012 self.uncouple_edge(op);
1013 self.add_to_edge(ccw_idx, op);
1014 j = 0;
1015 }
1016 } else {
1017 if op_is_larger == cw_is_toward_larger {
1018 self.edges[cw_idx][i] = Some(op);
1019 } else {
1020 self.edges[ccw_idx][j] = Some(op);
1021 }
1022 if op2_is_larger == cw_is_toward_larger {
1023 self.edges[cw_idx][i] = Some(op2);
1024 } else {
1025 self.edges[ccw_idx][j] = Some(op2);
1026 }
1027 }
1028 }
1029 }
1030
1031 fn get_path(&mut self, op_idx_ref: &mut Option<usize>) -> Path64 {
1034 let op_start = match *op_idx_ref {
1035 Some(idx) => idx,
1036 None => return Path64::new(),
1037 };
1038
1039 if self.arena[op_start].next == self.arena[op_start].prev {
1041 *op_idx_ref = None;
1042 return Path64::new();
1043 }
1044
1045 let mut op_idx = op_start;
1047 let mut op2_idx = self.arena[op_start].next;
1048 while op2_idx != op_idx {
1049 let prev_idx = self.arena[op2_idx].prev;
1050 let next_idx = self.arena[op2_idx].next;
1051 let prev_pt = self.arena[prev_idx].pt;
1052 let op2_pt = self.arena[op2_idx].pt;
1053 let next_pt = self.arena[next_idx].pt;
1054
1055 if is_collinear(prev_pt, op2_pt, next_pt) {
1056 op_idx = self.arena[op2_idx].prev;
1057 match self.unlink_op(op2_idx) {
1058 Some(new_idx) => op2_idx = new_idx,
1059 None => {
1060 *op_idx_ref = None;
1061 return Path64::new();
1062 }
1063 }
1064 } else {
1065 op2_idx = self.arena[op2_idx].next;
1066 }
1067 }
1068
1069 *op_idx_ref = Some(op2_idx);
1070 if self.arena[op2_idx].next == self.arena[op2_idx].prev {
1071 *op_idx_ref = None;
1072 return Path64::new();
1073 }
1074
1075 let mut result = Path64::new();
1076 let start = op2_idx;
1077 result.push(self.arena[start].pt);
1078 let mut curr = self.arena[start].next;
1079 while curr != start {
1080 result.push(self.arena[curr].pt);
1081 curr = self.arena[curr].next;
1082 }
1083 result
1084 }
1085
1086 pub fn execute(&mut self, paths: &Paths64) -> Paths64 {
1089 let mut result = Paths64::new();
1090 if self.rect.is_empty() {
1091 return result;
1092 }
1093
1094 for path in paths {
1095 if path.len() < 3 {
1096 continue;
1097 }
1098 self.path_bounds = get_bounds_path(path);
1099 if !self.rect.intersects(&self.path_bounds) {
1100 continue;
1101 } else if self.rect.contains_rect(&self.path_bounds) {
1102 result.push(path.clone());
1103 continue;
1104 }
1105
1106 self.execute_internal(path);
1107 self.check_edges();
1108 for edge_i in 0..4usize {
1109 self.tidy_edges(edge_i, edge_i * 2, edge_i * 2 + 1);
1110 }
1111
1112 for ri in 0..self.results.len() {
1113 let mut op_ref = self.results[ri];
1114 let tmp = self.get_path(&mut op_ref);
1115 self.results[ri] = op_ref;
1116 if !tmp.is_empty() {
1117 result.push(tmp);
1118 }
1119 }
1120
1121 self.clear();
1123 }
1124 result
1125 }
1126}
1127
1128pub struct RectClipLines64 {
1136 rect: Rect64,
1137 rect_as_path: Path64,
1138 #[allow(dead_code)]
1139 rect_mp: Point64,
1140 arena: Vec<OutPt2>,
1141 results: Vec<Option<usize>>,
1142 start_locs: Vec<Location>,
1143}
1144
1145impl RectClipLines64 {
1146 pub fn new(rect: Rect64) -> Self {
1149 let rect_as_path = rect.as_path();
1150 let rect_mp = rect.mid_point();
1151 Self {
1152 rect,
1153 rect_as_path,
1154 rect_mp,
1155 arena: Vec::new(),
1156 results: Vec::new(),
1157 start_locs: Vec::new(),
1158 }
1159 }
1160
1161 fn clear(&mut self) {
1162 self.arena.clear();
1163 self.results.clear();
1164 self.start_locs.clear();
1165 }
1166
1167 fn add(&mut self, pt: Point64, start_new: bool) -> usize {
1169 let curr_idx = self.results.len();
1170 if curr_idx == 0 || start_new {
1171 let new_idx = self.arena.len();
1172 let mut op = OutPt2::new(pt);
1173 op.next = new_idx;
1174 op.prev = new_idx;
1175 self.arena.push(op);
1176 self.results.push(Some(new_idx));
1177 new_idx
1178 } else {
1179 let result_idx = curr_idx - 1;
1180 let prev_op_idx = self.results[result_idx].unwrap();
1181 if self.arena[prev_op_idx].pt == pt {
1182 return prev_op_idx;
1183 }
1184 let new_idx = self.arena.len();
1185 let mut op = OutPt2::new(pt);
1186 op.owner_idx = result_idx;
1187
1188 let prev_next = self.arena[prev_op_idx].next;
1189 op.next = prev_next;
1190 op.prev = prev_op_idx;
1191 self.arena.push(op);
1192
1193 self.arena[prev_next].prev = new_idx;
1194 self.arena[prev_op_idx].next = new_idx;
1195
1196 self.results[result_idx] = Some(new_idx);
1197 new_idx
1198 }
1199 }
1200
1201 fn get_next_location(
1203 &mut self,
1204 path: &Path64,
1205 loc: &mut Location,
1206 i: &mut usize,
1207 high_i: usize,
1208 ) {
1209 match *loc {
1210 Location::Left => {
1211 while *i <= high_i && path[*i].x <= self.rect.left {
1212 *i += 1;
1213 }
1214 if *i > high_i {
1215 return;
1216 }
1217 if path[*i].x >= self.rect.right {
1218 *loc = Location::Right;
1219 } else if path[*i].y <= self.rect.top {
1220 *loc = Location::Top;
1221 } else if path[*i].y >= self.rect.bottom {
1222 *loc = Location::Bottom;
1223 } else {
1224 *loc = Location::Inside;
1225 }
1226 }
1227 Location::Top => {
1228 while *i <= high_i && path[*i].y <= self.rect.top {
1229 *i += 1;
1230 }
1231 if *i > high_i {
1232 return;
1233 }
1234 if path[*i].y >= self.rect.bottom {
1235 *loc = Location::Bottom;
1236 } else if path[*i].x <= self.rect.left {
1237 *loc = Location::Left;
1238 } else if path[*i].x >= self.rect.right {
1239 *loc = Location::Right;
1240 } else {
1241 *loc = Location::Inside;
1242 }
1243 }
1244 Location::Right => {
1245 while *i <= high_i && path[*i].x >= self.rect.right {
1246 *i += 1;
1247 }
1248 if *i > high_i {
1249 return;
1250 }
1251 if path[*i].x <= self.rect.left {
1252 *loc = Location::Left;
1253 } else if path[*i].y <= self.rect.top {
1254 *loc = Location::Top;
1255 } else if path[*i].y >= self.rect.bottom {
1256 *loc = Location::Bottom;
1257 } else {
1258 *loc = Location::Inside;
1259 }
1260 }
1261 Location::Bottom => {
1262 while *i <= high_i && path[*i].y >= self.rect.bottom {
1263 *i += 1;
1264 }
1265 if *i > high_i {
1266 return;
1267 }
1268 if path[*i].y <= self.rect.top {
1269 *loc = Location::Top;
1270 } else if path[*i].x <= self.rect.left {
1271 *loc = Location::Left;
1272 } else if path[*i].x >= self.rect.right {
1273 *loc = Location::Right;
1274 } else {
1275 *loc = Location::Inside;
1276 }
1277 }
1278 Location::Inside => {
1279 while *i <= high_i {
1280 if path[*i].x < self.rect.left {
1281 *loc = Location::Left;
1282 } else if path[*i].x > self.rect.right {
1283 *loc = Location::Right;
1284 } else if path[*i].y > self.rect.bottom {
1285 *loc = Location::Bottom;
1286 } else if path[*i].y < self.rect.top {
1287 *loc = Location::Top;
1288 } else {
1289 let pt = path[*i];
1290 self.add(pt, false);
1291 *i += 1;
1292 continue;
1293 }
1294 break;
1295 }
1296 }
1297 }
1298 }
1299
1300 fn execute_internal(&mut self, path: &Path64) {
1303 if self.rect.is_empty() || path.len() < 2 {
1304 return;
1305 }
1306
1307 self.clear();
1308
1309 let high_i = path.len() - 1;
1310 let mut i = 1usize;
1311 let mut prev = Location::Inside;
1312 let mut loc = Location::Inside;
1313
1314 if !get_location(&self.rect, &path[0], &mut loc) {
1315 while i <= high_i && !get_location(&self.rect, &path[i], &mut prev) {
1316 i += 1;
1317 }
1318 if i > high_i {
1319 for pt in path {
1321 self.add(*pt, false);
1322 }
1323 return;
1324 }
1325 if prev == Location::Inside {
1326 loc = Location::Inside;
1327 }
1328 i = 1;
1329 }
1330 if loc == Location::Inside {
1331 self.add(path[0], false);
1332 }
1333
1334 while i <= high_i {
1335 prev = loc;
1336 self.get_next_location(path, &mut loc, &mut i, high_i);
1337 if i > high_i {
1338 break;
1339 }
1340 let mut ip = Point64::new(0, 0);
1341 let mut ip2 = Point64::new(0, 0);
1342 let prev_pt = path[i - 1];
1343
1344 let mut crossing_loc = loc;
1345 if !get_intersection(
1346 &self.rect_as_path.clone(),
1347 path[i],
1348 prev_pt,
1349 &mut crossing_loc,
1350 &mut ip,
1351 ) {
1352 i += 1;
1353 continue;
1354 }
1355
1356 if loc == Location::Inside {
1357 self.add(ip, true);
1359 } else if prev != Location::Inside {
1360 crossing_loc = prev;
1362 let rect_as_path = self.rect_as_path.clone();
1363 get_intersection(&rect_as_path, prev_pt, path[i], &mut crossing_loc, &mut ip2);
1364 self.add(ip2, true);
1365 self.add(ip, false);
1366 } else {
1367 self.add(ip, false);
1369 }
1370 }
1371 }
1372
1373 fn get_path(&self, op_idx_ref: &mut Option<usize>) -> Path64 {
1376 let op_start = match *op_idx_ref {
1377 Some(idx) => idx,
1378 None => return Path64::new(),
1379 };
1380
1381 if self.arena[op_start].next == op_start {
1382 return Path64::new();
1383 }
1384
1385 let start = self.arena[op_start].next;
1387 let mut result = Path64::new();
1388 result.push(self.arena[start].pt);
1389 let mut op2 = self.arena[start].next;
1390 while op2 != start {
1391 result.push(self.arena[op2].pt);
1392 op2 = self.arena[op2].next;
1393 }
1394 result
1395 }
1396
1397 pub fn execute(&mut self, paths: &Paths64) -> Paths64 {
1400 let mut result = Paths64::new();
1401 if self.rect.is_empty() {
1402 return result;
1403 }
1404
1405 for path in paths {
1406 let path_rec = get_bounds_path(path);
1407 if !self.rect.intersects(&path_rec) {
1408 continue;
1409 }
1410
1411 self.execute_internal(path);
1412
1413 for ri in 0..self.results.len() {
1414 let mut op_ref = self.results[ri];
1415 let tmp = self.get_path(&mut op_ref);
1416 if !tmp.is_empty() {
1417 result.push(tmp);
1418 }
1419 }
1420 self.clear();
1421 }
1422 result
1423 }
1424}
1425
1426#[cfg(test)]
1428#[path = "rectclip_tests.rs"]
1429mod tests;