1mod clipper;
6pub use clipper::*;
7
8mod path;
9pub use path::*;
10
11mod paths;
12pub use paths::*;
13
14use crate::cxx_bridge::clipper2_sys_cxx;
15use crate::cxx_bridge::clipper2_sys_cxx::ClipperFillRule;
16use crate::paths_blob::{pathd_to_blob, pathsd_to_blob, DEFAULT_PATHD_PRECISION};
17use crate::{EndType, JoinType, LazyPaths64, PointInPolygonResult};
18
19pub type PointD = crate::cxx_bridge::clipper2_sys_cxx::PD;
23
24impl PointD {
25 pub fn new(x: f64, y: f64) -> Self {
27 Self { x, y }
28 }
29}
30
31impl PathD {
32 pub fn simplify(&self, epsilon: f64, is_open_path: bool) -> LazyPathsD {
34 let out = clipper2_sys_cxx::cxx_pathd_simplify(&pathd_to_blob(self), epsilon, is_open_path);
35 LazyPathsD::from_blob(out)
36 }
37
38 pub fn point_in_polygon(&self, point: PointD) -> PointInPolygonResult {
40 clipper2_sys_cxx::cxx_point_in_pathd(&pathd_to_blob(self), point.x, point.y).into()
41 }
42
43 pub fn to_path64(&self) -> LazyPaths64 {
45 let b =
46 clipper2_sys_cxx::cxx_pathd_to_path64(&pathd_to_blob(self), DEFAULT_PATHD_PRECISION);
47 LazyPaths64::from_blob(b)
48 }
49}
50
51impl PathsD {
52 pub fn simplify(&self, epsilon: f64, is_open_path: bool) -> LazyPathsD {
54 let out =
55 clipper2_sys_cxx::cxx_pathsd_simplify(&pathsd_to_blob(self), epsilon, is_open_path);
56 LazyPathsD::from_blob(out)
57 }
58
59 pub fn inflate(
63 &self,
64 delta: f64,
65 join_type: JoinType,
66 end_type: EndType,
67 miter_limit: f64,
68 precision: i32,
69 ) -> LazyPathsD {
70 let out = clipper2_sys_cxx::cxx_pathsd_inflate(
71 &pathsd_to_blob(self),
72 delta,
73 join_type.into(),
74 end_type.into(),
75 miter_limit,
76 precision,
77 );
78 LazyPathsD::from_blob(out)
79 }
80
81 pub fn to_paths64(&self) -> LazyPaths64 {
83 let b =
84 clipper2_sys_cxx::cxx_pathsd_to_paths64(&pathsd_to_blob(self), DEFAULT_PATHD_PRECISION);
85 LazyPaths64::from_blob(b)
86 }
87}
88
89impl PathD {
90 pub fn minkowski_sum(&self, pattern: &PathD, is_closed: bool, precision: i32) -> LazyPathsD {
92 LazyPathsD::from_blob(clipper2_sys_cxx::cxx_pathd_minkowski_sum(
93 &pathd_to_blob(pattern),
94 &pathd_to_blob(self),
95 is_closed,
96 precision,
97 ))
98 }
99
100 pub fn minkowski_diff(&self, pattern: &PathD, is_closed: bool, precision: i32) -> LazyPathsD {
102 LazyPathsD::from_blob(clipper2_sys_cxx::cxx_pathd_minkowski_diff(
103 &pathd_to_blob(pattern),
104 &pathd_to_blob(self),
105 is_closed,
106 precision,
107 ))
108 }
109}
110
111impl PathsD {
112 pub fn minkowski_sum(
114 &self,
115 pattern: &PathD,
116 is_closed: bool,
117 precision: i32,
118 fillrule: ClipperFillRule,
119 ) -> LazyPathsD {
120 LazyPathsD::from_blob(clipper2_sys_cxx::cxx_pathsd_minkowski_sum(
121 &pathd_to_blob(pattern),
122 &pathsd_to_blob(self),
123 is_closed,
124 precision,
125 fillrule,
126 ))
127 }
128
129 pub fn minkowski_diff(
131 &self,
132 pattern: &PathD,
133 is_closed: bool,
134 precision: i32,
135 fillrule: ClipperFillRule,
136 ) -> LazyPathsD {
137 LazyPathsD::from_blob(clipper2_sys_cxx::cxx_pathsd_minkowski_diff(
138 &pathd_to_blob(pattern),
139 &pathsd_to_blob(self),
140 is_closed,
141 precision,
142 fillrule,
143 ))
144 }
145}
146
147impl PathD {
148 pub fn area(&self) -> f64 {
150 clipper2_sys_cxx::cxx_pathd_area(&pathd_to_blob(self))
151 }
152}
153
154impl PathsD {
155 pub fn area(&self) -> f64 {
157 clipper2_sys_cxx::cxx_pathsd_area(&pathsd_to_blob(self))
158 }
159}
160
161#[cfg(test)]
162mod tests {
163 use super::{PathD, PointD};
164
165 #[test]
166 fn pathd_area_unit_square() {
167 let p = PathD::new(vec![
168 PointD::new(0.0, 0.0),
169 PointD::new(10.0, 0.0),
170 PointD::new(10.0, 10.0),
171 PointD::new(0.0, 10.0),
172 ]);
173 assert!((p.area().abs() - 100.0).abs() < 1e-6);
174 }
175
176 #[test]
177 fn pathd_simplify_reduces_collinear() {
178 let p = PathD::new(vec![
179 PointD::new(0.0, 0.0),
180 PointD::new(5.0, 0.0),
181 PointD::new(10.0, 0.0),
182 PointD::new(10.0, 10.0),
183 PointD::new(0.0, 10.0),
184 ]);
185 let s = p.simplify(1.0, false);
186 assert!(s.into_first_path().len() <= p.len());
187 }
188}