diff --git a/mutators.scad b/mutators.scad index d7de360..cdc4121 100644 --- a/mutators.scad +++ b/mutators.scad @@ -105,7 +105,7 @@ module bounding_box(excess=0, planar=false) { // a normal vector. The s parameter is needed for the module // version to control the size of the masking cube, which affects preview display. // When called as a function, you must supply a vnf, path or region in p. If planar is set to true for the module version the operation -// is performed in and UP and DOWN are treated as equivalent to BACK and FWD respectively. +// is performed in and UP and DOWN are treated as equivalent to BACK and FWD respectively. // // Arguments: // p = path, region or VNF to slice. (Function version) @@ -163,7 +163,7 @@ function half_of(p, v=UP, cp) = let( v = (v==UP)? BACK : (v==DOWN)? FWD : v, cp = is_undef(cp) ? [0,0] - : is_num(cp) ? v*cp + : is_num(cp) ? v*cp : assert(is_vector(cp,2) || (is_vector(cp,3) && cp.z==0),"Centerpoint must be 2-vector") cp ) @@ -179,7 +179,7 @@ function half_of(p, v=UP, cp) = intersection(box,p) : assert(false, "Input must be a region, path or VNF"); - + /* This code cut 3d paths but leaves behind connecting line segments is_path(p) ? @@ -824,13 +824,23 @@ module HSL(h,s=1,l=0.5,a=1) color(HSL(h,s,l),a) children(); // rgb = HSV(h=270,s=0.75,v=0.9); // color(rgb) cube(60, center=true); function HSV(h,s=1,v=1) = + assert(s>=0 && s<=1) + assert(v>=0 && v<=1) let( - h=posmod(h,360), - v2=v*(1-s), - r=lookup(h,[[0,v], [60,v], [120,v2], [240,v2], [300,v], [360,v]]), - g=lookup(h,[[0,v2], [60,v], [180,v], [240,v2], [360,v2]]), - b=lookup(h,[[0,v2], [120,v2], [180,v], [300,v], [360,v2]]) - ) [r,g,b]; + h = posmod(h,360), + c = v * s, + hprime = h/60, + x = c * (1- abs(hprime % 2 - 1)), + rgbprime = hprime <=1 ? [c,x,0] + : hprime <=2 ? [x,c,0] + : hprime <=3 ? [0,c,x] + : hprime <=4 ? [0,x,c] + : hprime <=5 ? [x,0,c] + : hprime <=6 ? [c,0,x] + : [0,0,0], + m=v-c + ) + rgbprime+[m,m,m]; module HSV(h,s=1,v=1,a=1) color(HSV(h,s,v),a) children(); diff --git a/tests/test_vectors.scad b/tests/test_vectors.scad index 52217ff..e2c6759 100644 --- a/tests/test_vectors.scad +++ b/tests/test_vectors.scad @@ -47,6 +47,23 @@ module test_v_ceil() { test_v_ceil(); +module test_v_lookup() { + lup = [[4, [3,4,5]], [5, [5,6,7]], [6, [4,5,6]]]; + assert_equal(v_lookup(3,lup), [3,4,5]); + assert_equal(v_lookup(3.5,lup), [3,4,5]); + assert_equal(v_lookup(4,lup), [3,4,5]); + assert_approx(v_lookup(4.2,lup), [3.4,4.4,5.4]); + assert_equal(v_lookup(4.5,lup), [4,5,6]); + assert_equal(v_lookup(5,lup), [5,6,7]); + assert_approx(v_lookup(5.2,lup), [4.8,5.8,6.8]); + assert_equal(v_lookup(5.5,lup), [4.5,5.5,6.5]); + assert_equal(v_lookup(6,lup), [4,5,6]); + assert_equal(v_lookup(6.5,lup), [4,5,6]); + assert_equal(v_lookup(7,lup), [4,5,6]); +} +test_v_lookup(); + + module test_v_mul() { assert_equal(v_mul([3,4,5], [8,7,6]), [24,28,30]); assert_equal(v_mul([1,2,3], [4,5,6]), [4,10,18]); diff --git a/tutorials/Mutators.md b/tutorials/Mutators.md index 299fc1e..276b62a 100644 --- a/tutorials/Mutators.md +++ b/tutorials/Mutators.md @@ -253,9 +253,11 @@ easier to select colors using other color schemes. You can use the HSL or Hue-S color scheme with the `HSL()` module: ```openscad -for (h=[0:0.1:1], s=[0:0.1:1], l=[0:0.1:1]) { - translate(100*[h,s,l]) { - HSL(h*360,1-s,l) cube(10,center=true); +n = 10; size = 100/n; +for (a=count(n), b=count(n), c=count(n)) { + let( h=360*a/n, s=1-b/(n-1), l=c/(n-1)) + translate(size*[a,b,c]) { + HSL(h,s,l) cube(size); } } ``` @@ -263,9 +265,11 @@ for (h=[0:0.1:1], s=[0:0.1:1], l=[0:0.1:1]) { You can use the HSV or Hue-Saturation-Value color scheme with the `HSV()` module: ```openscad -for (h=[0:0.1:1], s=[0:0.1:1], v=[0:0.1:1]) { - translate(100*[h,s,v]) { - HSV(h*360,1-s,v) cube(10,center=true); +n = 10; size = 100/n; +for (a=count(n), b=count(n), c=count(n)) { + let( h=360*a/n, s=1-b/(n-1), v=c/(n-1)) + translate(size*[a,b,c]) { + HSV(h,s,v) cube(size); } } ``` diff --git a/vectors.scad b/vectors.scad index 4bbfed7..25498b1 100644 --- a/vectors.scad +++ b/vectors.scad @@ -107,6 +107,31 @@ function v_ceil(v) = [for (x=v) ceil(x)]; +// Function: v_lookup() +// Description: +// Works just like the built-in function [`lookup()`](https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Mathematical_Functions#lookup), except that it can also interpolate between vector result values of the same length. +// Arguments: +// x = The scalar value to look up. +// v = A list of [KEY,VAL] pairs. KEYs are scalars. VALs should either all be scalar, or all be vectors of the same length. +// Example: +// x = v_lookup(4.5, [[4, [3,4,5]], [5, [5,6,7]]]); // Returns: [4,5,6] +function v_lookup(x, v) = + is_num(v[0][1])? lookup(x,v) : + let( + i = lookup(x, [for (i=idx(v)) [v[i].x,i]]), + vlo = v[floor(i)], + vhi = v[ceil(i)], + lo = vlo[1], + hi = vhi[1] + ) + assert(is_vector(lo) && is_vector(hi), + "Result values must all be numbers, or all be vectors.") + assert(len(lo) == len(hi), "Vector result values must be the same length") + vlo.x == vhi.x? vlo[1] : + let( u = (x - vlo.x) / (vhi.x - vlo.x) ) + lerp(lo,hi,u); + + // Function: unit() // Usage: // unit(v, [error]);