diff --git a/src/_impl/_trim_shape_impl.scad b/src/_impl/_trim_shape_impl.scad new file mode 100644 index 00000000..1f614fa7 --- /dev/null +++ b/src/_impl/_trim_shape_impl.scad @@ -0,0 +1,48 @@ +use <__comm__/__line_intersection.scad>; +use <__comm__/__in_line.scad>; +use <__comm__/__lines_from.scad>; + +function _trim_shape_any_intersection_sub(lines, line, lines_leng, i, epsilon) = + let( + p = __line_intersection(lines[i], line, epsilon) + ) + (p != [] && __in_line(line, p, epsilon) && __in_line(lines[i], p, epsilon)) ? [i, p] : _trim_shape_any_intersection(lines, line, lines_leng, i + 1, epsilon); + +// return [idx, [x, y]] or [] +function _trim_shape_any_intersection(lines, line, lines_leng, i, epsilon) = + i == lines_leng ? [] : _trim_shape_any_intersection_sub(lines, line, lines_leng, i, epsilon); + +function _trim_sub(lines, leng, epsilon) = + let( + current_line = lines[0], + next_line = lines[1], + lines_from_next = [for(j = 1; j < leng; j = j + 1) lines[j]], + lines_from_next2 = [for(j = 2; j < leng; j = j + 1) lines[j]], + current_p = current_line[0], + leng_lines_from_next2 = len(lines_from_next2), + inter_p = _trim_shape_any_intersection(lines_from_next2, current_line, leng_lines_from_next2, 0, epsilon) + ) + // no intersecting pt, collect current_p and trim remain lines + inter_p == [] ? (concat([current_p], _trim_shape_trim_lines(lines_from_next, epsilon))) : ( + // collect current_p, intersecting pt and the last pt + (leng == 3 || (inter_p[0] == (leng_lines_from_next2 - 1))) ? [current_p, inter_p[1], lines[leng - 1]] : ( + // collect current_p, intersecting pt and trim remain lines + concat([current_p, inter_p[1]], + _trim_shape_trim_lines([for(i = inter_p[0] + 1; i < leng_lines_from_next2; i = i + 1) lines_from_next2[i]], epsilon) + ) + ) + ); + +function _trim_shape_trim_lines(lines, epsilon) = + let(leng = len(lines)) + leng > 2 ? _trim_sub(lines, leng, epsilon) : _trim_shape_collect_pts_from(lines, leng); + +function _trim_shape_collect_pts_from(lines, leng) = + concat([for(line = lines) line[0]], [lines[leng - 1][1]]); + +function _trim_shape_impl(shape_pts, from, to, epsilon) = + let( + pts = [for(i = from; i <= to; i = i + 1) shape_pts[i]], + trimmed = _trim_shape_trim_lines(__lines_from(pts), epsilon) + ) + len(shape_pts) == len(trimmed) ? trimmed : _trim_shape_impl(trimmed, 0, len(trimmed) - 1, epsilon); diff --git a/src/trim_shape.scad b/src/trim_shape.scad index c436abc0..db866054 100644 --- a/src/trim_shape.scad +++ b/src/trim_shape.scad @@ -8,52 +8,7 @@ * **/ -include <__comm__/__to3d.scad>; -include <__comm__/__line_intersection.scad>; -include <__comm__/__in_line.scad>; -include <__comm__/__lines_from.scad>; - -function _trim_shape_any_intersection_sub(lines, line, lines_leng, i, epsilon) = - let( - p = __line_intersection(lines[i], line, epsilon) - ) - (p != [] && __in_line(line, p, epsilon) && __in_line(lines[i], p, epsilon)) ? [i, p] : _trim_shape_any_intersection(lines, line, lines_leng, i + 1, epsilon); - -// return [idx, [x, y]] or [] -function _trim_shape_any_intersection(lines, line, lines_leng, i, epsilon) = - i == lines_leng ? [] : _trim_shape_any_intersection_sub(lines, line, lines_leng, i, epsilon); - -function _trim_sub(lines, leng, epsilon) = - let( - current_line = lines[0], - next_line = lines[1], - lines_from_next = [for(j = 1; j < leng; j = j + 1) lines[j]], - lines_from_next2 = [for(j = 2; j < leng; j = j + 1) lines[j]], - current_p = current_line[0], - leng_lines_from_next2 = len(lines_from_next2), - inter_p = _trim_shape_any_intersection(lines_from_next2, current_line, leng_lines_from_next2, 0, epsilon) - ) - // no intersecting pt, collect current_p and trim remain lines - inter_p == [] ? (concat([current_p], _trim_shape_trim_lines(lines_from_next, epsilon))) : ( - // collect current_p, intersecting pt and the last pt - (leng == 3 || (inter_p[0] == (leng_lines_from_next2 - 1))) ? [current_p, inter_p[1], lines[leng - 1]] : ( - // collect current_p, intersecting pt and trim remain lines - concat([current_p, inter_p[1]], - _trim_shape_trim_lines([for(i = inter_p[0] + 1; i < leng_lines_from_next2; i = i + 1) lines_from_next2[i]], epsilon) - ) - ) - ); - -function _trim_shape_trim_lines(lines, epsilon) = - let(leng = len(lines)) - leng > 2 ? _trim_sub(lines, leng, epsilon) : _trim_shape_collect_pts_from(lines, leng); - -function _trim_shape_collect_pts_from(lines, leng) = - concat([for(line = lines) line[0]], [lines[leng - 1][1]]); +use <_impl/_trim_shape_impl.scad>; function trim_shape(shape_pts, from, to, epsilon = 0.0001) = - let( - pts = [for(i = from; i <= to; i = i + 1) shape_pts[i]], - trimmed = _trim_shape_trim_lines(__lines_from(pts), epsilon) - ) - len(shape_pts) == len(trimmed) ? trimmed : trim_shape(trimmed, 0, len(trimmed) - 1, epsilon); + _trim_shape_impl(shape_pts, from, to, epsilon); diff --git a/test/test_trim_shape.scad b/test/test_trim_shape.scad index 185cb1f1..bf867c82 100644 --- a/test/test_trim_shape.scad +++ b/test/test_trim_shape.scad @@ -1,7 +1,7 @@ -include ; -include ; -include ; -include ; +use ; +use ; +use ; +use ; module test_trim_shape() { echo("==== test_trim_shape ====");