You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

209 lines
5.8 KiB

/**
* sweep.scad
*
* @copyright Justin Lin, 2020
* @license https://opensource.org/licenses/lgpl-3.0.html
*
* @see https://openhome.cc/eGossip/OpenSCAD/lib3x-sweep.html
*
**/
use <reverse.scad>
module sweep(sections, triangles = "SOLID") {
function side_indexes(sects, begin_idx = 0) =
let(
leng_sects = len(sects),
leng_pts_sect = len(sects[0]),
range_j = [begin_idx:leng_pts_sect:begin_idx + (leng_sects - 2) * leng_pts_sect],
range_i = [0:leng_pts_sect - 1]
)
concat(
[
for(j = range_j, i = range_i)
let(i2 = j + (i + 1) % leng_pts_sect)
[
j + i,
i2,
i2 + leng_pts_sect
]
],
[
for(j = range_j, i = range_i)
let(ji = j + i)
[
ji,
j + (i + 1) % leng_pts_sect + leng_pts_sect ,
ji + leng_pts_sect
]
]
);
function the_same_after_twisting(f_sect, l_sect) =
let(found = search([l_sect[0]], f_sect)[0], leng = len(l_sect))
found != [] &&
len([for(i = 0; l_sect[i] == f_sect[(found + i) % leng]; i = i + 1) undef]) == leng;
function to_v_pts(sects) = [for(sect = sects) each sect];
module solid_sections(sects) {
leng_sects = len(sects);
leng_pts_sect = len(sects[0]);
first_sect = sects[0];
last_sect = sects[leng_sects - 1];
v_pts = to_v_pts(sects);
begin_end_the_same =
first_sect == last_sect || the_same_after_twisting(first_sect, last_sect);
if(begin_end_the_same) {
f_idxes = side_indexes(sects);
polyhedron(v_pts, f_idxes);
// hook for testing
test_sweep_solid(v_pts, f_idxes, triangles);
} else {
from = leng_pts_sect * (leng_sects - 1);
f_idxes = [
[each [leng_pts_sect - 1:-1:0]],
each side_indexes(sects),
[each [from:from + leng_pts_sect - 1]]
];
polyhedron(v_pts, f_idxes);
// hook for testing
test_sweep_solid(v_pts, f_idxes, triangles);
}
}
module hollow_sections(sects) {
leng_sects = len(sects);
leng_sect = len(sects[0]);
half_leng_sect = leng_sect / 2;
half_leng_v_pts = leng_sects * half_leng_sect;
function strip_sects(begin_idx, end_idx) =
let(range = [begin_idx:end_idx])
[for(sect = sects) [for(j = range) sect[j]]];
range = [0:half_leng_sect - 1];
function first_idxes() =
[
for(i = range)
let(i3 = (i + 1) % half_leng_sect)
[
i,
i + half_leng_v_pts,
i3 + half_leng_v_pts,
i3
]
];
function last_idxes(begin_idx) =
[
for(i = range)
let(bi = begin_idx + i, i2 = begin_idx + (i + 1) % half_leng_sect)
[
bi,
i2,
i2 + half_leng_v_pts,
bi + half_leng_v_pts
]
];
outer_sects = strip_sects(0, half_leng_sect - 1);
inner_sects = strip_sects(half_leng_sect, leng_sect - 1);
outer_idxes = side_indexes(outer_sects);
inner_idxes = [for(idxes = side_indexes(inner_sects, half_leng_v_pts)) reverse(idxes)];
first_outer_sect = outer_sects[0];
last_outer_sect = outer_sects[leng_sects - 1];
first_inner_sect = inner_sects[0];
last_inner_sect = inner_sects[leng_sects - 1];
leng_pts_sect = len(first_outer_sect);
begin_end_the_same =
(first_outer_sect == last_outer_sect && first_inner_sect == last_inner_sect) ||
(
the_same_after_twisting(first_outer_sect, last_outer_sect) &&
the_same_after_twisting(first_inner_sect, last_inner_sect)
);
v_pts = concat(to_v_pts(outer_sects), to_v_pts(inner_sects));
if(begin_end_the_same) {
f_idxes = concat(outer_idxes, inner_idxes);
polyhedron(
v_pts,
f_idxes
);
// hook for testing
test_sweep_solid(v_pts, f_idxes, triangles);
} else {
f_idxes = concat(
first_idxes(),
outer_idxes,
inner_idxes,
last_idxes(half_leng_v_pts - half_leng_sect)
);
polyhedron(
v_pts,
f_idxes
);
// hook for testing
test_sweep_solid(v_pts, f_idxes, triangles);
}
}
module triangles_defined_sections() {
faces = [
[0, 1, 2], [3, 5, 4],
[1, 3, 4], [2, 1, 4], [2, 3, 0],
[0, 3, 1], [2, 4, 5], [2, 5, 3]
];
module two_sections(section1, section2) {
for(idx = triangles) {
polyhedron(
concat(
[for(i = idx) section1[i]],
[for(i = idx) section2[i]]
),
faces
);
}
}
for(i = [0:len(sections) - 2]) {
two_sections(
sections[i],
sections[i + 1]
);
}
}
if(triangles == "SOLID") {
solid_sections(sections);
} else if(triangles == "HOLLOW") {
hollow_sections(sections);
}
else {
triangles_defined_sections();
}
}
// override it to test
module test_sweep_solid(points, faces, triangles) {
}