mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2024-12-29 16:29:40 +00:00
Fix for #985: cyl(r1,r2,h,chamfer)
This commit is contained in:
parent
d51634f554
commit
44866fc1e2
3 changed files with 80 additions and 259 deletions
|
@ -2771,8 +2771,7 @@ module show_anchors(s=10, std=true, custom=true) {
|
||||||
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
|
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
|
||||||
// Example:
|
// Example:
|
||||||
// anchor_arrow(s=20);
|
// anchor_arrow(s=20);
|
||||||
module anchor_arrow(s=10, color=[0.333,0.333,1], flag=true, $tag="anchor-arrow", anchor=BOT, spin=0, orient=UP) {
|
module anchor_arrow(s=10, color=[0.333,0.333,1], flag=true, $tag="anchor-arrow", $fn=12, anchor=BOT, spin=0, orient=UP) {
|
||||||
$fn=12;
|
|
||||||
attachable(anchor,spin,orient, r=s/6, l=s) {
|
attachable(anchor,spin,orient, r=s/6, l=s) {
|
||||||
down(s/2)
|
down(s/2)
|
||||||
recolor("gray") spheroid(d=s/6) {
|
recolor("gray") spheroid(d=s/6) {
|
||||||
|
|
207
shapes3d.scad
207
shapes3d.scad
|
@ -1186,13 +1186,15 @@ function cylinder(h, r1, r2, center, l, r, d, d1, d2, anchor, spin=0, orient=UP)
|
||||||
// d2 = Diameter of the positive (X+, Y+, Z+) end of cylinder.
|
// d2 = Diameter of the positive (X+, Y+, Z+) end of cylinder.
|
||||||
// circum = If true, cylinder should circumscribe the circle of the given size. Otherwise inscribes. Default: `false`
|
// circum = If true, cylinder should circumscribe the circle of the given size. Otherwise inscribes. Default: `false`
|
||||||
// shift = [X,Y] amount to shift the center of the top end with respect to the center of the bottom end.
|
// shift = [X,Y] amount to shift the center of the top end with respect to the center of the bottom end.
|
||||||
// chamfer = The size of the chamfers on the ends of the cylinder. Default: none.
|
// chamfer = The size of the chamfers on the ends of the cylinder. (Also see: `from_end=`) Default: none.
|
||||||
// chamfer1 = The size of the chamfer on the bottom end of the cylinder. Default: none.
|
// chamfer1 = The size of the chamfer on the bottom end of the cylinder. (Also see: `from_end1=`) Default: none.
|
||||||
// chamfer2 = The size of the chamfer on the top end of the cylinder. Default: none.
|
// chamfer2 = The size of the chamfer on the top end of the cylinder. (Also see: `from_end2=`) Default: none.
|
||||||
// chamfang = The angle in degrees of the chamfers on the ends of the cylinder.
|
// chamfang = The angle in degrees of the chamfers away from the ends of the cylinder. Default: Chamfer angle is halfway between the endcap and cone face.
|
||||||
// chamfang1 = The angle in degrees of the chamfer on the bottom end of the cylinder.
|
// chamfang1 = The angle in degrees of the bottom chamfer away from the bottom end of the cylinder. Default: Chamfer angle is halfway between the endcap and cone face.
|
||||||
// chamfang2 = The angle in degrees of the chamfer on the top end of the cylinder.
|
// chamfang2 = The angle in degrees of the top chamfer away from the top end of the cylinder. Default: Chamfer angle is halfway between the endcap and cone face.
|
||||||
// from_end = If true, chamfer is measured from the end of the cylinder, instead of inset from the edge. Default: `false`.
|
// from_end = If true, chamfer is measured along the conic face from the ends of the cylinder, instead of inset from the edge. Default: `false`.
|
||||||
|
// from_end1 = If true, chamfer on the bottom end of the cylinder is measured along the conic face from the end of the cylinder, instead of inset from the edge. Default: `false`.
|
||||||
|
// from_end2 = If true, chamfer on the top end of the cylinder is measured along the conic face from the end of the cylinder, instead of inset from the edge. Default: `false`.
|
||||||
// rounding = The radius of the rounding on the ends of the cylinder. Default: none.
|
// rounding = The radius of the rounding on the ends of the cylinder. Default: none.
|
||||||
// rounding1 = The radius of the rounding on the bottom end of the cylinder.
|
// rounding1 = The radius of the rounding on the bottom end of the cylinder.
|
||||||
// rounding2 = The radius of the rounding on the top end of the cylinder.
|
// rounding2 = The radius of the rounding on the top end of the cylinder.
|
||||||
|
@ -1339,8 +1341,8 @@ function cyl(
|
||||||
chamfer, chamfer1, chamfer2,
|
chamfer, chamfer1, chamfer2,
|
||||||
chamfang, chamfang1, chamfang2,
|
chamfang, chamfang1, chamfang2,
|
||||||
rounding, rounding1, rounding2,
|
rounding, rounding1, rounding2,
|
||||||
circum=false, realign=false,
|
circum=false, realign=false, shift=[0,0],
|
||||||
from_end=false, shift=[0,0],
|
from_end, from_end1, from_end2,
|
||||||
texture, tex_size=[5,5], tex_counts,
|
texture, tex_size=[5,5], tex_counts,
|
||||||
tex_inset=false, tex_rot=false,
|
tex_inset=false, tex_rot=false,
|
||||||
tex_scale=1, tex_samples,
|
tex_scale=1, tex_samples,
|
||||||
|
@ -1363,78 +1365,74 @@ function cyl(
|
||||||
assert(is_finite(r2), "r2 or d2 must be a finite number.")
|
assert(is_finite(r2), "r2 or d2 must be a finite number.")
|
||||||
assert(is_vector(shift,2), "shift must be a 2D vector.")
|
assert(is_vector(shift,2), "shift must be a 2D vector.")
|
||||||
let(
|
let(
|
||||||
vnf = texture != undef? _textured_cylinder(
|
vnf = !any_defined([chamfer, chamfer1, chamfer2, rounding, rounding1, rounding2, texture])
|
||||||
l=l, r1=r1, r2=r2,
|
? cylinder(h=l, r1=r1, r2=r2, center=true, $fn=sides)
|
||||||
texture=texture, tex_size=tex_size,
|
: let(
|
||||||
counts=tex_counts, tex_scale=tex_scale,
|
vang = atan2(r1-r2,l),
|
||||||
inset=tex_inset, rot=tex_rot,
|
_chamf1 = first_defined([chamfer1, chamfer, 0]),
|
||||||
style=tex_style, taper=tex_taper,
|
_chamf2 = first_defined([chamfer2, chamfer, 0]),
|
||||||
chamfer=chamfer,
|
_fromend1 = first_defined([from_end1, from_end, false]),
|
||||||
chamfer1=chamfer1,
|
_fromend2 = first_defined([from_end2, from_end, false]),
|
||||||
chamfer2=chamfer2,
|
chang1 = first_defined([chamfang1, chamfang, 45+vang/2]),
|
||||||
rounding=rounding,
|
chang2 = first_defined([chamfang2, chamfang, 45-vang/2]),
|
||||||
rounding1=rounding1,
|
|
||||||
rounding2=rounding2,
|
|
||||||
samples=tex_samples
|
|
||||||
) :
|
|
||||||
!any_defined([chamfer, chamfer1, chamfer2, rounding, rounding1, rounding2])?
|
|
||||||
cylinder(h=l, r1=r1, r2=r2, center=true, $fn=sides) :
|
|
||||||
let(
|
|
||||||
vang = atan2(l, r1-r2)/2,
|
|
||||||
chang = default(chamfang, 45),
|
|
||||||
chang1 = 90-first_defined([chamfang1, chamfang, vang]),
|
|
||||||
chang2 = 90-first_defined([chamfang2, chamfang, 90-vang]),
|
|
||||||
checks1 =
|
|
||||||
assert(is_finite(chang) && chang>0 && chang<90, "chamfang must be a number between 0 and 90 (exclusive) if given.")
|
|
||||||
assert(is_finite(chang1) && chang1>0 && chang1<90, "chamfang1 must be a number between 0 and 90 (exclusive) if given.")
|
|
||||||
assert(is_finite(chang2) && chang2>0 && chang2<90, "chamfang2 must be a number between 0 and 90 (exclusive) if given.")
|
|
||||||
undef,
|
|
||||||
chamf = default(chamfer, 0) * (from_end? 1 : tan(chang1)),
|
|
||||||
chamf1 = first_defined([chamfer1, chamfer, 0]) * (from_end? 1 : tan(chang1)),
|
|
||||||
chamf2 = first_defined([chamfer2, chamfer, 0]) * (from_end? 1 : tan(chang2)),
|
|
||||||
round = default(rounding, 0),
|
|
||||||
round1 = first_defined([rounding1, rounding, 0]),
|
round1 = first_defined([rounding1, rounding, 0]),
|
||||||
round2 = first_defined([rounding2, rounding, 0]),
|
round2 = first_defined([rounding2, rounding, 0]),
|
||||||
dy1 = abs(first_defined([chamf1, round1, 0])),
|
checks1 =
|
||||||
dy2 = abs(first_defined([chamf2, round2, 0])),
|
assert(is_finite(_chamf1), "chamfer1 must be a finite number if given.")
|
||||||
|
assert(is_finite(_chamf2), "chamfer2 must be a finite number if given.")
|
||||||
|
assert(is_finite(chang1) && chang1>0 && chang1<90, "chamfang1 must be a number between 0 and 90 (exclusive) if given.")
|
||||||
|
assert(is_finite(chang2) && chang2>0 && chang2<90, "chamfang2 must be a number between 0 and 90 (exclusive) if given.")
|
||||||
|
assert(chang1<=90+vang, "chamfang1 is larger than the cone face angle")
|
||||||
|
assert(180-chang2>=90+vang, "chamfang2 is larger than the cone face angle")
|
||||||
|
undef,
|
||||||
|
chamf1r = !_chamf1? 0 : !_fromend1? _chamf1 :
|
||||||
|
law_of_sines(a=_chamf1, A=chang1, B=180-chang1-(90-vang)),
|
||||||
|
chamf2r = !_chamf2? 0 : !_fromend2? _chamf2 :
|
||||||
|
law_of_sines(a=_chamf2, A=chang2, B=180-chang2-(90+vang)),
|
||||||
|
chamf1l = !_chamf1? 0 : _fromend1? _chamf1 :
|
||||||
|
law_of_sines(a=_chamf1, A=180-chang1-(90-vang), B=chang1),
|
||||||
|
chamf2l = !_chamf2? 0 : _fromend2? _chamf2 :
|
||||||
|
law_of_sines(a=_chamf2, A=180-chang2-(90+vang), B=chang2),
|
||||||
|
facelen = adj_ang_to_hyp(l, abs(vang)),
|
||||||
|
cp1 = [r1,-l/2],
|
||||||
|
cp2 = [r2,+l/2],
|
||||||
|
dy1 = abs(first_defined([chamf1l, round1, 0])),
|
||||||
|
dy2 = abs(first_defined([chamf2l, round2, 0])),
|
||||||
checks2 =
|
checks2 =
|
||||||
assert(is_finite(chamf), "chamfer must be a finite number if given.")
|
|
||||||
assert(is_finite(chamf1), "chamfer1 must be a finite number if given.")
|
|
||||||
assert(is_finite(chamf2), "chamfer2 must be a finite number if given.")
|
|
||||||
assert(is_finite(round), "rounding must be a finite number if given.")
|
|
||||||
assert(is_finite(round1), "rounding1 must be a finite number if given.")
|
assert(is_finite(round1), "rounding1 must be a finite number if given.")
|
||||||
assert(is_finite(round2), "rounding2 must be a finite number if given.")
|
assert(is_finite(round2), "rounding2 must be a finite number if given.")
|
||||||
assert(chamf <= r1, "chamfer is larger than the r1 radius of the cylinder.")
|
assert(chamf1r <= r1, "chamfer1 is larger than the r1 radius of the cylinder.")
|
||||||
assert(chamf <= r2, "chamfer is larger than the r2 radius of the cylinder.")
|
assert(chamf2r <= r2, "chamfer2 is larger than the r2 radius of the cylinder.")
|
||||||
assert(chamf1 <= r1, "chamfer1 is larger than the r1 radius of the cylinder.")
|
|
||||||
assert(chamf2 <= r2, "chamfer2 is larger than the r2 radius of the cylinder.")
|
|
||||||
assert(round <= r1, "rounding is larger than the r1 radius of the cylinder.")
|
|
||||||
assert(round <= r2, "rounding is larger than the r2 radius of the cylinder.")
|
|
||||||
assert(round1 <= r1, "rounding1 is larger than the r1 radius of the cylinder.")
|
assert(round1 <= r1, "rounding1 is larger than the r1 radius of the cylinder.")
|
||||||
assert(round2 <= r2, "rounding2 is larger than the r1 radius of the cylinder.")
|
assert(round2 <= r2, "rounding2 is larger than the r1 radius of the cylinder.")
|
||||||
assert(dy1+dy2 <= l, "Sum of fillets and chamfer sizes must be less than the length of the cylinder.")
|
assert(dy1+dy2 <= facelen, "Sum of fillets and chamfer sizes must be less than the length of the cylinder/cone face.")
|
||||||
undef,
|
undef,
|
||||||
path = [
|
path = [
|
||||||
[0,-l/2],
|
if (texture==undef) [0,-l/2],
|
||||||
if (is_finite(chamf1) && !approx(chamf1,0))
|
if (is_finite(chamf1r) && !approx(chamf1r,0))
|
||||||
let(
|
each [
|
||||||
p1 = [r1-chamf1/tan(chang1),-l/2],
|
[r1, -l/2] + polar_to_xy(chamf1r,180),
|
||||||
p2 = lerp([r1,-l/2],[r2,l/2],abs(chamf1)/l)
|
[r1, -l/2] + polar_to_xy(chamf1l,90+vang),
|
||||||
) each [p1,p2]
|
]
|
||||||
else if (is_finite(round1) && !approx(round1,0))
|
else if (is_finite(round1) && !approx(round1,0))
|
||||||
each arc(r=abs(round1), corner=[[(round1>0?0:1e6),-l/2],[r1,-l/2],[r2,l/2]])
|
each arc(r=abs(round1), corner=[[(round1>0?0:1e6),-l/2],[r1,-l/2],[r2,l/2]])
|
||||||
else [r1,-l/2],
|
else [r1,-l/2],
|
||||||
if (is_finite(chamf2) && !approx(chamf2,0))
|
if (is_finite(chamf2r) && !approx(chamf2r,0))
|
||||||
let(
|
each [
|
||||||
p1 = lerp([r2,l/2],[r1,-l/2],abs(chamf2)/l),
|
[r2, l/2] + polar_to_xy(chamf2l,270+vang),
|
||||||
p2 = [r2-chamf2/tan(chang2),l/2]
|
[r2, l/2] + polar_to_xy(chamf2r,180),
|
||||||
) each [p1,p2]
|
]
|
||||||
else if (is_finite(round2) && !approx(round2,0))
|
else if (is_finite(round2) && !approx(round2,0))
|
||||||
each arc(r=abs(round2), corner=[[r1,-l/2],[r2,l/2],[(round2>0?0:1e6),l/2]])
|
each arc(r=abs(round2), corner=[[r1,-l/2],[r2,l/2],[(round2>0?0:1e6),l/2]])
|
||||||
else [r2,l/2],
|
else [r2,l/2],
|
||||||
[0,l/2]
|
if (texture==undef) [0,l/2],
|
||||||
]
|
]
|
||||||
) rotate_sweep(path),
|
) rotate_sweep(path,
|
||||||
|
texture=texture, tex_counts=tex_counts, tex_size=tex_size,
|
||||||
|
tex_inset=tex_inset, tex_rot=tex_rot,
|
||||||
|
tex_scale=tex_scale, tex_samples=tex_samples,
|
||||||
|
tex_taper=tex_taper, style=tex_style, closed=false
|
||||||
|
),
|
||||||
skmat = down(l/2) *
|
skmat = down(l/2) *
|
||||||
skew(sxz=shift.x/l, syz=shift.y/l) *
|
skew(sxz=shift.x/l, syz=shift.y/l) *
|
||||||
up(l/2) *
|
up(l/2) *
|
||||||
|
@ -1451,8 +1449,8 @@ module cyl(
|
||||||
chamfer, chamfer1, chamfer2,
|
chamfer, chamfer1, chamfer2,
|
||||||
chamfang, chamfang1, chamfang2,
|
chamfang, chamfang1, chamfang2,
|
||||||
rounding, rounding1, rounding2,
|
rounding, rounding1, rounding2,
|
||||||
circum=false, realign=false,
|
circum=false, realign=false, shift=[0,0],
|
||||||
from_end=false, shift=[0,0],
|
from_end, from_end1, from_end2,
|
||||||
texture, tex_size=[5,5], tex_counts,
|
texture, tex_size=[5,5], tex_counts,
|
||||||
tex_inset=false, tex_rot=false,
|
tex_inset=false, tex_rot=false,
|
||||||
tex_scale=1, tex_samples,
|
tex_scale=1, tex_samples,
|
||||||
|
@ -1472,69 +1470,22 @@ module cyl(
|
||||||
attachable(anchor,spin,orient, r1=r1, r2=r2, l=l, shift=shift) {
|
attachable(anchor,spin,orient, r1=r1, r2=r2, l=l, shift=shift) {
|
||||||
multmatrix(skmat)
|
multmatrix(skmat)
|
||||||
zrot(realign? 180/sides : 0) {
|
zrot(realign? 180/sides : 0) {
|
||||||
if (texture != undef) {
|
if (!any_defined([chamfer, chamfer1, chamfer2, rounding, rounding1, rounding2, texture])) {
|
||||||
_textured_cylinder(
|
|
||||||
l=l, r1=r1, r2=r2,
|
|
||||||
texture=texture, tex_size=tex_size,
|
|
||||||
counts=tex_counts, tex_scale=tex_scale,
|
|
||||||
inset=tex_inset, rot=tex_rot,
|
|
||||||
style=tex_style, taper=tex_taper,
|
|
||||||
chamfer=chamfer,
|
|
||||||
chamfer1=chamfer1,
|
|
||||||
chamfer2=chamfer2,
|
|
||||||
rounding=rounding,
|
|
||||||
rounding1=rounding1,
|
|
||||||
rounding2=rounding2,
|
|
||||||
convexity=10, samples=tex_samples
|
|
||||||
);
|
|
||||||
} else if (!any_defined([chamfer, chamfer1, chamfer2, rounding, rounding1, rounding2])) {
|
|
||||||
cylinder(h=l, r1=r1, r2=r2, center=true, $fn=sides);
|
cylinder(h=l, r1=r1, r2=r2, center=true, $fn=sides);
|
||||||
} else {
|
} else {
|
||||||
vang = atan2(l, r1-r2)/2;
|
vnf = cyl(
|
||||||
chang1 = 90-first_defined([chamfang1, chamfang, vang,]);
|
l=l, r1=r1, r2=r2, center=true, $fn=sides,
|
||||||
chang2 = 90-first_defined([chamfang2, chamfang, 90-vang]);
|
chamfer=chamfer, chamfer1=chamfer1, chamfer2=chamfer2,
|
||||||
chamf = default(chamfer, 0) * (from_end? 1 : tan(chang1));
|
chamfang=chamfang, chamfang1=chamfang1, chamfang2=chamfang2,
|
||||||
chamf1 = first_defined([chamfer1, chamfer, 0]) * (from_end? 1 : tan(chang1));
|
rounding=rounding, rounding1=rounding1, rounding2=rounding2,
|
||||||
chamf2 = first_defined([chamfer2, chamfer, 0]) * (from_end? 1 : tan(chang2));
|
from_end=from_end, from_end1=from_end1, from_end2=from_end2,
|
||||||
round = default(rounding, 0);
|
texture=texture, tex_size=tex_size,
|
||||||
round1 = first_defined([rounding1, rounding, 0]);
|
tex_counts=tex_counts, tex_scale=tex_scale,
|
||||||
round2 = first_defined([rounding2, rounding, 0]);
|
tex_inset=tex_inset, tex_rot=tex_rot,
|
||||||
dy1 = abs(first_defined([chamf1, round1, 0]));
|
tex_style=tex_style, tex_taper=tex_taper,
|
||||||
dy2 = abs(first_defined([chamf2, round2, 0]));
|
tex_samples=tex_samples
|
||||||
checks =
|
);
|
||||||
assert(chamf <= r1, "chamfer is larger than the r1 radius of the cylinder.")
|
vnf_polyhedron(vnf, convexity=texture!=undef? 2 : 10);
|
||||||
assert(chamf <= r2, "chamfer is larger than the r2 radius of the cylinder.")
|
|
||||||
assert(chamf1 <= r1, "chamfer1 is larger than the r1 radius of the cylinder.")
|
|
||||||
assert(chamf2 <= r2, "chamfer2 is larger than the r2 radius of the cylinder.")
|
|
||||||
assert(round <= r1, "rounding is larger than the r1 radius of the cylinder.")
|
|
||||||
assert(round <= r2, "rounding is larger than the r2 radius of the cylinder.")
|
|
||||||
assert(round1 <= r1, "rounding1 is larger than the r1 radius of the cylinder.")
|
|
||||||
assert(round2 <= r2, "rounding2 is larger than the r1 radius of the cylinder.")
|
|
||||||
assert(dy1+dy2 <= l, "Sum of fillets and chamfer sizes must be less than the length of the cylinder.")
|
|
||||||
undef;
|
|
||||||
path = [
|
|
||||||
[0,-l/2],
|
|
||||||
if (is_finite(chamf1) && !approx(chamf1,0))
|
|
||||||
let(
|
|
||||||
p1 = [r1-chamf1/tan(chang1),-l/2],
|
|
||||||
p2 = lerp([r1,-l/2],[r2,l/2],abs(chamf1)/l)
|
|
||||||
) each [p1,p2]
|
|
||||||
else if (is_finite(round1) && !approx(round1,0))
|
|
||||||
each arc(r=abs(round1), corner=[[(round1>0?0:1e6),-l/2],[r1,-l/2],[r2,l/2]])
|
|
||||||
else [r1,-l/2],
|
|
||||||
if (is_finite(chamf2) && !approx(chamf2,0))
|
|
||||||
let(
|
|
||||||
p1 = lerp([r2,l/2],[r1,-l/2],abs(chamf2)/l),
|
|
||||||
p2 = [r2-chamf2/tan(chang2),l/2]
|
|
||||||
) each [p1,p2]
|
|
||||||
else if (is_finite(round2) && !approx(round2,0))
|
|
||||||
each arc(r=abs(round2), corner=[[r1,-l/2],[r2,l/2],[(round2>0?0:1e6),l/2]])
|
|
||||||
else [r2,l/2],
|
|
||||||
[0,l/2]
|
|
||||||
];
|
|
||||||
|
|
||||||
vnf = rotate_sweep(path);
|
|
||||||
vnf_polyhedron(vnf, convexity=2);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
children();
|
children();
|
||||||
|
|
129
skin.scad
129
skin.scad
|
@ -3625,134 +3625,5 @@ module _textured_revolution(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Function&Module: _textured_cylinder()
|
|
||||||
/// Usage: As Function
|
|
||||||
/// vnf = _textured_cylinder(h|l=, r|d=, texture, tex_size|counts=, [tex_scale=], [inset=], [rot=], ...);
|
|
||||||
/// vnf = _textured_cylinder(h|l=, r1=|d1=, r2=|d2=, texture=, tex_size=|counts=, [tex_scale=], [inset=], [rot=], ...);
|
|
||||||
/// Usage: As Module
|
|
||||||
/// _textured_cylinder(h, r|d=, texture, tex_size|counts=, [tex_scale=], [inset=], [rot=], ...) [ATTACHMENTS];
|
|
||||||
/// _textured_cylinder(h, r1=|d1=, r2=|d2=, texture=, tex_size=|counts=, [tex_scale=], [inset=], [rot=], ...) [ATTACHMENTS];
|
|
||||||
/// Topics: Sweep, Extrusion, Textures, Knurling
|
|
||||||
/// Description:
|
|
||||||
/// Creates a cylinder or cone with optional chamfers or roundings, covered in a textured surface.
|
|
||||||
/// The texture can be given in one of three ways:
|
|
||||||
/// - As a texture name string. (See {{texture()}} for supported named textures.)
|
|
||||||
/// - As a 2D array of evenly spread height values. (AKA a heightfield.)
|
|
||||||
/// - As a VNF texture tile. A VNF tile exactly defines a surface from `[0,0]` to `[1,1]`, with the Z coordinates
|
|
||||||
/// being the height of the texture point from the surface. VNF tiles MUST be able to tile in both X and Y
|
|
||||||
/// directions with no gaps, with the front and back edges aligned exactly, and the left and right edges as well.
|
|
||||||
/// One script to convert a grayscale image to a texture heightfield array in a .scad file can be found at:
|
|
||||||
/// https://raw.githubusercontent.com/revarbat/BOSL2/master/scripts/img2scad.py
|
|
||||||
/// Arguments:
|
|
||||||
/// h | l = The height of the cylinder.
|
|
||||||
/// r = The radius of the cylinder.
|
|
||||||
/// texture = A texture name string, or a rectangular array of scalar height values (0.0 to 1.0), or a VNF tile that defines the texture to apply to the cylinder wall surfaces. See {{texture()}} for what named textures are supported.
|
|
||||||
/// tex_size = An optional 2D target size for the textures. Actual texture sizes will be scaled somewhat to evenly fit the available surface. Default: `[5,5]`
|
|
||||||
/// ---
|
|
||||||
/// r1 = The radius of the bottom of the cylinder.
|
|
||||||
/// r2 = The radius of the top of the cylinder.
|
|
||||||
/// d = The diameter of the cylinder.
|
|
||||||
/// d1 = The diameter of the bottom of the cylinder.
|
|
||||||
/// d2 = The diameter of the top of the cylinder.
|
|
||||||
/// tex_scale = Scaling multiplier for the texture depth.
|
|
||||||
/// inset = If numeric, lowers the texture into the surface by that amount, before the tex_scale multiplier is applied. If `true`, insets by exactly `1`. Default: `false`
|
|
||||||
/// rot = If true, rotates the texture 90º.
|
|
||||||
/// caps = (function only) If true, create endcaps for the extruded shape. Default: `true`
|
|
||||||
/// shift = [X,Y] amount to translate the top, relative to the bottom. Default: [0,0]
|
|
||||||
/// style = The triangulation style used. See {{vnf_vertex_array()}} for valid styles. Default: `"min_edge"`
|
|
||||||
/// taper = If given, tapers the texture height to zero over the given percentage of the top and bottom of the cylinder face. Default: `undef` (no taper)
|
|
||||||
/// counts = If given instead of tex_size, gives the tile repetition counts for textures over the surface length and height.
|
|
||||||
/// chamfer = If given, chamfers the top and bottom of the cylinder by the given size. If given a negative size, creates a chamfer that juts *outward* from the cylinder.
|
|
||||||
/// chamfer1 = If given, chamfers the bottom of the cylinder by the given size. If given a negative size, creates a chamfer that juts *outward* from the cylinder.
|
|
||||||
/// chamfer2 = If given, chamfers the top of the cylinder by the given size. If given a negative size, creates a chamfer that juts *outward* from the cylinder.
|
|
||||||
/// rounding = If given, rounds the top and bottom of the cylinder to the given radius. If given a negative size, creates a roundover that juts *outward* from the cylinder.
|
|
||||||
/// rounding1 = If given, rounds the bottom of the cylinder to the given radius. If given a negative size, creates a roundover that juts *outward* from the cylinder.
|
|
||||||
/// rounding2 = If given, rounds the top of the cylinder to the given radius. If given a negative size, creates a roundover that juts *outward* from the cylinder.
|
|
||||||
/// samples = Minimum number of "bend points" to have in VNF texture tiles. Default: 8
|
|
||||||
/// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
|
|
||||||
/// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
|
|
||||||
/// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
|
|
||||||
/// See Also: heightfield(), cylindrical_heightfield(), texture()
|
|
||||||
|
|
||||||
function _textured_cylinder(
|
|
||||||
h, r, texture, tex_size=[1,1], counts,
|
|
||||||
tex_scale=1, inset=false, rot=false,
|
|
||||||
caps=true, style="min_edge", taper,
|
|
||||||
shift=[0,0], l, r1, r2, d, d1, d2,
|
|
||||||
chamfer, chamfer1, chamfer2,
|
|
||||||
rounding, rounding1, rounding2,
|
|
||||||
samples
|
|
||||||
) =
|
|
||||||
let(
|
|
||||||
h = first_defined([h, l, 1]),
|
|
||||||
r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=1),
|
|
||||||
r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=1),
|
|
||||||
chamf1 = first_defined([chamfer1, chamfer, 0]),
|
|
||||||
chamf2 = first_defined([chamfer2, chamfer, 0]),
|
|
||||||
round1 = first_defined([rounding1, rounding, 0]),
|
|
||||||
round2 = first_defined([rounding2, rounding, 0]),
|
|
||||||
needed_h = chamf1 + chamf2 + round1 + round2,
|
|
||||||
needed_r1 = chamf1 + round1,
|
|
||||||
needed_r2 = chamf2 + round2,
|
|
||||||
checks =
|
|
||||||
assert(needed_h <= h, "Cylinder not tall enough for specified roundings and chamfers.")
|
|
||||||
assert(needed_r1 <= r1, "Cylinder bottom radius too small for given rounding or chamfer.")
|
|
||||||
assert(needed_r2 <= r2, "Cylinder top radius too small for given rounding or chamfer.")
|
|
||||||
,
|
|
||||||
path = [
|
|
||||||
if (is_finite(chamf1) && !approx(chamf1,0))
|
|
||||||
each arc(n=2, r=abs(chamf1), corner=[[(chamf1>0?0:1e6),-h/2],[r1,-h/2],[r2,h/2]])
|
|
||||||
else if (is_finite(round1) && !approx(round1,0))
|
|
||||||
each arc(r=abs(round1), corner=[[(round1>0?0:1e6),-h/2],[r1,-h/2],[r2,h/2]])
|
|
||||||
else [r1,-h/2],
|
|
||||||
if (is_finite(chamf2) && !approx(chamf2,0))
|
|
||||||
each arc(n=2, r=abs(chamf2), corner=[[r1,-h/2],[r2,h/2],[(chamf2>0?0:1e6),h/2]])
|
|
||||||
else if (is_finite(round2) && !approx(round2,0))
|
|
||||||
each arc(r=abs(round2), corner=[[r1,-h/2],[r2,h/2],[(round2>0?0:1e6),h/2]])
|
|
||||||
else [r2,h/2],
|
|
||||||
],
|
|
||||||
vnf = _textured_revolution(
|
|
||||||
reverse(path), texture, closed=false,
|
|
||||||
tex_size=tex_size, counts=counts,
|
|
||||||
tex_scale=tex_scale, inset=inset, rot=rot,
|
|
||||||
style=style, shift=shift, taper=taper,
|
|
||||||
samples=samples
|
|
||||||
)
|
|
||||||
) vnf;
|
|
||||||
|
|
||||||
|
|
||||||
module _textured_cylinder(
|
|
||||||
h, r, texture, tex_size=[1,1],
|
|
||||||
counts, tex_scale=1, inset=false, rot=false,
|
|
||||||
style="min_edge", shift=[0,0], taper,
|
|
||||||
l, r1, r2, d, d1, d2,
|
|
||||||
chamfer, chamfer1, chamfer2,
|
|
||||||
rounding, rounding1, rounding2,
|
|
||||||
convexity=10, samples,
|
|
||||||
anchor=CENTER, spin=0, orient=UP
|
|
||||||
) {
|
|
||||||
h = first_defined([h, l, 1]);
|
|
||||||
r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=1);
|
|
||||||
r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=1);
|
|
||||||
chamf1 = first_defined([chamfer1, chamfer]);
|
|
||||||
chamf2 = first_defined([chamfer2, chamfer]);
|
|
||||||
round1 = first_defined([rounding1, rounding]);
|
|
||||||
round2 = first_defined([rounding2, rounding]);
|
|
||||||
vnf = _textured_cylinder(
|
|
||||||
texture=texture, h=h, r1=r1, r2=r2,
|
|
||||||
tex_scale=tex_scale, inset=inset, rot=rot,
|
|
||||||
counts=counts, tex_size=tex_size,
|
|
||||||
caps=true, style=style, taper=taper,
|
|
||||||
shift=shift, samples=samples,
|
|
||||||
chamfer1=chamf1, chamfer2=chamf2,
|
|
||||||
rounding1=round1, rounding2=round2
|
|
||||||
);
|
|
||||||
attachable(anchor,spin,orient, r1=r1, r2=r2, h=h, shift=shift) {
|
|
||||||
vnf_polyhedron(vnf, convexity=convexity);
|
|
||||||
children();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||||
|
|
Loading…
Reference in a new issue