_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);