1use crate::core::*;
8use crate::engine::*;
9use crate::engine_fns::*;
10
11#[derive(Debug, Clone)]
19pub struct PolyPath64 {
20 parent: Option<usize>, children: Vec<usize>, pub(crate) polygon: Path64,
23}
24
25impl PolyPath64 {
26 pub fn new() -> Self {
27 Self {
28 parent: None,
29 children: Vec::new(),
30 polygon: Path64::new(),
31 }
32 }
33
34 pub fn with_parent(parent_idx: usize) -> Self {
35 Self {
36 parent: Some(parent_idx),
37 children: Vec::new(),
38 polygon: Path64::new(),
39 }
40 }
41
42 pub fn with_path(parent_idx: usize, path: Path64) -> Self {
43 Self {
44 parent: Some(parent_idx),
45 children: Vec::new(),
46 polygon: path,
47 }
48 }
49
50 pub fn polygon(&self) -> &Path64 {
51 &self.polygon
52 }
53
54 pub fn count(&self) -> usize {
55 self.children.len()
56 }
57
58 pub fn parent(&self) -> Option<usize> {
59 self.parent
60 }
61
62 pub fn children(&self) -> &[usize] {
63 &self.children
64 }
65}
66
67impl Default for PolyPath64 {
68 fn default() -> Self {
69 Self::new()
70 }
71}
72
73pub struct PolyTree64 {
76 pub nodes: Vec<PolyPath64>,
77}
78
79impl PolyTree64 {
80 pub fn new() -> Self {
81 let root = PolyPath64::new();
83 Self { nodes: vec![root] }
84 }
85
86 pub fn add_child(&mut self, parent_idx: usize, path: Path64) -> usize {
88 let child_idx = self.nodes.len();
89 self.nodes.push(PolyPath64::with_path(parent_idx, path));
90 self.nodes[parent_idx].children.push(child_idx);
91 child_idx
92 }
93
94 pub fn root(&self) -> &PolyPath64 {
96 &self.nodes[0]
97 }
98
99 pub fn clear(&mut self) {
101 self.nodes.clear();
102 self.nodes.push(PolyPath64::new());
103 }
104
105 pub fn level(&self, node_idx: usize) -> u32 {
107 let mut result = 0u32;
108 let mut p = self.nodes[node_idx].parent;
109 while let Some(parent_idx) = p {
110 result += 1;
111 p = self.nodes[parent_idx].parent;
112 }
113 result
114 }
115
116 pub fn is_hole(&self, node_idx: usize) -> bool {
118 let lvl = self.level(node_idx);
119 lvl > 0 && (lvl & 1) == 0
120 }
121
122 pub fn area_of(&self, node_idx: usize) -> f64 {
124 let mut result = area(&self.nodes[node_idx].polygon);
125 for &child_idx in &self.nodes[node_idx].children {
126 result += self.area_of(child_idx);
127 }
128 result
129 }
130}
131
132impl Default for PolyTree64 {
133 fn default() -> Self {
134 Self::new()
135 }
136}
137
138#[derive(Debug, Clone)]
141pub struct PolyPathD {
142 parent: Option<usize>,
143 children: Vec<usize>,
144 polygon: PathD,
145 pub(crate) scale: f64,
146}
147
148impl PolyPathD {
149 pub fn new() -> Self {
150 Self {
151 parent: None,
152 children: Vec::new(),
153 polygon: PathD::new(),
154 scale: 1.0,
155 }
156 }
157
158 pub fn with_parent(parent_idx: usize, scale: f64) -> Self {
159 Self {
160 parent: Some(parent_idx),
161 children: Vec::new(),
162 polygon: PathD::new(),
163 scale,
164 }
165 }
166
167 pub fn polygon(&self) -> &PathD {
168 &self.polygon
169 }
170
171 pub fn set_polygon(&mut self, polygon: PathD) {
172 self.polygon = polygon;
173 }
174
175 pub fn count(&self) -> usize {
176 self.children.len()
177 }
178
179 pub fn scale(&self) -> f64 {
180 self.scale
181 }
182
183 pub fn set_scale(&mut self, scale: f64) {
184 self.scale = scale;
185 }
186
187 pub fn parent(&self) -> Option<usize> {
188 self.parent
189 }
190
191 pub fn children(&self) -> &[usize] {
192 &self.children
193 }
194}
195
196impl Default for PolyPathD {
197 fn default() -> Self {
198 Self::new()
199 }
200}
201
202pub struct PolyTreeD {
204 pub nodes: Vec<PolyPathD>,
205}
206
207impl PolyTreeD {
208 pub fn new() -> Self {
209 Self {
210 nodes: vec![PolyPathD::new()],
211 }
212 }
213
214 pub fn add_child(&mut self, parent_idx: usize, path: PathD) -> usize {
215 let scale = self.nodes[parent_idx].scale;
216 let child_idx = self.nodes.len();
217 let mut node = PolyPathD::with_parent(parent_idx, scale);
218 node.polygon = path;
219 self.nodes.push(node);
220 self.nodes[parent_idx].children.push(child_idx);
221 child_idx
222 }
223
224 pub fn add_child_from_path64(&mut self, parent_idx: usize, path: &Path64) -> usize {
225 let scale = self.nodes[parent_idx].scale;
226 let child_idx = self.nodes.len();
227 let mut node = PolyPathD::with_parent(parent_idx, scale);
228 let mut error_code = 0;
229 node.polygon = scale_path(path, scale, scale, &mut error_code);
230 self.nodes.push(node);
231 self.nodes[parent_idx].children.push(child_idx);
232 child_idx
233 }
234
235 pub fn root(&self) -> &PolyPathD {
236 &self.nodes[0]
237 }
238
239 pub fn clear(&mut self) {
240 self.nodes.clear();
241 let mut root = PolyPathD::new();
242 root.scale = 1.0;
243 self.nodes.push(root);
244 }
245
246 pub fn set_scale(&mut self, scale: f64) {
247 self.nodes[0].scale = scale;
248 }
249
250 pub fn level(&self, node_idx: usize) -> u32 {
251 let mut result = 0u32;
252 let mut p = self.nodes[node_idx].parent;
253 while let Some(parent_idx) = p {
254 result += 1;
255 p = self.nodes[parent_idx].parent;
256 }
257 result
258 }
259
260 pub fn is_hole(&self, node_idx: usize) -> bool {
261 let lvl = self.level(node_idx);
262 lvl > 0 && (lvl & 1) == 0
263 }
264}
265
266impl Default for PolyTreeD {
267 fn default() -> Self {
268 Self::new()
269 }
270}
271
272pub struct Clipper64 {
280 pub base: ClipperBase,
281}
282
283impl Clipper64 {
284 pub fn new() -> Self {
285 Self {
286 base: ClipperBase::new(),
287 }
288 }
289
290 pub fn add_subject(&mut self, subjects: &Paths64) {
292 self.base.add_paths(subjects, PathType::Subject, false);
293 }
294
295 pub fn add_open_subject(&mut self, open_subjects: &Paths64) {
297 self.base.add_paths(open_subjects, PathType::Subject, true);
298 }
299
300 pub fn add_clip(&mut self, clips: &Paths64) {
302 self.base.add_paths(clips, PathType::Clip, false);
303 }
304
305 pub fn error_code(&self) -> i32 {
307 self.base.error_code
308 }
309
310 pub fn set_preserve_collinear(&mut self, val: bool) {
312 self.base.preserve_collinear = val;
313 }
314
315 pub fn preserve_collinear(&self) -> bool {
316 self.base.preserve_collinear
317 }
318
319 pub fn set_reverse_solution(&mut self, val: bool) {
321 self.base.reverse_solution = val;
322 }
323
324 pub fn reverse_solution(&self) -> bool {
325 self.base.reverse_solution
326 }
327
328 pub fn clear(&mut self) {
330 self.base.clear();
331 }
332
333 pub fn execute(
336 &mut self,
337 clip_type: ClipType,
338 fill_rule: FillRule,
339 solution_closed: &mut Paths64,
340 mut solution_open: Option<&mut Paths64>,
341 ) -> bool {
342 solution_closed.clear();
343 if let Some(ref mut open) = solution_open {
344 open.clear();
345 }
346
347 if self.base.execute_internal(clip_type, fill_rule, false) {
348 self.build_paths64(solution_closed, solution_open);
349 }
350 self.base.clean_up();
351 self.base.succeeded
352 }
353
354 pub fn execute_tree(
357 &mut self,
358 clip_type: ClipType,
359 fill_rule: FillRule,
360 polytree: &mut PolyTree64,
361 open_paths: &mut Paths64,
362 ) -> bool {
363 polytree.clear();
364 open_paths.clear();
365
366 if self.base.execute_internal(clip_type, fill_rule, true) {
367 self.build_tree64(polytree, open_paths);
368 }
369 self.base.clean_up();
370 self.base.succeeded
371 }
372
373 fn build_paths64(
376 &mut self,
377 solution_closed: &mut Paths64,
378 solution_open: Option<&mut Paths64>,
379 ) {
380 solution_closed.clear();
381 solution_closed.reserve(self.base.outrec_list.len());
382
383 let mut open_paths = Vec::new();
384
385 let mut i = 0;
386 while i < self.base.outrec_list.len() {
387 if self.base.outrec_list[i].pts.is_none() {
388 i += 1;
389 continue;
390 }
391
392 if self.base.outrec_list[i].is_open {
393 let op = self.base.outrec_list[i].pts.unwrap();
394 if let Some(path) = build_path64_from_outpt(
395 op,
396 self.base.reverse_solution,
397 true,
398 &self.base.outpt_arena,
399 ) {
400 open_paths.push(path);
401 }
402 } else {
403 self.base.clean_collinear(i);
404 if self.base.outrec_list[i].pts.is_some() {
405 let op = self.base.outrec_list[i].pts.unwrap();
406 if let Some(path) = build_path64_from_outpt(
407 op,
408 self.base.reverse_solution,
409 false,
410 &self.base.outpt_arena,
411 ) {
412 solution_closed.push(path);
413 }
414 }
415 }
416 i += 1;
417 }
418
419 if let Some(open) = solution_open {
420 *open = open_paths;
421 }
422 }
423
424 fn build_tree64(&mut self, polytree: &mut PolyTree64, open_paths: &mut Paths64) {
427 polytree.clear();
428 open_paths.clear();
429 if self.base.has_open_paths {
430 open_paths.reserve(self.base.outrec_list.len());
431 }
432
433 let mut i = 0;
434 while i < self.base.outrec_list.len() {
435 if self.base.outrec_list[i].pts.is_none() {
436 i += 1;
437 continue;
438 }
439
440 if self.base.outrec_list[i].is_open {
441 let op = self.base.outrec_list[i].pts.unwrap();
442 if let Some(path) = build_path64_from_outpt(
443 op,
444 self.base.reverse_solution,
445 true,
446 &self.base.outpt_arena,
447 ) {
448 open_paths.push(path);
449 }
450 i += 1;
451 continue;
452 }
453
454 if self.base.check_bounds(i) {
455 self.base.recursive_check_owners(i, polytree);
456 }
457 i += 1;
458 }
459 }
460}
461
462impl Default for Clipper64 {
463 fn default() -> Self {
464 Self::new()
465 }
466}
467
468pub struct ClipperD {
471 pub base: ClipperBase,
472 scale: f64,
473 inv_scale: f64,
474}
475
476impl ClipperD {
477 pub fn new(precision: i32) -> Self {
478 let mut prec = precision;
479 let mut error_code = 0;
480 check_precision_range(&mut prec, &mut error_code);
481
482 let scale = 2.0f64.powi(((10.0f64.powi(prec)).log2().floor() as i32) + 1);
484 let inv_scale = 1.0 / scale;
485
486 let mut base = ClipperBase::new();
487 base.error_code = error_code;
488
489 Self {
490 base,
491 scale,
492 inv_scale,
493 }
494 }
495
496 pub fn scale(&self) -> f64 {
497 self.scale
498 }
499
500 pub fn inv_scale(&self) -> f64 {
501 self.inv_scale
502 }
503
504 pub fn add_subject(&mut self, subjects: &PathsD) {
506 let scaled: Paths64 =
507 scale_paths(subjects, self.scale, self.scale, &mut self.base.error_code);
508 self.base.add_paths(&scaled, PathType::Subject, false);
509 }
510
511 pub fn add_open_subject(&mut self, open_subjects: &PathsD) {
513 let scaled: Paths64 = scale_paths(
514 open_subjects,
515 self.scale,
516 self.scale,
517 &mut self.base.error_code,
518 );
519 self.base.add_paths(&scaled, PathType::Subject, true);
520 }
521
522 pub fn add_clip(&mut self, clips: &PathsD) {
524 let scaled: Paths64 = scale_paths(clips, self.scale, self.scale, &mut self.base.error_code);
525 self.base.add_paths(&scaled, PathType::Clip, false);
526 }
527
528 pub fn error_code(&self) -> i32 {
529 self.base.error_code
530 }
531
532 pub fn set_preserve_collinear(&mut self, val: bool) {
533 self.base.preserve_collinear = val;
534 }
535
536 pub fn preserve_collinear(&self) -> bool {
537 self.base.preserve_collinear
538 }
539
540 pub fn set_reverse_solution(&mut self, val: bool) {
541 self.base.reverse_solution = val;
542 }
543
544 pub fn reverse_solution(&self) -> bool {
545 self.base.reverse_solution
546 }
547
548 pub fn clear(&mut self) {
549 self.base.clear();
550 }
551
552 pub fn execute(
555 &mut self,
556 clip_type: ClipType,
557 fill_rule: FillRule,
558 solution_closed: &mut PathsD,
559 mut solution_open: Option<&mut PathsD>,
560 ) -> bool {
561 solution_closed.clear();
562 if let Some(ref mut open) = solution_open {
563 open.clear();
564 }
565
566 if self.base.execute_internal(clip_type, fill_rule, false) {
567 self.build_paths_d(solution_closed, solution_open);
568 }
569 self.base.clean_up();
570 self.base.succeeded
571 }
572
573 pub fn execute_tree(
575 &mut self,
576 clip_type: ClipType,
577 fill_rule: FillRule,
578 polytree: &mut PolyTreeD,
579 open_paths: &mut PathsD,
580 ) -> bool {
581 polytree.clear();
582 open_paths.clear();
583
584 if self.base.execute_internal(clip_type, fill_rule, true) {
585 self.build_tree_d(polytree, open_paths);
586 }
587 self.base.clean_up();
588 self.base.succeeded
589 }
590
591 fn build_paths_d(&mut self, solution_closed: &mut PathsD, solution_open: Option<&mut PathsD>) {
594 solution_closed.clear();
595 solution_closed.reserve(self.base.outrec_list.len());
596
597 let mut open_paths = Vec::new();
598
599 let mut i = 0;
600 while i < self.base.outrec_list.len() {
601 if self.base.outrec_list[i].pts.is_none() {
602 i += 1;
603 continue;
604 }
605
606 if self.base.outrec_list[i].is_open {
607 let op = self.base.outrec_list[i].pts.unwrap();
608 if let Some(path) = build_path_d_from_outpt(
609 op,
610 self.base.reverse_solution,
611 true,
612 &self.base.outpt_arena,
613 self.inv_scale,
614 ) {
615 open_paths.push(path);
616 }
617 } else {
618 self.base.clean_collinear(i);
619 if self.base.outrec_list[i].pts.is_some() {
620 let op = self.base.outrec_list[i].pts.unwrap();
621 if let Some(path) = build_path_d_from_outpt(
622 op,
623 self.base.reverse_solution,
624 false,
625 &self.base.outpt_arena,
626 self.inv_scale,
627 ) {
628 solution_closed.push(path);
629 }
630 }
631 }
632 i += 1;
633 }
634
635 if let Some(open) = solution_open {
636 *open = open_paths;
637 }
638 }
639
640 fn build_tree_d(&mut self, polytree: &mut PolyTreeD, open_paths: &mut PathsD) {
643 polytree.clear();
644 polytree.set_scale(self.inv_scale);
645 open_paths.clear();
646 if self.base.has_open_paths {
647 open_paths.reserve(self.base.outrec_list.len());
648 }
649
650 let mut polytree64 = PolyTree64::new();
653
654 let mut i = 0;
655 while i < self.base.outrec_list.len() {
656 if self.base.outrec_list[i].pts.is_none() {
657 i += 1;
658 continue;
659 }
660
661 if self.base.outrec_list[i].is_open {
662 let op = self.base.outrec_list[i].pts.unwrap();
663 if let Some(path) = build_path_d_from_outpt(
664 op,
665 self.base.reverse_solution,
666 true,
667 &self.base.outpt_arena,
668 self.inv_scale,
669 ) {
670 open_paths.push(path);
671 }
672 i += 1;
673 continue;
674 }
675
676 if self.base.check_bounds(i) {
677 self.base.recursive_check_owners(i, &mut polytree64);
678 }
679 i += 1;
680 }
681
682 self.convert_polytree64_to_d(&polytree64, polytree);
684 }
685
686 fn convert_polytree64_to_d(&self, src: &PolyTree64, dst: &mut PolyTreeD) {
688 dst.clear();
689 dst.set_scale(self.inv_scale);
690 let root_children = src.nodes[0].children.clone();
692 for &child_idx in &root_children {
693 Self::convert_polypath64_node(src, child_idx, 0, dst);
694 }
695 }
696
697 fn convert_polypath64_node(
698 src: &PolyTree64,
699 src_idx: usize,
700 dst_parent: usize,
701 dst: &mut PolyTreeD,
702 ) {
703 let src_node = &src.nodes[src_idx];
704 let dst_idx = dst.add_child_from_path64(dst_parent, &src_node.polygon);
705 let children = src_node.children.clone();
706 for &child_idx in &children {
707 Self::convert_polypath64_node(src, child_idx, dst_idx, dst);
708 }
709 }
710}