Skip to main content

clipper2_sys/clipperd/
mod.rs

1//! Double-precision paths (`PointD`, `PathD`, `PathsD`) and [`ClipperD`].
2//!
3//! 双精度坐标路径与 [`ClipperD`]。
4
5mod 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
19/// Double-precision point (`PointD`); same layout as cxx `PD`.
20///
21/// 双精度点,布局与 cxx `PD` 一致。
22pub type PointD = crate::cxx_bridge::clipper2_sys_cxx::PD;
23
24impl PointD {
25    /// Creates a point. / 构造点。
26    pub fn new(x: f64, y: f64) -> Self {
27        Self { x, y }
28    }
29}
30
31impl PathD {
32    /// Simplifies this path. / 简化路径。
33    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    /// Point-in-polygon test. / 点在多边形内外判定。
39    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    /// Quantizes to `Path64` (default precision). / 量化为 `Path64`(默认精度)。
44    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    /// Simplifies all paths. / 简化所有路径。
53    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    /// Offsets all paths; `precision` is ClipperD decimal precision.
60    ///
61    /// 偏移所有路径;`precision` 为 ClipperD 小数精度。
62    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    /// Converts to integer paths. / 转为整数路径集合。
82    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    /// Minkowski sum in double space. / 双精度闵可夫斯基和。
91    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    /// Minkowski difference. / 闵可夫斯基差。
101    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    /// Minkowski sum with fill rule. / 闵可夫斯基和(填充规则)。
113    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    /// Minkowski difference with fill rule. / 闵可夫斯基差(填充规则)。
130    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    /// Signed area. / 有向面积。
149    pub fn area(&self) -> f64 {
150        clipper2_sys_cxx::cxx_pathd_area(&pathd_to_blob(self))
151    }
152}
153
154impl PathsD {
155    /// Sum of signed areas. / 有向面积之和。
156    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}