diff --git a/rounding.scad b/rounding.scad index 6ea92329..44a023a9 100644 --- a/rounding.scad +++ b/rounding.scad @@ -3475,6 +3475,35 @@ Access to the derivative smoothing parameter? // attach(RIGHT,"root") // join_prism(circle(r=8,$fn=32), // l=10, base="plane", fillet=4); +// Example(3D,NoScales,VPR=[47.3,0,14.5],VPT=[-2.8467,-2.05938,-10.6999],VPD=220): Two join_prism objects are placed on the parent cylinder using anchors, and then their descriptions are used to contruct a curved handle with a bezier. +// $fs=.5; $fa=4; +// vspace=25; +// bezlen=40; +// cylr=20; +// straightlen=10; +// circ = circle(r=6); +// cyl(r=cylr,h=50, rounding=3) +// let(cyl=parent()) +// down(vspace/2) +// attach(RIGHT+FWD, "root", spin=90) +// join_prism(circ, base="cyl", base_r=20, height=straightlen, fillet=4) +// let(base1=parent()) +// restore(cyl) +// up(vspace/2) +// attach(LEFT+FWD, "root", spin=90) +// join_prism(circ, base="cyl", base_r=20, height=straightlen, fillet=4) +// let(base2=parent()) +// let( +// avg_dir = desc_dir(base1,anchor=TOP)+desc_dir(base2,anchor=TOP), +// bez=[ +// desc_point(base1,anchor=TOP), +// desc_point(base1,anchor=TOP)+bezlen*desc_dir(base1,anchor=TOP), +// (cylr+straightlen+bezlen)*avg_dir, +// desc_point(base2,anchor=TOP)+bezlen*desc_dir(base2,anchor=TOP), +// desc_point(base2,anchor=TOP)] +// ) +// path_sweep(circ,bezier_curve(bez,40)); + module join_prism(polygon, base, base_r, base_d, base_T=IDENT, scale=1, prism_end_T=IDENT, short=false, length, l, height, h, @@ -4045,6 +4074,9 @@ function _prism_fillet_prism(name, basepoly, bot, top, d, k, N, overlap, uniform // n = number of facets to use for the fillets. Default: 15 // n1 = number of facets at object1 // n2 = number of facets at object2 +// fillet = fillet for both ends of the prism. Default: 0 +// fillet1 = fillet for the joint at object1 +// fillet2 = fillet for the joint at object2 // k = fillet curvature parameter for both ends. Default: 0.7 // k1 = fillet curvature parameter at object1 // k2 = fillet curvature parameter at object2 @@ -4513,8 +4545,8 @@ module prism_connector(profile, desc1, anchor1, desc2, anchor2, shift1=0, shift2 smooth_normals, smooth_normals1, smooth_normals2, debug=false, debug_pos=false) { - base_fillet = default(fillet1,fillet); - aux_fillet = default(fillet2,fillet); + base_fillet = first_defined([fillet1,fillet,0]); + aux_fillet = first_defined([fillet2,fillet,0]); base_overlap = first_defined([overlap1,overlap,1]); aux_overlap = first_defined([overlap2,overlap,1]); diff --git a/shapes3d.scad b/shapes3d.scad index d62152a7..7dc6170b 100644 --- a/shapes3d.scad +++ b/shapes3d.scad @@ -1218,12 +1218,12 @@ function regular_prism(n, // 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` -// Example(3D,NoScale,VPT=[-0.257402,0.467403,-0.648606],VPR=[46.6,0,16.6],VPD=29.2405): Basic textured tile +// 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,NoScale,VPT=[-0.0852782,0.259593,0.139667],VPR=[58.5,0,345.1],VPD=36.0994): Attaching a tile to a cube +// 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"); -// Example(3D,NoScale,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. +// 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); // 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() @@ -1233,17 +1233,17 @@ function regular_prism(n, // 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); // 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) show_anchors(2); +// textured_tile("diamonds", w1=10, w2=7, ysize=7); // 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); -// Example(3D,NoScales,VPT=[-0.0889877,-0.31974,0.554444],VPR=[58.5,0,21.5],VPD=32.4895): This example shows what happens if you set `extra` to zero for the "pyramids" texture. Note that the texture doesn't finish. The default of `extra=1` produces the correct result. +// 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 `extra` to zero for the "pyramids" texture. Note that the texture doesn't finish. The default of `extra=1` produces the correct result. // textured_tile("pyramids", 10, tex_reps=[5,5], extra=0); -// Example(3D,NoScales,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 `extra=1`. -// textured_tile("trunc_ribs", 10, tex_reps=[5,2]); -// Example(3D,NoScales,VPT=[-0.212176,-0.651766,0.124004],VPR=[58.5,0,21.5],VPD=29.2405): It could be fixed by setting `extra=2`, which would place an extra flat strip on the right. But another option is to use the `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. You can also set `skip` to a vector. +// 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 `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 `extra=2`, which would place an extra flat strip on the right. But another option is to use the `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 `skip` to a vector. // textured_tile("trunc_ribs", 10, tex_reps=[5,2], skip=1); diff --git a/skin.scad b/skin.scad index 39cf1505..3d7a45ef 100644 --- a/skin.scad +++ b/skin.scad @@ -651,7 +651,7 @@ function skin(profiles, slices, refine=1, method="direct", sampling, caps, close // linear_sweep(path, texture=tex, tex_size=[5,5], h=40); // Example: Textured with twist and scale. // linear_sweep(regular_ngon(n=3, d=50), -// texture="rough", h=100, tex_depth=2, +// texture="rough", h=100, tex_depth=.4, // tex_size=[20,20], style="min_edge", // convexity=10, scale=0.2, twist=120); // Example: As Function @@ -717,7 +717,7 @@ function skin(profiles, slices, refine=1, method="direct", sampling, caps, close // [24, 25, 35, 33], [33, 35, 34], [24, 33, 6, 31], [34, 35, 11, 7], // [35, 25, 32, 11], [30, 32, 25, 23]] // ]; -// front_half(y=3){ +// front_half(y=33){ // cyl(d=14.5,h=1,anchor=BOT,rounding=1/3,$fa=1,$fs=.5); // linear_sweep(circle(d=12), h=12, scale=1.3, texture=diag_weave_vnf, // tex_size=[5,5], convexity=12); @@ -1041,7 +1041,7 @@ function linear_sweep( // path = [for(y=[-30:30]) [ 20-3*(1-cos((y+30)/60*360)),y]]; // rotate_sweep(path, closed=false, texture=tile, tex_rot=90, // tex_size=[12,8], tex_depth=9, angle=360); -// Example(3D,Med,NoAxes: A basket weave texture, here only half way around the circle to avoid clutter. +// Example(3D,Med,NoAxes,VPR=[78.1,0,199.3],VPT=[-4.55445,1.37814,-4.39897],VPD=192.044): A basket weave texture, here only half way around the circle to avoid clutter. // diag_weave_vnf = [ // [[0.2, 0, 0], [0.8, 0, 0], [1, 0.2, 0.5], [1, 0.8, 0.5], [0.7, 0.5, 0.5], // [0.5, 0.3, 0], [0.2, 0, 0.5], [0.8, 0, 0.5], [1, 0.2, 1], [1, 0.8, 1], @@ -4016,7 +4016,6 @@ function _validate_texture(texture) = min_xy = point2d(bounds[0]), max_xy = point2d(bounds[1]) ) - //assert(min_xy==[0,0] && max_xy==[1,1],"VNF tiles must span exactly from [0,0] to [1,1] in the X and Y components.")) assert(all_nonnegative(concat(min_xy,[1,1]-max_xy)), "VNF tile X and Y components must be between 0 and 1.") let( verts = texture[0], @@ -4059,8 +4058,8 @@ function _textured_linear_sweep( frac = pos-ind, texh = scale<0 ? -(1-tilez - inset) * scale : (tilez - inset) * scale, - base = lerp(bases[ind], select(bases,ind+1), frac), - norm = unit(lerp(norms[ind], select(norms,ind+1), frac)) + base = lerp(select(bases,ind), select(bases,ind+1), frac), + norm = unit(lerp(select(norms,ind), select(norms,ind+1), frac)) ) base + norm * texh, @@ -4083,38 +4082,36 @@ function _textured_linear_sweep( samples = !is_vnf(texture)? len(texture[0]) : is_num(samples)? samples : 8, check_tex = _validate_texture(texture), - sorted_tile = - !is_vnf(texture)? texture : + vnf_tile = + !is_vnf(texture) || samples==1 ? texture + : let( s = 1 / max(1, samples), - vnf = samples<=1? texture : - let( - slice_us = list([s:s:1-s/2]), - vnft1 = vnf_slice(texture, "X", slice_us), - vnft = twist? vnf_slice(vnft1, "Y", slice_us) : vnft1, - zvnf = [ - [ - for (p=vnft[0]) [ + slice_us = list([s:s:1-s/2]), + vnft1 = vnf_slice(texture, "X", slice_us), + vnft = twist? vnf_slice(vnft1, "Y", slice_us) : vnft1, + zvnf = [ + [ + for (p=vnft[0]) [ approx(p.x,0)? 0 : approx(p.x,1)? 1 : p.x, approx(p.y,0)? 0 : approx(p.y,1)? 1 : p.y, p.z ] - ], - vnft[1] - ] - ) zvnf - ) _vnf_sort_vertices(vnf, idx=[1,0]), - vertzs = !is_vnf(sorted_tile)? undef : - group_sort(sorted_tile[0], idx=1), - edge_paths = is_vnf(sorted_tile) ? _tile_edge_path_list(sorted_tile,1) : undef, + ], + vnft[1] + ] + ) zvnf, + edge_paths = is_vnf(texture) ? _tile_edge_path_list(vnf_tile,1) : undef, tpath = is_def(edge_paths) ? len(edge_paths[0])==0 ? [] : hstack([column(edge_paths[0][0],0), column(edge_paths[0][0],2)]) : let( - row = sorted_tile[0], + row = texture[0], rlen = len(row) ) [for (i = [0:1:rlen]) [i/rlen, row[i%rlen]]], edge_closed_paths = is_def(edge_paths) ? edge_paths[1] : [], tmat = scale(scale) * zrot(twist) * up(h/2), + texcnt = is_vnf(texture) ? undef + : [len(texture[0]), len(texture)], pre_skew_vnf = vnf_join([ for (rgn = regions) let( walls_vnf = vnf_join([ @@ -4125,19 +4122,16 @@ function _textured_linear_sweep( is_vector(tex_size,2) ? [round(plen/tex_size.x), max(1,round(h/tex_size.y)), ] : [ceil(6*plen/h), 6], - obases = resample_path(path, n=counts.x * samples, closed=true), - onorms = path_normals(obases, closed=true), - bases = list_wrap(obases), - norms = list_wrap(onorms), + bases = resample_path(path, n=counts.x * samples, closed=true), + norms = path_normals(bases, closed=true), vnf = is_vnf(texture) ? vnf_join( // VNF tile texture let( row_vnf = vnf_join([ for (i = [0:1:(scale==1?0:counts.y-1)], j = [0:1:counts.x-1]) [ [ - for (group = vertzs) - each [ - for (vert = group) let( + for (vert=vnf_tile[0]) + let( xy = transform_pt(j,vert.x,vert.z,samples, inset, tex_scale, bases, norms), pt = point3d(xy,vert.y), v = vert.y / counts.y, @@ -4149,9 +4143,8 @@ function _textured_linear_sweep( zrot(twist*(v+vv)) * zscale(h/counts.y) ) apply(mat, pt) - ] ], - sorted_tile[1] + vnf_tile[1] ] ]) ) [ @@ -4168,7 +4161,6 @@ function _textured_linear_sweep( ] ) : let( // Heightfield texture - texcnt = [len(texture[0]), len(texture)], tile_rows = [ for (ti = [0:1:texcnt.y-1]) path3d([ @@ -4204,10 +4196,8 @@ function _textured_linear_sweep( is_vector(tex_size,2) ? [round(plen/tex_size.x), max(1,round(h/tex_size.y)), ] : [ceil(6*plen/h), 6], - obases = resample_path(path, n=counts.x * samples, closed=true), - onorms = path_normals(obases, closed=true), - bases = list_wrap(obases), - norms = list_wrap(onorms), + bases = resample_path(path, n=counts.x * samples, closed=true), + norms = path_normals(bases, closed=true), nupath = [ for (j = [0:1:counts.x-1], vert = tpath) transform_pt(j,vert.x,vert.y,samples,inset,tex_scale,bases,norms) @@ -4224,10 +4214,8 @@ function _textured_linear_sweep( is_vector(tex_size,2) ? [round(plen/tex_size.x), max(1,round(h/tex_size.y)), ] : [ceil(6*plen/h), 6], - obases = resample_path(path, n=counts.x * samples, closed=true), - onorms = path_normals(obases, closed=true), - bases = list_wrap(obases), - norms = list_wrap(onorms), + bases = resample_path(path, n=counts.x * samples, closed=true), + norms = path_normals(bases, closed=true), modpaths = [for (j = [0:1:counts.x-1], cpath = edge_closed_paths) [for(vert = cpath) transform_pt(j,vert.x,vert.z,samples,inset,tex_scale,bases, norms)] @@ -4382,28 +4370,24 @@ function _textured_revolution( maxy = bounds[1].y, h = maxy - miny, circumf = 2 * PI * maxx, - tile = !is_vnf(texture)? texture : + tile = !is_vnf(texture) || samples==1 ? texture : let( - utex = samples<=1? texture : - let( - s = 1 / samples, - slices = list([s : s : 1-s/2]), - vnfx = vnf_slice(texture, "X", slices), - vnfy = inhibit_y_slicing? vnfx : vnf_slice(vnfx, "Y", slices), - vnft = vnf_triangulate(vnfy), - zvnf = [ - [ - for (p=vnft[0]) [ - approx(p.x,0)? 0 : approx(p.x,1)? 1 : p.x, - approx(p.y,0)? 0 : approx(p.y,1)? 1 : p.y, - p.z - ] - ], - vnft[1] + s = 1 / samples, + slices = list([s : s : 1-s/2]), + vnfx = vnf_slice(texture, "X", slices), + vnfy = inhibit_y_slicing? vnfx : vnf_slice(vnfx, "Y", slices), + vnft = vnf_triangulate(vnfy), + zvnf = [ + [ + for (p=vnft[0]) [ + approx(p.x,0)? 0 : approx(p.x,1)? 1 : p.x, + approx(p.y,0)? 0 : approx(p.y,1)? 1 : p.y, + p.z ] - ) zvnf - ) _vnf_sort_vertices(utex, idx=[0,1]), - vertzs = is_vnf(texture)? group_sort(tile[0], idx=0) : undef, + ], + vnft[1] + ] + ) zvnf, edge_paths = is_vnf(tile) ? _tile_edge_path_list(tile,1) : undef, bpath = is_def(edge_paths) ? len(edge_paths[0])==0 ? [] : hstack([column(edge_paths[0][0],0), column(edge_paths[0][0],2)]) @@ -4436,8 +4420,8 @@ function _textured_revolution( part = tileind * samples, ind = floor(part), frac = part - ind, - base = lerp(bases[ind], select(bases,ind+1), frac), - norm = unit(lerp(norms[ind], select(norms,ind+1), frac)), + base = lerp(select(bases,ind), select(bases,ind+1), frac), + norm = unit(lerp(select(norms,ind), select(norms,ind+1), frac)), scale = tex_scale * lookup(tileind/counts_y, taper_lup) * base.x/maxx, texh = scale<0 ? -(1-tilez - inset) * scale : (tilez - inset) * scale @@ -4452,26 +4436,21 @@ function _textured_revolution( is_vector(tex_size,2)? max(1,round(plen/tex_size.y)) : 6, obases = resample_path(path, n=counts_y * samples + (closed?0:1), closed=closed), onorms = path_normals(obases, closed=closed), - rbases = closed? list_wrap(obases) : obases, - rnorms = closed? list_wrap(onorms) : onorms, - bases = xrot(90, p=path3d(rbases)), - norms = xrot(90, p=path3d(rnorms)), + bases = xrot(90, p=path3d(obases)), + norms = xrot(90, p=path3d(onorms)), vnf = is_vnf(texture) ? vnf_join([ // VNF tile texture for (j = [0:1:counts_y-1]) [ [ - for (group = vertzs) each [ - for (vert = group) + for (vert = tile[0]) let(xyz = transform_point(j + (1-vert.y),vert.z,counts_y,bases, norms)) zrot(vert.x*angle/counts_x, p=xyz) - ] ], tile[1] ] ]) : let( // Heightfield texture - texcnt = [len(texture[0]), len(texture)], tiles = transpose([ for (j = [0,1], tj = [0:1:texcnt.x-1]) if (j == 0 || tj == 0) @@ -4502,23 +4481,18 @@ function _textured_revolution( plen = path_length(path, closed=closed), counts_y = is_vector(counts,2)? counts.y : is_vector(tex_size,2)? max(1,round(plen/tex_size.y)) : 6, - obases = resample_path(path, n=counts_y * samples + (closed?0:1), closed=closed), - onorms = path_normals(obases, closed=closed), - bases = closed? list_wrap(obases) : obases, - norms = closed? list_wrap(onorms) : onorms, + bases = resample_path(path, n=counts_y * samples + (closed?0:1), closed=closed), + norms = path_normals(bases, closed=closed), ppath = is_vnf(texture) ? [ // VNF tile texture - for (j = [0:1:counts_y-1]) - //for (group = vertzs, vert = reverse(group)) - for(vert=side_open_path) + for (j = [0:1:counts_y-1], vert=side_open_path) transform_point(j + (1 - vert.y),vert.z,counts_y,bases, norms) ] - : let( // Heightfield texture - texcnt = [len(texture[0]), len(texture)] - ) [ + : + [ // Heightfield texture for (i = [0:1:counts_y-(closed?1:0)], ti = [0:1:texcnt.y-1]) - if (i != counts_y || ti == 0) - transform_point(i + (ti/texcnt.y),texture[ti][0],counts_y,bases, norms) + if (i != counts_y || ti == 0) + transform_point(i + (ti/texcnt.y),texture[ti][0],counts_y,bases, norms) ], path = closed? ppath : [ [0, ppath[0].y], @@ -4534,10 +4508,8 @@ function _textured_revolution( plen = path_length(path, closed=closed), counts_y = is_vector(counts,2)? counts.y : is_vector(tex_size,2)? max(1,round(plen/tex_size.y)) : 6, - obases = resample_path(path, n=counts_y * samples + (closed?0:1), closed=closed), - onorms = path_normals(obases, closed=closed), - bases = closed? list_wrap(obases) : obases, - norms = closed? list_wrap(onorms) : onorms, + bases = resample_path(path, n=counts_y * samples + (closed?0:1), closed=closed), + norms = path_normals(bases, closed=closed), modpaths = [for (j = [0:1:counts_y-1], cpath=side_closed_paths) [for(vert=cpath) transform_point(j + (1 - vert.y),vert.z,counts_y,bases, norms)] @@ -4557,10 +4529,8 @@ function _textured_revolution( is_vector(tex_size,2)? max(1,round(plen/tex_size.y)) : 6, obases = resample_path(rgn[0], n=counts_y * samples + (closed?0:1), closed=closed), onorms = path_normals(obases, closed=closed), - rbases = closed? list_wrap(obases) : obases, - rnorms = closed? list_wrap(onorms) : onorms, - bases = xrot(90, p=path3d(rbases)), - norms = xrot(90, p=path3d(rnorms)), + bases = xrot(90, p=path3d(obases)), + norms = xrot(90, p=path3d(onorms)), caps_vnf = vnf_join([ for (epath=edge_closed_paths, j = [-1,0]) let( diff --git a/vnf.scad b/vnf.scad index ddc0a03a..d50990a9 100644 --- a/vnf.scad +++ b/vnf.scad @@ -27,13 +27,14 @@ EMPTY_VNF = [[],[]]; // The standard empty VNF with no vertices or faces. -// Function: vnf_vertex_array() +// Function&Module: vnf_vertex_array() // Synopsis: Returns a VNF structure from a rectangular vertex list. -// SynTags: VNF +// SynTags: VNF, Geom // Topics: VNF Generators, Lists // See Also: vnf_tri_array(), vnf_join(), vnf_from_polygons(), vnf_from_region() // Usage: // vnf = vnf_vertex_array(points, [caps=], [cap1=], [cap2=], [style=], [reverse=], [col_wrap=], [row_wrap=], [triangulate=]); +// vnf_vertex_array(points, [caps=], [cap1=], [cap2=], [style=], [reverse=], [col_wrap=], [row_wrap=], [triangulate=],...) [ATTACHMENTS]; // Description: // Creates a VNF structure from a rectangular vertex list, creating edges that connect the adjacent vertices in the vertex list // and creating the faces defined by those edges. You can optionally create the edges and faces to wrap the last column @@ -58,6 +59,17 @@ EMPTY_VNF = [[],[]]; // The standard empty VNF with no vertices or faces. // reverse = If true, reverse all face normals. // style = The style of subdividing the quads into faces. Valid options are "default", "alt", "flip1", "flip2", "min_edge", "min_area", "quincunx", "convex" and "concave". // triangulate = If true, triangulates endcaps to resolve possible CGAL issues. This can be an expensive operation if the endcaps are complex. Default: false +// convexity = (module) Max number of times a line could intersect a wall of the shape. +// cp = (module) Centerpoint for determining intersection anchors or centering the shape. Determines the base of the anchor vector. Can be "centroid", "mean", "box" or a 3D point. Default: "centroid" +// anchor = (module) Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `"origin"` +// spin = (module) Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0` +// orient = (module) Vector to rotate top toward, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP` +// atype = (module) Select "hull" or "intersect" anchor type. Default: "hull" +// Anchor Types: +// "hull" = Anchors to the virtual convex hull of the shape. +// "intersect" = Anchors to the surface of the shape. +// Named Anchors: +// "origin" = Anchor at the origin, oriented UP. // Example(3D): // vnf = vnf_vertex_array( // points=[ @@ -160,6 +172,23 @@ EMPTY_VNF = [[],[]]; // The standard empty VNF with no vertices or faces. // apply(m, [ [rgroove[0].x,0,-z], each rgroove, [last(rgroove).x,0,-z] ]) // ], caps=true, col_wrap=true, reverse=true); // vnf_polyhedron(vnf, convexity=8); + +module vnf_vertex_array( + points, + caps, cap1, cap2, + col_wrap=false, + row_wrap=false, + reverse=false, + style="default", + triangulate = false, + convexity=2, cp="centroid", anchor="origin", spin=0, orient=UP, atype="hull") +{ + vnf = vnf_vertex_array(points=points, caps=caps, cap1=cap2, cap2=cap2, + col_wrap=col_wrap, row_wrap=row_wrap, reverse=reverse, style=style,triangulate=triangulate); + vnf_polyhedron(vnf, convexity=2, cp="centroid", anchor="origin", spin=0, orient=UP, atype="hull") children(); +} + + function vnf_vertex_array( points, caps, cap1, cap2, @@ -1013,20 +1042,6 @@ function _detri_combine_faces(edgelist,faces,normals,facelist,curface) = -function _vnf_sort_vertices(vnf, idx=[2,1,0]) = - let( - verts = vnf[0], - faces = vnf[1], - vidx = sortidx(verts, idx=idx), - rvidx = sortidx(vidx), - sorted_vnf = [ - [ for (i = vidx) verts[i] ], - [ for (face = faces) [ for (i = face) rvidx[i] ] ], - ] - ) sorted_vnf; - - - // Function: vnf_slice() // Synopsis: Slice the faces of a VNF along an axis.