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 time_limit_ms: u64,
38
39 pub rapid_speed: f64,
42
43 pub cut_speed: f64,
46
47 pub exterior_direction: CutDirectionPreference,
49
50 pub interior_direction: CutDirectionPreference,
52
53 pub home_position: (f64, f64),
56
57 pub pierce_candidates: usize,
61
62 pub tolerance: f64,
64
65 pub lead_in: LeadInConfig,
67
68 pub bridge: BridgeConfig,
70
71 pub thermal: ThermalConfig,
73}
74
75#[derive(Debug, Clone, Copy, PartialEq, Eq)]
77#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
78pub enum CutDirectionPreference {
79 Ccw,
81 Cw,
83 Auto,
85}
86
87impl Default for CuttingConfig {
88 fn default() -> Self {
89 Self {
90 kerf_width: 0.0,
91 pierce_weight: 10.0,
92 max_2opt_iterations: 1000,
93 time_limit_ms: 5000,
94 rapid_speed: 1000.0,
95 cut_speed: 100.0,
96 exterior_direction: CutDirectionPreference::Auto,
97 interior_direction: CutDirectionPreference::Auto,
98 home_position: (0.0, 0.0),
99 pierce_candidates: 1,
100 tolerance: 1e-6,
101 lead_in: LeadInConfig::default(),
102 bridge: BridgeConfig::default(),
103 thermal: ThermalConfig::default(),
104 }
105 }
106}
107
108impl CuttingConfig {
109 pub fn new() -> Self {
111 Self::default()
112 }
113
114 pub fn with_kerf_width(mut self, width: f64) -> Self {
116 self.kerf_width = width;
117 self
118 }
119
120 pub fn with_pierce_weight(mut self, weight: f64) -> Self {
122 self.pierce_weight = weight;
123 self
124 }
125
126 pub fn with_max_2opt_iterations(mut self, iterations: usize) -> Self {
128 self.max_2opt_iterations = iterations;
129 self
130 }
131
132 pub fn with_time_limit_ms(mut self, time_limit_ms: u64) -> Self {
134 self.time_limit_ms = time_limit_ms;
135 self
136 }
137
138 pub fn with_home_position(mut self, x: f64, y: f64) -> Self {
140 self.home_position = (x, y);
141 self
142 }
143
144 pub fn with_pierce_candidates(mut self, candidates: usize) -> Self {
146 self.pierce_candidates = candidates.max(1);
147 self
148 }
149
150 pub fn with_lead_in(mut self, lead_in: LeadInConfig) -> Self {
152 self.lead_in = lead_in;
153 self
154 }
155
156 pub fn with_bridge(mut self, bridge: BridgeConfig) -> Self {
158 self.bridge = bridge;
159 self
160 }
161
162 pub fn with_thermal(mut self, thermal: ThermalConfig) -> Self {
164 self.thermal = thermal;
165 self
166 }
167}
168
169#[cfg(test)]
170mod tests {
171 use super::*;
172
173 #[test]
174 fn test_default_config() {
175 let config = CuttingConfig::default();
176 assert_eq!(config.kerf_width, 0.0);
177 assert_eq!(config.pierce_weight, 10.0);
178 assert_eq!(config.max_2opt_iterations, 1000);
179 assert_eq!(config.time_limit_ms, 5000);
180 assert_eq!(config.home_position, (0.0, 0.0));
181 }
182
183 #[test]
184 fn test_builder() {
185 let config = CuttingConfig::new()
186 .with_kerf_width(0.5)
187 .with_pierce_weight(20.0)
188 .with_home_position(10.0, 10.0);
189
190 assert_eq!(config.kerf_width, 0.5);
191 assert_eq!(config.pierce_weight, 20.0);
192 assert_eq!(config.home_position, (10.0, 10.0));
193 }
194
195 #[test]
196 fn test_pierce_candidates_minimum() {
197 let config = CuttingConfig::new().with_pierce_candidates(0);
198 assert_eq!(config.pierce_candidates, 1);
199 }
200}