Skip to content

Commit eae6652

Browse files
committed
add a starting-point parameter
change behavior when optimizing path , we take care of starting point in some optimisation operations
1 parent 06dc7c6 commit eae6652

4 files changed

Lines changed: 43 additions & 18 deletions

File tree

cli/src/main.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@ struct Opt {
102102
/// <https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Selectors>
103103
#[arg(long)]
104104
selector_filter: Option<String>,
105+
/// Starting point , usefull only if try optimize path
106+
#[arg(long)]
107+
starting_point: Option<String>,
105108
}
106109

107110
fn main() -> io::Result<()> {
@@ -164,6 +167,24 @@ fn main() -> io::Result<()> {
164167
}
165168
}
166169
}
170+
{
171+
if let Some(starting_point) = opt.starting_point {
172+
for (i, dimension_starting_point) in starting_point
173+
.split(',')
174+
.map(|point| {
175+
if point.is_empty() {
176+
Default::default()
177+
} else {
178+
point.parse::<f64>().expect("could not parse coordinate")
179+
}
180+
})
181+
.take(2)
182+
.enumerate()
183+
{
184+
settings.conversion.starting_point[i] =dimension_starting_point ;
185+
}
186+
}
187+
}
167188

168189
if let Some(line_numbers) = opt.line_numbers {
169190
settings.postprocess.line_numbers = line_numbers;

lib/src/converter/mod.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ pub struct ConversionConfig {
5555
/// <https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Selectors>
5656
#[cfg_attr(feature = "serde", serde(default))]
5757
pub selector_filter: Option<String>,
58+
pub starting_point: [f64; 2],
5859
}
5960

6061
const fn zero_origin() -> [Option<f64>; 2] {
@@ -71,6 +72,7 @@ impl Default for ConversionConfig {
7172
extra_attribute_name: None,
7273
optimize_path_order: false,
7374
selector_filter: None,
75+
starting_point: [0.0 , 0.0 ] ,
7476
}
7577
}
7678
}
@@ -208,7 +210,7 @@ pub fn svg2program<'a, 'input: 'a>(
208210

209211
if config.optimize_path_order {
210212
let strokes =
211-
svg2strokes_optimized(doc, config, options, origin_transform, selector_filter);
213+
svg2strokes_optimized(doc, config, options, origin_transform, selector_filter,config.starting_point);
212214
let turtle = &mut conversion_visitor.terrarium.turtle;
213215
for stroke in strokes {
214216
turtle.move_to(stroke.start_point());
@@ -260,6 +262,7 @@ pub fn svg2preview(
260262
options,
261263
Transform2D::identity(),
262264
selector_filter,
265+
config.starting_point,
263266
);
264267
let turtle = &mut conversion_visitor.terrarium.turtle;
265268
for stroke in strokes {
@@ -283,6 +286,7 @@ fn svg2strokes_optimized(
283286
options: ConversionOptions,
284287
origin_transform: Transform2D<f64>,
285288
selector_filter: Option<SelectorList>,
289+
starting_point: [f64;2]
286290
) -> Vec<crate::turtle::Stroke> {
287291
let mut collect_visitor = ConversionVisitor {
288292
terrarium: Terrarium::new(StrokeCollectingTurtle::default()),
@@ -298,7 +302,7 @@ fn svg2strokes_optimized(
298302
collect_visitor.end();
299303
collect_visitor.terrarium.pop_transform();
300304
let strokes = collect_visitor.terrarium.turtle.into_strokes();
301-
tsp::minimize_travel_time(strokes)
305+
tsp::minimize_travel_time(strokes,starting_point)
302306
}
303307

304308
fn node_name(node: &Node, attr_to_print: &Option<String>) -> String {

lib/src/tsp.rs

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,23 @@ fn dist(a: Point<f64>, b: Point<f64>) -> f64 {
2424
///
2525
/// <https://github.com/sameer/raster2svg>
2626
/// <https://www.mdpi.com/2076-3417/9/19/3985/pdf>
27-
pub fn minimize_travel_time(strokes: Vec<Stroke>) -> Vec<Stroke> {
27+
pub fn minimize_travel_time(strokes: Vec<Stroke>,starting_point: [f64; 2] ) -> Vec<Stroke> {
2828
if strokes.len() <= 1 {
2929
return strokes;
3030
}
31-
let path = nearest_neighbor_greedy(strokes);
32-
local_improvement_with_tabu_search(&path)
31+
let the_starting_point : Point<f64> = Point::new(starting_point[0]*96.0/25.4,starting_point[1]*96.0/25.4);
32+
33+
let path = nearest_neighbor_greedy(strokes,the_starting_point);
34+
local_improvement_with_tabu_search(&path,the_starting_point)
3335
}
3436

3537
/// Greedy nearest-neighbour ordering with flips.
3638
///
3739
/// Repeatedly chooses the [Stroke] or [Stroke::reversed] closest to the current point until none remain.
38-
fn nearest_neighbor_greedy(mut remaining: Vec<Stroke>) -> Vec<Stroke> {
40+
fn nearest_neighbor_greedy(mut remaining: Vec<Stroke>,the_starting_point: Point<f64> ) -> Vec<Stroke> {
3941
let mut result = Vec::with_capacity(remaining.len());
4042
// TODO: this assumption may be incorrect? depends on the GCode begin sequence, which this can't account for.
41-
let mut pos = Point::zero();
43+
let mut pos : Point<f64> = the_starting_point ;
4244

4345
while !remaining.is_empty() {
4446
let mut best_idx = 0;
@@ -129,9 +131,9 @@ fn reverse_and_flip(strokes: &mut [Stroke]) {
129131
/// - TwoOpt and LinkSwap reversals also flip each stroke in the reversed range.
130132
/// - Relocate tries both the normal and reversed orientation of the moved stroke.
131133
/// - Distances are `f64` Euclidean rather than squared integers.
132-
fn local_improvement_with_tabu_search(path: &[Stroke]) -> Vec<Stroke> {
134+
fn local_improvement_with_tabu_search(path: &[Stroke],the_starting_point: Point<f64> ) -> Vec<Stroke> {
133135
let mut best = path.to_owned();
134-
let mut best_sum: f64 = stroke_distances(&best).iter().sum();
136+
let mut best_sum: f64 = stroke_distances(&best).iter().sum::<f64>() + dist(the_starting_point,best[0].start_point()) ;
135137

136138
let mut current = best.clone();
137139
let mut current_distances = stroke_distances(&current);
@@ -279,8 +281,8 @@ fn local_improvement_with_tabu_search(path: &[Stroke]) -> Vec<Stroke> {
279281
// 2 = [first_start, last_end]: both
280282
let candidates = [
281283
(0usize, dist(from, last_end)),
282-
(1usize, dist(first_start, to)),
283-
(2usize, dist(first_start, last_end)),
284+
(1usize, dist(first_start, to) +dist(the_starting_point,to)-dist(the_starting_point,first_start)),
285+
(2usize, dist(first_start, last_end)+dist(the_starting_point,last_end)-dist(the_starting_point,first_start)),
284286
];
285287
let (opt, best_new_dist) = candidates
286288
.into_iter()
@@ -319,14 +321,8 @@ fn local_improvement_with_tabu_search(path: &[Stroke]) -> Vec<Stroke> {
319321
}
320322
}
321323

322-
let prev_sum = current_sum;
323324
current_distances = stroke_distances(&current);
324-
current_sum = current_distances.iter().sum::<f64>();
325-
326-
debug_assert!(
327-
prev_sum > current_sum - f64::EPSILON,
328-
"operator={operator:?} prev={prev_sum} current={current_sum}"
329-
);
325+
current_sum = current_distances.iter().sum::<f64>() +dist(the_starting_point,current[0].start_point()) ;
330326

331327
if current_sum < best_sum {
332328
best = current.clone();

web/src/state.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ impl TryInto<Settings> for &FormState {
5757
extra_attribute_name: None,
5858
optimize_path_order: self.optimize_path_order,
5959
selector_filter: None,
60+
starting_point: [
61+
self.starting_point[0].clone().transpose()?,
62+
self.starting_point[1].clone().transpose()?,
63+
],
6064
},
6165
machine: MachineConfig {
6266
supported_functionality: SupportedFunctionality {

0 commit comments

Comments
 (0)