Merge pull request #1660 from adrianVmariano/master

rotate_sweep doc tweaks
This commit is contained in:
adrianVmariano
2025-04-30 21:59:11 -04:00
committed by GitHub
2 changed files with 59 additions and 55 deletions

View File

@@ -1151,7 +1151,7 @@ function regular_prism(n,
// Synopsis: Creates a cube or trapezoidal prism with a textured top face for attaching to objects.
// SynTags: Geom, VNF
// Topics: Shapes (3D), Attachable, VNF Generators, Textures
// See Also: cuboid(), prismoid(), texture(), cyl(), rotate_sweep(), linear_sweep()
// See Also: cuboid(), prismoid(), texture(), cyl(), rotate_sweep(), linear_sweep(), plot3d()
// Usage:
// textured_tile(texture, [size], [w1=], [w2=], [ang=], [shift=], [h=/height=/thickness=], [atype=], [diff=], [tex_extra=], [tex_skip=], ...) [ATTACHMENTS];
// vnf = textured_tile(texture, [size], [w1=], [w2=], [ang=], [shift=], [h=/height=/thickness=], [atype=], [tex_extra=], [tex_skip=], ...);
@@ -1166,6 +1166,10 @@ function regular_prism(n,
// then the texture actually sinks into its base, so the default is set to the 0.1 more than the inset depth. To ensure a valid geometry, with a positive
// `inset` or a texture that has negative values you must select a thickness strictly **larger** than the depth the texture extends below zero.
// .
// Textures are meant to be between 0 and 1 so that `tex_depth` and `tex_inset` behave as expected. If you have a custom textures that
// has a different range you can still use it directly, but you may find it more convenient to rescale a height map texture using {{fit_to_range()}]
// or a VNF texture using {{fit_to_box()}}.
// .
// You can also specify a trapzoidal prism using parameters equivalent to those accepted by {{trapezoid()}}, with one change:
// `ysize` specifies the width of the prism in the Y direction, and `h`, `height` or `thickness` are used to specify the height
// in the Z direction. When you texture a trapezoid the texture will be scaled to the `w1` length if you specify it by size using `tex_size`. The
@@ -1174,7 +1178,7 @@ function regular_prism(n,
// Two anchor types are available. The default atype is "tex" which assumes you want to place the texture on another object using
// {{attach()}}. It provides anchors that ignore the base object and place the BOTTOM anchor at the bottom of the texture. The TOP anchor
// will be at the top face of the texture. Note that if your texture doesn't span the range from [0,1] these anchors won't be correctly located.
// For an inset texture, the "tex" anchors are all at the top of the texture. This anchor type works with `anchor(face,BOT)` where `face` is some
// For an inset texture, the "tex" anchors are all at the top of the texture. This anchor type works with `attach(face,BOT)` where `face` is some
// face on a parent object that needs a texture. If you want to use the textured object directly the "std" anchors are probably more useful.
// These anchors are the usual anchors for the base object, ignoring the applied texture. If you want the anchors to be on top of the texture,
// set `tex_inset=true`.
@@ -1216,33 +1220,37 @@ function regular_prism(n,
// tex_extra = number of extra lines of a hightfield texture to add at the end. Can be a scalar or 2-vector to give x and y values. Default: 0 if `tex_reps=[1,1]`, 1 otherwise
// tex_skip = number of lines of a heightfield texture to skip when starting. Can be a scalar or two vector to give x and y values. Default: 0
// style = {{vnf_vertex_array()}} style used to triangulate heightfield textures. Default: "min_edge"
// 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: `BOTTOM` if `astyle` is "tex", `CENTER` otherwise
// 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`
// Example(3D,NoScales,VPT=[-0.257402,0.467403,-0.648606],VPR=[46.6,0,16.6],VPD=29.2405): Basic textured tile
// textured_tile("trunc_diamonds", 10, tex_reps=[5,5]);
// Example(3D,NoAxes,VPT=[-0.0852782,0.259593,0.139667],VPR=[58.5,0,345.1],VPD=36.0994): Attaching a tile to a cube
// cuboid([12,12,4]) attach(TOP,BOT)
// textured_tile("trunc_pyramids", 10, tex_reps=[5,5], style="convex");
// textured_tile("trunc_pyramids", 10, tex_reps=[5,5],
// style="convex");
// Example(3D,NoScales,VPT = [-0.0788193, 0.10015, -0.0938629], VPR = [57.8, 0, 34.1], VPD = 29.2405): This inset texture doesn't look obviously different, but you can see that the object is below the XY plane.
// textured_tile("trunc_pyramids_vnf", 10, tex_reps=[5,5], tex_inset=true);
// textured_tile("trunc_pyramids_vnf", 10, tex_reps=[5,5],
// tex_inset=true);
// Example(3D,NoAxes,VPT=[0.242444,0.170054,-0.0714754],VPR=[67.6,0,33.4],VPD=36.0994): Here we use the `diff` option combined with {{diff()}} to attach the inset texture to the front of a parent cuboid.
// diff()
// cuboid([12,5,10]) attach(FRONT, BOT)
// textured_tile("trunc_pyramids_vnf", [10,8],
// tex_reps=[5,5], tex_inset=true, diff=true);
// Example(3D,NoAxes,VPT=[5.86588,-0.107082,-0.311155],VPR=[17.2,0,9.6],VPD=32.4895): Tile shaped like a rhombic prism
// textured_tile("ribs", w1=10, w2=10, shift=4, ysize=7, tex_reps=[5,1]);
// textured_tile("ribs", w1=10, w2=10, shift=4, ysize=7,
// tex_reps=[5,1]);
// Example(3D,NoAxes,VPT=[-0.487417,-0.398897,-0.143258],VPR=[10.2,0,12.4],VPD=26.3165): A tile shaped like a trapezoidal prism. Note that trapezoidal tiles will always distort the texture, resulting in curves
// textured_tile("diamonds", w1=10, w2=7, ysize=7, tex_reps=5);
// Example(3D,NoAxes,VPT=[-0.0889877,-0.31974,0.554444],VPR=[22.1,0,22.2],VPD=32.4895): An inset trapezoidal tile placed into a cube
// diff()cuboid([10,10,2])
// attach(TOP,BOT)
// textured_tile("trunc_diamonds", tex_reps=[5,5], tex_inset=true,
// w1=8, w2=4, ysize=8, diff=true);
// textured_tile("trunc_diamonds", tex_reps=[5,5],
// tex_inset=true, diff=true,
// w1=8, w2=4, ysize=8);
// Example(3D,NoAxes,VPT=[-0.0889877,-0.31974,0.554444],VPR=[58.5,0,21.5],VPD=32.4895): This example shows what happens if you set `tex_extra` to zero for the "pyramids" texture. Note that the texture doesn't finish. The default of `tex_extra=1` produces the correct result.
// textured_tile("pyramids", 10, tex_reps=[5,5], tex_extra=0);
// Example(3D,NoAxes,VPT=[-0.212176,-0.651766,0.124004],VPR=[58.5,0,21.5],VPD=29.2405): This texture has an asymmetry even with the default `tex_extra=1`.
// Example(3D,NoAxes,VPT=[-0.212176,-0.651766,0.124004],VPR=[58.5,0,21.5],VPD=29.2405): This texture has an asymmetry with the default `tex_extra=1`.
// textured_tile("trunc_ribs", 10, tex_reps=[5,1]);
// Example(3D,NoAxes,VPT=[-0.212176,-0.651766,0.124004],VPR=[58.5,0,21.5],VPD=29.2405): It could be fixed by setting `tex_extra=2`, which would place an extra flat strip on the right. But another option is to use the `tex_skip` parameter to trim the flat part from the left. Note that we are also skipping in the y direction, but it doesn't make a difference for this texture, except that you need to have enough texture tiles to accommodate the skip, so we increased the Y reps value to 2. You can also set `tex_skip` to a vector.
// textured_tile("trunc_ribs", 10, tex_reps=[5,2], tex_skip=1);
@@ -1279,10 +1287,10 @@ module textured_tile(
tex_skip=0,
style="min_edge",
atype="tex",
anchor=CENTER, spin=0, orient=UP
anchor, spin=0, orient=UP
)
{
anchor = default(anchor, atype=="tex" ? BOTTOM : CENTER);
vnf_data = textured_tile(size=size,
ysize=ysize, height=height, w1=w1, w2=w2, ang=ang, h=h, shift=shift,
texture=texture, tex_size=tex_size, tex_reps=tex_reps,tex_extra=tex_extra,
@@ -1330,15 +1338,17 @@ function textured_tile(
atype="tex",
tex_extra,
tex_skip=0,
anchor=CENTER, spin=0, orient=UP,
anchor, spin=0, orient=UP,
_return_anchor=false
) =
) =
assert(in_list(atype,["tex","std"]), "atype must be \"tex\" or \"std\"")
assert(is_undef(tex_reps) || is_int(tex_reps) || (all_integer(tex_reps) && len(tex_reps)==2), "tex_reps must be an integer or list of two integers")
assert(is_undef(tex_size) || is_vector(tex_size,2) || is_finite(tex_size))
assert(num_defined([tex_size, tex_reps])==1, "Must give exactly one of tex_size and tex_reps")
assert(is_undef(size) || is_num(size) || is_vector(size,2) || is_vector(size,3), "size must be a 2-vector or 3-vector")
assert(is_undef(size) || num_defined([ysize,h, height, thickness, w1,w2,ang])==0, "Cannot combine size with any other dimensional specifications")
let(
anchor = default(anchor, atype=="tex" ? BOTTOM : CENTER),
inset = is_num(tex_inset)? tex_inset : tex_inset? 1 : 0,
default_thick = inset>0 ? 0.1+abs(tex_depth)*inset : 0.1,
extra_ht = max(0,abs(tex_depth)*(1-inset)),
@@ -1364,8 +1374,8 @@ function textured_tile(
tex_reps = is_def(tex_reps) ? force_list(tex_reps,2)
: let(tex_size=force_list(tex_size,2))
[round(size.x/tex_size.x), round(size.y/tex_size.y)],
extra = is_undef(extra)? tex_reps == [1,1] ? [0,0] : [1,1]
: force_list(tex_extra,2),
extra = is_undef(tex_extra)? tex_reps == [1,1] ? [0,0] : [1,1]
: force_list(tex_extra,2),
skip = force_list(tex_skip,2),
scale = [size.x/tex_reps.x, size.y/tex_reps.y],
setz=function (v,z) [v.x,v.y,z],
@@ -1381,7 +1391,7 @@ function textured_tile(
scaled_tex = tex_depth < 0 ? [for(row=texture) [for(p=row) -(1-p-inset)*tex_depth]]
: [for(row=texture) [for(p=row) (p-inset)*tex_depth]],
check = [for(row=scaled_tex, p=row) if (p<=-height) p],
dummy=assert(check==[], str("texture extends too far below zero (",min([each check,0]),") to fit in cube with height ",height)),
dummy=assert(check==[], str("texture extends too far below zero (",min([each check,0]),") to fit entirely within height ",height)),
pts=[for(y=idx(ypts))
[ [xpts[0],ypts[y],-height/2],
for(x=idx(xpts))
@@ -1394,9 +1404,12 @@ function textured_tile(
:
let(
zadj_vnf = [
[for(p=texture[0]) [p.x, p.y, tex_depth<0 ? height/2-(1-p.z-inset)*tex_depth : height/2+(p.z-inset)*tex_depth]],
[for(p=texture[0]) [p.x, p.y, height/2 + _tex_height(tex_depth,inset,p.z)]],
texture[1]
],
minz = min(column(zadj_vnf[0],2)),
dummy=assert(minz>-height/2, str("texture extends too far below zero (",minz-height/2,") to fit entirely within height ",height)),
scaled_vnf = scale(scale, zadj_vnf),
tiled_vnf = [for(i=[0:1:tex_reps.x-1], j=[0:1:tex_reps.y-1]) move([scale.x*i,scale.y*j], scaled_vnf)],
@@ -1778,12 +1791,12 @@ function rect_tube(
// wedge([20, 40, 15], center=true);
// Example: *Non*-Centered
// wedge([20, 40, 15]);
// Example: Standard Anchors
// Example(3D,Med,VPR=[59.50,0.00,36.90],VPD=257.38,VPT=[5.60,-1.98,3.65]): Standard Anchors
// wedge([40, 80, 30], center=true)
// show_anchors(custom=false);
// color([0.5,0.5,0.5,0.1])
// cube([40, 80, 30], center=true);
// Example: Named Anchors
// Example(3D,Med,VPR=[55.00,0.00,25.00],VPD=151.98,VPT=[2.30,-11.81,-5.66]): Named Anchors
// wedge([40, 80, 30], center=true)
// show_anchors(std=false);
@@ -4234,7 +4247,7 @@ module fillet(l, r, ang, r1, r2, excess=0.01, d1, d2,d,length, h, height, anchor
// Synopsis: Generates a surface by evaluating a function on a 2D grid
// SynTags: Geom, VNF
// Topics: Function Plotting
// See Also: plot_revolution()
// See Also: plot_revolution(), textured_tile()
// Usage: As Module
// plot3d(f, x, y, [zclip=], [zspan=], [base=], [convexity=], [style=]) [ATTACHMENTS];
// Usage: As Function

View File

@@ -949,7 +949,12 @@ function linear_sweep(
// Anchor Types:
// "hull" = Anchors to the virtual convex hull of the shape.
// "intersect" = Anchors to the surface of the shape.
// Example:
// Example(3D,NoAxes,VPR=[60.20,0.00,41.80],VPD=151.98,VPT=[0.85,-2.95,3.10]): Sweeping a shape that looks like a plus sign
// rgn = right(30,
// union([for (a = [0, 90])
// zrot(a, rect([15,5]))]));
// rotate_sweep(rgn);
// Example(3D,NoAxes,VPR=[50.40,0.00,28.50],VPD=208.48,VPT=[0.23,-1.89,5.20]): Sweeping a region with multiple components
// rgn = [
// for (a = [0, 120, 240]) let(
// cp = polar_to_xy(15, a) + [30,0]
@@ -959,27 +964,35 @@ function linear_sweep(
// ]
// ];
// rotate_sweep(rgn, angle=240);
// Example:
// rgn = right(30, p=union([for (a = [0, 90]) rot(a, p=rect([15,5]))]));
// rotate_sweep(rgn);
// Example(3D,NoAxes,VPR=[55.00,0.00,25.00],VPD=292.71,VPT=[1.59,1.80,-1.35]): Torus with bricks texture
// path = right(50, p=circle(d=40));
// rotate_sweep(path, texture="bricks_vnf",tex_size=10,
// tex_depth=0.5, style="concave");
// Example(3D,NoAxes,VPR=[76.30,0.00,44.60],VPD=257.38,VPT=[2.58,-5.21,0.37]): Applying a texture to a region. Both the inside and outside receive texture.
// rgn = [
// right(40, p=circle(d=50)),
// right(40, p=circle(d=40,$fn=6)),
// ];
// rotate_sweep(
// rgn, texture="diamonds",
// tex_size=[10,10], tex_depth=1,
// angle=240, style="concave");
// Example(NoAxes): The simplest way to create a cylinder with just a single line segment and `caps=true`. With this cylinder, the top and bottom have no texture.
// rotate_sweep([[20,-10],[20,10]], texture="dots",
// tex_reps=[6,2],caps=true);
// Example(NoAxes): If we manually connect the top and bottom then they also receive texture.
// rotate_sweep([[0,-10],[20,-10],[20,10],[0,10]], texture="dots",
// tex_reps=[6,6],,tex_depth=1.5);
// rotate_sweep([[0,-10],[20,-10],[20,10],[0,10]],
// tex_reps=[6,6],,tex_depth=1.5,
// texture="dots");
// Example(NoAxes,VPR=[95.60,0.00,69.80],VPD=74.40,VPT=[5.81,5.74,1.97]): You can connect just the top or bottom alone instead of both to get texture on one and a flat cap on the other. Here you can see that the sloped top has texture but the bottom does not. Also note that the texture doesn't fit neatly on the side and top like it did in the previous two examples, but makes a somewhat ugly transition across the corner. You have to size your object carefully so that the tops and sides each fit an integer number of texture tiles to avoid this type of transition.
// rotate_sweep([[15,-10],[15,10],[0,15]], texture="dots", tex_reps=[6,6],
// rotate_sweep([[15,-10],[15,10],[0,15]],
// texture="dots", tex_reps=[6,6],
// angle=90,caps=true,tex_depth=1.5);
// Example(NoAxes,VPR=[55.00,0.00,25.00],VPD=126.00,VPT=[1.37,0.06,-0.75]): Ribbed sphere.
// path = arc(r=20, $fn=64, angle=[-90, 90]);
// rotate_sweep(path, 360, texture = texture("wave_ribs",n=15),
// tex_size=[8,1.5]);
// Example: For this model we use `closed=false` to create the flat, untextured caps.
// Example(3D,NoAxes,VPR=[60.20,0.00,56.50],VPD=231.64,VPT=[4.18,-2.66,1.31]): This model uses `caps=true` to create the untextured caps with a user supplied texture. They are flat because the texture is zero at its edges.
// tex = [
// [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
// [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1],
@@ -999,7 +1012,7 @@ function linear_sweep(
// path, caps=true,
// texture=tex, tex_size=[20,20],
// tex_depth=1, style="concave");
// Example:
// Example(3D,NoAxes,VPR=[60.20,0.00,56.50],VPD=187.63,VPT=[2.07,-4.53,2.58]): An example with a more complicated path. Here the caps are not flat because the diamonds texture is not zero at the edges.
// bezpath = [
// [15, 30], [10,15],
// [10, 0], [20, 10], [30,12],
@@ -1011,28 +1024,7 @@ function linear_sweep(
// path, caps=true,
// texture="diamonds", tex_size=[10,10],
// tex_depth=1, style="concave");
// Example:
// path = [
// [20, 30], [20, 20],
// each arc(r=20, corner=[[20,20],[10,0],[20,-20]]),
// [20,-20], [20,-30],
// ];
// vnf = rotate_sweep(
// path, caps=true,
// texture="trunc_pyramids",
// tex_size=[5,5], tex_depth=1,
// style="convex");
// vnf_polyhedron(vnf, convexity=10);
// Example:
// rgn = [
// right(40, p=circle(d=50)),
// right(40, p=circle(d=40,$fn=6)),
// ];
// rotate_sweep(
// rgn, texture="diamonds",
// tex_size=[10,10], tex_depth=1,
// angle=240, style="concave");
// Example(3D,NoAxes): Tapering the ends of the texturing to zero produces flat caps.
// Example(3D,NoAxes,VPR=[70.00,0.00,58.60],VPD=208.48,VPT=[1.92,-3.81,2.21]): The normal direction at the ends is perpendicular to the Z axis, so even though the texture is not zero, the caps are flat, unlike the previous example.
// path = [
// [20, 30], [20, 20],
// each arc(r=20, corner=[[20,20],[10,0],[20,-20]]),
@@ -1042,16 +1034,15 @@ function linear_sweep(
// path, caps=true,
// texture="diamonds",
// tex_size=[5,5], tex_depth=1,
// tex_taper=undef,
// style="flip2",
// style="concave",
// convexity=10);
// Example(3D,NoAxes,VPR=[59.20,0.00,226.90],VPD=113.40,VPT=[-4.53,3.03,3.84]): The top cap is definite not flat.
// Example(3D,NoAxes,VPR=[59.20,0.00,226.90],VPD=113.40,VPT=[-4.53,3.03,3.84]): The top cap is definitely not flat.
// rotate_sweep(
// arc(r=20,angle=[-45,45],n=45),
// caps=true, texture="diamonds",
// tex_size=[5,5], tex_depth=2,
// convexity=10);
// Example(3D,NoAxes,VPR=[59.20,0.00,226.90],VPD=113.40,VPT=[-4.53,3.03,3.84]): Setting `tex_taper=0` abruptly tapers right the the caps so that the cap is flat:
// Example(3D,NoAxes,VPR=[59.20,0.00,226.90],VPD=113.40,VPT=[-4.53,3.03,3.84]): Setting `tex_taper=0` abruptly tapers right at the caps so that the cap is flat:
// rotate_sweep(
// arc(r=20,angle=[-45,45],n=45),
// caps=true, texture="diamonds",