Skip to content

Commit 8ca3ef2

Browse files
committed
Refactor offset functions: update polyline translation logic and adjust offset reconnecting methods for improved clarity and functionality.
1 parent 4a97de5 commit 8ca3ef2

3 files changed

Lines changed: 35 additions & 31 deletions

File tree

examples/offset_pline1.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ fn main() {
1111

1212
let poly_orig = pline_01()[0].clone();
1313
// Translate to fit in the SVG viewport
14-
let poly = polyline_translate(&poly_orig, point(100.0, -50.0));
14+
let p1 = polyline_reverse(&poly_orig);
15+
let poly = polyline_translate(&p1, point(100.0, -50.0));
1516

1617
// Offset the polyline
1718
// let offset_polylines = offset_polyline_to_polyline(&poly, 15.0, &mut cfg);
@@ -21,7 +22,8 @@ fn main() {
2122

2223
// Internal offsetting
2324
let poly = polyline_reverse(&poly);
24-
let _offset_polylines = offset_polyline_to_polyline(&poly, 15.5600615, &mut cfg);
25+
//let _offset_polylines = offset_polyline_to_polyline(&poly, 15.5600615, &mut cfg);
26+
let _offset_polylines = offset_polyline_to_polyline(&poly, 16.0, &mut cfg);
2527

2628
if let Some(svg) = cfg.svg.as_deref_mut() {
2729
// Write svg to file

src/offset.rs

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,10 @@ impl<'a> Default for OffsetCfg<'a> {
9191
///
9292
/// The offsetting process involves several stages:
9393
/// 1. Convert input polyline to raw offset segments (lines and arcs)
94-
/// 2. Compute offset for each segment
95-
/// 3. Connect adjacent offset segments with transition arcs
96-
/// 4. Split overlapping segments at intersection points
97-
/// 5. Prune invalid segments that are too close to the original
98-
/// 6. Reconnect valid segments into continuous paths
99-
/// 7. Convert final arcs back to polylines with pvertex segments
94+
/// 2. Connect adjacent offset segments with transition arcs
95+
/// 3. Split overlapping segments at intersection points
96+
/// 4. Prune invalid segments that are too close to the original
97+
/// 5. Reconnect valid segments into continuous paths
10098
///
10199
/// # Notes
102100
///
@@ -114,8 +112,14 @@ pub fn offset_polyline_to_polyline(
114112
}
115113
let offset_arcs = offset_polyline_to_polyline_impl(poly, off, cfg);
116114

115+
// remove bridges
116+
let offset_arcs = remove_bridge_arcs(&offset_arcs);
117+
118+
// Slightly adjust arc endpoints
119+
let offset_arcs = find_middle_points(&offset_arcs);
120+
117121
// Always reconnect arcs
118-
let reconnect_arcs = offset_reconnect_arcs(&mut offset_arcs.clone());
122+
let reconnect_arcs = offset_reconnect_arcs(&offset_arcs);
119123
// println!(
120124
// "DEBUG: offset_reconnect_arcs returned {} components",
121125
// reconnect_arcs.len()
@@ -181,12 +185,10 @@ pub fn offset_polyline_to_polyline(
181185
/// The offsetting process follows the same stages as polyline offsetting but preserves
182186
/// arc geometry throughout:
183187
/// 1. Convert input arcline to raw offset segments (lines and arcs)
184-
/// 2. Compute precise offset for each segment maintaining arc properties
185-
/// 3. Connect adjacent offset segments with transition arcs
186-
/// 4. Split overlapping segments at intersection points
187-
/// 5. Prune invalid segments that are too close to the original
188-
/// 6. Reconnect valid segments into continuous arc-preserving paths
189-
/// 7. Return final result as arclines (no conversion to line segments)
188+
/// 2. Connect adjacent offset segments with transition arcs
189+
/// 3. Split overlapping segments at intersection points
190+
/// 4. Prune invalid segments that are too close to the original
191+
/// 5. Reconnect valid segments into continuous arc-paths
190192
///
191193
pub fn offset_arcline_to_arcline(arcs: &Arcline, off: f64, cfg: &mut OffsetCfg) -> Vec<Arcline> {
192194
if let Some(svg) = cfg.svg.as_deref_mut()
@@ -196,15 +198,15 @@ pub fn offset_arcline_to_arcline(arcs: &Arcline, off: f64, cfg: &mut OffsetCfg)
196198
}
197199
let offset_arcs = offset_arcline_to_arcline_impl(arcs, off, cfg);
198200

199-
// Slightly adjust arc endpoints
200-
let mut mod_arcs = find_middle_points(&mut offset_arcs.clone());
201-
202201
// remove bridges
203-
remove_bridge_arcs(&mut mod_arcs);
202+
let offset_arcs = remove_bridge_arcs(&offset_arcs);
203+
204+
// Slightly adjust arc endpoints
205+
let offset_arcs = find_middle_points(&offset_arcs);
204206

205207
let mut final_arcs = Vec::new();
206208
if cfg.reconnect {
207-
final_arcs = offset_reconnect_arcs(&mut mod_arcs);
209+
final_arcs = offset_reconnect_arcs(&offset_arcs);
208210
println!(
209211
"offset_reconnect_arcs returned {} components",
210212
final_arcs.len()
@@ -213,7 +215,7 @@ pub fn offset_arcline_to_arcline(arcs: &Arcline, off: f64, cfg: &mut OffsetCfg)
213215
println!(" Component {}: {} arcs", i, component.len());
214216
}
215217
} else {
216-
final_arcs.push(mod_arcs);
218+
final_arcs.push(offset_arcs);
217219
}
218220

219221
if let Some(svg) = cfg.svg.as_deref_mut() {

src/offset_reconnect_arcs.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const EPS_CONNECT: f64 = 1e-8;
99

1010
#[doc(hidden)]
1111
/// Reconnects offset segments by merging adjacent arcs vertices.
12-
pub fn offset_reconnect_arcs(arcs: &mut Vec<Arc>) -> Vec<Vec<Arc>> {
12+
pub fn offset_reconnect_arcs(arcs: &Arcline) -> Vec<Arcline> {
1313
let mut result = Vec::new();
1414

1515
let len = arcs.len();
@@ -60,8 +60,6 @@ pub fn offset_reconnect_arcs(arcs: &mut Vec<Arc>) -> Vec<Vec<Arc>> {
6060
}
6161
}
6262

63-
merge_points(&mut arc_map, &merge);
64-
6563
// println!("DEBUG: Merge operations: {:?}", merge);
6664
// println!("DEBUG: Arc map after merge: {:?}", arc_map);
6765

@@ -141,7 +139,7 @@ pub fn find_middle_points(arcs: &Arcline) -> Arcline {
141139
}
142140
}
143141
}
144-
res.clone()
142+
res
145143
}
146144

147145

@@ -297,12 +295,13 @@ fn should_use_forward_direction(from_vertex: usize, to_vertex: usize, len: usize
297295
/// Removes duplicate arcs that overlap as 2D graphics elements.
298296
///
299297
/// DO NOT CHANGE THIS FUNCTION - it's a critical component for maintaining geometric consistency.
300-
pub fn remove_bridge_arcs(arcs: &mut Vec<Arc>) {
298+
pub fn remove_bridge_arcs(arcs: &Arcline) -> Arcline {
299+
let mut result = arcs.clone();
301300
let mut to_remove = Vec::new();
302-
for i in 0..arcs.len() {
303-
for j in (i + 1)..arcs.len() {
304-
let arc0 = &arcs[i];
305-
let arc1 = &arcs[j];
301+
for i in 0..result.len() {
302+
for j in (i + 1)..result.len() {
303+
let arc0 = &result[i];
304+
let arc1 = &result[j];
306305
if arc0.is_line() && arc1.is_line() {
307306
if (arc0.a.close_enough(arc1.a, EPS_CONNECT)
308307
&& arc0.b.close_enough(arc1.b, EPS_CONNECT))
@@ -330,8 +329,9 @@ pub fn remove_bridge_arcs(arcs: &mut Vec<Arc>) {
330329
to_remove.sort_unstable();
331330
to_remove.dedup();
332331
for i in to_remove.iter().rev() {
333-
arcs.remove(*i);
332+
result.remove(*i);
334333
}
334+
result
335335
}
336336

337337
#[doc(hidden)]

0 commit comments

Comments
 (0)