1
0
mirror of https://github.com/JustinSDK/dotSCAD.git synced 2025-01-17 14:18:13 +01:00
dotSCAD/src/along_with.scad

195 lines
6.4 KiB
OpenSCAD
Raw Normal View History

2017-04-23 11:16:34 +08:00
/**
* along_with.scad
*
* @copyright Justin Lin, 2017
* @license https://opensource.org/licenses/lgpl-3.0.html
*
* @see https://openhome.cc/eGossip/OpenSCAD/lib-along_with.html
*
**/
2019-05-07 17:35:32 +08:00
include <__private__/__angy_angz.scad>;
2017-06-17 17:50:11 +08:00
include <__private__/__to3d.scad>;
2019-05-04 10:04:50 +08:00
2019-05-31 10:12:59 +08:00
module along_with(points, angles, twist = 0, scale = 1.0, method = "AXIS_ANGLE") {
2017-05-19 11:24:43 +08:00
leng_points = len(points);
2017-05-19 13:42:34 +08:00
leng_points_minus_one = leng_points - 1;
2017-05-19 13:19:03 +08:00
twist_step_a = twist / leng_points;
2019-05-31 09:55:02 +08:00
2019-06-12 08:59:54 +08:00
angles_defined = !is_undef(angles);
2017-05-19 13:42:34 +08:00
2019-06-11 08:39:57 +08:00
scale_step_vt = is_num(scale) ?
2019-06-16 21:09:41 +08:00
let(s = (scale - 1) / leng_points_minus_one) [s, s, s] :
2017-05-19 13:42:34 +08:00
[
(scale[0] - 1) / leng_points_minus_one,
(scale[1] - 1) / leng_points_minus_one,
2019-06-12 08:59:54 +08:00
is_undef(scale[2]) ? 0 : (scale[2] - 1) / leng_points_minus_one
2019-05-15 19:35:42 +08:00
];
2019-05-04 10:04:50 +08:00
2019-05-31 10:19:33 +08:00
/*
Sadly, children(n) cannot be used with inner modules
so I have to do things in the first level. Ugly!!
*/
// >>> begin: modules and functions for "AXIS-ANGLE"
// get rotation matrice for sections
2019-05-13 09:50:53 +08:00
identity_matrix = [
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]
];
2019-05-31 10:09:49 +08:00
function axis_angle_local_ang_vects(j) =
2019-06-15 10:56:33 +08:00
[
for(i = j; i > 0; i = i - 1)
let(
vt0 = points[i] - points[i - 1],
vt1 = points[i + 1] - points[i],
a = acos((vt0 * vt1) / (norm(vt0) * norm(vt1))),
v = cross(vt0, vt1)
)
[a, v]
];
2019-05-04 10:04:50 +08:00
2019-05-31 10:09:49 +08:00
function axis_angle_cumulated_rot_matrice(i, rot_matrice) =
2019-05-04 10:04:50 +08:00
let(
leng_rot_matrice = len(rot_matrice),
leng_rot_matrice_minus_one = leng_rot_matrice - 1,
leng_rot_matrice_minus_two = leng_rot_matrice - 2
)
2019-05-13 09:50:53 +08:00
leng_rot_matrice == 0 ? [identity_matrix] : (
leng_rot_matrice == 1 ? [rot_matrice[0], identity_matrix] : (
i == leng_rot_matrice_minus_two ?
2019-05-04 10:04:50 +08:00
[
rot_matrice[leng_rot_matrice_minus_one],
2019-05-07 17:35:32 +08:00
rot_matrice[leng_rot_matrice_minus_two] * rot_matrice[leng_rot_matrice_minus_one]
2019-05-04 10:04:50 +08:00
]
2019-05-31 10:09:49 +08:00
: axis_angle_cumulated_rot_matrice_sub(i, rot_matrice)
2019-05-13 09:50:53 +08:00
)
);
2019-05-04 10:04:50 +08:00
2019-05-31 10:09:49 +08:00
function axis_angle_cumulated_rot_matrice_sub(i, rot_matrice) =
2019-05-04 10:04:50 +08:00
let(
2019-05-31 10:09:49 +08:00
matrice = axis_angle_cumulated_rot_matrice(i + 1, rot_matrice),
2019-05-04 10:04:50 +08:00
curr_matrix = rot_matrice[i],
prev_matrix = matrice[len(matrice) - 1]
)
2019-05-07 17:35:32 +08:00
concat(matrice, [curr_matrix * prev_matrix]);
2019-05-04 10:04:50 +08:00
// align modules
2019-05-31 10:09:49 +08:00
module axis_angle_align_with_pts_angles(i) {
translate(points[i])
2019-04-29 10:49:27 +08:00
rotate(angles[i])
rotate(twist_step_a * i)
scale([1, 1, 1] + scale_step_vt * i)
children(0);
2017-05-19 13:42:34 +08:00
}
2017-05-03 16:21:49 +08:00
2019-05-31 10:09:49 +08:00
module axis_angle_align_with_pts_init(a, s) {
2019-06-15 10:49:58 +08:00
angleyz = __angy_angz(__to3d(points[0]), __to3d(points[1]));
2019-04-29 10:49:27 +08:00
rotate([0, -angleyz[0], angleyz[1]])
rotate([90, 0, -90])
rotate(a)
scale(s)
children(0);
}
2019-05-31 10:09:49 +08:00
module axis_angle_align_with_pts_local_rotate(j, init_a, init_s, cumu_rot_matrice) {
2019-04-29 10:49:27 +08:00
if(j == 0) { // first child
2019-05-31 10:09:49 +08:00
axis_angle_align_with_pts_init(init_a, init_s)
2019-04-29 10:49:27 +08:00
children(0);
}
else {
2019-05-04 10:04:50 +08:00
multmatrix(cumu_rot_matrice[j - 1])
2019-05-31 10:09:49 +08:00
axis_angle_align_with_pts_init(init_a, init_s)
2019-04-29 10:49:27 +08:00
children(0);
2017-04-23 11:16:34 +08:00
}
2019-05-04 10:48:38 +08:00
}
2019-04-29 10:49:27 +08:00
2019-05-31 10:19:33 +08:00
// <<< end: modules and functions for "AXIS-ANGLE"
// >>> begin: modules and functions for "EULER-ANGLE"
2019-06-15 11:04:16 +08:00
function _euler_angle_path_angles(pts, end_i) =
[for(i = 0; i < end_i; i = i + 1) [__angy_angz(pts[i], pts[i + 1])]];
2019-05-31 10:19:33 +08:00
function euler_angle_path_angles(children) =
let(
pts = len(points[0]) == 3 ? points : [for(pt = points) __to3d(pt)],
end_i = children == 1 ? leng_points_minus_one : children - 1,
angs = _euler_angle_path_angles(pts, end_i)
)
concat(
[[0, -angs[0][0], angs[0][1]]],
[for(a = angs) [0, -a[0], a[1]]]
);
module euler_angle_align(i, angs) {
translate(points[i])
rotate(angs[i])
rotate(angles_defined ? [0, 0, 0] : [90, 0, -90])
rotate(twist_step_a * i)
scale([1, 1, 1] + scale_step_vt * i)
children(0);
}
// <<< end: modules and functions for "EULER-ANGLE"
2019-05-31 10:12:59 +08:00
if(method == "AXIS_ANGLE") {
if(angles_defined) {
if($children == 1) {
for(i = [0:leng_points_minus_one]) {
axis_angle_align_with_pts_angles(i) children(0);
}
} else {
for(i = [0:min(leng_points, $children) - 1]) {
axis_angle_align_with_pts_angles(i) children(i);
}
2019-04-29 10:49:27 +08:00
}
2017-04-23 11:16:34 +08:00
}
2019-05-31 10:12:59 +08:00
else {
cumu_rot_matrice = axis_angle_cumulated_rot_matrice(0, [
for(ang_vect = axis_angle_local_ang_vects(leng_points - 2))
m_rotation(ang_vect[0], ang_vect[1])
]);
translate(points[0])
axis_angle_align_with_pts_local_rotate(0, 0, [1, 1, 1], cumu_rot_matrice)
children(0);
if($children == 1) {
for(i = [0:leng_points - 2]) {
translate(points[i + 1])
axis_angle_align_with_pts_local_rotate(i, i * twist_step_a, [1, 1, 1] + scale_step_vt * i, cumu_rot_matrice)
children(0);
}
} else {
for(i = [0:min(leng_points, $children) - 2]) {
translate(points[i + 1])
axis_angle_align_with_pts_local_rotate(i, i * twist_step_a, [1, 1, 1] + scale_step_vt * i, cumu_rot_matrice)
children(i + 1);
}
2019-04-29 10:49:27 +08:00
}
}
}
2019-05-31 10:19:33 +08:00
else if(method == "EULER_ANGLE") {
if($children == 1) {
angs = angles_defined ? angles : euler_angle_path_angles($children);
for(i = [0:leng_points_minus_one]) {
euler_angle_align(i, angs) children(0);
}
} else {
for(i = [0:min(leng_points, $children) - 1]) {
euler_angle_align(i, angs) children(i);
}
}
}
2019-05-31 10:12:59 +08:00
2017-04-23 11:16:34 +08:00
}