diff --git a/README.md b/README.md index f47d115b..91958ecc 100644 --- a/README.md +++ b/README.md @@ -23,3 +23,5 @@ I've been using OpenSCAD for years and created some funny things. Some of them i - [hollow_out](https://openhome.cc/eGossip/OpenSCAD/lib-hollow_out.html) - [bend](https://openhome.cc/eGossip/OpenSCAD/lib-bend.html) +- Math + - [bezier](https://openhome.cc/eGossip/OpenSCAD/lib-bezier.html) diff --git a/docs/images/lib-bezier-1.JPG b/docs/images/lib-bezier-1.JPG new file mode 100644 index 00000000..a2a136d0 Binary files /dev/null and b/docs/images/lib-bezier-1.JPG differ diff --git a/docs/lib-bezier.md b/docs/lib-bezier.md new file mode 100644 index 00000000..c27321f8 --- /dev/null +++ b/docs/lib-bezier.md @@ -0,0 +1,28 @@ +# bezier + +Given a set of control points, the bezier function returns points of the Bézier path. Combined with the `polyline`, `polyline3d` or `hull_polyline3d` module defined in my lib-openscad, you can create a Bézier curve. + +## Parameters + +- `t_step` : The distance between two points of the Bézier path. +- `points` : A set of `[x, y, z]` control points. + +## Examples + +If you have four control points and combine with the `hull_polyline3d` module: + + t_step = 0.05; + width = 2; + + p0 = [0, 0, 0]; + p1 = [40, 60, 35]; + p2 = [-50, 90, 0]; + p3 = [0, 200, -35]; + + points = bezier(t_step, + [p0, p1, p2, p3] + ); + + hull_polyline3d(points, width); + +![bezier](images/lib-bezier-1.JPG) diff --git a/src/bezier.scad b/src/bezier.scad new file mode 100644 index 00000000..667da796 --- /dev/null +++ b/src/bezier.scad @@ -0,0 +1,46 @@ +/** +* bezier.scad +* +* Given a set of control points, the bezier function returns points of the Bézier path. +* Combined with the polyline, polyline3d or hull_polyline3d module defined in my lib-openscad, +* you can create a Bézier curve. +* +* @copyright Justin Lin, 2017 +* @license https://opensource.org/licenses/lgpl-3.0.html +* +* @see https://openhome.cc/eGossip/OpenSCAD/lib-bezier.html +* +**/ + +function _combi(r, n) = + n == 0 ? 1 : (_combi(r, n - 1) * (r - n + 1) / n); + +function bezier_coordinate(t, pn, n, i = 0) = + i == n + 1 ? 0 : + (_combi(n, i) * pn[i] * pow(1 - t, n - i) * pow(t, i) + + bezier_coordinate(t, pn, n, i + 1)); + +function _bezier_point(t, points) = + [ + bezier_coordinate( + t, + [points[0][0], points[1][0], points[2][0], points[3][0]], + len(points) - 1 + ), + bezier_coordinate( + t, + [points[0][1], points[1][1], points[2][1], points[3][1]], + len(points) - 1 + ), + bezier_coordinate( + t, + [points[0][2], points[1][2], points[2][2], points[3][2]], + len(points) - 1 + ) + ]; + +function bezier(t_step, points) = + [ + for(t = [0: t_step: 1 + t_step]) + _bezier_point(t, points) + ]; \ No newline at end of file