move color_this and recolor into color.scad

doc tweaks for rounding
This commit is contained in:
Adrian Mariano 2022-03-27 19:23:47 -04:00
parent 2ad35eca20
commit 26855429d8
3 changed files with 134 additions and 98 deletions

View File

@ -819,62 +819,6 @@ module hulling(a)
}
// Module: recolor()
// Usage:
// recolor([c]) {...}
// Topics: Attachments
// See Also: color_this(), tags(), hide(), show(), diff(), intersect()
// Description:
// Sets the color for children and all their descendants. This only works with attachables and you cannot
// have any color() modules above it in any parents, only other recolor() or color_this() modules.
// This works by setting the special `$color` variable.
// For a more step-by-step explanation of attachments, see the [[Attachments Tutorial|Tutorial-Attachments]].
// Arguments:
// c = Color name or RGBA vector. Default: The default color in your color scheme.
// Example:
// cuboid([10,10,5])
// recolor("green")attach(TOP,BOT) cuboid([9,9,4.5])
// attach(TOP,BOT) cuboid([8,8,4])
// recolor("purple") attach(TOP,BOT) cuboid([7,7,3.5])
// attach(TOP,BOT) cuboid([6,6,3])
// recolor("cyan")attach(TOP,BOT) cuboid([5,5,2.5])
// attach(TOP,BOT) cuboid([4,4,2]);
module recolor(c="default")
{
$color=c;
children();
}
// Module: color_this()
// Usage:
// color_this([c]) {...}
// Topics: Attachments
// See Also: tags(), recolor()
// Description:
// Sets the color for children at one level, reverting to the previous color for further descendants.
// This works only with attachables and you cannot have any color() modules above it in any parents,
// only recolor() or other color_this() modules. This works using the `$color` and `$save_color` variables.
// .
// For a more step-by-step explanation of attachments, see the [[Attachments Tutorial|Tutorial-Attachments]].
// Arguments:
// c = Color name or RGBA vector. Default: the default color in your color scheme
// Example:
// cuboid([10,10,5])
// color_this("green")attach(TOP,BOT) cuboid([9,9,4.5])
// attach(TOP,BOT) cuboid([8,8,4])
// color_this("purple") attach(TOP,BOT) cuboid([7,7,3.5])
// attach(TOP,BOT) cuboid([6,6,3])
// color_this("cyan")attach(TOP,BOT) cuboid([5,5,2.5])
// attach(TOP,BOT) cuboid([4,4,2]);
module color_this(c="default")
{
$save_color=default($color,"default");
$color=c;
children();
}
// Module: hide()
// Usage:
// hide(tags) {...}

View File

@ -11,15 +11,69 @@
use <builtins.scad>
// Section: Coloring Objects
// Module: recolor()
// Usage:
// recolor([c]) {...}
// Topics: Attachments
// See Also: color_this()
// Description:
// Sets the color for attachable children and all their descendants. This only works with attachables and you cannot
// have any color() modules above it in any parents, only other recolor() or color_this() modules.
// This works by setting the special `$color` variable, which attachable objects make use of to set the color.
// Arguments:
// c = Color name or RGBA vector. Default: The default color in your color scheme.
// Example:
// cuboid([10,10,5])
// recolor("green")attach(TOP,BOT) cuboid([9,9,4.5])
// attach(TOP,BOT) cuboid([8,8,4])
// recolor("purple") attach(TOP,BOT) cuboid([7,7,3.5])
// attach(TOP,BOT) cuboid([6,6,3])
// recolor("cyan")attach(TOP,BOT) cuboid([5,5,2.5])
// attach(TOP,BOT) cuboid([4,4,2]);
module recolor(c="default")
{
$color=c;
children();
}
// Module: color_this()
// Usage:
// color_this([c]) {...}
// Topics: Attachments
// See Also: recolor()
// Description:
// Sets the color for children at one level, reverting to the previous color for further descendants.
// This works only with attachables and you cannot have any color() modules above it in any parents,
// only recolor() or other color_this() modules. This works using the `$color` and `$save_color` variables,
// which attachable objects make use of to set the color.
// Arguments:
// c = Color name or RGBA vector. Default: the default color in your color scheme
// Example:
// cuboid([10,10,5])
// color_this("green")attach(TOP,BOT) cuboid([9,9,4.5])
// attach(TOP,BOT) cuboid([8,8,4])
// color_this("purple") attach(TOP,BOT) cuboid([7,7,3.5])
// attach(TOP,BOT) cuboid([6,6,3])
// color_this("cyan")attach(TOP,BOT) cuboid([5,5,2.5])
// attach(TOP,BOT) cuboid([4,4,2]);
module color_this(c="default")
{
$save_color=default($color,"default");
$color=c;
children();
}
// Module: rainbow()
// Usage:
// rainbow(list) ...
// Description:
// Iterates the list, displaying children in different colors for each list item.
// This is useful for debugging lists of paths and such.
// Iterates the list, displaying children in different colors for each list item. The color
// is set using the color() module, so this module is not compatible with {{recolor()}} or
// {{color_this}}. This is useful for debugging regions or lists of paths.
// Arguments:
// list = The list of items to iterate through.
// stride = Consecutive colors stride around the color wheel divided into this many parts.
@ -54,27 +108,29 @@ module rainbow(list, stride=1, maxhues, shuffle=false, seed)
// Function&Module: HSL()
// Usage:
// HSL(h,[s],[l],[a]) ...
// rgb = HSL(h,[s],[l]);
// rgb = HSL(h,[s],[l],[a]);
// Description:
// When called as a function, returns the [R,G,B] color for the given hue `h`, saturation `s`, and lightness `l` from the HSL colorspace.
// When called as a module, sets the color to the given hue `h`, saturation `s`, and lightness `l` from the HSL colorspace.
// When called as a function, returns the [R,G,B] color for the given hue `h`, saturation `s`, and lightness `l` from the HSL colorspace. If you supply
// the `a` value then you'll get a length 4 list [R,G,B,A].
// When called as a module, sets the color using the color() module to the given hue `h`, saturation `s`, and lightness `l` from the HSL colorspace.
// Arguments:
// h = The hue, given as a value between 0 and 360. 0=red, 60=yellow, 120=green, 180=cyan, 240=blue, 300=magenta.
// s = The saturation, given as a value between 0 and 1. 0 = grayscale, 1 = vivid colors. Default: 1
// l = The lightness, between 0 and 1. 0 = black, 0.5 = bright colors, 1 = white. Default: 0.5
// a = When called as a module, specifies the alpha channel as a value between 0 and 1. 0 = fully transparent, 1=opaque. Default: 1
// a = Specifies the alpha channel as a value between 0 and 1. 0 = fully transparent, 1=opaque. Default: 1
// Example:
// HSL(h=120,s=1,l=0.5) sphere(d=60);
// Example:
// rgb = HSL(h=270,s=0.75,l=0.6);
// color(rgb) cube(60, center=true);
function HSL(h,s=1,l=0.5) =
function HSL(h,s=1,l=0.5,a) =
let(
h=posmod(h,360)
) [
for (n=[0,8,4]) let(
k=(n+h/30)%12
) l - s*min(l,1-l)*max(min(k-3,9-k,1),-1)
for (n=[0,8,4])
let(k=(n+h/30)%12)
l - s*min(l,1-l)*max(min(k-3,9-k,1),-1),
if (is_def(a)) a
];
module HSL(h,s=1,l=0.5,a=1) color(HSL(h,s,l),a) children();
@ -83,23 +139,25 @@ module HSL(h,s=1,l=0.5,a=1) color(HSL(h,s,l),a) children();
// Function&Module: HSV()
// Usage:
// HSV(h,[s],[v],[a]) ...
// rgb = HSV(h,[s],[v]);
// rgb = HSV(h,[s],[v],[a]);
// Description:
// When called as a function, returns the [R,G,B] color for the given hue `h`, saturation `s`, and value `v` from the HSV colorspace.
// When called as a module, sets the color to the given hue `h`, saturation `s`, and value `v` from the HSV colorspace.
// When called as a function, returns the [R,G,B] color for the given hue `h`, saturation `s`, and value `v` from the HSV colorspace. If you supply
// the `a` value then you'll get a length 4 list [R,G,B,A].
// When called as a module, sets the color using the color() module to the given hue `h`, saturation `s`, and value `v` from the HSV colorspace.
// Arguments:
// h = The hue, given as a value between 0 and 360. 0=red, 60=yellow, 120=green, 180=cyan, 240=blue, 300=magenta.
// s = The saturation, given as a value between 0 and 1. 0 = grayscale, 1 = vivid colors. Default: 1
// v = The value, between 0 and 1. 0 = darkest black, 1 = bright. Default: 1
// a = When called as a module, specifies the alpha channel as a value between 0 and 1. 0 = fully transparent, 1=opaque. Default: 1
// a = Specifies the alpha channel as a value between 0 and 1. 0 = fully transparent, 1=opaque. Default: 1
// Example:
// HSV(h=120,s=1,v=1) sphere(d=60);
// Example:
// rgb = HSV(h=270,s=0.75,v=0.9);
// color(rgb) cube(60, center=true);
function HSV(h,s=1,v=1) =
function HSV(h,s=1,v=1,a) =
assert(s>=0 && s<=1)
assert(v>=0 && v<=1)
assert(is_undef(a) || a>=0 && a<=1)
let(
h = posmod(h,360),
c = v * s,
@ -114,7 +172,8 @@ function HSV(h,s=1,v=1) =
: [0,0,0],
m=v-c
)
rgbprime+[m,m,m];
is_def(a) ? point4d(add_scalar(rgbprime,m),a)
: add_scalar(rgbprime,m);
module HSV(h,s=1,v=1,a=1) color(HSV(h,s,v),a) children();

View File

@ -306,21 +306,25 @@ include <structs.scad>
// $fn=64;
// path = [[0, 0],[10, 0],[20, 20],[30, -10]];
// debug_polygon(path);
// //polygon(round_corners(path,cut = [1,3,1,1], method="circle"));
// //polygon(round_corners(path,cut = [1,3,1,1],
// // method="circle"));
// Example(2D): The list of factors shows that the problem is in the first two rounding values, because the factors are smaller than one. If we multiply the first two parameters by 0.85 then the roundings fit. The verbose option gives us the same fit factors.
// $fn=64;
// path = [[0, 0],[10, 0],[20, 20],[30, -10]];
// polygon(round_corners(path,cut = [0.85,3*0.85,1,1], method="circle", verbose=true));
// polygon(round_corners(path,cut = [0.85,3*0.85,1,1],
// method="circle", verbose=true));
// Example(2D): From the fit factors we can see that rounding at vertices 2 and 3 could be increased a lot. Applying those factors we get this more rounded shape. The new fit factors show that we can still further increase the rounding parameters if we wish.
// $fn=64;
// path = [[0, 0],[10, 0],[20, 20],[30, -10]];
// polygon(round_corners(path,cut = [0.85,3*0.85,2.13, 10.15], method="circle",verbose=true));
// polygon(round_corners(path,cut = [0.85,3*0.85,2.13, 10.15],
// method="circle",verbose=true));
// Example(2D): Using the `joint` parameter it's easier to understand whether your roundvers will fit. We can guarantee a fairly large roundover on any path by picking each one to use up half the segment distance along the shorter of its two segments:
// $fn=64;
// path = [[0, 0],[10, 0],[20, 20],[30, -10]];
// path_len = path_segment_lengths(path,closed=true);
// halflen = [for(i=idx(path)) min(select(path_len,i-1,i))/2];
// polygon(round_corners(path,joint = halflen, method="circle",verbose=true));
// polygon(round_corners(path,joint = halflen,
// method="circle",verbose=true));
// Example(2D): Chamfering, specifying the chamfer width
// path = star(5, step=2, d=100);
// path2 = round_corners(path, method="chamfer", width=5);
@ -619,16 +623,23 @@ function _rounding_offsets(edgespec,z_dir=1) =
// polygon(smooth_path(square(4),size=0.4,closed=true));
// Example(2D): Turning on uniform tangent calculation also changes the end derivatives:
// color("green")stroke(square(4), width=0.1);
// stroke(smooth_path(square(4),size=0.4,uniform=true), width=0.1);
// stroke(smooth_path(square(4),size=0.4,uniform=true),
// width=0.1);
// Example(2D): Here's a wide rectangle. Using size means all edges bulge the same amount, regardless of their length.
// color("green")
// stroke(square([10,4]), closed=true, width=0.1);
// stroke(smooth_path(square([10,4]),size=1,closed=true),
// width=0.1);
// Example(2D): With relsize the bulge is proportional to the side length.
// color("green")stroke(square([10,4]), closed=true, width=0.1);
// stroke(smooth_path(square([10,4]),size=1,closed=true),width=0.1);
// Example(2D): Here's a wide rectangle. With relsize the bulge is proportional to the side length.
// color("green")stroke(square([10,4]), closed=true, width=0.1);
// stroke(smooth_path(square([10,4]),relsize=0.1,closed=true),width=0.1);
// Example(2D): Here's a wide rectangle. Settting uniform to true biases the tangents to aline more with the line sides
// color("green")stroke(square([10,4]), closed=true, width=0.1);
// stroke(smooth_path(square([10,4]),uniform=true,relsize=0.1,closed=true),width=0.1);
// stroke(smooth_path(square([10,4]),relsize=0.1,closed=true),
// width=0.1);
// Example(2D): Settting uniform to true biases the tangents to aline more with the line sides
// color("green")
// stroke(square([10,4]), closed=true, width=0.1);
// stroke(smooth_path(square([10,4]),uniform=true,
// relsize=0.1,closed=true),
// width=0.1);
// Example(2D): A more interesting shape:
// path = [[0,0], [4,0], [7,14], [-3,12]];
// polygon(smooth_path(path,size=1,closed=true));
@ -636,11 +647,13 @@ function _rounding_offsets(edgespec,z_dir=1) =
// polygon(smooth_path(square(4), size=.25,closed=true));
// Example(2D): Here's the square with a size that's too big to achieve, so you get the maximum possible curve:
// color("green")stroke(square(4), width=0.1,closed=true);
// stroke(smooth_path(square(4), size=4, closed=true),closed=true,width=.1);
// stroke(smooth_path(square(4), size=4, closed=true),
// closed=true,width=.1);
// Example(2D): You can alter the shape of the curve by specifying your own arbitrary tangent values
// polygon(smooth_path(square(4),tangents=1.25*[[-2,-1], [-4,1], [1,2], [6,-1]],size=0.4,closed=true));
// Example(2D): Or you can give a different size for each segment
// polygon(smooth_path(square(4),size = [.4, .05, 1, .3],closed=true));
// polygon(smooth_path(square(4),size = [.4, .05, 1, .3],
// closed=true));
// Example(FlatSpin,VPD=35,VPT=[4.5,4.5,1]): Works on 3d paths as well
// path = [[0,0,0],[3,3,2],[6,0,1],[9,9,0]];
// stroke(smooth_path(path,relsize=.1),width=.3);
@ -716,23 +729,31 @@ function _scalar_to_vector(value,length,varname) =
// Example(2D): Specifying pairs of joint values at a path joint creates an asymmetric curve
// horiz = [[0,0],[10,0]];
// vert = [[0,0],[0,10]];
// stroke(path_join([horiz, vert, -horiz],joint=[[4,1],[1,4]],$fn=16),width=.3);
// stroke(path_join([horiz, vert, -horiz],
// joint=[[4,1],[1,4]],$fn=16),width=.3);
// Example(2D): A closed square
// horiz = [[0,0],[10,0]];
// vert = [[0,0],[0,10]];
// stroke(path_join([horiz, vert, -horiz, -vert],joint=3,k=1,closed=true,$fn=16),closed=true);
// stroke(path_join([horiz, vert, -horiz, -vert],
// joint=3,k=1,closed=true,$fn=16),closed=true);
// Example(2D): Different curve at each corner by changing the joint size
// horiz = [[0,0],[10,0]];
// vert = [[0,0],[0,10]];
// stroke(path_join([horiz, vert, -horiz, -vert],joint=[3,0,1,2],k=1,closed=true,$fn=16),closed=true,width=0.4);
// stroke(path_join([horiz, vert, -horiz, -vert],
// joint=[3,0,1,2],k=1,closed=true,$fn=16),
// closed=true,width=0.4);
// Example(2D): Different curve at each corner by changing the curvature parameter. Note that k=0 still gives a small curve, unlike joint=0 which gives a sharp corner.
// horiz = [[0,0],[10,0]];
// vert = [[0,0],[0,10]];
// stroke(path_join([horiz, vert, -horiz, -vert],joint=3,k=[1,.5,0,.7],closed=true,$fn=16),closed=true,width=0.4);
// stroke(path_join([horiz, vert, -horiz, -vert],joint=3,
// k=[1,.5,0,.7],closed=true,$fn=16),
// closed=true,width=0.4);
// Example(2D): Joint value of 7 is larger than half the square so curves interfere with each other, which breaks symmetry because they are computed sequentially
// horiz = [[0,0],[10,0]];
// vert = [[0,0],[0,10]];
// stroke(path_join([horiz, vert, -horiz, -vert],joint=7,k=.4,closed=true,$fn=16),closed=true);
// stroke(path_join([horiz, vert, -horiz, -vert],joint=7,
// k=.4,closed=true,$fn=16),
// closed=true);
// Example(2D): Unlike round_corners, we can add curves onto curves.
// $fn=64;
// myarc = arc(width=20, thickness=5 );
@ -740,29 +761,41 @@ function _scalar_to_vector(value,length,varname) =
// Example(2D): Here we make a closed shape from two arcs and round the sharp tips
// arc1 = arc(width=20, thickness=4,$fn=75);
// arc2 = reverse(arc(width=20, thickness=2,$fn=75));
// stroke(path_join([arc1,arc2]),width=.3); // Join without rounding
// color("red")stroke(path_join([arc1,arc2], 3,k=1,closed=true), width=.3,closed=true,$fn=12); // Join with rounding
// // Without rounding
// stroke(path_join([arc1,arc2]),width=.3);
// // With rounding
// color("red")stroke(path_join([arc1,arc2], 3,k=1,closed=true),
// width=.3,closed=true,$fn=12);
// Example(2D): Combining arcs with segments
// arc1 = arc(width=20, thickness=4,$fn=75);
// arc2 = reverse(arc(width=20, thickness=2,$fn=75));
// vpath = [[0,0],[0,-5]];
// stroke(path_join([arc1,vpath,arc2,reverse(vpath)]),width=.2);
// color("red")stroke(path_join([arc1,vpath,arc2,reverse(vpath)], [1,2,2,1],k=1,closed=true), width=.2,closed=true,$fn=12);
// color("red")stroke(path_join([arc1,vpath,arc2,reverse(vpath)],
// [1,2,2,1],k=1,closed=true),
// width=.2,closed=true,$fn=12);
// Example(2D): Here relocation is off. We have three segments (in yellow) and add the curves to the segments. Notice that joint zero still produces a curve because it refers to the endpoints of the supplied paths.
// p1 = [[0,0],[2,0]];
// p2 = [[3,1],[1,3]];
// p3 = [[0,3],[-1,1]];
// color("red")stroke(path_join([p1,p2,p3], joint=0, relocate=false,closed=true),width=.3,$fn=12);
// color("red")stroke(
// path_join([p1,p2,p3], joint=0, relocate=false,
// closed=true),
// width=.3,$fn=12);
// for(x=[p1,p2,p3]) stroke(x,width=.3);
// Example(2D): If you specify closed=true when the last path doesn't meet the first one then it is similar to using relocate=false: the function tries to close the path using a curve. In the example below, this results in a long curve to the left, when given the unclosed three segments as input. Note that if the segments are parallel the function fails with an error. The extension of the curves must intersect in a corner for the rounding to be well-defined. To get a normal rounding of the closed shape, you must include a fourth path, the last segment that closes the shape.
// horiz = [[0,0],[10,0]];
// vert = [[0,0],[0,10]];
// h2 = [[0,-3],[10,0]];
// color("red")stroke(path_join([horiz, vert, -h2],closed=true,joint=3,$fn=25),closed=true,width=.5);
// color("red")stroke(
// path_join([horiz, vert, -h2],closed=true,
// joint=3,$fn=25),
// closed=true,width=.5);
// stroke(path_join([horiz, vert, -h2]),width=.3);
// Example(2D): With a single path with closed=true the start and end junction is rounded.
// tri = regular_ngon(n=3, r=7);
// stroke(path_join([tri], joint=3,closed=true,$fn=12),closed=true,width=.5);
// stroke(path_join([tri], joint=3,closed=true,$fn=12),
// closed=true,width=.5);
module path_join(paths,joint=0,k=0.5,relocate=true,closed=false) { no_module();}
function path_join(paths,joint=0,k=0.5,relocate=true,closed=false)=
assert(is_list(paths),"Input paths must be a list of paths")