From 0fe11992d0de4107a2d5cfad266ce11c6ead8438 Mon Sep 17 00:00:00 2001 From: Justin Lin Date: Mon, 1 May 2017 09:28:44 +0800 Subject: [PATCH] added path_extend --- docs/images/lib-path_extend-1.JPG | Bin 0 -> 35734 bytes docs/lib-path_extend.md | 42 +++++++++++++++++++ src/path_extend.scad | 66 ++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+) create mode 100644 docs/images/lib-path_extend-1.JPG create mode 100644 docs/lib-path_extend.md create mode 100644 src/path_extend.scad diff --git a/docs/images/lib-path_extend-1.JPG b/docs/images/lib-path_extend-1.JPG new file mode 100644 index 0000000000000000000000000000000000000000..77710e45f5825777d487a97f0991af93c8b71007 GIT binary patch literal 35734 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 DV@99= literal 0 HcmV?d00001 diff --git a/docs/lib-path_extend.md b/docs/lib-path_extend.md new file mode 100644 index 00000000..49f7caf5 --- /dev/null +++ b/docs/lib-path_extend.md @@ -0,0 +1,42 @@ +# path_extend + +It extends a 2D stroke along a path. This module is suitable for a path created by a continuous function. + +It depends on the rotate_p function and the polytransversals module. Remember to include "rotate_p.scad" and "polytransversals.scad". + +When using this module, you should use points to represent the 2D stroke. + +## Parameters + +- `stroke_pts` : A list of points represent a stroke. See the example below. +- `path_pts` : A list of points represent the path. + +## Examples + + include ; + include ; + include ; + include ; + include ; + + $fn = 96; + + stroke1 = [[-5, 2.5], [-2.5, 0], [0, 2.5], [2.5, 0], [5, 2.5]]; + path_pts1 = circle_path(50, 60); + path_extend(stroke1, path_pts1); + + stroke2 = [[-4, 0], [0, 4], [4, 0]]; + pts_angles = archimedean_spiral( + arm_distance = 17, + init_angle = 180, + point_distance = 5, + num_of_points = 85 + ); + + translate([120, 0, 0]) + path_extend( + stroke2, + [for(pa = pts_angles) pa[0]] + ); + +![path_extend](images/lib-path_extend-1.JPG) \ No newline at end of file diff --git a/src/path_extend.scad b/src/path_extend.scad new file mode 100644 index 00000000..1f2cc7e3 --- /dev/null +++ b/src/path_extend.scad @@ -0,0 +1,66 @@ +/** +* path_extend.scad +* +* It extends a 2D stroke along a path. +* This module is suitable for a path created by a continuous function. +* It depends on the rotate_p function and the polytransversals module. +* Remember to include "rotate_p.scad" and "polytransversals.scad". +* +* @copyright Justin Lin, 2017 +* @license https://opensource.org/licenses/lgpl-3.0.html +* +* @see https://openhome.cc/eGossip/OpenSCAD/lib-path_extend.html +* +**/ + +module path_extend(stroke_pts, path_pts) { + function length(p1, p2) = + let( + x1 = p1[0], + y1 = p1[1], + x2 = p2[0], + y2 = p2[1] + ) sqrt(pow(x2 - x1, 2) + pow(y2 - y1, 2)); + + function az(p1, p2) = + let( + x1 = p1[0], + y1 = p1[1], + x2 = p2[0], + y2 = p2[1] + ) -90 + atan2((y2 - y1), (x2 - x1)); + + leng_path_pts = len(path_pts); + + function first_stroke() = + let( + p1 = path_pts[0], + p2 = path_pts[1], + a = az(p1, p2) + ) + [ + for(p = stroke_pts) + rotate_p(p, a) + p1 + ]; + + function stroke(p1, p2) = + let( + leng = length(p1, p2), + a = az(p1, p2) + ) + [ + for(p = stroke_pts) + rotate_p(p + [0, leng], a) + p1 + ]; + + function path_extend_inner(index) = + index == leng_path_pts ? [] : + concat( + [stroke(path_pts[index - 1], path_pts[index])], + path_extend_inner(index + 1) + ); + + polytransversals( + concat([first_stroke()], path_extend_inner(1)) + ); +}