geo_booleanop/boolean/
compute_fields.rs1use super::helper::Float;
2use super::sweep_event::{EdgeType, ResultTransition, SweepEvent};
3use super::Operation;
4use std::rc::Rc;
5
6pub fn compute_fields<F>(event: &Rc<SweepEvent<F>>, maybe_prev: Option<&Rc<SweepEvent<F>>>, operation: Operation)
7where
8 F: Float,
9{
10 if let Some(prev) = maybe_prev {
11 if event.is_subject == prev.is_subject {
12 event.set_in_out(!prev.is_in_out(), prev.is_other_in_out());
13 } else if prev.is_vertical() {
14 event.set_in_out(!prev.is_other_in_out(), !prev.is_in_out());
15 } else {
16 event.set_in_out(!prev.is_other_in_out(), prev.is_in_out());
17 }
18
19 if prev.is_in_result() && !prev.is_vertical() {
23 event.set_prev_in_result(prev);
24 } else if let Some(prev_of_prev) = prev.get_prev_in_result() {
25 event.set_prev_in_result(&prev_of_prev);
26 } else {
27 event.unset_prev_in_result();
30 }
31 } else {
32 event.set_in_out(false, true);
33 event.unset_prev_in_result();
36 }
37
38 let in_result = in_result(event, operation);
41 let result_transition = if !in_result {
42 ResultTransition::None
43 } else {
44 determine_result_transition(&event, operation)
45 };
46 event.set_result_transition(result_transition);
47
48 #[cfg(feature = "debug-booleanop")]
49 {
50 println!(
51 "{{\"computeFields\": {{\"inOut\": {}, \"otherOut\": {}, \"resultTransition\": \"{:?}\", \"edgeType\": \"{:?}\"}}}}",
52 event.is_in_out(),
53 event.is_other_in_out(),
54 event.get_result_transition(),
55 event.get_edge_type(),
56 );
57 }
58}
59
60fn in_result<F>(event: &SweepEvent<F>, operation: Operation) -> bool
61where
62 F: Float,
63{
64 match event.get_edge_type() {
65 EdgeType::Normal => match operation {
66 Operation::Intersection => !event.is_other_in_out(),
67 Operation::Union => event.is_other_in_out(),
68 Operation::Difference => {
69 (event.is_subject && event.is_other_in_out()) || (!event.is_subject && !event.is_other_in_out())
70 }
71 Operation::Xor => true,
72 },
73 EdgeType::SameTransition => operation == Operation::Intersection || operation == Operation::Union,
74 EdgeType::DifferentTransition => operation == Operation::Difference,
75 EdgeType::NonContributing => false,
76 }
77}
78
79fn determine_result_transition<F>(event: &SweepEvent<F>, operation: Operation) -> ResultTransition
80where
81 F: Float,
82{
83 let this_in = !event.is_in_out();
84 let that_in = !event.is_other_in_out();
85 let is_in = match operation {
86 Operation::Intersection => this_in && that_in,
87 Operation::Union => this_in || that_in,
88 Operation::Xor => this_in ^ that_in,
89 Operation::Difference =>
90 {
92 if event.is_subject {
93 this_in && !that_in
94 } else {
95 that_in && !this_in
96 }
97 }
98 };
99 if is_in {
100 ResultTransition::OutIn
101 } else {
102 ResultTransition::InOut
103 }
104}