/ src / _impl / _trim_shape_impl.scad
_trim_shape_impl.scad
 1  use <../__comm__/__line_intersection.scad>
 2  use <../__comm__/__in_line.scad>
 3  use <../__comm__/__lines_from.scad>
 4  
 5  function _any_intersection_sub(lines, line, lines_leng, i, epsilon) =
 6      let(p = __line_intersection2(lines[i], line, false, epsilon))
 7      p != [] ? [i, p] : _any_intersection(lines, line, lines_leng, i + 1, epsilon);
 8  
 9  // return [idx, [x, y]] or []
10  function _any_intersection(lines, line, lines_leng, i, epsilon) =
11      i == lines_leng ? [] : _any_intersection_sub(lines, line, lines_leng, i, epsilon);
12  
13  function _trim_sub(lines, leng, epsilon) = 
14      let(
15          current_line = lines[0],
16          next_line = lines[1],
17          lines_from_next = [for(j = 1; j < leng; j = j + 1) lines[j]],
18          lines_from_next2 = [for(j = 2; j < leng; j = j + 1) lines[j]],
19          current_p = current_line[0],
20          leng_lines_from_next2 = len(lines_from_next2),
21          inter_p = _any_intersection(lines_from_next2, current_line, leng_lines_from_next2, 0, epsilon)
22      )
23      // no intersecting pt, collect current_p and trim remain lines
24      inter_p == [] ? [current_p, each _trim_lines(lines_from_next, epsilon)] : 
25      // collect current_p, intersecting pt and the last pt
26      leng == 3 || (inter_p.x == (leng_lines_from_next2 - 1)) ? [current_p, inter_p.y, lines[leng - 1]] : 
27          // collect current_p, intersecting pt and trim remain lines
28          [current_p, inter_p.y, each _trim_lines([for(i = inter_p.x + 1; i < leng_lines_from_next2; i = i + 1) lines_from_next2[i]], epsilon)];
29      
30  function _trim_lines(lines, epsilon) = 
31      let(leng = len(lines))
32      leng > 2 ? _trim_sub(lines, leng, epsilon) : _collect_pts_from(lines, leng);
33  
34  function _collect_pts_from(lines, leng) = 
35      [each [for(line = lines) line[0]], lines[leng - 1][1]];
36  
37  function _trim_shape_impl(shape_pts, from, to, epsilon) = 
38      let(
39          pts = [for(i = from; i <= to; i = i + 1) shape_pts[i]],
40          trimmed = _trim_lines(__lines_from(pts), epsilon)
41      )
42      len(shape_pts) == len(trimmed) ? trimmed : _trim_shape_impl(trimmed, 0, len(trimmed) - 1, epsilon);