mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2024-12-29 16:29:40 +00:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
b0dce28b44
4 changed files with 132 additions and 50 deletions
12
gears.scad
12
gears.scad
|
@ -2395,7 +2395,7 @@ function enveloping_worm(
|
|||
assert(is_finite(gear_spin))
|
||||
let(
|
||||
hsteps = segs(d/2),
|
||||
vsteps = hsteps*3,
|
||||
vsteps = hsteps,
|
||||
helical = asin(starts * circ_pitch / PI / d),
|
||||
pr = pitch_radius(circ_pitch, mate_teeth, helical=helical),
|
||||
taper_table = taper
|
||||
|
@ -2647,11 +2647,11 @@ function worm_gear(
|
|||
u = i / oslices,
|
||||
w_ang = worm_arc * (u - 0.5),
|
||||
g_ang_delta = w_ang/360 * tang * worm_starts * (left_handed?1:-1),
|
||||
m = zrot(dir*(rteeth-0.0)*tang, cp=[worm_diam/2+pr,0,0]) *
|
||||
m = zrot(dir*rteeth*tang+g_ang_delta, cp=[worm_diam/2+pr,0,0]) *
|
||||
left(crowning) *
|
||||
yrot(w_ang) *
|
||||
right(worm_diam/2+crowning) *
|
||||
zrot(-1*dir*(rteeth+0.0)*tang+g_ang_delta, cp=[pr,0,0]) *
|
||||
zrot(-dir*rteeth*tang+g_ang_delta, cp=[pr,0,0]) *
|
||||
xrot(180)
|
||||
) apply(m, point3d(pt))
|
||||
]
|
||||
|
@ -2674,7 +2674,7 @@ function worm_gear(
|
|||
twang1 = v_theta(truncrows[0][0]),
|
||||
twang2 = v_theta(last(truncrows[0])),
|
||||
twang = modang(twang1 - twang2) / (maxz-minz),
|
||||
resampled_rows = [for (row = truncrows) resample_path(row, n=slices, closed=false)],
|
||||
resampled_rows = [for (row = truncrows) resample_path(row, n=slices, keep_corners=30, closed=false)],
|
||||
tooth_rows = [
|
||||
for (row = resampled_rows) [
|
||||
zrot(twang*(zmax-row[0].z), p=[row[0].x, row[0].y, zmax]),
|
||||
|
@ -2963,7 +2963,7 @@ function _gear_tooth_profile(
|
|||
|
||||
// Reduce number of vertices.
|
||||
tooth = path_merge_collinear(
|
||||
resample_path(full_tooth, n=ceil(2*steps), closed=false)
|
||||
resample_path(full_tooth, n=ceil(2*steps), keep_corners=30, closed=false)
|
||||
),
|
||||
|
||||
out = center? fwd(prad, p=tooth) : tooth
|
||||
|
@ -3944,7 +3944,7 @@ module _show_gear_tooth_profile(
|
|||
stroke([polar_to_xy(min(rr,br)-mod/10,90+180/teeth),polar_to_xy(or+mod/10,90+180/teeth)], width=0.05, closed=true);
|
||||
}
|
||||
zrot_copies([0]) { // Tooth profile overlay
|
||||
stroke(tooth, width=0.1, dots=(show_verts?"dot":false), endcap_color1="green");
|
||||
stroke(tooth, width=0.1, dots=(show_verts?"dot":false), endcap_color1="green", endcap_color2="red");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -168,14 +168,14 @@ function is_collinear(a, b, c, eps=EPSILON) =
|
|||
// Topics: Geometry, Points, Lines, Distance
|
||||
// See Also: is_collinear(), is_point_on_line(), point_line_distance(), line_from_points()
|
||||
// Usage:
|
||||
// dist = point_line_distance(line, pt, [bounded]);
|
||||
// dist = point_line_distance(pt, line, [bounded]);
|
||||
// Description:
|
||||
// Finds the shortest distance from the point `pt` to the specified line, segment or ray.
|
||||
// The bounded parameter specifies the whether the endpoints give a ray or segment.
|
||||
// By default assumes an unbounded line.
|
||||
// Arguments:
|
||||
// line = A list of two points defining a line.
|
||||
// pt = A point to find the distance of from the line.
|
||||
// line = A list of two points defining a line.
|
||||
// bounded = a boolean or list of two booleans specifiying whether each end is bounded. Default: false
|
||||
// Example:
|
||||
// dist1 = point_line_distance([3,8], [[-10,0], [10,0]]); // Returns: 8
|
||||
|
|
74
paths.scad
74
paths.scad
|
@ -473,7 +473,8 @@ function subdivide_path(path, n, refine, maxlen, closed=true, exact, method) =
|
|||
// Description:
|
||||
// Compute a uniform resampling of the input path. If you specify `n` then the output path will have n
|
||||
// points spaced uniformly (by linear interpolation along the input path segments). The only points of the
|
||||
// input path that are guaranteed to appear in the output path are the starting and ending points.
|
||||
// input path that are guaranteed to appear in the output path are the starting and ending points, and any
|
||||
// points that have an angular deflection of at least the number of degrees given in `keep_corners`.
|
||||
// If you specify `spacing` then the length you give will be rounded to the nearest spacing that gives
|
||||
// a uniform sampling of the path and the resulting uniformly sampled path is returned.
|
||||
// Note that because this function operates on a discrete input path the quality of the output depends on
|
||||
|
@ -483,6 +484,7 @@ function subdivide_path(path, n, refine, maxlen, closed=true, exact, method) =
|
|||
// n = Number of points in output
|
||||
// ---
|
||||
// spacing = Approximate spacing desired
|
||||
// keep_corners = If given a scalar, path vertices with deflection angle greater than this are preserved in the output.
|
||||
// closed = set to true if path is closed. Default: true
|
||||
// Example(2D): Subsampling lots of points from a smooth curve
|
||||
// path = xscale(2,circle($fn=250, r=10));
|
||||
|
@ -494,35 +496,67 @@ function subdivide_path(path, n, refine, maxlen, closed=true, exact, method) =
|
|||
// sampled = resample_path(path, spacing=17);
|
||||
// stroke(path);
|
||||
// color("red")move_copies(sampled) circle($fn=16);
|
||||
// Example(2D): Notice that the corners are excluded
|
||||
// Example(2D): Notice that the corners are excluded.
|
||||
// path = square(20);
|
||||
// sampled = resample_path(path, spacing=6);
|
||||
// stroke(path,closed=true);
|
||||
// color("red")move_copies(sampled) circle($fn=16);
|
||||
// Example(2D): Forcing preservation of corners.
|
||||
// path = square(20);
|
||||
// sampled = resample_path(path, spacing=6, keep_corners=90);
|
||||
// stroke(path,closed=true);
|
||||
// color("red")move_copies(sampled) circle($fn=16);
|
||||
// Example(2D): Closed set to false
|
||||
// path = square(20);
|
||||
// sampled = resample_path(path, spacing=6,closed=false);
|
||||
// stroke(path);
|
||||
// color("red")move_copies(sampled) circle($fn=16);
|
||||
|
||||
|
||||
function resample_path(path, n, spacing, closed=true) =
|
||||
let(path = force_path(path))
|
||||
assert(is_path(path))
|
||||
assert(num_defined([n,spacing])==1,"Must define exactly one of n and spacing")
|
||||
assert(is_bool(closed))
|
||||
let(
|
||||
length = path_length(path,closed),
|
||||
// In the open path case decrease n by 1 so that we don't try to get
|
||||
// path_cut to return the endpoint (which might fail due to rounding)
|
||||
// Add last point later
|
||||
n = is_def(n) ? n-(closed?0:1) : round(length/spacing),
|
||||
distlist = lerpn(0,length,n,false),
|
||||
cuts = path_cut_points(path, distlist, closed=closed)
|
||||
)
|
||||
[ each column(cuts,0),
|
||||
if (!closed) last(path) // Then add last point here
|
||||
];
|
||||
function resample_path(path, n, spacing, keep_corners, closed=true) =
|
||||
let(path = force_path(path))
|
||||
assert(is_path(path))
|
||||
assert(num_defined([n,spacing])==1,"Must define exactly one of n and spacing")
|
||||
assert(n==undef || (is_integer(n) && n>0))
|
||||
assert(spacing==undef || (is_finite(spacing) && spacing>0))
|
||||
assert(is_bool(closed))
|
||||
let(
|
||||
corners = is_undef(keep_corners)
|
||||
? [0, len(path)-(closed?0:1)]
|
||||
: [
|
||||
0,
|
||||
for (i = [1:1:len(path)-(closed?1:2)])
|
||||
let( ang = abs(modang(vector_angle(select(path,i-1,i+1))-180)) )
|
||||
if (ang >= keep_corners) i,
|
||||
len(path)-(closed?0:1),
|
||||
],
|
||||
pcnt = len(path),
|
||||
plen = path_length(path, closed=closed),
|
||||
subpaths = [ for (p = pair(corners)) [for(i = [p.x:1:p.y]) path[i%pcnt]] ],
|
||||
n = is_undef(n)? undef : closed? n+1 : n
|
||||
)
|
||||
assert(n==undef || n >= len(corners), "There are nore than `n=` corners whose angle is greater than `keep_corners=`.")
|
||||
let(
|
||||
lens = [for (subpath = subpaths) path_length(subpath)],
|
||||
part_ns = is_undef(n)
|
||||
? [for (i=idx(subpaths)) max(1,round(lens[i]/spacing)-1)]
|
||||
: let(
|
||||
ccnt = len(corners),
|
||||
parts = [for (l=lens) (n-ccnt) * l/plen]
|
||||
)
|
||||
_sum_preserving_round(parts),
|
||||
out = [
|
||||
for (i = idx(subpaths))
|
||||
let(
|
||||
subpath = subpaths[i],
|
||||
splen = lens[i],
|
||||
pn = part_ns[i] + 1,
|
||||
distlist = lerpn(0, splen, pn, false),
|
||||
cuts = path_cut_points(subpath, distlist, closed=false)
|
||||
)
|
||||
each column(cuts,0),
|
||||
if (!closed) last(path)
|
||||
]
|
||||
) out;
|
||||
|
||||
|
||||
// Section: Path Geometry
|
||||
|
|
|
@ -173,29 +173,77 @@ test_subdivide_long_segments();
|
|||
|
||||
module test_resample_path(){
|
||||
path = xscale(2,circle($fn=250, r=10));
|
||||
sampled = resample_path(path, 16);
|
||||
assert_approx(sampled,
|
||||
[[20, 0], [17.1657142861, -5.13020769642],
|
||||
[11.8890531315, -8.04075246881], [6.03095737128,
|
||||
-9.53380030092], [1.72917236085e-14, -9.99921044204],
|
||||
[-6.03095737128, -9.53380030092], [-11.8890531315,
|
||||
-8.04075246881], [-17.1657142861, -5.13020769642], [-20,
|
||||
-3.19176120946e-14], [-17.1657142861, 5.13020769642],
|
||||
[-11.8890531315, 8.04075246881], [-6.03095737128,
|
||||
9.53380030092], [-4.20219414821e-14, 9.99921044204],
|
||||
[6.03095737128, 9.53380030092], [11.8890531315,
|
||||
8.04075246881], [17.1657142861, 5.13020769642]]);
|
||||
assert_approx(
|
||||
resample_path(path, 16), [
|
||||
[20, 0],
|
||||
[17.1657142861, -5.13020769642],
|
||||
[11.8890531315, -8.04075246881],
|
||||
[6.03095737128, -9.53380030092],
|
||||
[1.72917236085e-14, -9.99921044204],
|
||||
[-6.03095737128, -9.53380030092],
|
||||
[-11.8890531315, -8.04075246881],
|
||||
[-17.1657142861, -5.13020769642],
|
||||
[-20, -3.19176120946e-14],
|
||||
[-17.1657142861, 5.13020769642],
|
||||
[-11.8890531315, 8.04075246881],
|
||||
[-6.03095737128, 9.53380030092],
|
||||
[-4.20219414821e-14, 9.99921044204],
|
||||
[6.03095737128, 9.53380030092],
|
||||
[11.8890531315, 8.04075246881],
|
||||
[17.1657142861, 5.13020769642]
|
||||
]
|
||||
);
|
||||
path2 = square(20);
|
||||
assert_approx(resample_path(path2, spacing=6),
|
||||
[[20, 0], [13.8461538462, 0], [7.69230769231, 0], [1.53846153846, 0],
|
||||
[0, 4.61538461538], [0, 10.7692307692], [0, 16.9230769231], [3.07692307692, 20],
|
||||
[9.23076923077, 20], [15.3846153846, 20], [20, 18.4615384615], [20, 12.3076923077], [20, 6.15384615385]]);
|
||||
assert_equal(resample_path(path2, spacing=6,closed=false),[[20, 0], [14, 0], [8, 0], [2, 0], [0, 4], [0, 10], [0, 16], [2, 20], [8, 20], [14, 20], [20, 20]]);
|
||||
assert_approx(resample_path(path, spacing=17),
|
||||
[[20, 0], [8.01443073309, -9.16170407964],
|
||||
[-8.01443073309, -9.16170407964], [-20,
|
||||
-1.59309060367e-14], [-8.01443073309, 9.16170407964],
|
||||
[8.01443073309, 9.16170407964]]);
|
||||
assert_approx(
|
||||
resample_path(path2, spacing=6), [
|
||||
[20, 0], [13.8461538462, 0], [7.69230769231, 0],
|
||||
[1.53846153846, 0], [0, 4.61538461538],
|
||||
[0, 10.7692307692], [0, 16.9230769231],
|
||||
[3.07692307692, 20], [9.23076923077, 20],
|
||||
[15.3846153846, 20], [20, 18.4615384615],
|
||||
[20, 12.3076923077], [20, 6.15384615385]
|
||||
]
|
||||
);
|
||||
assert_equal(
|
||||
resample_path(path2, spacing=6,closed=false), [
|
||||
[20, 0], [14, 0], [ 8, 0], [ 2, 0],
|
||||
[ 0, 4], [ 0,10], [ 0,16], [ 2,20],
|
||||
[ 8,20], [14,20], [20,20]
|
||||
]
|
||||
);
|
||||
assert_equal(
|
||||
resample_path(path2, n=7, keep_corners=90, closed=true), [
|
||||
[20,0],[10,0],[0,0],[0,10],[0,20],[20,20],[20,10]
|
||||
]
|
||||
);
|
||||
assert_equal(
|
||||
resample_path(path2, n=7, keep_corners=90, closed=false), [
|
||||
[20,0],[10,0],[0,0],[0,10],[0,20],[10,20],[20,20]
|
||||
]
|
||||
);
|
||||
assert_approx(
|
||||
resample_path(path2, spacing=6, keep_corners=90, closed=false), [
|
||||
[20, 0], [13.3333333333, 0], [6.66666666667,0],
|
||||
[ 0, 0], [ 0,6.66666666667], [0,13.3333333333],
|
||||
[ 0,20], [ 6.66666666667,20], [13.3333333333,20],
|
||||
[20,20]
|
||||
]
|
||||
);
|
||||
assert_approx(
|
||||
resample_path(path2, spacing=6, keep_corners=90), [
|
||||
[20, 0], [13.3333333333, 0], [ 6.66666666667, 0],
|
||||
[ 0, 0], [ 0, 6.66666666667], [ 0,13.3333333333],
|
||||
[ 0,20], [ 6.66666666667,20], [13.3333333333,20],
|
||||
[20,20], [20,13.3333333333], [20, 6.66666666667]
|
||||
]
|
||||
);
|
||||
assert_approx(
|
||||
resample_path(path, spacing=17), [
|
||||
[20, 0], [8.01443073309, -9.16170407964],
|
||||
[-8.01443073309, -9.16170407964], [-20, -1.59309060367e-14],
|
||||
[-8.01443073309, 9.16170407964], [8.01443073309, 9.16170407964]
|
||||
]
|
||||
);
|
||||
}
|
||||
test_resample_path();
|
||||
|
||||
|
|
Loading…
Reference in a new issue