Add shift= to linear_sweep()

This commit is contained in:
Garth Minette 2022-04-18 03:21:10 -07:00
parent e4bac06df7
commit f87b5b8c2f

204
skin.scad
View file

@ -517,20 +517,25 @@ function skin(profiles, slices, refine=1, method="direct", sampling, caps, close
// a custom point location. // a custom point location.
// Arguments: // Arguments:
// region = The 2D [Region](regions.scad) or polygon that is to be extruded. // region = The 2D [Region](regions.scad) or polygon that is to be extruded.
// height = The height to extrude the region. Default: 1 // h | height = The height to extrude the region. Default: 1
// ---
// center = If true, the created polyhedron will be vertically centered. If false, it will be extruded upwards from the XY plane. Default: `false` // center = If true, the created polyhedron will be vertically centered. If false, it will be extruded upwards from the XY plane. Default: `false`
// ---
// twist = The number of degrees to rotate the top of the shape, clockwise around the Z axis, relative to the bottom. Default: 0
// scale = The amount to scale the top of the shape, in the X and Y directions, relative to the size of the bottom. Default: 1
// shift = The amount to shift the top of the shape, in the X and Y directions, relative to the position of the bottom. Default: [0,0]
// slices = The number of slices to divide the shape into along the Z axis, to allow refinement of detail, especially when working with a twist. Default: `twist/5` // slices = The number of slices to divide the shape into along the Z axis, to allow refinement of detail, especially when working with a twist. Default: `twist/5`
// maxseg = If given, then any long segments of the region will be subdivided to be shorter than this length. This can refine twisting flat faces a lot. Default: `undef` (no subsampling) // maxseg = If given, then any long segments of the region will be subdivided to be shorter than this length. This can refine twisting flat faces a lot. Default: `undef` (no subsampling)
// twist = The number of degrees to rotate the shape clockwise around the Z axis, as it rises from bottom to top. Default: 0
// scale = The amount to scale the shape, from bottom to top. Default: 1
// style = The style to use when triangulating the surface of the object. Valid values are `"default"`, `"alt"`, or `"quincunx"`. // style = The style to use when triangulating the surface of the object. Valid values are `"default"`, `"alt"`, or `"quincunx"`.
// convexity = Max number of surfaces any single ray could pass through. Module use only. // convexity = Max number of surfaces any single ray could pass through. Module use only.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `"origin"`
// atype = Set to "hull" or "intersect" to select anchor type. Default: "hull"
// cp = Centerpoint for determining intersection anchors or centering the shape. Determintes the base of the anchor vector. Can be "centroid", "mean", "box" or a 3D point. Default: "centroid" // cp = Centerpoint for determining intersection anchors or centering the shape. Determintes the base of the anchor vector. Can be "centroid", "mean", "box" or a 3D point. Default: "centroid"
// atype = Set to "hull" or "intersect" to select anchor type. Default: "hull"
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `"origin"`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0` // 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` // orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Extra Anchors:
// centroid_top = The centroid of the top of the shape, oriented UP.
// centroid = The centroid of the center of the shape, oriented UP.
// centroid_bot = The centroid of the bottom of the shape, oriented DOWN.
// Example: Extruding a Compound Region. // Example: Extruding a Compound Region.
// rgn1 = [for (d=[10:10:60]) circle(d=d,$fn=8)]; // rgn1 = [for (d=[10:10:60]) circle(d=d,$fn=8)];
// rgn2 = [square(30,center=false)]; // rgn2 = [square(30,center=false)];
@ -538,52 +543,86 @@ function skin(profiles, slices, refine=1, method="direct", sampling, caps, close
// mrgn = union(rgn1,rgn2); // mrgn = union(rgn1,rgn2);
// orgn = difference(mrgn,rgn3); // orgn = difference(mrgn,rgn3);
// linear_sweep(orgn,height=20,convexity=16); // linear_sweep(orgn,height=20,convexity=16);
// Example: With Twist, Scale, Slices and Maxseg. // Example: With Twist, Scale, Shift, Slices and Maxseg.
// rgn1 = [for (d=[10:10:60]) circle(d=d,$fn=8)]; // rgn1 = [for (d=[10:10:60]) circle(d=d,$fn=8)];
// rgn2 = [square(30,center=false)]; // rgn2 = [square(30,center=false)];
// rgn3 = [for (size=[10:10:20]) move([15,15],p=square(size=size, center=true))]; // rgn3 = [
// for (size=[10:10:20])
// apply(
// move([15,15]),
// square(size=size, center=true)
// )
// ];
// mrgn = union(rgn1,rgn2); // mrgn = union(rgn1,rgn2);
// orgn = difference(mrgn,rgn3); // orgn = difference(mrgn,rgn3);
// linear_sweep(orgn,height=50,maxseg=2,slices=40,twist=180,scale=0.5,convexity=16); // linear_sweep(
// orgn, height=50, maxseg=2, slices=40,
// twist=90, scale=0.5, shift=[10,5],
// convexity=16
// );
// Example: Anchors on an Extruded Region // Example: Anchors on an Extruded Region
// rgn1 = [for (d=[10:10:60]) circle(d=d,$fn=8)]; // rgn1 = [for (d=[10:10:60]) circle(d=d,$fn=8)];
// rgn2 = [square(30,center=false)]; // rgn2 = [square(30,center=false)];
// rgn3 = [for (size=[10:10:20]) move([15,15],p=square(size=size, center=true))]; // rgn3 = [
// for (size=[10:10:20])
// apply(
// move([15,15]),
// rect(size=size)
// )
// ];
// mrgn = union(rgn1,rgn2); // mrgn = union(rgn1,rgn2);
// orgn = difference(mrgn,rgn3); // orgn = difference(mrgn,rgn3);
// linear_sweep(orgn,height=20,convexity=16) show_anchors(); // linear_sweep(orgn,height=20,convexity=16)
module linear_sweep(region, height=1, center, twist=0, scale=1, slices, maxseg, style="default", convexity, // show_anchors();
spin=0, orient=UP, cp="centroid", anchor="origin", atype="hull") { module linear_sweep(
region, height, center,
twist=0, scale=1, shift=[0,0],
slices, maxseg, style="default", convexity,
cp="centroid", atype="hull", h,
anchor, spin=0, orient=UP
) {
h = first_defined([h, height, 1]);
region = force_region(region); region = force_region(region);
dummy=assert(is_region(region),"Input is not a region"); dummy=assert(is_region(region),"Input is not a region");
anchor = center ? "zcenter" : anchor; anchor = get_anchor(anchor, center, BOT, BOT);
anchors = [named_anchor("zcenter", [0,0,height/2], UP)];
vnf = linear_sweep( vnf = linear_sweep(
region, height=height, region, height=h,
twist=twist, scale=scale, twist=twist, scale=scale, shift=shift,
slices=slices, maxseg=maxseg, slices=slices, maxseg=maxseg, style=style
style=style
); );
attachable(anchor,spin,orient, cp=cp, region=region, h=height, extent=atype=="hull", anchors=anchors) { cent = centroid(path);
anchors = [
named_anchor("centroid_top", point3d(cent, h/2), UP),
named_anchor("centroid", point3d(cent), UP),
named_anchor("centroid_bot", point3d(cent,-h/2), DOWN)
];
geom = atype=="hull"? attach_geom(cp=cp, region=region, h=h, extent=true, anchors=anchors) :
atype=="intersect"? attach_geom(cp=cp, region=region, h=h, extent=false, anchors=anchors) :
assert(in_list(atype, ["hull", "intersect"]));
attachable(anchor,spin,orient, geom=geom) {
vnf_polyhedron(vnf, convexity=convexity); vnf_polyhedron(vnf, convexity=convexity);
children(); children();
} }
} }
function linear_sweep(region, height=1, center, twist=0, scale=1, slices, function linear_sweep(
maxseg, style="default", cp="centroid", atype="hull", anchor, spin=0, orient=UP) = region, height, center,
let( twist=0, scale=1, shift=[0,0],
slices, maxseg, style="default",
cp="centroid", atype="hull", h,
anchor, spin=0, orient=UP
) = let(
region = force_region(region) region = force_region(region)
) )
assert(is_region(region), "Input is not a region") assert(is_region(region), "Input is not a region or polygon.")
let( let(
anchor = center ? "zcenter" : anchor, h = first_defined([h, height, 1]),
anchors = [named_anchor("zcenter", [0,0,height/2], UP)], anchor = get_anchor(anchor, center, BOT, BOT),
regions = region_parts(region), regions = region_parts(region),
slices = default(slices, floor(twist/5+1)), slices = default(slices, ceil(abs(twist)/5)),
step = twist/slices, scale = is_num(scale)? [scale,scale] : point2d(scale),
hstep = height/slices, topmat = move(shift) * scale(scale) * rot(-twist),
trgns = [ trgns = [
for (rgn=regions) [ for (rgn=regions) [
for (path=rgn) let( for (path=rgn) let(
@ -593,8 +632,7 @@ function linear_sweep(region, height=1, center, twist=0, scale=1, slices,
let(steps=ceil(norm(seg.y-seg.x)/maxseg)) let(steps=ceil(norm(seg.y-seg.x)/maxseg))
lerpn(seg.x, seg.y, steps, false) lerpn(seg.x, seg.y, steps, false)
] ]
) ) apply(topmat, path)
rot(twist, p=scale([scale,scale],p=path))
] ]
], ],
vnf = vnf_join([ vnf = vnf_join([
@ -608,16 +646,27 @@ function linear_sweep(region, height=1, center, twist=0, scale=1, slices,
], ],
verts = [ verts = [
for (i=[0:1:slices]) let( for (i=[0:1:slices]) let(
sc = lerp(1, scale, i/slices), u = i/slices,
ang = i * step, scl = lerp([1,1], scale, u),
h = i * hstep //- height/2 ang = lerp(0, -twist, u),
) scale([sc,sc,1], p=rot(ang, p=path3d(path,h))) off = lerp([0,0,0], point3d(shift,h), u),
m = move(off) * scale(scl) * rot(ang)
) apply(m, path3d(path))
] ]
) vnf_vertex_array(verts, caps=false, col_wrap=true, style=style), ) vnf_vertex_array(verts, caps=false, col_wrap=true, style=style),
for (rgn = regions) vnf_from_region(rgn, ident(4), reverse=true), for (rgn = regions) vnf_from_region(rgn, ident(4), reverse=true),
for (rgn = trgns) vnf_from_region(rgn, up(height), reverse=false) for (rgn = trgns) vnf_from_region(rgn, up(h), reverse=false)
]) ]),
) reorient(anchor,spin,orient, cp=cp, vnf=vnf, extent=atype=="hull", p=vnf, anchors=anchors); cent = centroid(path),
anchors = [
named_anchor("centroid_top", point3d(cent, h/2), UP),
named_anchor("centroid", point3d(cent), UP),
named_anchor("centroid_bot", point3d(cent,-h/2), DOWN)
],
geom = atype=="hull"? attach_geom(cp=cp, region=region, h=h, extent=true, anchors=anchors) :
atype=="intersect"? attach_geom(cp=cp, region=region, h=h, extent=false, anchors=anchors) :
assert(in_list(atype, ["hull", "intersect"]))
) reorient(anchor,spin,orient, geom=geom, p=vnf);
@ -2040,6 +2089,7 @@ function associate_vertices(polygons, split, curpoly=0) =
// Section: Texturing // Section: Texturing
// DefineHeader(Table;Headers=Texture Name|Description): Texture Values
function _get_texture(tex,n,m) = function _get_texture(tex,n,m) =
tex=="ribs"? [[1,0]] : tex=="ribs"? [[1,0]] :
@ -2086,6 +2136,22 @@ function _get_texture(tex,n,m) =
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER` // 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` // 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` // orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Texture Values:
// "ribs" = Vertically aligned triangular ribs.
// "trunc_ribs" = Like "ribs" but with flat rib tips.
// "wave_ribs" = Vertically aligned wavy ribs.
// "diamonds" = Diamond shapes with tips aligned with the axes. Useful for knurling.
// "pyramids" = Pyramids shapes with flat sides aligned with the axes. Also useful for knurling.
// "trunc_pyramids" = Like "pyramids" but with flattened tips.
// "dimpled_pyramids" = Like "trunc_pyramids" but with dimples in the flat tips.
// "hills" = Wavy hills and valleys,
// "waves" = A raised sine-wave patten, oriented vertically.
// "dots" = Raised small round bumps.
// "cones" = Raised conical spikes.
// Extra Anchors:
// centroid_top = The centroid of the top of the shape, oriented UP.
// centroid = The centroid of the center of the shape, oriented UP.
// centroid_bot = The centroid of the bottom of the shape, oriented DOWN.
// See Also: textured_revolution(), textured_cylinder() // See Also: textured_revolution(), textured_cylinder()
// Example: "ribs" texture. // Example: "ribs" texture.
// path = glued_circles(r=15, spread=40, tangent=45); // path = glued_circles(r=15, spread=40, tangent=45);
@ -2135,6 +2201,10 @@ function _get_texture(tex,n,m) =
// Example: "cones" texture. // Example: "cones" texture.
// path = glued_circles(r=15, spread=40, tangent=45); // path = glued_circles(r=15, spread=40, tangent=45);
// textured_linear_sweep(path, "cones", tex_size=[5,5], h=40, style="concave"); // textured_linear_sweep(path, "cones", tex_size=[5,5], h=40, style="concave");
// Example: User defined texture.
// path = ellipse(r=[20,10]);
// texture = [for (i=[0:9]) [ for (j=[0:9]) 1/max(0.5,norm([i,j]-[5,5])) ]];
// textured_linear_sweep(path, texture, tex_size=[5,5], h=40, style="min_edge", anchor=BOT);
// Example: As Function // Example: As Function
// path = glued_circles(r=15, spread=40, tangent=45); // path = glued_circles(r=15, spread=40, tangent=45);
// vnf = textured_linear_sweep(path, h=40, "trunc_pyramids", tex_size=[5,5], tscale=1, style="convex"); // vnf = textured_linear_sweep(path, h=40, "trunc_pyramids", tex_size=[5,5], tscale=1, style="convex");
@ -2189,8 +2259,14 @@ function textured_linear_sweep(
vnf = vnf_vertex_array( vnf = vnf_vertex_array(
tiles, caps=caps, style=style, reverse=reverse, tiles, caps=caps, style=style, reverse=reverse,
col_wrap=col_wrap, row_wrap=false col_wrap=col_wrap, row_wrap=false
) ),
) reorient(anchor,spin,orient, vnf=vnf, extent=true, p=vnf); cent = centroid(path),
anchors = [
named_anchor("centroid_top", point3d(cent, h/2), UP),
named_anchor("centroid", point3d(cent), UP),
named_anchor("centroid_bot", point3d(cent,-h/2), DOWN)
]
) reorient(anchor,spin,orient, vnf=vnf, extent=true, anchors=anchors, p=vnf);
module textured_linear_sweep( module textured_linear_sweep(
@ -2211,7 +2287,13 @@ module textured_linear_sweep(
style=style, reverse=reverse, style=style, reverse=reverse,
anchor=CENTER, spin=0, orient=UP anchor=CENTER, spin=0, orient=UP
); );
attachable(anchor,spin,orient, vnf=vnf, extent=true) { cent = centroid(path);
anchors = [
named_anchor("centroid_top", point3d(cent, h/2), UP),
named_anchor("centroid", point3d(cent), UP),
named_anchor("centroid_bot", point3d(cent,-h/2), DOWN)
];
attachable(anchor,spin,orient, vnf=vnf, extent=true, anchors=anchors) {
vnf_polyhedron(vnf, convexity=convexity); vnf_polyhedron(vnf, convexity=convexity);
children(); children();
} }
@ -2246,6 +2328,18 @@ module textured_linear_sweep(
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER` // 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` // 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` // orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Texture Values:
// "ribs" = Vertically aligned triangular ribs.
// "trunc_ribs" = Like "ribs" but with flat rib tips.
// "wave_ribs" = Vertically aligned wavy ribs.
// "diamonds" = Diamond shapes with tips aligned with the axes. Useful for knurling.
// "pyramids" = Pyramids shapes with flat sides aligned with the axes. Also useful for knurling.
// "trunc_pyramids" = Like "pyramids" but with flattened tips.
// "dimpled_pyramids" = Like "trunc_pyramids" but with dimples in the flat tips.
// "hills" = Wavy hills and valleys,
// "waves" = A raised sine-wave patten, oriented vertically.
// "dots" = Raised small round bumps.
// "cones" = Raised conical spikes.
// See Also: textured_linear_sweep(), textured_cylinder() // See Also: textured_linear_sweep(), textured_cylinder()
// Example: // Example:
// include <BOSL2/beziers.scad> // include <BOSL2/beziers.scad>
@ -2379,6 +2473,18 @@ module textured_revolution(
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER` // 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` // 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` // orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Texture Values:
// "ribs" = Vertically aligned triangular ribs.
// "trunc_ribs" = Like "ribs" but with flat rib tips.
// "wave_ribs" = Vertically aligned wavy ribs.
// "diamonds" = Diamond shapes with tips aligned with the axes. Useful for knurling.
// "pyramids" = Pyramids shapes with flat sides aligned with the axes. Also useful for knurling.
// "trunc_pyramids" = Like "pyramids" but with flattened tips.
// "dimpled_pyramids" = Like "trunc_pyramids" but with dimples in the flat tips.
// "hills" = Wavy hills and valleys,
// "waves" = A raised sine-wave patten, oriented vertically.
// "dots" = Raised small round bumps.
// "cones" = Raised conical spikes.
// See Also: textured_linear_sweep(), textured_revolution() // See Also: textured_linear_sweep(), textured_revolution()
// Examples: // Examples:
// textured_cylinder(h=40, r=20, texture="diamonds", tex_size=[5,5]); // textured_cylinder(h=40, r=20, texture="diamonds", tex_size=[5,5]);
@ -2386,7 +2492,7 @@ module textured_revolution(
// textured_cylinder(h=40, r1=20, r2=15, texture="trunc_pyramids", tex_size=[5,5], chamfer=5, style="convex"); // textured_cylinder(h=40, r1=20, r2=15, texture="trunc_pyramids", tex_size=[5,5], chamfer=5, style="convex");
// textured_cylinder(h=40, r1=20, r2=15, texture="dots", tex_size=[5,5], rounding=8, style="convex"); // textured_cylinder(h=40, r1=20, r2=15, texture="dots", tex_size=[5,5], rounding=8, style="convex");
function textured_cylinder( function textured_cylinder(
h=20, r=100, texture, tex_size=[5,5], counts, h, r, texture, tex_size=[1,1], counts,
tscale=1, inset=false, rot=false, tscale=1, inset=false, rot=false,
caps=true, style="min_edge", caps=true, style="min_edge",
reverse=false, shift=[0,0], reverse=false, shift=[0,0],
@ -2395,9 +2501,9 @@ function textured_cylinder(
rounding, rounding1, rounding2 rounding, rounding1, rounding2
) = ) =
let( let(
h = first_defined([h, l]), h = first_defined([h, l, 1]),
r1 = get_radius(r1=r1, r=r, d1=d1, d=d), r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=1),
r2 = get_radius(r1=r2, r=r, d1=d2, d=d), r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=1),
chamf1 = first_defined([chamfer1, chamfer]), chamf1 = first_defined([chamfer1, chamfer]),
chamf2 = first_defined([chamfer2, chamfer]), chamf2 = first_defined([chamfer2, chamfer]),
round1 = first_defined([rounding1, rounding]), round1 = first_defined([rounding1, rounding]),
@ -2421,7 +2527,7 @@ function textured_cylinder(
module textured_cylinder( module textured_cylinder(
texture, tex_size=[5,5], h=20, r=50, h, r, texture, tex_size=[1,1],
counts, tscale=1, inset=false, rot=false, counts, tscale=1, inset=false, rot=false,
style="min_edge", reverse=false, shift=[0,0], style="min_edge", reverse=false, shift=[0,0],
l, r1, r2, d, d1, d2, l, r1, r2, d, d1, d2,
@ -2430,9 +2536,9 @@ module textured_cylinder(
convexity=10, convexity=10,
anchor=CENTER, spin=0, orient=UP anchor=CENTER, spin=0, orient=UP
) { ) {
h = first_defined([h, l]); h = first_defined([h, l, 1]);
r1 = get_radius(r1=r1, r=r, d1=d1, d=d); r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=1);
r2 = get_radius(r1=r2, r=r, d1=d2, d=d); r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=1);
chamf1 = first_defined([chamfer1, chamfer]); chamf1 = first_defined([chamfer1, chamfer]);
chamf2 = first_defined([chamfer2, chamfer]); chamf2 = first_defined([chamfer2, chamfer]);
round1 = first_defined([rounding1, rounding]); round1 = first_defined([rounding1, rounding]);