Skip to main content

clipper2_sys/clipper64/
mod.rs

1//! Integer grid paths (`Point64`, `Path64`, `Paths64`) and [`Clipper64`].
2//!
3//! 整数网格坐标路径与布尔裁剪主入口 [`Clipper64`]。
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::{path64_to_blob, paths64_to_blob};
17use crate::{EndType, JoinType, LazyPathsD, PointInPolygonResult};
18
19/// Single point on the integer Clipper2 grid (`Point64`); same layout as cxx `P64`.
20///
21/// Clipper2 整数网格上的点,布局与 cxx `P64` 一致。
22pub type Point64 = crate::cxx_bridge::clipper2_sys_cxx::P64;
23
24impl Point64 {
25    /// Creates a point from coordinates. / 由坐标构造点。
26    pub fn new(x: i64, y: i64) -> Self {
27        Self { x, y }
28    }
29}
30
31impl Path64 {
32    /// Simplifies the path (RDP-style via Clipper). `is_open_path` marks open polylines.
33    ///
34    /// 简化路径(Clipper 实现)。`is_open_path` 表示开放折线。
35    pub fn simplify(&self, epsilon: f64, is_open_path: bool) -> LazyPaths64 {
36        let out = clipper2_sys_cxx::cxx_path64_simplify(
37            &path64_to_blob(self),
38            epsilon,
39            is_open_path,
40        );
41        LazyPaths64::from_blob(out)
42    }
43
44    /// Tests where `point` lies relative to this path. / 判断 `point` 与路径的位置关系。
45    pub fn point_in_polygon(&self, point: Point64) -> PointInPolygonResult {
46        clipper2_sys_cxx::cxx_point_in_path64(&path64_to_blob(self), point.x, point.y).into()
47    }
48
49    /// Converts to double paths (`LazyPathsD`) for `ClipperD` workflows.
50    ///
51    /// 转为双精度路径,便于走 `ClipperD` 流程。
52    pub fn to_pathd(&self) -> LazyPathsD {
53        let b = clipper2_sys_cxx::cxx_path64_to_pathd(&path64_to_blob(self));
54        LazyPathsD::from_blob(b)
55    }
56}
57
58impl Paths64 {
59    /// Simplifies every path. / 对每条路径做简化。
60    pub fn simplify(&self, epsilon: f64, is_open_path: bool) -> LazyPaths64 {
61        let out = clipper2_sys_cxx::cxx_paths64_simplify(
62            &paths64_to_blob(self),
63            epsilon,
64            is_open_path,
65        );
66        LazyPaths64::from_blob(out)
67    }
68
69    /// Offsets (inflates/deflates) all paths by `delta` using join/end rules.
70    ///
71    /// 按连接/端点规则对全部路径做 `delta` 偏移(膨胀或收缩)。
72    pub fn inflate(
73        &self,
74        delta: f64,
75        join_type: JoinType,
76        end_type: EndType,
77        miter_limit: f64,
78    ) -> LazyPaths64 {
79        let out = clipper2_sys_cxx::cxx_paths64_inflate(
80            &paths64_to_blob(self),
81            delta,
82            join_type.into(),
83            end_type.into(),
84            miter_limit,
85        );
86        LazyPaths64::from_blob(out)
87    }
88
89    /// Converts all paths to `PathD` blobs. / 将全部路径转为双精度。
90    pub fn to_pathsd(&self) -> LazyPathsD {
91        let b = clipper2_sys_cxx::cxx_paths64_to_pathsd(&paths64_to_blob(self));
92        LazyPathsD::from_blob(b)
93    }
94}
95
96impl Path64 {
97    /// Minkowski sum with `pattern`; `is_closed` toggles closed semantics.
98    ///
99    /// 与 `pattern` 的闵可夫斯基和。
100    pub fn minkowski_sum(&self, pattern: &Path64, is_closed: bool) -> LazyPaths64 {
101        LazyPaths64::from_blob(clipper2_sys_cxx::cxx_path64_minkowski_sum(
102            &path64_to_blob(pattern),
103            &path64_to_blob(self),
104            is_closed,
105        ))
106    }
107
108    /// Minkowski difference. / 闵可夫斯基差。
109    pub fn minkowski_diff(&self, pattern: &Path64, is_closed: bool) -> LazyPaths64 {
110        LazyPaths64::from_blob(clipper2_sys_cxx::cxx_path64_minkowski_diff(
111            &path64_to_blob(pattern),
112            &path64_to_blob(self),
113            is_closed,
114        ))
115    }
116}
117
118impl Paths64 {
119    /// Minkowski sum against each path with fill rule. / 对多条路径做闵可夫斯基和(含填充规则)。
120    pub fn minkowski_sum(
121        &self,
122        pattern: &Path64,
123        is_closed: bool,
124        fillrule: ClipperFillRule,
125    ) -> LazyPaths64 {
126        LazyPaths64::from_blob(clipper2_sys_cxx::cxx_paths64_minkowski_sum(
127            &path64_to_blob(pattern),
128            &paths64_to_blob(self),
129            is_closed,
130            fillrule,
131        ))
132    }
133
134    /// Minkowski difference with fill rule. / 闵可夫斯基差(含填充规则)。
135    pub fn minkowski_diff(
136        &self,
137        pattern: &Path64,
138        is_closed: bool,
139        fillrule: ClipperFillRule,
140    ) -> LazyPaths64 {
141        LazyPaths64::from_blob(clipper2_sys_cxx::cxx_paths64_minkowski_diff(
142            &path64_to_blob(pattern),
143            &paths64_to_blob(self),
144            is_closed,
145            fillrule,
146        ))
147    }
148}
149
150impl Path64 {
151    /// Signed area of a closed path. / 闭合路径的有向面积。
152    pub fn area(&self) -> f64 {
153        clipper2_sys_cxx::cxx_path64_area(&path64_to_blob(self))
154    }
155}
156
157impl Paths64 {
158    /// Sum of signed areas. / 各路径有向面积之和。
159    pub fn area(&self) -> f64 {
160        clipper2_sys_cxx::cxx_paths64_area(&paths64_to_blob(self))
161    }
162}
163
164#[cfg(test)]
165mod tests {
166    use super::{Path64, Point64, PointInPolygonResult};
167
168    #[test]
169    fn path64_area_unit_square() {
170        let p = Path64::new(vec![
171            Point64::new(0, 0),
172            Point64::new(10, 0),
173            Point64::new(10, 10),
174            Point64::new(0, 10),
175        ]);
176        assert!((p.area().abs() - 100.0).abs() < 1e-6);
177    }
178
179    #[test]
180    fn point_in_polygon_center_inside_square() {
181        let p = Path64::new(vec![
182            Point64::new(0, 0),
183            Point64::new(10, 0),
184            Point64::new(10, 10),
185            Point64::new(0, 10),
186        ]);
187        let r = p.point_in_polygon(Point64::new(5, 5));
188        assert!(matches!(r, PointInPolygonResult::Inside));
189    }
190}