u_nesting_cutting/
config.rs1#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5
6use crate::bridge::BridgeConfig;
7use crate::leadin::LeadInConfig;
8use crate::thermal::ThermalConfig;
9
10#[derive(Debug, Clone)]
12#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
13pub struct CuttingConfig {
14 pub kerf_width: f64,
17
18 pub pierce_weight: f64,
21
22 pub max_2opt_iterations: usize,
25
26 pub rapid_speed: f64,
29
30 pub cut_speed: f64,
33
34 pub exterior_direction: CutDirectionPreference,
36
37 pub interior_direction: CutDirectionPreference,
39
40 pub home_position: (f64, f64),
43
44 pub pierce_candidates: usize,
48
49 pub tolerance: f64,
51
52 pub lead_in: LeadInConfig,
54
55 pub bridge: BridgeConfig,
57
58 pub thermal: ThermalConfig,
60}
61
62#[derive(Debug, Clone, Copy, PartialEq, Eq)]
64#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
65pub enum CutDirectionPreference {
66 Ccw,
68 Cw,
70 Auto,
72}
73
74impl Default for CuttingConfig {
75 fn default() -> Self {
76 Self {
77 kerf_width: 0.0,
78 pierce_weight: 10.0,
79 max_2opt_iterations: 1000,
80 rapid_speed: 1000.0,
81 cut_speed: 100.0,
82 exterior_direction: CutDirectionPreference::Auto,
83 interior_direction: CutDirectionPreference::Auto,
84 home_position: (0.0, 0.0),
85 pierce_candidates: 1,
86 tolerance: 1e-6,
87 lead_in: LeadInConfig::default(),
88 bridge: BridgeConfig::default(),
89 thermal: ThermalConfig::default(),
90 }
91 }
92}
93
94impl CuttingConfig {
95 pub fn new() -> Self {
97 Self::default()
98 }
99
100 pub fn with_kerf_width(mut self, width: f64) -> Self {
102 self.kerf_width = width;
103 self
104 }
105
106 pub fn with_pierce_weight(mut self, weight: f64) -> Self {
108 self.pierce_weight = weight;
109 self
110 }
111
112 pub fn with_max_2opt_iterations(mut self, iterations: usize) -> Self {
114 self.max_2opt_iterations = iterations;
115 self
116 }
117
118 pub fn with_home_position(mut self, x: f64, y: f64) -> Self {
120 self.home_position = (x, y);
121 self
122 }
123
124 pub fn with_pierce_candidates(mut self, candidates: usize) -> Self {
126 self.pierce_candidates = candidates.max(1);
127 self
128 }
129
130 pub fn with_lead_in(mut self, lead_in: LeadInConfig) -> Self {
132 self.lead_in = lead_in;
133 self
134 }
135
136 pub fn with_bridge(mut self, bridge: BridgeConfig) -> Self {
138 self.bridge = bridge;
139 self
140 }
141
142 pub fn with_thermal(mut self, thermal: ThermalConfig) -> Self {
144 self.thermal = thermal;
145 self
146 }
147}
148
149#[cfg(test)]
150mod tests {
151 use super::*;
152
153 #[test]
154 fn test_default_config() {
155 let config = CuttingConfig::default();
156 assert_eq!(config.kerf_width, 0.0);
157 assert_eq!(config.pierce_weight, 10.0);
158 assert_eq!(config.max_2opt_iterations, 1000);
159 assert_eq!(config.home_position, (0.0, 0.0));
160 }
161
162 #[test]
163 fn test_builder() {
164 let config = CuttingConfig::new()
165 .with_kerf_width(0.5)
166 .with_pierce_weight(20.0)
167 .with_home_position(10.0, 10.0);
168
169 assert_eq!(config.kerf_width, 0.5);
170 assert_eq!(config.pierce_weight, 20.0);
171 assert_eq!(config.home_position, (10.0, 10.0));
172 }
173
174 #[test]
175 fn test_pierce_candidates_minimum() {
176 let config = CuttingConfig::new().with_pierce_candidates(0);
177 assert_eq!(config.pierce_candidates, 1);
178 }
179}