From 2eb0ce034854e57654d45dda370440c423f10d99 Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Fri, 28 Aug 2020 23:16:11 -0400 Subject: [PATCH] added os_mask to rounding and tweaked error messages in transpose --- arrays.scad | 26 ++++++++++++++------------ rounding.scad | 24 +++++++++++++++++++++++- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/arrays.scad b/arrays.scad index 835fd65..a6d43d1 100644 --- a/arrays.scad +++ b/arrays.scad @@ -1286,10 +1286,12 @@ function array_dim(v, depth=undef) = // Function: transpose() -// Description: Returns the transposition of the given array. -// When reverse=true, the transposition is done in respect to the secondary diagonal, that is: -// . -// reverse(transpose(reverse(arr))) == transpose(arr, reverse=true) +// Usage: +// transpose(arr, [reverse]) +// Description: +// Returns the transpose of the given input array. The input should be a list of lists that are +// all the same length. If you give a vector then transpose returns it unchanged. +// When reverse=true, the transpose is done across to the secondary diagonal. (See example below.) // By default, reverse=false. // Example: // arr = [ @@ -1329,19 +1331,19 @@ function array_dim(v, depth=undef) = // // ["h", "e", "b"], // // ["g", "d", "a"] // // ] -// Example: +// Example: Transpose on a list of numbers returns the list unchanged // transpose([3,4,5]); // Returns: [3,4,5] function transpose(arr, reverse=false) = - assert( is_list(arr) && len(arr)>0, "The array is not a vector neither a matrix." ) + assert( is_list(arr) && len(arr)>0, "Input to transpose must be a nonempty list.") is_list(arr[0]) - ? let( l0 = len(arr[0]) ) - assert([for(a=arr) if(!is_list(a) || len(a)!=l0) 1 ]==[], "The array is not a vector neither a matrix." ) + ? let( len0 = len(arr[0]) ) + assert([for(a=arr) if(!is_list(a) || len(a)!=len0) 1 ]==[], "Input to transpose has inconsistent row lengths." ) reverse - ? [for (i=[0:1:l0-1]) - [ for (j=[0:1:len(arr)-1]) arr[len(arr)-1-j][l0-1-i] ] ] - : [for (i=[0:1:l0-1]) + ? [for (i=[0:1:len0-1]) + [ for (j=[0:1:len(arr)-1]) arr[len(arr)-1-j][len0-1-i] ] ] + : [for (i=[0:1:len0-1]) [ for (j=[0:1:len(arr)-1]) arr[j][i] ] ] - : assert( is_vector(arr), "The array is not a vector neither a matrix." ) + : assert( is_vector(arr), "Input to transpose must be a vector or list of lists.") arr; diff --git a/rounding.scad b/rounding.scad index ae2aed0..c57a76f 100644 --- a/rounding.scad +++ b/rounding.scad @@ -488,6 +488,7 @@ function smooth_path(path, tangents, size, relsize, splinesteps=10, uniform=fals // - smooth: os_smooth(cut|joint). Define continuous curvature rounding, with `cut` and `joint` as for round_corners. // - teardrop: os_teardrop(r|cut). Rounding using a 1/8 circle that then changes to a 45 degree chamfer. The chamfer is at the end, and enables the object to be 3d printed without support. The radius gives the radius of the circular part. // - chamfer: os_chamfer([height], [width], [cut], [angle]). Chamfer the edge at desired angle or with desired height and width. You can specify height and width together and the angle will be ignored, or specify just one of height and width and the angle is used to determine the shape. Alternatively, specify "cut" along with angle to specify the cut back distance of the chamfer. +// - mask: os_mask(mask, [out]). Create a profile from one of the [2d masking shapes](shapes2d.scad#5-2d-masking-shapes). The `out` parameter specifies that the mask should flare outward (like crown molding or baseboard). This is set false by default. // . // The general settings that you can use with all of the helper functions are mostly used to control how offset_sweep() calls the offset() function. // - extra: Add an extra vertical step of the specified height, to be used for intersections or differences. This extra step will extend the resulting object beyond the height you specify. Default: 0 @@ -654,6 +655,15 @@ function smooth_path(path, tangents, size, relsize, splinesteps=10, uniform=fals // up(1) // offset_sweep(offset(rhex,r=-1), height=9.5, bottom=os_circle(r=2), top=os_teardrop(r=-4)); // } +// Example: Using os_mask to create ogee profiles: +// ogee = mask2d_ogee([ +// "xstep",1, "ystep",1, // Starting shoulder. +// "fillet",5, "round",5, // S-curve. +// "ystep",1, // Ending shoulder. +// ]); +// star = star(5, r=220, ir=130); +// rounded_star = round_corners(star, cut=flatten(repeat([5,0],5)), $fn=24); +// offset_sweep(rounded_star, height=100, top=os_mask(ogee), bottom=os_mask(ogee,out=true)); // This function does the actual work of repeatedly calling offset() and concatenating the resulting face and vertex lists to produce @@ -880,6 +890,18 @@ function os_profile(points, extra,check_valid, quality, offset_maxstep, offset) ]); +function os_mask(mask, out=false, extra,check_valid, quality, offset_maxstep, offset) = + let( + origin_index = [for(i=idx(mask)) if (mask[i].x<0 && mask[i].y<0) i], + xfactor = out ? -1 : 1 + ) + assert(len(origin_index)==1,"Cannot find origin in the mask") + let( + points = ([for(pt=polygon_shift(mask,origin_index[0])) [xfactor*max(pt.x,0),-max(pt.y,0)]]) + ) + os_profile(deduplicate(move(-points[1],p=select(points,1,-1))), extra,check_valid,quality,offset_maxstep,offset); + + // Module: convex_offset_extrude() // // Description: @@ -1994,4 +2016,4 @@ module bent_cutout_mask(r, thickness, path, convexity=10) } -// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap \ No newline at end of file +// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap