geo/algorithm/bool_ops/
mod.rs1use geo_types::{MultiLineString, MultiPolygon};
2
3use crate::{CoordsIter, GeoFloat, GeoNum, Polygon};
4
5pub trait BooleanOps: Sized {
26 type Scalar: GeoNum;
27
28 fn boolean_op(&self, other: &Self, op: OpType) -> MultiPolygon<Self::Scalar>;
29 fn intersection(&self, other: &Self) -> MultiPolygon<Self::Scalar> {
30 self.boolean_op(other, OpType::Intersection)
31 }
32 fn union(&self, other: &Self) -> MultiPolygon<Self::Scalar> {
33 self.boolean_op(other, OpType::Union)
34 }
35 fn xor(&self, other: &Self) -> MultiPolygon<Self::Scalar> {
36 self.boolean_op(other, OpType::Xor)
37 }
38 fn difference(&self, other: &Self) -> MultiPolygon<Self::Scalar> {
39 self.boolean_op(other, OpType::Difference)
40 }
41
42 fn clip(
47 &self,
48 ls: &MultiLineString<Self::Scalar>,
49 invert: bool,
50 ) -> MultiLineString<Self::Scalar>;
51}
52
53#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
54pub enum OpType {
55 Intersection,
56 Union,
57 Difference,
58 Xor,
59}
60
61impl<T: GeoFloat> BooleanOps for Polygon<T> {
62 type Scalar = T;
63
64 fn boolean_op(&self, other: &Self, op: OpType) -> MultiPolygon<Self::Scalar> {
65 let spec = BoolOp::from(op);
66 let mut bop = Proc::new(spec, self.coords_count() + other.coords_count());
67 bop.add_polygon(self, 0);
68 bop.add_polygon(other, 1);
69 bop.sweep()
70 }
71
72 fn clip(
73 &self,
74 ls: &MultiLineString<Self::Scalar>,
75 invert: bool,
76 ) -> MultiLineString<Self::Scalar> {
77 let spec = ClipOp::new(invert);
78 let mut bop = Proc::new(spec, self.coords_count() + ls.coords_count());
79 bop.add_polygon(self, 0);
80 ls.0.iter().enumerate().for_each(|(idx, l)| {
81 bop.add_line_string(l, idx + 1);
82 });
83 bop.sweep()
84 }
85}
86impl<T: GeoFloat> BooleanOps for MultiPolygon<T> {
87 type Scalar = T;
88
89 fn boolean_op(&self, other: &Self, op: OpType) -> MultiPolygon<Self::Scalar> {
90 let spec = BoolOp::from(op);
91 let mut bop = Proc::new(spec, self.coords_count() + other.coords_count());
92 bop.add_multi_polygon(self, 0);
93 bop.add_multi_polygon(other, 1);
94 bop.sweep()
95 }
96
97 fn clip(
98 &self,
99 ls: &MultiLineString<Self::Scalar>,
100 invert: bool,
101 ) -> MultiLineString<Self::Scalar> {
102 let spec = ClipOp::new(invert);
103 let mut bop = Proc::new(spec, self.coords_count() + ls.coords_count());
104 bop.add_multi_polygon(self, 0);
105 ls.0.iter().enumerate().for_each(|(idx, l)| {
106 bop.add_line_string(l, idx + 1);
107 });
108 bop.sweep()
109 }
110}
111
112mod op;
113use op::*;
114mod assembly;
115use assembly::*;
116mod spec;
117use spec::*;
118
119#[cfg(test)]
120mod tests;