@@ -12,7 +12,12 @@ use uom::si::{
1212} ;
1313
1414use self :: units:: CSS_DEFAULT_DPI ;
15- use crate :: { Machine , turtle:: * } ;
15+ use crate :: {
16+ Machine , Turtle , tsp,
17+ turtle:: {
18+ DpiConvertingTurtle , GCodeTurtle , PreprocessTurtle , StrokeCollectingTurtle , Terrarium ,
19+ } ,
20+ } ;
1621
1722#[ cfg( feature = "serde" ) ]
1823mod length_serde;
@@ -36,6 +41,9 @@ pub struct ConversionConfig {
3641 pub origin : [ Option < f64 > ; 2 ] ,
3742 /// Set extra attribute to add when printing node name
3843 pub extra_attribute_name : Option < String > ,
44+ /// Reorder paths to minimize travel time
45+ #[ cfg_attr( feature = "serde" , serde( default ) ) ]
46+ pub optimize_path_order : bool ,
3947}
4048
4149const fn zero_origin ( ) -> [ Option < f64 > ; 2 ] {
@@ -50,6 +58,7 @@ impl Default for ConversionConfig {
5058 dpi : 96.0 ,
5159 origin : zero_origin ( ) ,
5260 extra_attribute_name : None ,
61+ optimize_path_order : false ,
5362 }
5463 }
5564}
@@ -160,7 +169,7 @@ pub fn svg2program<'a, 'input: 'a>(
160169 dpi : config. dpi ,
161170 } ) ,
162171 _config : config,
163- options,
172+ options : options . clone ( ) ,
164173 name_stack : vec ! [ ] ,
165174 viewport_dim_stack : vec ! [ ] ,
166175 } ;
@@ -169,7 +178,43 @@ pub fn svg2program<'a, 'input: 'a>(
169178 . terrarium
170179 . push_transform ( origin_transform) ;
171180 conversion_visitor. begin ( ) ;
172- visit:: depth_first_visit ( doc, & mut conversion_visitor) ;
181+
182+ if config. optimize_path_order {
183+ // Collect strokes in machine space
184+ let strokes = {
185+ let mut collect_visitor = ConversionVisitor {
186+ terrarium : Terrarium :: new ( DpiConvertingTurtle {
187+ inner : StrokeCollectingTurtle :: default ( ) ,
188+ dpi : config. dpi ,
189+ } ) ,
190+ _config : config,
191+ options,
192+ name_stack : vec ! [ ] ,
193+ viewport_dim_stack : vec ! [ ] ,
194+ } ;
195+ collect_visitor. terrarium . push_transform ( origin_transform) ;
196+ collect_visitor. begin ( ) ;
197+ visit:: depth_first_visit ( doc, & mut collect_visitor) ;
198+ collect_visitor. end ( ) ;
199+ collect_visitor. terrarium . pop_transform ( ) ;
200+ collect_visitor. terrarium . turtle . inner . into_strokes ( )
201+ } ;
202+
203+ // Optimize order
204+ let strokes = tsp:: minimize_travel_time ( strokes) ;
205+
206+ // Replay reordered strokes into the g-code turtle
207+ let turtle = & mut conversion_visitor. terrarium . turtle ;
208+ for stroke in strokes {
209+ turtle. move_to ( stroke. start_point ( ) ) ;
210+ for cmd in stroke. commands ( ) {
211+ cmd. apply ( turtle) ;
212+ }
213+ }
214+ } else {
215+ visit:: depth_first_visit ( doc, & mut conversion_visitor) ;
216+ }
217+
173218 conversion_visitor. end ( ) ;
174219 conversion_visitor. terrarium . pop_transform ( ) ;
175220
0 commit comments