Skip to content

Commit 96df331

Browse files
authored
add a starting-point parameter (#117)
* add a starting-point parameter change behavior when optimizing path , we take care of starting point in some optimisation operations * - fix ci/cd errors * fix ci/cd * - remove unused module * remove unuseful comment
1 parent 10d19ac commit 96df331

4 files changed

Lines changed: 53 additions & 19 deletions

File tree

cli/src/main.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ struct Opt {
106106
/// <https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Selectors>
107107
#[arg(long)]
108108
selector_filter: Option<String>,
109+
/// Starting point , usefull only if try optimize path
110+
#[arg(long)]
111+
starting_point: Option<String>,
109112
}
110113

111114
fn main() -> io::Result<()> {
@@ -168,6 +171,24 @@ fn main() -> io::Result<()> {
168171
}
169172
}
170173
}
174+
{
175+
if let Some(starting_point) = opt.starting_point {
176+
for (i, dimension_starting_point) in starting_point
177+
.split(',')
178+
.map(|point| {
179+
if point.is_empty() {
180+
Default::default()
181+
} else {
182+
point.parse::<f64>().expect("could not parse coordinate")
183+
}
184+
})
185+
.take(2)
186+
.enumerate()
187+
{
188+
settings.conversion.inner.starting_point[i] = Some(dimension_starting_point);
189+
}
190+
}
191+
}
171192

172193
if let Some(line_numbers) = opt.line_numbers {
173194
settings.postprocess.line_numbers = line_numbers;

star/src/lower/mod.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ pub struct ConversionConfig {
4949
/// <https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Selectors>
5050
#[cfg_attr(feature = "serde", serde(default))]
5151
pub selector_filter: Option<String>,
52+
pub starting_point: [Option<f64>; 2],
5253
}
5354

5455
const fn zero_origin() -> [Option<f64>; 2] {
@@ -63,6 +64,7 @@ impl Default for ConversionConfig {
6364
extra_attribute_name: None,
6465
optimize_path_order: false,
6566
selector_filter: None,
67+
starting_point: zero_origin() ,
6668
}
6769
}
6870
}
@@ -177,6 +179,11 @@ pub fn svg_to_turtle<T: Turtle>(
177179
.origin
178180
.map(|dim| dim.map(|d| UomLength::new::<millimeter>(d).get::<inch>() * CSS_DEFAULT_DPI));
179181

182+
// Convert from millimeters to user units
183+
let starting_point = config
184+
.starting_point
185+
.map(|dim| dim.map(|d| UomLength::new::<millimeter>(d).get::<inch>() * CSS_DEFAULT_DPI));
186+
180187
let origin_transform = match origin {
181188
[None, Some(origin_y)] => {
182189
let bb = bounding_box_generator();
@@ -219,6 +226,7 @@ pub fn svg_to_turtle<T: Turtle>(
219226
origin_transform,
220227
selector_filter,
221228
coordinate_system,
229+
starting_point,
222230
);
223231
let turtle = &mut conversion_visitor.terrarium.turtle;
224232
for stroke in strokes {
@@ -244,6 +252,7 @@ fn svg_to_optimized_strokes(
244252
origin_transform: Transform2D<f64>,
245253
selector_filter: Option<SelectorList>,
246254
coordinate_system: CoordinateSystem,
255+
starting_point: [Option<f64>; 2]
247256
) -> Vec<Stroke> {
248257
let mut collect_visitor = ConversionVisitor {
249258
terrarium: Terrarium::new(StrokeCollectingTurtle::default()),
@@ -260,7 +269,7 @@ fn svg_to_optimized_strokes(
260269
collect_visitor.end();
261270
collect_visitor.terrarium.pop_transform();
262271
let strokes = collect_visitor.terrarium.turtle.into_strokes();
263-
minimize_travel_time(strokes)
272+
minimize_travel_time(strokes,starting_point)
264273
}
265274

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

star/src/turtle/elements/tsp.rs

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,22 @@ fn dist(a: Point<f64>, b: Point<f64>) -> f64 {
2727
///
2828
/// <https://github.com/sameer/raster2svg>
2929
/// <https://www.mdpi.com/2076-3417/9/19/3985/pdf>
30-
pub fn minimize_travel_time(strokes: Vec<Stroke>) -> Vec<Stroke> {
30+
pub fn minimize_travel_time(strokes: Vec<Stroke>,starting_point: [Option<f64>; 2] ) -> Vec<Stroke> {
3131
if strokes.len() <= 1 {
3232
return strokes;
3333
}
34-
let path = nearest_neighbor_greedy(strokes);
35-
local_improvement_with_tabu_search(&path)
34+
let the_starting_point : Point<f64> = Point::new(starting_point[0].expect("No starting point Y"),starting_point[1].expect("No starting point Y"));
35+
36+
let path = nearest_neighbor_greedy(strokes,the_starting_point);
37+
local_improvement_with_tabu_search(&path,the_starting_point)
3638
}
3739

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

4647
while !remaining.is_empty() {
4748
let mut best_idx = 0;
@@ -132,13 +133,13 @@ fn reverse_and_flip(strokes: &mut [Stroke]) {
132133
/// - TwoOpt and LinkSwap reversals also flip each stroke in the reversed range.
133134
/// - Relocate tries both the normal and reversed orientation of the moved stroke.
134135
/// - Distances are `f64` Euclidean rather than squared integers.
135-
fn local_improvement_with_tabu_search(path: &[Stroke]) -> Vec<Stroke> {
136+
fn local_improvement_with_tabu_search(path: &[Stroke],the_starting_point: Point<f64> ) -> Vec<Stroke> {
136137
let mut best = path.to_owned();
137-
let mut best_sum: f64 = stroke_distances(&best).iter().sum();
138+
let mut best_sum: f64 = stroke_distances(&best).iter().sum::<f64>() + dist(the_starting_point,best[0].start_point()) ;
138139

139140
let mut current = best.clone();
140141
let mut current_distances = stroke_distances(&current);
141-
let mut current_sum = best_sum;
142+
let mut current_sum ;
142143

143144
const ITERATIONS: usize = 20000;
144145
let mut rng = rand::rng();
@@ -282,8 +283,8 @@ fn local_improvement_with_tabu_search(path: &[Stroke]) -> Vec<Stroke> {
282283
// 2 = [first_start, last_end]: both
283284
let candidates = [
284285
(0usize, dist(from, last_end)),
285-
(1usize, dist(first_start, to)),
286-
(2usize, dist(first_start, last_end)),
286+
(1usize, dist(first_start, to) +dist(the_starting_point,to)-dist(the_starting_point,first_start)),
287+
(2usize, dist(first_start, last_end)+dist(the_starting_point,last_end)-dist(the_starting_point,first_start)),
287288
];
288289
let (opt, best_new_dist) = candidates
289290
.into_iter()
@@ -322,14 +323,8 @@ fn local_improvement_with_tabu_search(path: &[Stroke]) -> Vec<Stroke> {
322323
}
323324
}
324325

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

334329
if current_sum < best_sum {
335330
best = current.clone();

web/src/state.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ pub struct FormState {
2424
pub checksums: bool,
2525
pub line_numbers: bool,
2626
pub newline_before_comment: bool,
27+
pub starting_point: [Option<Result<f64, ParseFloatError>>; 2],
2728
}
2829

2930
impl Default for FormState {
@@ -56,6 +57,10 @@ impl TryInto<Settings> for &FormState {
5657
extra_attribute_name: None,
5758
optimize_path_order: self.optimize_path_order,
5859
selector_filter: None,
60+
starting_point: [
61+
self.starting_point[0].clone().transpose()?,
62+
self.starting_point[1].clone().transpose()?,
63+
],
5964
},
6065
tolerance: self.tolerance.clone()?,
6166
feedrate: self.feedrate.clone()?,
@@ -117,6 +122,10 @@ impl From<&Settings> for FormState {
117122
checksums: settings.postprocess.checksums,
118123
line_numbers: settings.postprocess.line_numbers,
119124
newline_before_comment: settings.postprocess.newline_before_comment,
125+
starting_point: [
126+
settings.conversion.inner.starting_point[0].map(Ok),
127+
settings.conversion.inner.starting_point[1].map(Ok),
128+
],
120129
}
121130
}
122131
}

0 commit comments

Comments
 (0)