Skip to main content

clipper2_sys/
offset.rs

1use crate::cxx_bridge::clipper2_sys_cxx;
2use crate::paths_blob::{path64_to_blob, paths64_to_blob};
3use crate::{EndType, JoinType, LazyPaths64, Path64, Paths64};
4
5/// Clipper2 path offsetter: inflate or deflate polygons/polylines (integer `Path64`).
6///
7/// Clipper2 路径偏移器:对 `Path64` 做膨胀或收缩。
8pub struct ClipperOffset {
9    inner: cxx::UniquePtr<clipper2_sys_cxx::ClipperOffsetBox>,
10}
11
12impl ClipperOffset {
13    /// Creates an offset engine (`miter_limit`, `arc_tolerance`, flags).
14    ///
15    /// 创建偏移引擎(斜接上限、圆弧容差、布尔选项)。
16    pub fn new(
17        miter_limit: f64,
18        arc_tolerance: f64,
19        preserve_collinear: bool,
20        reverse_solution: bool,
21    ) -> Self {
22        Self {
23            inner: clipper2_sys_cxx::cxx_clipper_offset_new(
24                miter_limit,
25                arc_tolerance,
26                preserve_collinear,
27                reverse_solution,
28            ),
29        }
30    }
31
32    /// Adds one path with join and end types. / 添加单条路径及连接/端点类型。
33    pub fn add_path(&mut self, path: &Path64, join_type: JoinType, end_type: EndType) {
34        clipper2_sys_cxx::cxx_clipper_offset_add_path(
35            self.inner.pin_mut(),
36            &path64_to_blob(path),
37            join_type.into(),
38            end_type.into(),
39        );
40    }
41
42    /// Adds many paths. / 添加多条路径。
43    pub fn add_paths(&mut self, paths: &Paths64, join_type: JoinType, end_type: EndType) {
44        clipper2_sys_cxx::cxx_clipper_offset_add_paths(
45            self.inner.pin_mut(),
46            &paths64_to_blob(paths),
47            join_type.into(),
48            end_type.into(),
49        );
50    }
51
52    /// Runs offset by signed `delta` (positive = outward for closed paths). / 按有符号 `delta` 执行偏移。
53    pub fn execute(&mut self, delta: f64) -> LazyPaths64 {
54        let out = clipper2_sys_cxx::cxx_clipper_offset_execute(self.inner.pin_mut(), delta);
55        LazyPaths64::from_blob(out)
56    }
57
58    /// Clears queued paths. / 清空已添加路径。
59    pub fn clear(&mut self) {
60        clipper2_sys_cxx::cxx_clipper_offset_clear(self.inner.pin_mut());
61    }
62
63    /// Miter limit. / 斜接上限。
64    pub fn get_miter_limit(&self) -> f64 {
65        clipper2_sys_cxx::cxx_clipper_offset_get_miter_limit(&self.inner)
66    }
67
68    /// Sets miter limit. / 设置斜接上限。
69    pub fn set_miter_limit(&mut self, miter_limit: f64) {
70        clipper2_sys_cxx::cxx_clipper_offset_set_miter_limit(self.inner.pin_mut(), miter_limit);
71    }
72
73    /// Arc tolerance for rounding. / 圆角弧形容差。
74    pub fn get_arc_tolerance(&self) -> f64 {
75        clipper2_sys_cxx::cxx_clipper_offset_get_arc_tolerance(&self.inner)
76    }
77
78    /// Sets arc tolerance. / 设置弧形容差。
79    pub fn set_arc_tolerance(&mut self, arc_tolerance: f64) {
80        clipper2_sys_cxx::cxx_clipper_offset_set_arc_tolerance(self.inner.pin_mut(), arc_tolerance);
81    }
82
83    /// Preserve-collinear flag. / 保留共线顶点。
84    pub fn get_preserve_collinear(&self) -> bool {
85        clipper2_sys_cxx::cxx_clipper_offset_get_preserve_collinear(&self.inner)
86    }
87
88    /// Sets preserve-collinear. / 设置是否保留共线顶点。
89    pub fn set_preserve_collinear(&mut self, preserve_collinear: bool) {
90        clipper2_sys_cxx::cxx_clipper_offset_set_preserve_collinear(
91            self.inner.pin_mut(),
92            preserve_collinear,
93        );
94    }
95
96    /// Reverse-solution flag. / 反转解。
97    pub fn get_reverse_solution(&self) -> bool {
98        clipper2_sys_cxx::cxx_clipper_offset_get_reverse_solution(&self.inner)
99    }
100
101    /// Sets reverse-solution. / 设置是否反转解方向。
102    pub fn set_reverse_solution(&mut self, reverse_solution: bool) {
103        clipper2_sys_cxx::cxx_clipper_offset_set_reverse_solution(
104            self.inner.pin_mut(),
105            reverse_solution,
106        );
107    }
108}
109
110#[cfg(test)]
111mod tests {
112    use crate::{ClipperOffset, EndType, JoinType, Path64, Point64};
113
114    #[test]
115    fn offset_square_returns_paths() {
116        let path = Path64::new(vec![
117            Point64::new(0, 0),
118            Point64::new(100, 0),
119            Point64::new(100, 100),
120            Point64::new(0, 100),
121        ]);
122        let mut co = ClipperOffset::new(2.0, 0.0, false, false);
123        co.add_path(&path, JoinType::MiterJoin, EndType::PolygonEnd);
124        let out = co.execute(10.0);
125        assert!(!out.is_empty());
126    }
127}