mirror of
https://github.com/JustinSDK/dotSCAD.git
synced 2025-01-17 14:18:13 +01:00
fix crossing bug when touching z axis
This commit is contained in:
parent
3efef1b2bb
commit
e89804cadf
@ -19,62 +19,94 @@ include <__private__/__angy_angz.scad>;
|
||||
include <__private__/__length_between.scad>;
|
||||
|
||||
module path_extrude(shape_pts, path_pts, triangles = "SOLID", twist = 0, scale = 1.0, closed = false) {
|
||||
function scale_pts(pts, s) = [
|
||||
for(p = pts) [p[0] * s[0], p[1] * s[1], p[2] * s[2]]
|
||||
];
|
||||
|
||||
function translate_pts(pts, t) = [
|
||||
for(p = pts) [p[0] + t[0], p[1] + t[1], p[2] + t[2]]
|
||||
];
|
||||
|
||||
function rotate_pts(pts, a, v) = [for(p = pts) rotate_p(p, a, v)];
|
||||
|
||||
sh_pts = len(shape_pts[0]) == 3 ? shape_pts : [for(p = shape_pts) __to3d(p)];
|
||||
pth_pts = len(path_pts[0]) == 3 ? path_pts : [for(p = path_pts) __to3d(p)];
|
||||
|
||||
len_path_pts = len(pth_pts);
|
||||
len_path_pts_minus_one = len_path_pts - 1;
|
||||
twist_step_a = twist / len_path_pts;
|
||||
|
||||
len_path_pts = len(pth_pts);
|
||||
len_path_pts_minus_one = len_path_pts - 1;
|
||||
function scale_step() =
|
||||
let(s = (scale - 1) / len_path_pts_minus_one)
|
||||
[s, s, s];
|
||||
|
||||
scale_step_vt = __is_vector(scale) ?
|
||||
[(scale[0] - 1) / len_path_pts_minus_one, (scale[1] - 1) / len_path_pts_minus_one] :
|
||||
[(scale - 1) / len_path_pts_minus_one, (scale - 1) / len_path_pts_minus_one];
|
||||
|
||||
scale_step_x = scale_step_vt[0];
|
||||
scale_step_y = scale_step_vt[1];
|
||||
twist_step = twist / len_path_pts_minus_one;
|
||||
|
||||
function section(p1, p2, i) =
|
||||
let(
|
||||
length = __length_between(p1, p2),
|
||||
angy_angz = __angy_angz(p1, p2),
|
||||
ay = -angy_angz[0],
|
||||
az = angy_angz[1]
|
||||
)
|
||||
[
|
||||
for(p = sh_pts)
|
||||
let(scaled_p = [p[0] * (1 + scale_step_x * i), p[1] * (1 + scale_step_y * i), p[2]])
|
||||
rotate_p(
|
||||
rotate_p(
|
||||
rotate_p(scaled_p, twist_step * i), [90, 0, -90]
|
||||
) + [i == 0 ? 0 : length, 0, 0],
|
||||
[0, ay, az]
|
||||
) + p1
|
||||
];
|
||||
(scale[0] - 1) / len_path_pts_minus_one,
|
||||
(scale[1] - 1) / len_path_pts_minus_one,
|
||||
scale[2] == undef ? 0 : (scale[2] - 1) / len_path_pts_minus_one
|
||||
] : scale_step();
|
||||
|
||||
function path_extrude_inner(index) =
|
||||
index == len_path_pts ? [] :
|
||||
concat(
|
||||
[section(pth_pts[index - 1], pth_pts[index], index)],
|
||||
path_extrude_inner(index + 1)
|
||||
);
|
||||
function init_section(a, s) =
|
||||
let(angleyz = __angy_angz(pth_pts[0], pth_pts[1]))
|
||||
rotate_pts(
|
||||
rotate_pts(
|
||||
rotate_pts(
|
||||
scale_pts(sh_pts, s), a
|
||||
), [90, 0, -90]
|
||||
), [0, -angleyz[0], angleyz[1]]
|
||||
);
|
||||
|
||||
function local_rotate_section(j, init_a, init_s) =
|
||||
j == 0 ?
|
||||
init_section(init_a, init_s) :
|
||||
local_rotate_section_sub(j, init_a, init_s);
|
||||
|
||||
function local_rotate_section_sub(j, init_a, init_s) =
|
||||
let(
|
||||
vt0 = pth_pts[j] - pth_pts[j - 1],
|
||||
vt1 = pth_pts[j + 1] - pth_pts[j],
|
||||
a = acos((vt0 * vt1) / (norm(vt0) * norm(vt1)))
|
||||
)
|
||||
rotate_pts(
|
||||
local_rotate_section(j - 1, init_a, init_s),
|
||||
a,
|
||||
cross(vt0, vt1)
|
||||
);
|
||||
|
||||
function sections() =
|
||||
let(
|
||||
fst_section =
|
||||
translate_pts(local_rotate_section(0, 0, [1, 1, 1]), pth_pts[0]),
|
||||
remain_sections = [
|
||||
for(i = [0:len_path_pts - 2])
|
||||
|
||||
translate_pts(
|
||||
local_rotate_section(i, i * twist_step_a, [1, 1, 1] + scale_step_vt * i),
|
||||
pth_pts[i + 1]
|
||||
)
|
||||
|
||||
|
||||
]
|
||||
) concat([fst_section], remain_sections);
|
||||
|
||||
sects = sections();
|
||||
|
||||
function calculated_sections() =
|
||||
let(sections = path_extrude_inner(1))
|
||||
closed && pth_pts[0] == pth_pts[len_path_pts_minus_one] ?
|
||||
concat(sections, [sections[0]]) : // round-robin
|
||||
concat([section(pth_pts[0], pth_pts[1], 0)], sections);
|
||||
|
||||
sections = calculated_sections();
|
||||
|
||||
polysections(
|
||||
sections,
|
||||
closed && pth_pts[0] == pth_pts[len_path_pts - 1] ?
|
||||
concat(sects, [sects[0]]) : // round-robin
|
||||
sects;
|
||||
|
||||
polysections(
|
||||
calculated_sections(),
|
||||
triangles = triangles
|
||||
);
|
||||
|
||||
// hook for testing
|
||||
test_path_extrude(sections);
|
||||
test_path_extrude(sects);
|
||||
}
|
||||
|
||||
|
||||
// override to test
|
||||
module test_path_extrude(sections) {
|
||||
|
||||
|
@ -1,73 +0,0 @@
|
||||
/**
|
||||
* rounded_extrude.scad
|
||||
*
|
||||
* Extrudes a 2D object roundly from 0 to 180 degrees.
|
||||
*
|
||||
* @copyright Justin Lin, 2017
|
||||
* @license https://opensource.org/licenses/lgpl-3.0.html
|
||||
*
|
||||
* @see https://openhome.cc/eGossip/OpenSCAD/lib-rounded_extrude.html
|
||||
*
|
||||
**/
|
||||
|
||||
include <__private__/__frags.scad>;
|
||||
include <__private__/__is_vector.scad>;
|
||||
|
||||
module rounded_extrude(size, round_r, angle = 90, twist = 0, convexity = 10) {
|
||||
|
||||
is_vt = __is_vector(size);
|
||||
x = is_vt ? size[0] : size;
|
||||
y = is_vt ? size[1] : size;
|
||||
|
||||
q_corner_frags = __frags(round_r) / 4;
|
||||
|
||||
step_a = angle / q_corner_frags;
|
||||
twist_step = twist / q_corner_frags;
|
||||
|
||||
module layers(pre_x, pre_y, pre_h = 0, i = 1) {
|
||||
module one_layer(current_a) {
|
||||
wx = pre_x;
|
||||
wy = pre_y;
|
||||
|
||||
h = (round_r - pre_h) - round_r * cos(current_a);
|
||||
|
||||
d_leng =
|
||||
round_r * (sin(current_a) - sin(step_a * (i - 1)));
|
||||
|
||||
sx = (d_leng * 2 + wx) / wx;
|
||||
sy = (d_leng * 2 + wy) / wy;
|
||||
|
||||
translate([0, 0, pre_h])
|
||||
rotate(-twist_step * (i - 1))
|
||||
linear_extrude(
|
||||
h,
|
||||
slices = 1,
|
||||
scale = [sx, sy],
|
||||
convexity = convexity,
|
||||
twist = twist_step
|
||||
) scale([wx / x, wy / y])
|
||||
children();
|
||||
|
||||
test_rounded_extrude_data(i, wx, wy, pre_h, sx, sy);
|
||||
|
||||
layers(wx * sx, wy * sy, h + pre_h, i + 1)
|
||||
children();
|
||||
|
||||
}
|
||||
|
||||
if(i <= q_corner_frags) {
|
||||
one_layer(i * step_a)
|
||||
children();
|
||||
} else if(i - q_corner_frags < 1) {
|
||||
one_layer(q_corner_frags * step_a)
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
layers(x, y)
|
||||
children();
|
||||
}
|
||||
|
||||
module test_rounded_extrude_data(i, wx, wy, pre_h, sx, sy) {
|
||||
|
||||
}
|
@ -39,10 +39,8 @@ include <test_sphere_spiral.scad>;
|
||||
// Extrude
|
||||
include <test_ellipse_extrude.scad>;
|
||||
include <test_stereographic_extrude.scad>;
|
||||
include <test_rounded_extrude.scad>;
|
||||
|
||||
// 2D Shape
|
||||
include <test_shape_arc.scad>;
|
||||
include <test_shape_cyclicpolygon.scad>;
|
||||
include <test_shape_ellipse.scad>;
|
||||
include <test_shape_pie.scad>;
|
||||
@ -52,7 +50,6 @@ include <test_shape_superformula.scad>;
|
||||
include <test_shape_path_extend.scad>;
|
||||
|
||||
// 2D Shape Extrusion
|
||||
include <test_path_extrude.scad>;
|
||||
include <test_ring_extrude.scad>;
|
||||
include <test_helix_extrude.scad>;
|
||||
include <test_golden_spiral_extrude.scad>;
|
||||
|
@ -1,110 +0,0 @@
|
||||
include <unittest.scad>;
|
||||
include <rotate_p.scad>;
|
||||
include <polysections.scad>;
|
||||
include <bezier_curve.scad>;
|
||||
|
||||
module test_path_extrude_solid() {
|
||||
echo("==== test_path_extrude_solid ====");
|
||||
|
||||
include <path_extrude.scad>;
|
||||
|
||||
|
||||
module test_path_extrude(sections) {
|
||||
|
||||
expected = [
|
||||
[[5.397, -0.555, -4.535], [1.822, -2.918, 3.628], [-1.011, -1.847, 4.535], [-3.374, 4.248, -4.535]]
|
||||
, [[11.589, 10.753, 1.45], [8.014, 8.389, 9.613], [5.181, 9.461, 10.52], [2.817, 15.556, 1.45]]
|
||||
, [[14.618, 21.695, 5.415], [11.753, 19.184, 13.811], [8.78, 19.721, 14.744], [5.059, 24.634, 5.415]]
|
||||
, [[15.197, 31.507, 7.655], [13.009, 29.421, 16.365], [9.998, 29.428, 17.332], [5.234, 32.368, 7.655]]
|
||||
, [[14.187, 40.279, 8.465], [12.292, 39.109, 17.411], [9.317, 38.707, 18.406], [4.235, 39.3, 8.465]]
|
||||
, [[12.296, 48.252, 8.117], [10.269, 48.138, 17.11], [7.339, 47.494, 18.11], [2.558, 45.978, 8.117]]
|
||||
, [[10.014, 55.647, 6.808], [7.65, 56.504, 15.678], [4.737, 55.771, 16.664], [0.469, 52.664, 6.808]]
|
||||
, [[7.713, 62.556, 4.706], [5.023, 64.284, 13.353], [2.091, 63.591, 14.314], [-1.767, 59.372, 4.706]]
|
||||
, [[5.701, 68.972, 1.99], [2.82, 71.53, 10.366], [-0.155, 70.996, 11.297], [-3.856, 66.028, 1.99]]
|
||||
, [[4.212, 74.821, -1.149], [1.361, 78.214, 6.935], [-1.66, 77.957, 7.833], [-5.524, 72.536, -1.149]]
|
||||
, [[3.385, 79.976, -4.515], [0.869, 84.217, 3.275], [-2.169, 84.362, 4.14], [-6.546, 78.801, -4.515]]
|
||||
, [[3.243, 84.268, -7.913], [1.477, 89.313, -0.401], [-1.494, 90.003, 0.434], [-6.747, 84.736, -7.913]]
|
||||
, [[3.659, 87.529, -11.16], [3.195, 93.152, -3.868], [0.474, 94.545, -3.058], [-5.951, 90.293, -11.16]]
|
||||
, [[4.359, 89.714, -14.108], [5.8, 95.248, -6.876], [3.687, 97.459, -6.073], [-3.825, 95.46, -14.108]]
|
||||
, [[5.254, 91.116, -16.683], [8.57, 95.212, -9.118], [7.605, 98.104, -8.278], [0.452, 99.888, -16.683]]
|
||||
, [[7.267, 91.738, -18.724], [10.636, 93.636, -10.354], [11.096, 96.623, -9.425], [7.573, 101.734, -18.724]]
|
||||
, [[10.944, 90.082, -19.636], [12.796, 91.353, -10.695], [14.324, 93.937, -9.701], [15.704, 98.876, -19.636]]
|
||||
, [[15.178, 85.229, -19.043], [16.155, 87.132, -10.075], [18.329, 89.202, -9.079], [22.611, 91.918, -19.043]]
|
||||
, [[19.277, 76.941, -16.947], [20.204, 79.466, -8.129], [22.762, 81.046, -7.149], [28.116, 81.619, -16.947]]
|
||||
, [[22.824, 64.683, -13.254], [24.031, 67.528, -4.568], [26.817, 68.672, -3.603], [32.37, 67.664, -13.254]]
|
||||
, [[25.296, 47.757, -7.779], [26.852, 50.686, 0.823], [29.767, 51.452, 1.779], [35.17, 49.34, -7.779]]
|
||||
];
|
||||
|
||||
for(i = [0:len(expected) - 1]) {
|
||||
assertEqualPoints(expected[i], sections[i], float_digits = 3);
|
||||
}
|
||||
}
|
||||
|
||||
t_step = 0.05;
|
||||
width = 2;
|
||||
|
||||
p0 = [0, 0, 0];
|
||||
p1 = [40, 60, 35];
|
||||
p2 = [-50, 70, 0];
|
||||
p3 = [20, 150, -35];
|
||||
p4 = [30, 50, -3];
|
||||
|
||||
shape_pts = [
|
||||
[5, -5],
|
||||
[3, 4],
|
||||
[0, 5],
|
||||
[-5, -5]
|
||||
];
|
||||
|
||||
path_pts = bezier_curve(t_step,
|
||||
[p0, p1, p2, p3, p4]
|
||||
);
|
||||
|
||||
path_extrude(shape_pts, path_pts);
|
||||
}
|
||||
|
||||
|
||||
module test_path_extrude_hollow() {
|
||||
echo("==== test_path_extrude_hollow ====");
|
||||
|
||||
include <path_extrude.scad>;
|
||||
|
||||
module test_path_extrude(sections) {
|
||||
|
||||
expected = [[[4.386, -2.401, 0], [0.811, -4.765, 8.163], [-2.022, -3.693, 9.07], [-4.386, 2.401, 0], [2.227, -2.18, 1.814], [0.339, -3.546, 6.349], [-1.416, -2.585, 6.349], [-3.036, 0.702, 1.814]], [[10.577, 8.906, 5.985], [7.003, 6.543, 14.148], [4.169, 7.614, 15.055], [1.806, 13.709, 5.985], [8.419, 9.128, 7.799], [6.53, 7.762, 12.334], [4.776, 8.722, 12.334], [3.156, 12.01, 7.799]], [[14.088, 19.973, 10.08], [11.223, 17.462, 18.475], [8.25, 18, 19.408], [4.53, 22.913, 10.08], [11.965, 19.872, 11.945], [10.479, 18.445, 16.61], [8.568, 19.033, 16.61], [6.23, 21.636, 11.945]], [[15.088, 30.253, 12.493], [12.901, 28.166, 21.203], [9.89, 28.173, 22.171], [5.125, 31.113, 12.493], [13.052, 29.923, 14.429], [11.948, 28.754, 19.268], [9.955, 28.926, 19.268], [7.075, 30.439, 14.429]], [[14.24, 39.738, 13.435], [12.345, 38.568, 22.382], [9.371, 38.166, 23.376], [4.288, 38.758, 13.435], [12.271, 39.325, 15.423], [11.329, 38.686, 20.394], [9.339, 38.49, 20.394], [6.3, 38.738, 15.423]], [[12.252, 48.442, 13.113], [10.225, 48.328, 22.106], [7.294, 47.683, 23.106], [2.514, 46.168, 13.113], [10.287, 48.063, 15.112], [9.269, 48.024, 20.108], [7.321, 47.57, 20.108], [4.444, 46.698, 15.112]], [[9.761, 56.455, 11.736], [7.398, 57.312, 20.606], [4.484, 56.578, 21.591], [0.217, 53.471, 11.736], [7.751, 56.181, 13.707], [6.545, 56.69, 18.635], [4.636, 56.094, 18.635], [2.025, 54.391, 13.707]], [[7.272, 63.87, 9.51], [4.581, 65.597, 18.157], [1.649, 64.905, 19.118], [-2.208, 60.685, 9.51], [5.199, 63.758, 11.432], [3.81, 64.754, 16.236], [1.914, 64.117, 16.236], [-0.489, 61.848, 11.432]], [[5.162, 70.72, 6.643], [2.281, 73.278, 15.019], [-0.693, 72.744, 15.95], [-4.394, 67.776, 6.643], [3.036, 70.831, 8.505], [1.541, 72.284, 13.158], [-0.37, 71.695, 13.158], [-2.698, 69.064, 8.505]], [[3.709, 76.96, 3.342], [0.859, 80.354, 11.426], [-2.162, 80.096, 12.325], [-6.026, 74.675, 3.342], [1.562, 77.359, 5.139], [0.086, 79.269, 9.63], [-1.861, 78.812, 9.63], [-4.28, 75.988, 5.139]], [[3.09, 82.463, -0.188], [0.574, 86.704, 7.602], [-2.464, 86.849, 8.468], [-6.84, 81.287, -0.188], [0.986, 83.222, 1.544], [-0.301, 85.592, 5.871], [-2.287, 85.357, 5.871], [-4.972, 82.517, 1.544]], [[3.371, 87.019, -3.74], [1.605, 92.063, 3.773], [-1.366, 92.754, 4.607], [-6.618, 87.487, -3.74], [1.425, 88.213, -2.07], [0.555, 91.01, 2.103], [-1.443, 91.103, 2.103], [-4.568, 88.493, -2.07]], [[4.469, 90.346, -7.109], [4.005, 95.969, 0.183], [1.284, 97.361, 0.993], [-5.141, 93.11, -7.109], [2.871, 92.025, -5.488], [2.72, 95.119, -1.438], [0.798, 95.671, -1.438], [-2.895, 93.684, -5.488]], [[6.069, 92.15, -10.091], [7.51, 97.684, -2.858], [5.397, 99.894, -2.055], [-2.116, 97.895, -10.091], [5.116, 94.273, -8.483], [6.008, 97.284, -4.466], [4.371, 98.433, -4.466], [0.205, 97.721, -8.483]], [[7.63, 92.417, -12.48], [10.947, 96.513, -4.916], [9.981, 99.404, -4.075], [2.828, 101.189, -12.48], [7.62, 94.692, -10.799], [9.516, 96.87, -6.597], [8.556, 98.624, -6.597], [4.739, 99.955, -10.799]], [[9.105, 91.682, -14.074], [12.474, 93.58, -5.705], [12.933, 96.567, -4.775], [9.411, 101.677, -14.074], [9.901, 93.659, -12.214], [11.77, 94.602, -7.565], [11.831, 96.601, -7.565], [10.085, 99.656, -12.214]], [[11.444, 89.811, -14.669], [13.296, 91.082, -5.727], [14.825, 93.666, -4.734], [16.204, 98.605, -14.669], [12.596, 91.461, -12.682], [13.572, 92.07, -7.714], [14.524, 93.829, -7.714], [15.452, 96.738, -12.682]], [[14.895, 85.543, -14.061], [15.872, 87.447, -5.093], [18.046, 89.517, -4.097], [22.328, 92.232, -14.061], [16.269, 87.007, -12.068], [16.729, 87.99, -7.086], [18.216, 89.328, -7.086], [20.729, 91.02, -12.068]], [[18.81, 77.824, -12.048], [19.736, 80.349, -3.23], [22.294, 81.929, -2.25], [27.648, 82.502, -12.048], [20.391, 79.113, -10.089], [20.807, 80.464, -5.189], [22.575, 81.399, -5.189], [25.694, 81.919, -10.089]], [[22.434, 65.933, -8.429], [23.641, 68.777, 0.258], [26.427, 69.921, 1.223], [31.98, 68.913, -8.429], [24.187, 67.028, -6.498], [24.752, 68.576, -1.673], [26.661, 69.172, -1.673], [29.914, 68.817, -6.498]], [[25.063, 49.209, -3], [26.619, 52.138, 5.602], [29.535, 52.903, 6.558], [34.937, 50.791, -3], [26.945, 50.106, -1.088], [27.699, 51.716, 3.691], [29.674, 52.032, 3.691], [32.869, 51.056, -1.088]]];
|
||||
|
||||
for(i = [0:len(expected) - 1]) {
|
||||
assertEqualPoints(expected[i], sections[i], float_digits = 3);
|
||||
}
|
||||
}
|
||||
|
||||
t_step = 0.05;
|
||||
|
||||
p0 = [0, 0, 0];
|
||||
p1 = [40, 60, 35];
|
||||
p2 = [-50, 70, 0];
|
||||
p3 = [20, 150, -35];
|
||||
p4 = [30, 50, -3];
|
||||
|
||||
shape_pts = [
|
||||
// 外輪廓
|
||||
[5, 0],
|
||||
[3, 9],
|
||||
[0, 10],
|
||||
[-5, 0],
|
||||
// 內輪廓
|
||||
[3, 2],
|
||||
[2, 7],
|
||||
[0, 7],
|
||||
[-3, 2]
|
||||
];
|
||||
|
||||
path_pts = bezier_curve(t_step,
|
||||
[p0, p1, p2, p3, p4]
|
||||
);
|
||||
|
||||
path_extrude(shape_pts, path_pts, triangles = "HOLLOW");
|
||||
}
|
||||
|
||||
test_path_extrude_solid();
|
||||
test_path_extrude_hollow();
|
@ -1,14 +0,0 @@
|
||||
include <unittest.scad>;
|
||||
include <shape_arc.scad>;
|
||||
|
||||
module test_shape_arc() {
|
||||
echo("==== test_shape_arc ====");
|
||||
|
||||
expected = [[0, -12.4315], [1.3066, -12.4315], [3.8627, -11.8882], [6.25, -10.8253], [8.3641, -9.2893], [10.1127, -7.3473], [11.4193, -5.0842], [12.2268, -2.5989], [12.5, 0], [12.2268, 2.5989], [11.4193, 5.0842], [10.1127, 7.3473], [8.3641, 9.2893], [6.25, 10.8253], [3.8627, 11.8882], [1.3066, 12.4315], [0, 12.4315], [0, 7.4589], [0.784, 7.4589], [2.3176, 7.1329], [3.75, 6.4952], [5.0185, 5.5736], [6.0676, 4.4084], [6.8516, 3.0505], [7.3361, 1.5593], [7.5, 0], [7.3361, -1.5593], [6.8516, -3.0505], [6.0676, -4.4084], [5.0185, -5.5736], [3.75, -6.4952], [2.3176, -7.1329], [0.784, -7.4589], [0, -7.4589]];
|
||||
|
||||
actual = shape_arc(radius = 10, angle = [-90, 90], width = 5);
|
||||
|
||||
assertEqualPoints(expected, actual);
|
||||
}
|
||||
|
||||
test_shape_arc();
|
Loading…
x
Reference in New Issue
Block a user