mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2024-12-29 16:29:40 +00:00
First pass at attachments support.
This commit is contained in:
parent
96739c3ea0
commit
6f342f450f
10 changed files with 861 additions and 174 deletions
|
@ -342,5 +342,20 @@ function corner_edge_count(edges, v) =
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Default values for attachment code.
|
||||||
|
$color = undef;
|
||||||
|
$overlap = 0.01;
|
||||||
|
$attach_to = undef;
|
||||||
|
$attach_conn = ["center", V_ZERO, V_UP, 0];
|
||||||
|
$parent_size = undef;
|
||||||
|
$parent_size2 = undef;
|
||||||
|
$parent_shift = [0,0];
|
||||||
|
$parent_orient = ORIENT_Z;
|
||||||
|
$parent_align = "center";
|
||||||
|
$parent_conns = [];
|
||||||
|
$tags_shown = [];
|
||||||
|
$tags_hidden = [];
|
||||||
|
$tags = "";
|
||||||
|
|
||||||
|
|
||||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||||
|
|
72
debug.scad
72
debug.scad
|
@ -175,4 +175,76 @@ module debug_polyhedron(points, faces, convexity=10, txtsize=1, disabled=false)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Function: all_conns()
|
||||||
|
// Description:
|
||||||
|
// Return the names for all standard connectors for a region.
|
||||||
|
// Arguments:
|
||||||
|
// type = The type of region to show connectors for. "cube", "cylinder", "sphere"
|
||||||
|
function all_conns(type="cube") =
|
||||||
|
assert(in_list(type,["cube", "cylinder", "sphere"]))
|
||||||
|
let (
|
||||||
|
zs = ["top", "bottom"],
|
||||||
|
ys = ["front", "back"],
|
||||||
|
xs = ["left", "right"]
|
||||||
|
) concat(
|
||||||
|
["center"],
|
||||||
|
[for (a=concat(xs,ys,zs)) a],
|
||||||
|
in_list(type,["cube","cylinder"])? [for (a=zs, b=ys) str(a,"-",b)] : [],
|
||||||
|
in_list(type,["cube","cylinder"])? [for (a=zs, b=xs) str(a,"-",b)] : [],
|
||||||
|
in_list(type,["cube"])? [for (a=ys, b=xs) str(a,"-",b)] : [],
|
||||||
|
in_list(type,["cube"])? [for (a=zs, b=ys, c=xs) str(a,"-",b,"-",c)] : []
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Module: connector_arrow()
|
||||||
|
// Usage:
|
||||||
|
// connector_arrow([s], [color], [flag]);
|
||||||
|
// Description:
|
||||||
|
// Show a connector orientation arrow.
|
||||||
|
// Arguments:
|
||||||
|
// s = Length of the arrows.
|
||||||
|
// color = Color of the arrow.
|
||||||
|
// flag = If true, draw the orientation flag on the arrowhead.
|
||||||
|
module connector_arrow(s=10, color=[0.333,0.333,1], flag=true) {
|
||||||
|
$fn=12;
|
||||||
|
recolor("gray") spheroid(d=s/6)
|
||||||
|
recolor(color) cyl(h=s*2/3, d=s/15, align=V_UP)
|
||||||
|
attach("top") cyl(h=s/3, d1=s/5, d2=0, align=V_UP) {
|
||||||
|
if(flag) {
|
||||||
|
attach("bottom") recolor([1,0.5,0.5]) cuboid([s/50, s/6, s/4], align="front-top");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Module: show_connectors()
|
||||||
|
// Description:
|
||||||
|
// Show all standard connectors for a given region.
|
||||||
|
// Arguments:
|
||||||
|
// type = The type of region to show connectors for. "cube", "cylinder", "sphere"
|
||||||
|
module show_connectors(type="cube") {
|
||||||
|
for (conn=all_conns(type)) {
|
||||||
|
attach(conn) connector_arrow();
|
||||||
|
}
|
||||||
|
children();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Module: frameref()
|
||||||
|
// Description:
|
||||||
|
// Displays X,Y,Z axis arrows in red, green, and blue respectively.
|
||||||
|
// Arguments:
|
||||||
|
// s = Length of the arrows.
|
||||||
|
module frameref(s=15) {
|
||||||
|
sphere(0.001) {
|
||||||
|
attach("right") connector_arrow(s=s, color="red", flag=false);
|
||||||
|
attach("back") connector_arrow(s=s, color="green", flag=false);
|
||||||
|
attach("top") connector_arrow(s=s, color="blue", flag=false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||||
|
|
21
examples/attachments.scad
Normal file
21
examples/attachments.scad
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
include <BOSL/constants.scad>
|
||||||
|
include <BOSL/transforms.scad>
|
||||||
|
include <BOSL/primitives.scad>
|
||||||
|
include <BOSL/shapes.scad>
|
||||||
|
include <BOSL/debug.scad>
|
||||||
|
|
||||||
|
cuboid([60,40,40], fillet=5, edges=EDGES_Z_ALL, align="bottom") {
|
||||||
|
attach("top") rounded_prismoid([60,40],[20,20], h=50, r1=5, r2=10) {
|
||||||
|
attach("top") cylinder(d=20, h=30) {
|
||||||
|
attach("top") cylinder(d1=50, d2=30, h=12);
|
||||||
|
}
|
||||||
|
for (a = ["front", "back", "left", "right"]) {
|
||||||
|
attach(a) cylinder(d1=14, d2=5, h=20) {
|
||||||
|
attach("top", "left", overlap=5) prismoid([30,20], [20,20], h=10, shift=[-7,0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
9
examples/cylinder_connectors.scad
Normal file
9
examples/cylinder_connectors.scad
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
include <BOSL/constants.scad>
|
||||||
|
include <BOSL/primitives.scad>
|
||||||
|
include <BOSL/debug.scad>
|
||||||
|
|
||||||
|
|
||||||
|
cylinder(h=30, d1=50, d2=30) show_connectors("cylinder");
|
||||||
|
|
||||||
|
|
||||||
|
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
42
examples/fractal_tree.scad
Normal file
42
examples/fractal_tree.scad
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
include <BOSL/constants.scad>
|
||||||
|
include <BOSL/transforms.scad>
|
||||||
|
include <BOSL/primitives.scad>
|
||||||
|
include <BOSL/beziers.scad>
|
||||||
|
|
||||||
|
module leaf(s) {
|
||||||
|
path = [
|
||||||
|
[0,0], [1.5,-1],
|
||||||
|
[2,1], [0,3], [-2,1],
|
||||||
|
[-1.5,-1], [0,0]
|
||||||
|
];
|
||||||
|
xrot(90)
|
||||||
|
linear_extrude_bezier(
|
||||||
|
scale_points(path, [s,s]/2),
|
||||||
|
height=0.02
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
module branches(minsize){
|
||||||
|
if($parent_size2.x>minsize) {
|
||||||
|
attach("top")
|
||||||
|
zrot(gaussian_rand(90,10))
|
||||||
|
zring(n=floor(log_rand(2,5,4)))
|
||||||
|
zrot(gaussian_rand(0,5))
|
||||||
|
yrot(gaussian_rand(30,5))
|
||||||
|
let(
|
||||||
|
sc = gaussian_rand(0.7,0.05),
|
||||||
|
s1 = $parent_size.z*sc,
|
||||||
|
s2 = $parent_size2.x
|
||||||
|
)
|
||||||
|
cylinder(d1=s2, d2=s2*sc, l=s1)
|
||||||
|
branches(minsize);
|
||||||
|
} else {
|
||||||
|
recolor("springgreen")
|
||||||
|
attach("top") zrot(90)
|
||||||
|
leaf(gaussian_rand(100,5));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
recolor("lightgray") cylinder(d1=300, d2=250, l=1500) branches(5);
|
||||||
|
|
||||||
|
|
||||||
|
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
9
examples/prismoid_connectors.scad
Normal file
9
examples/prismoid_connectors.scad
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
include <BOSL/constants.scad>
|
||||||
|
include <BOSL/shapes.scad>
|
||||||
|
include <BOSL/debug.scad>
|
||||||
|
|
||||||
|
|
||||||
|
prismoid([60,40], [30,20], h=40) show_connectors();
|
||||||
|
|
||||||
|
|
||||||
|
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
18
examples/tagged_diff.scad
Normal file
18
examples/tagged_diff.scad
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
include <BOSL/constants.scad>
|
||||||
|
include <BOSL/transforms.scad>
|
||||||
|
include <BOSL/primitives.scad>
|
||||||
|
include <BOSL/shapes.scad>
|
||||||
|
|
||||||
|
|
||||||
|
diff("hole", "body pole")
|
||||||
|
sphere(d=100, $tags="body") {
|
||||||
|
zcyl(d=55, h=100, $tags="pole"); // attach() not needed for center-to-center.
|
||||||
|
tags("hole") {
|
||||||
|
xcyl(d=55, h=101);
|
||||||
|
ycyl(d=55, h=101);
|
||||||
|
}
|
||||||
|
zcyl(d=15, h=140, $tags="axle");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
153
primitives.scad
Normal file
153
primitives.scad
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// LibFile: primitives.scad
|
||||||
|
// The basic built-in shapes, reworked to integrate better with
|
||||||
|
// other BOSL library shapes and utilities.
|
||||||
|
// To use, add the following lines to the beginning of your file:
|
||||||
|
// ```
|
||||||
|
// include <BOSL/constants.scad>
|
||||||
|
// use <BOSL/primitives.scad>
|
||||||
|
// ```
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/*
|
||||||
|
BSD 2-Clause License
|
||||||
|
|
||||||
|
Copyright (c) 2017, Revar Desmera
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
include <constants.scad>
|
||||||
|
include <compat.scad>
|
||||||
|
use <transforms.scad>
|
||||||
|
use <math.scad>
|
||||||
|
|
||||||
|
|
||||||
|
// Section: Primitive Shapes
|
||||||
|
|
||||||
|
|
||||||
|
// Module: cube()
|
||||||
|
//
|
||||||
|
// Description:
|
||||||
|
// Creates a cube object, with support for alignment and attachments.
|
||||||
|
// This is a drop-in replacement for the built-in `cube()` module.
|
||||||
|
//
|
||||||
|
// Arguments:
|
||||||
|
// size = The size of the cube.
|
||||||
|
// align = The side of the origin to align to. Use `V_` constants from `constants.scad`. Default: `V_CENTER`
|
||||||
|
// center = If given, overrides `align`. A true value sets `align=V_CENTER`, false sets `align=V_UP+V_BACK+V_RIGHT`.
|
||||||
|
//
|
||||||
|
// Example: Simple regular cube.
|
||||||
|
// cube(40);
|
||||||
|
// Example: Rectangular cube, with given X, Y, and Z sizes.
|
||||||
|
// cuboid([20,40,50]);
|
||||||
|
module cube(size, center=undef, align=V_ALLPOS)
|
||||||
|
{
|
||||||
|
size = scalar_vec3(size);
|
||||||
|
orient_and_align(size, ORIENT_Z, align, center, noncentered=V_ALLPOS, chain=true) {
|
||||||
|
linear_extrude(height=size.z, convexity=2, center=true) {
|
||||||
|
square([size.x, size.y], center=true);
|
||||||
|
}
|
||||||
|
children();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Module: cylinder()
|
||||||
|
// Usage:
|
||||||
|
// cylinder(h, r|d, [center], [orient], [align]);
|
||||||
|
// cylinder(h, r1/d1, r2/d2, [center], [orient], [align]);
|
||||||
|
// Description:
|
||||||
|
// Creates a cylinder object, with support for alignment and attachments.
|
||||||
|
// This is a drop-in replacement for the built-in `cylinder()` module.
|
||||||
|
// Arguments:
|
||||||
|
// l / h = The height of the cylinder.
|
||||||
|
// r = The radius of the cylinder.
|
||||||
|
// r1 = The bottom radius of the cylinder. (Before orientation.)
|
||||||
|
// r2 = The top radius of the cylinder. (Before orientation.)
|
||||||
|
// d = The diameter of the cylinder.
|
||||||
|
// d1 = The bottom diameter of the cylinder. (Before orientation.)
|
||||||
|
// d2 = The top diameter of the cylinder. (Before orientation.)
|
||||||
|
// orient = Orientation of the cylinder. Use the `ORIENT_` constants from `constants.scad`. Default: vertical.
|
||||||
|
// align = The side of the origin to align to. Use `V_` constants from `constants.scad`. Default: `V_CENTER`
|
||||||
|
// center = If given, overrides `align`. A true value sets `align=V_CENTER`, false sets `align=V_UP+V_BACK+V_RIGHT`.
|
||||||
|
// Example: By Radius
|
||||||
|
// xdistribute(30) {
|
||||||
|
// cylinder(h=40, r=10);
|
||||||
|
// cylinder(h=40, r1=10, r2=5);
|
||||||
|
// }
|
||||||
|
// Example: By Diameter
|
||||||
|
// xdistribute(30) {
|
||||||
|
// cylinder(h=40, d=25);
|
||||||
|
// cylinder(h=40, d1=25, d2=10);
|
||||||
|
// }
|
||||||
|
module cylinder(r=undef, d=undef, r1=undef, r2=undef, d1=undef, d2=undef, h=undef, l=undef, center=undef, orient=ORIENT_Z, align=ALIGN_POS)
|
||||||
|
{
|
||||||
|
r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=1);
|
||||||
|
r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=1);
|
||||||
|
l = first_defined([h, l]);
|
||||||
|
sides = segs(max(r1,r2));
|
||||||
|
size = [r1*2, r1*2, l];
|
||||||
|
orient_and_align(size, orient, align, center, size2=[r2*2,r2*2], noncentered=ALIGN_POS, chain=true) {
|
||||||
|
linear_extrude(height=l, scale=r2/r1, convexity=2, center=true) {
|
||||||
|
circle(r=r1, $fn=sides);
|
||||||
|
}
|
||||||
|
children();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Module: sphere()
|
||||||
|
// Usage:
|
||||||
|
// sphere(r|d, [orient], [align])
|
||||||
|
// Description:
|
||||||
|
// Creates a sphere object, with support for alignment and attachments.
|
||||||
|
// This is a drop-in replacement for the built-in `sphere()` module.
|
||||||
|
// Arguments:
|
||||||
|
// r = Radius of the sphere.
|
||||||
|
// d = Diameter of the sphere.
|
||||||
|
// orient = Orientation of the sphere, if you don't like where the vertices lay. Use the `ORIENT_` constants from `constants.scad`. Default: `ORIENT_Z`.
|
||||||
|
// align = Alignment of the sphere. Use the `V_` constants from `constants.scad`. Default: `V_CENTER`.
|
||||||
|
// Example:
|
||||||
|
// staggered_sphere(d=100);
|
||||||
|
module sphere(r=undef, d=undef, orient=ORIENT_Z, align=V_CENTER)
|
||||||
|
{
|
||||||
|
r = get_radius(r=r, d=d, dflt=1);
|
||||||
|
sides = segs(r);
|
||||||
|
size = [r*2, r*2, r*2];
|
||||||
|
orient_and_align(size, orient, align, chain=true) {
|
||||||
|
rotate_extrude(convexity=2) {
|
||||||
|
difference() {
|
||||||
|
circle(r=r, $fn=sides);
|
||||||
|
left(r+0.1) square(r*2+0.2, center=true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
children();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
318
shapes.scad
318
shapes.scad
|
@ -96,26 +96,25 @@ module cuboid(
|
||||||
if (is_def(p1)) {
|
if (is_def(p1)) {
|
||||||
if (is_def(p2)) {
|
if (is_def(p2)) {
|
||||||
translate([for (v=array_zip([p1,p2],0)) min(v)]) {
|
translate([for (v=array_zip([p1,p2],0)) min(v)]) {
|
||||||
cuboid(size=vabs(p2-p1), chamfer=chamfer, fillet=fillet, edges=edges, trimcorners=trimcorners, align=V_ALLPOS);
|
cuboid(size=vabs(p2-p1), chamfer=chamfer, fillet=fillet, edges=edges, trimcorners=trimcorners, align=V_ALLPOS) children();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
translate(p1) {
|
translate(p1) {
|
||||||
cuboid(size=size, chamfer=chamfer, fillet=fillet, edges=edges, trimcorners=trimcorners, align=V_ALLPOS);
|
cuboid(size=size, chamfer=chamfer, fillet=fillet, edges=edges, trimcorners=trimcorners, align=V_ALLPOS) children();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
majrots = [[0,90,0], [90,0,0], [0,0,0]];
|
|
||||||
if (chamfer != undef) assertion(chamfer <= min(size)/2, "chamfer must be smaller than half the cube width, length, or height.");
|
if (chamfer != undef) assertion(chamfer <= min(size)/2, "chamfer must be smaller than half the cube width, length, or height.");
|
||||||
if (fillet != undef) assertion(fillet <= min(size)/2, "fillet must be smaller than half the cube width, length, or height.");
|
if (fillet != undef) assertion(fillet <= min(size)/2, "fillet must be smaller than half the cube width, length, or height.");
|
||||||
algn = (!is_def(center))? (is_scalar(align)? align*V_UP : align) : (center==true)? V_CENTER : V_ALLPOS;
|
majrots = [[0,90,0], [90,0,0], [0,0,0]];
|
||||||
translate(vmul(size/2, algn)) {
|
orient_and_align(size, ORIENT_Z, align, center=center, noncentered=V_ALLPOS, chain=true) {
|
||||||
if (chamfer != undef) {
|
if (chamfer != undef) {
|
||||||
isize = [for (v = size) max(0.001, v-2*chamfer)];
|
isize = [for (v = size) max(0.001, v-2*chamfer)];
|
||||||
if (edges == EDGES_ALL && trimcorners) {
|
if (edges == EDGES_ALL && trimcorners) {
|
||||||
hull() {
|
hull() {
|
||||||
cube([size[0], isize[1], isize[2]], center=true);
|
cube([size.x, isize.y, isize.z], center=true);
|
||||||
cube([isize[0], size[1], isize[2]], center=true);
|
cube([isize.x, size.y, isize.z], center=true);
|
||||||
cube([isize[0], isize[1], size[2]], center=true);
|
cube([isize.x, isize.y, size.z], center=true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
difference() {
|
difference() {
|
||||||
|
@ -201,6 +200,7 @@ module cuboid(
|
||||||
} else {
|
} else {
|
||||||
cube(size=size, center=true);
|
cube(size=size, center=true);
|
||||||
}
|
}
|
||||||
|
children();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -221,7 +221,7 @@ module cuboid(
|
||||||
// p2 = Coordinate point of opposite cube corner.
|
// p2 = Coordinate point of opposite cube corner.
|
||||||
module cube2pt(p1,p2) {
|
module cube2pt(p1,p2) {
|
||||||
deprecate("cube2pt()", "cuboid(p1,p2)");
|
deprecate("cube2pt()", "cuboid(p1,p2)");
|
||||||
cuboid(p1=p1, p2=p2);
|
cuboid(p1=p1, p2=p2) children();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -240,7 +240,7 @@ module cube2pt(p1,p2) {
|
||||||
// span_cube([0,15], [5,10], [0, 10]);
|
// span_cube([0,15], [5,10], [0, 10]);
|
||||||
module span_cube(xspan, yspan, zspan) {
|
module span_cube(xspan, yspan, zspan) {
|
||||||
span = [xspan, yspan, zspan];
|
span = [xspan, yspan, zspan];
|
||||||
cuboid(p1=array_subindex(span,0), p2=array_subindex(span,1));
|
cuboid(p1=array_subindex(span,0), p2=array_subindex(span,1)) children();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -257,7 +257,7 @@ module span_cube(xspan, yspan, zspan) {
|
||||||
// v = vector to offset along.
|
// v = vector to offset along.
|
||||||
module offsetcube(size=[1,1,1], v=[0,0,0]) {
|
module offsetcube(size=[1,1,1], v=[0,0,0]) {
|
||||||
deprecate("offsetcube()", "cuboid()");
|
deprecate("offsetcube()", "cuboid()");
|
||||||
cuboid(size=size, align=v);
|
cuboid(size=size, align=v) children();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -379,7 +379,7 @@ module chamfcube(size=[1,1,1], chamfer=0.25, chamfaxes=[1,1,1], chamfcorners=fal
|
||||||
(chamfaxes[1]? EDGES_Y_ALL : EDGES_NONE) +
|
(chamfaxes[1]? EDGES_Y_ALL : EDGES_NONE) +
|
||||||
(chamfaxes[2]? EDGES_Z_ALL : EDGES_NONE)
|
(chamfaxes[2]? EDGES_Z_ALL : EDGES_NONE)
|
||||||
)
|
)
|
||||||
);
|
) children();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -396,7 +396,7 @@ module chamfcube(size=[1,1,1], chamfer=0.25, chamfaxes=[1,1,1], chamfcorners=fal
|
||||||
// center = If true, object will be centered. If false, sits on top of XY plane.
|
// center = If true, object will be centered. If false, sits on top of XY plane.
|
||||||
module rrect(size=[1,1,1], r=0.25, center=false) {
|
module rrect(size=[1,1,1], r=0.25, center=false) {
|
||||||
deprecate("rrect()", "cuboid()");
|
deprecate("rrect()", "cuboid()");
|
||||||
cuboid(size=size, fillet=r, edges=EDGES_Z_ALL, align=center? V_CENTER : V_UP);
|
cuboid(size=size, fillet=r, edges=EDGES_Z_ALL, align=center? V_CENTER : V_UP) children();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -413,7 +413,7 @@ module rrect(size=[1,1,1], r=0.25, center=false) {
|
||||||
// center = If true, object will be centered. If false, sits on top of XY plane.
|
// center = If true, object will be centered. If false, sits on top of XY plane.
|
||||||
module rcube(size=[1,1,1], r=0.25, center=false) {
|
module rcube(size=[1,1,1], r=0.25, center=false) {
|
||||||
deprecate("rcube()", "cuboid()");
|
deprecate("rcube()", "cuboid()");
|
||||||
cuboid(size=size, fillet=r, align=center? V_CENTER : V_UP);
|
cuboid(size=size, fillet=r, align=center? V_CENTER : V_UP) children();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -459,20 +459,20 @@ module prismoid(
|
||||||
orient=ORIENT_Z, align=ALIGN_POS, center=undef
|
orient=ORIENT_Z, align=ALIGN_POS, center=undef
|
||||||
) {
|
) {
|
||||||
eps = 0.001;
|
eps = 0.001;
|
||||||
s1 = [max(size1[0], eps), max(size1[1], eps)];
|
shiftby = point3d(point2d(shift));
|
||||||
s2 = [max(size2[0], eps), max(size2[1], eps)];
|
s1 = [max(size1.x, eps), max(size1.y, eps)];
|
||||||
shiftby = point3d(shift);
|
s2 = [max(size2.x, eps), max(size2.y, eps)];
|
||||||
orient_and_align([s1[0], s1[1], h], orient, align, center, noncentered=ALIGN_POS) {
|
orient_and_align([s1.x,s1.y,h], orient, align, center, size2=s2, shift=shift, noncentered=ALIGN_POS, chain=true) {
|
||||||
polyhedron(
|
polyhedron(
|
||||||
points=[
|
points=[
|
||||||
[+s2[0]/2, +s2[1]/2, +h/2] + shiftby,
|
[+s2.x/2, +s2.y/2, +h/2] + shiftby,
|
||||||
[+s2[0]/2, -s2[1]/2, +h/2] + shiftby,
|
[+s2.x/2, -s2.y/2, +h/2] + shiftby,
|
||||||
[-s2[0]/2, -s2[1]/2, +h/2] + shiftby,
|
[-s2.x/2, -s2.y/2, +h/2] + shiftby,
|
||||||
[-s2[0]/2, +s2[1]/2, +h/2] + shiftby,
|
[-s2.x/2, +s2.y/2, +h/2] + shiftby,
|
||||||
[+s1[0]/2, +s1[1]/2, -h/2],
|
[+s1.x/2, +s1.y/2, -h/2],
|
||||||
[+s1[0]/2, -s1[1]/2, -h/2],
|
[+s1.x/2, -s1.y/2, -h/2],
|
||||||
[-s1[0]/2, -s1[1]/2, -h/2],
|
[-s1.x/2, -s1.y/2, -h/2],
|
||||||
[-s1[0]/2, +s1[1]/2, -h/2],
|
[-s1.x/2, +s1.y/2, -h/2],
|
||||||
],
|
],
|
||||||
faces=[
|
faces=[
|
||||||
[0, 1, 2],
|
[0, 1, 2],
|
||||||
|
@ -490,6 +490,7 @@ module prismoid(
|
||||||
],
|
],
|
||||||
convexity=2
|
convexity=2
|
||||||
);
|
);
|
||||||
|
children();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -513,7 +514,7 @@ module prismoid(
|
||||||
// center = If given, overrides `align`. A true value sets `align=V_CENTER`, false sets `align=V_UP`.
|
// center = If given, overrides `align`. A true value sets `align=V_CENTER`, false sets `align=V_UP`.
|
||||||
module trapezoid(size1=[1,1], size2=[1,1], h=1, center=false) {
|
module trapezoid(size1=[1,1], size2=[1,1], h=1, center=false) {
|
||||||
deprecate("trapezoid()", "prismoid()");
|
deprecate("trapezoid()", "prismoid()");
|
||||||
prismoid(size=size, size2=size2, h=h, center=center);
|
prismoid(size=size, size2=size2, h=h, center=center) children();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -548,29 +549,31 @@ module rounded_prismoid(
|
||||||
align=V_UP, orient=ORIENT_Z, center=undef
|
align=V_UP, orient=ORIENT_Z, center=undef
|
||||||
) {
|
) {
|
||||||
eps = 0.001;
|
eps = 0.001;
|
||||||
maxrad1 = min(size1[0]/2, size1[1]/2);
|
maxrad1 = min(size1.x/2, size1.y/2);
|
||||||
maxrad2 = min(size2[0]/2, size2[1]/2);
|
maxrad2 = min(size2.x/2, size2.y/2);
|
||||||
rr1 = min(maxrad1, (r1!=undef)? r1 : r);
|
rr1 = min(maxrad1, (r1!=undef)? r1 : r);
|
||||||
rr2 = min(maxrad2, (r2!=undef)? r2 : r);
|
rr2 = min(maxrad2, (r2!=undef)? r2 : r);
|
||||||
shiftby = point3d(shift);
|
shiftby = point3d(shift);
|
||||||
orient_and_align([size1.x, size1.y, h], orient, align, center, noncentered=ALIGN_POS) {
|
orient_and_align([size1.x, size1.y, h], orient, align, center, size2=size2, shift=shift, noncentered=ALIGN_POS, chain=true) {
|
||||||
down(h/2)
|
down(h/2) {
|
||||||
hull() {
|
hull() {
|
||||||
linear_extrude(height=eps, center=false, convexity=2) {
|
linear_extrude(height=eps, center=false, convexity=2) {
|
||||||
offset(r=rr1) {
|
offset(r=rr1) {
|
||||||
square([max(eps, size1[0]-2*rr1), max(eps, size1[1]-2*rr1)], center=true);
|
square([max(eps, size1[0]-2*rr1), max(eps, size1[1]-2*rr1)], center=true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
up(h-0.01) {
|
||||||
up(h-0.01) {
|
translate(shiftby) {
|
||||||
translate(shiftby) {
|
linear_extrude(height=eps, center=false, convexity=2) {
|
||||||
linear_extrude(height=eps, center=false, convexity=2) {
|
offset(r=rr2) {
|
||||||
offset(r=rr2) {
|
square([max(eps, size2[0]-2*rr2), max(eps, size2[1]-2*rr2)], center=true);
|
||||||
square([max(eps, size2[0]-2*rr2), max(eps, size2[1]-2*rr2)], center=true);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
children();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -596,7 +599,7 @@ module pyramid(n=4, h=1, l=1, r=undef, d=undef, circum=false)
|
||||||
{
|
{
|
||||||
deprecate("pyramid()", "cyl()");
|
deprecate("pyramid()", "cyl()");
|
||||||
radius = get_radius(r=r, d=d, dflt=l/2/sin(180/n));
|
radius = get_radius(r=r, d=d, dflt=l/2/sin(180/n));
|
||||||
cyl(r1=radius, r2=0, l=h, circum=circum, $fn=n, realign=true, align=ALIGN_POS);
|
cyl(r1=radius, r2=0, l=h, circum=circum, $fn=n, realign=true, align=ALIGN_POS) children();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -620,7 +623,7 @@ module prism(n=3, h=1, l=1, r=undef, d=undef, circum=false, center=false)
|
||||||
{
|
{
|
||||||
deprecate("prism()", "cyl()");
|
deprecate("prism()", "cyl()");
|
||||||
radius = get_radius(r=r, d=d, dflt=l/2/sin(180/n));
|
radius = get_radius(r=r, d=d, dflt=l/2/sin(180/n));
|
||||||
cyl(r=radius, l=h, circum=circum, $fn=n, realign=true, center=center);
|
cyl(r=radius, l=h, circum=circum, $fn=n, realign=true, center=center) children();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -644,36 +647,37 @@ module prism(n=3, h=1, l=1, r=undef, d=undef, circum=false, center=false)
|
||||||
// right_triangle([60, 10, 40]);
|
// right_triangle([60, 10, 40]);
|
||||||
module right_triangle(size=[1, 1, 1], orient=ORIENT_Y, align=V_ALLPOS, center=undef)
|
module right_triangle(size=[1, 1, 1], orient=ORIENT_Y, align=V_ALLPOS, center=undef)
|
||||||
{
|
{
|
||||||
siz = scalar_vec3(size);
|
size = scalar_vec3(size);
|
||||||
orient_and_align(siz, align=align, center=center) {
|
orient_and_align(size, align=align, center=center, chain=true) {
|
||||||
if (orient == ORIENT_X) {
|
if (orient == ORIENT_X) {
|
||||||
ang = atan2(siz[1], siz[2]);
|
ang = atan2(size.y, size.z);
|
||||||
masksize = [siz[0], siz[1], norm([siz[1],siz[2]])] + [1,1,1];
|
masksize = [size.x, size.y, norm([size.y,size.z])] + [1,1,1];
|
||||||
xrot(ang) {
|
xrot(ang) {
|
||||||
difference() {
|
difference() {
|
||||||
xrot(-ang) cube(siz, center=true);
|
xrot(-ang) cube(size, center=true);
|
||||||
back(masksize[1]/2) cube(masksize, center=true);
|
back(masksize.y/2) cube(masksize, center=true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (orient == ORIENT_Y) {
|
} else if (orient == ORIENT_Y) {
|
||||||
ang = atan2(siz[0], siz[2]);
|
ang = atan2(size.x, size.z);
|
||||||
masksize = [siz[0], siz[1], norm([siz[0],siz[2]])] + [1,1,1];
|
masksize = [size.x, size.y, norm([size.x,size.z])] + [1,1,1];
|
||||||
yrot(-ang) {
|
yrot(-ang) {
|
||||||
difference() {
|
difference() {
|
||||||
yrot(ang) cube(siz, center=true);
|
yrot(ang) cube(size, center=true);
|
||||||
right(masksize[0]/2) cube(masksize, center=true);
|
right(masksize.x/2) cube(masksize, center=true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (orient == ORIENT_Z) {
|
} else if (orient == ORIENT_Z) {
|
||||||
ang = atan2(siz[0], siz[1]);
|
ang = atan2(size.x, size.y);
|
||||||
masksize = [norm([siz[0],siz[1]]), siz[1], siz[2]] + [1,1,1];
|
masksize = [norm([size.x,size.y]), size.y, size.z] + [1,1,1];
|
||||||
zrot(-ang) {
|
zrot(-ang) {
|
||||||
difference() {
|
difference() {
|
||||||
zrot(ang) cube(siz, center=true);
|
zrot(ang) cube(size, center=true);
|
||||||
back(masksize[1]/2) cube(masksize, center=true);
|
back(masksize.y/2) cube(masksize, center=true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
children();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -778,9 +782,12 @@ module cyl(
|
||||||
r1 = get_radius(r1, r, d1, d, 1);
|
r1 = get_radius(r1, r, d1, d, 1);
|
||||||
r2 = get_radius(r2, r, d2, d, 1);
|
r2 = get_radius(r2, r, d2, d, 1);
|
||||||
l = first_defined([l, h, 1]);
|
l = first_defined([l, h, 1]);
|
||||||
|
size1 = [r1*2,r1*2,l];
|
||||||
|
size2 = [r2*2,r2*2,l];
|
||||||
sides = segs(max(r1,r2));
|
sides = segs(max(r1,r2));
|
||||||
sc = circum? 1/cos(180/sides) : 1;
|
sc = circum? 1/cos(180/sides) : 1;
|
||||||
orient_and_align([r1*2,r1*2,l], orient, align, center=center) {
|
phi = atan2(l, r1-r2);
|
||||||
|
orient_and_align(size1, orient, align, center=center, size2=size2, chain=true) {
|
||||||
zrot(realign? 180/sides : 0) {
|
zrot(realign? 180/sides : 0) {
|
||||||
if (!any_defined([chamfer, chamfer1, chamfer2, fillet, fillet1, fillet2])) {
|
if (!any_defined([chamfer, chamfer1, chamfer2, fillet, fillet1, fillet2])) {
|
||||||
cylinder(h=l, r1=r1*sc, r2=r2*sc, center=true, $fn=sides);
|
cylinder(h=l, r1=r1*sc, r2=r2*sc, center=true, $fn=sides);
|
||||||
|
@ -901,6 +908,7 @@ module cyl(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
children();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -930,10 +938,8 @@ module cyl(
|
||||||
// downcyl(r1=10, r2=20, h=40);
|
// downcyl(r1=10, r2=20, h=40);
|
||||||
module downcyl(r=undef, h=undef, l=undef, d=undef, d1=undef, d2=undef, r1=undef, r2=undef)
|
module downcyl(r=undef, h=undef, l=undef, d=undef, d1=undef, d2=undef, r1=undef, r2=undef)
|
||||||
{
|
{
|
||||||
h = first_defined([l, h, 1]);
|
l = first_defined([l, h, 1]);
|
||||||
down(h/2) {
|
cyl(r=r, r1=r1, r2=r2, d=d, d1=d1, d2=d2, l=l, align=V_DOWN) children();
|
||||||
cylinder(r=r, r1=r1, r2=r2, d=d, d1=d1, d2=d2, h=h, center=true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -971,7 +977,7 @@ module downcyl(r=undef, h=undef, l=undef, d=undef, d1=undef, d2=undef, r1=undef,
|
||||||
// }
|
// }
|
||||||
module xcyl(l=undef, r=undef, d=undef, r1=undef, r2=undef, d1=undef, d2=undef, h=undef, align=V_CENTER, center=undef)
|
module xcyl(l=undef, r=undef, d=undef, r1=undef, r2=undef, d1=undef, d2=undef, h=undef, align=V_CENTER, center=undef)
|
||||||
{
|
{
|
||||||
cyl(l=l, h=h, r=r, r1=r1, r2=r2, d=d, d1=d1, d2=d2, orient=ORIENT_X, align=align, center=center);
|
cyl(l=l, h=h, r=r, r1=r1, r2=r2, d=d, d1=d1, d2=d2, orient=ORIENT_X, align=align, center=center) children();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1009,7 +1015,7 @@ module xcyl(l=undef, r=undef, d=undef, r1=undef, r2=undef, d1=undef, d2=undef, h
|
||||||
// }
|
// }
|
||||||
module ycyl(l=undef, r=undef, d=undef, r1=undef, r2=undef, d1=undef, d2=undef, h=undef, align=V_CENTER, center=undef)
|
module ycyl(l=undef, r=undef, d=undef, r1=undef, r2=undef, d1=undef, d2=undef, h=undef, align=V_CENTER, center=undef)
|
||||||
{
|
{
|
||||||
cyl(l=l, h=h, r=r, r1=r1, r2=r2, d=d, d1=d1, d2=d2, orient=ORIENT_Y, align=align, center=center);
|
cyl(l=l, h=h, r=r, r1=r1, r2=r2, d=d, d1=d1, d2=d2, orient=ORIENT_Y, align=align, center=center) children();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1047,7 +1053,7 @@ module ycyl(l=undef, r=undef, d=undef, r1=undef, r2=undef, d1=undef, d2=undef, h
|
||||||
// }
|
// }
|
||||||
module zcyl(l=undef, r=undef, d=undef, r1=undef, r2=undef, d1=undef, d2=undef, h=undef, align=V_CENTER, center=undef)
|
module zcyl(l=undef, r=undef, d=undef, r1=undef, r2=undef, d1=undef, d2=undef, h=undef, align=V_CENTER, center=undef)
|
||||||
{
|
{
|
||||||
cyl(l=l, h=h, r=r, r1=r1, r2=r2, d=d, d1=d1, d2=d2, orient=ORIENT_Z, align=align, center=center);
|
cyl(l=l, h=h, r=r, r1=r1, r2=r2, d=d, d1=d1, d2=d2, orient=ORIENT_Z, align=align, center=center) children();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1075,7 +1081,7 @@ module chamferred_cylinder(h=1, r=undef, d=undef, chamfer=0.25, chamfedge=undef,
|
||||||
deprecate("chamf_cyl()` and `chamferred_cylinder()", "cyl()");
|
deprecate("chamf_cyl()` and `chamferred_cylinder()", "cyl()");
|
||||||
r = get_radius(r=r, d=d, dflt=1);
|
r = get_radius(r=r, d=d, dflt=1);
|
||||||
chamf = (chamfedge == undef)? chamfer : chamfedge * cos(angle);
|
chamf = (chamfedge == undef)? chamfer : chamfedge * cos(angle);
|
||||||
cyl(l=h, r=r, chamfer1=bottom? chamf : 0, chamfer2=top? chamf : 0, chamfang=angle, center=center);
|
cyl(l=h, r=r, chamfer1=bottom? chamf : 0, chamfer2=top? chamf : 0, chamfang=angle, center=center) children();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1099,7 +1105,7 @@ module chamferred_cylinder(h=1, r=undef, d=undef, chamfer=0.25, chamfedge=undef,
|
||||||
// bottom = boolean. If true, chamfer the bottom edges. (Default: True)
|
// bottom = boolean. If true, chamfer the bottom edges. (Default: True)
|
||||||
// center = boolean. If true, cylinder is centered. (Default: false)
|
// center = boolean. If true, cylinder is centered. (Default: false)
|
||||||
module chamf_cyl(h=1, r=undef, d=undef, chamfer=0.25, chamfedge=undef, angle=45, center=false, top=true, bottom=true)
|
module chamf_cyl(h=1, r=undef, d=undef, chamfer=0.25, chamfedge=undef, angle=45, center=false, top=true, bottom=true)
|
||||||
chamferred_cylinder(h=h, r=r, d=d, chamfer=chamfer, chamfedge=chamfedge, angle=angle, center=center, top=top, bottom=bottom);
|
chamferred_cylinder(h=h, r=r, d=d, chamfer=chamfer, chamfedge=chamfedge, angle=angle, center=center, top=top, bottom=bottom) children();
|
||||||
|
|
||||||
|
|
||||||
// Module: filleted_cylinder()
|
// Module: filleted_cylinder()
|
||||||
|
@ -1119,7 +1125,7 @@ module chamf_cyl(h=1, r=undef, d=undef, chamfer=0.25, chamfedge=undef, angle=45,
|
||||||
// center = boolean. If true, cylinder is centered. (Default: false)
|
// center = boolean. If true, cylinder is centered. (Default: false)
|
||||||
module filleted_cylinder(h=1, r=undef, d=undef, r1=undef, r2=undef, d1=undef, d2=undef, fillet=0.25, center=false) {
|
module filleted_cylinder(h=1, r=undef, d=undef, r1=undef, r2=undef, d1=undef, d2=undef, fillet=0.25, center=false) {
|
||||||
deprecate("filleted_cylinder()", "cyl()");
|
deprecate("filleted_cylinder()", "cyl()");
|
||||||
cyl(l=h, r=r, d=d, r1=r1, r2=r2, d1=d1, d2=d2, fillet=fillet, orient=ORIENT_Z, center=center);
|
cyl(l=h, r=r, d=d, r1=r1, r2=r2, d1=d1, d2=d2, fillet=fillet, orient=ORIENT_Z, center=center) children();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1142,7 +1148,7 @@ module filleted_cylinder(h=1, r=undef, d=undef, r1=undef, r2=undef, d1=undef, d2
|
||||||
// center = boolean. If true, cylinder is centered. (Default: false)
|
// center = boolean. If true, cylinder is centered. (Default: false)
|
||||||
module rcylinder(h=1, r=1, r1=undef, r2=undef, d=undef, d1=undef, d2=undef, fillet=0.25, center=false) {
|
module rcylinder(h=1, r=1, r1=undef, r2=undef, d=undef, d1=undef, d2=undef, fillet=0.25, center=false) {
|
||||||
deprecate("rcylinder()", "cyl(..., fillet)");
|
deprecate("rcylinder()", "cyl(..., fillet)");
|
||||||
cyl(l=h, r=r, d=d, r1=r1, r2=r2, d1=d1, d2=d2, fillet=fillet, orient=ORIENT_Z, center=center);
|
cyl(l=h, r=r, d=d, r1=r1, r2=r2, d1=d1, d2=d2, fillet=fillet, orient=ORIENT_Z, center=center) children();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1208,13 +1214,16 @@ module tube(
|
||||||
assertion(ir1 <= r1, "Inner radius is larger than outer radius.");
|
assertion(ir1 <= r1, "Inner radius is larger than outer radius.");
|
||||||
assertion(ir2 <= r2, "Inner radius is larger than outer radius.");
|
assertion(ir2 <= r2, "Inner radius is larger than outer radius.");
|
||||||
sides = segs(max(r1,r2));
|
sides = segs(max(r1,r2));
|
||||||
orient_and_align([r1*2,r1*2,h], orient, align, center=center) {
|
size = [r1*2,r1*2,h];
|
||||||
|
size2 = [r2*2,r2*2,h];
|
||||||
|
orient_and_align(size, orient, align, center=center, size2=size2, chain=true) {
|
||||||
zrot(realign? 180/sides : 0) {
|
zrot(realign? 180/sides : 0) {
|
||||||
difference() {
|
difference() {
|
||||||
cylinder(h=h, r1=r1, r2=r2, center=true, $fn=sides);
|
cyl(h=h, r1=r1, r2=r2, $fn=sides) children();
|
||||||
cylinder(h=h+0.05, r1=ir1, r2=ir2, center=true);
|
cyl(h=h+0.05, r1=ir1, r2=ir2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
children();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1257,10 +1266,12 @@ module torus(
|
||||||
irr = get_radius(r=ir, d=id, dflt=0.5);
|
irr = get_radius(r=ir, d=id, dflt=0.5);
|
||||||
majrad = get_radius(r=r, d=d, dflt=(orr+irr)/2);
|
majrad = get_radius(r=r, d=d, dflt=(orr+irr)/2);
|
||||||
minrad = get_radius(r=r2, d=d2, dflt=(orr-irr)/2);
|
minrad = get_radius(r=r2, d=d2, dflt=(orr-irr)/2);
|
||||||
orient_and_align([(majrad+minrad)*2, (majrad+minrad)*2, minrad*2], orient, align, center=center) {
|
size = [(majrad+minrad)*2, (majrad+minrad)*2, minrad*2];
|
||||||
|
orient_and_align(size, orient, align, center=center, chain=true) {
|
||||||
rotate_extrude(convexity=4) {
|
rotate_extrude(convexity=4) {
|
||||||
right(majrad) circle(minrad);
|
right(majrad) circle(minrad);
|
||||||
}
|
}
|
||||||
|
children();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1269,6 +1280,34 @@ module torus(
|
||||||
// Section: Spheroids
|
// Section: Spheroids
|
||||||
|
|
||||||
|
|
||||||
|
// Module: spheroid()
|
||||||
|
// Description:
|
||||||
|
// An version of `sphere()` with connector points, orientation, and alignment.
|
||||||
|
// Usage:
|
||||||
|
// spheroid(r|d, [circum])
|
||||||
|
// Arguments:
|
||||||
|
// r = Radius of the sphere.
|
||||||
|
// d = Diameter of the sphere.
|
||||||
|
// circum = If true, circumscribes the perfect sphere of the given radius/diameter.
|
||||||
|
// orient = Orientation of the sphere, if you don't like where the vertices lay. Use the `ORIENT_` constants from `constants.scad`. Default: `ORIENT_Z`.
|
||||||
|
// align = Alignment of the sphere. Use the `V_` constants from `constants.scad`. Default: `V_CENTER`.
|
||||||
|
// Example:
|
||||||
|
// spheroid(d=100, circum=true, $fn=10);
|
||||||
|
module spheroid(r=undef, d=undef, circum=false, orient=V_UP, align=V_CENTER)
|
||||||
|
{
|
||||||
|
r = get_radius(r=r, d=d, dflt=1);
|
||||||
|
hsides = segs(r);
|
||||||
|
vsides = ceil(hsides/2);
|
||||||
|
rr = circum? (r / cos(90/vsides) / cos(180/hsides)) : r;
|
||||||
|
size = [2*rr, 2*rr, 2*rr];
|
||||||
|
orient_and_align(size, orient, align, chain=true) {
|
||||||
|
sphere(r=rr);
|
||||||
|
children();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Module: staggered_sphere()
|
// Module: staggered_sphere()
|
||||||
//
|
//
|
||||||
// Description:
|
// Description:
|
||||||
|
@ -1281,16 +1320,18 @@ module torus(
|
||||||
// r = Radius of the sphere.
|
// r = Radius of the sphere.
|
||||||
// d = Diameter of the sphere.
|
// d = Diameter of the sphere.
|
||||||
// circum = If true, circumscribes the perfect sphere of the given size.
|
// circum = If true, circumscribes the perfect sphere of the given size.
|
||||||
|
// orient = Orientation of the sphere, if you don't like where the vertices lay. Use the `ORIENT_` constants from `constants.scad`. Default: `ORIENT_Z`.
|
||||||
|
// align = Alignment of the sphere. Use the `V_` constants from `constants.scad`. Default: `V_CENTER`.
|
||||||
//
|
//
|
||||||
// Example:
|
// Example:
|
||||||
// staggered_sphere(d=100, circum=true, $fn=10);
|
// staggered_sphere(d=100, circum=true, $fn=10);
|
||||||
module staggered_sphere(r=undef, d=undef, circum=false, align=V_CENTER) {
|
module staggered_sphere(r=undef, d=undef, circum=false, orient=V_UP, align=V_CENTER) {
|
||||||
r = get_radius(r=r, d=d, dflt=1);
|
r = get_radius(r=r, d=d, dflt=1);
|
||||||
sides = segs(r);
|
sides = segs(r);
|
||||||
vsides = max(3, ceil(sides/2))+1;
|
vsides = max(3, ceil(sides/2))+1;
|
||||||
step = 360/sides;
|
step = 360/sides;
|
||||||
vstep = 180/(vsides-1);
|
vstep = 180/(vsides-1);
|
||||||
rr = circum? r/cos(180/sides)/cos(180/sides) : r;
|
rr = circum? (r / cos(180/sides) / cos(90/vsides)) : r;
|
||||||
pts = concat(
|
pts = concat(
|
||||||
[[0,0,rr]],
|
[[0,0,rr]],
|
||||||
[
|
[
|
||||||
|
@ -1320,7 +1361,11 @@ module staggered_sphere(r=undef, d=undef, circum=false, align=V_CENTER) {
|
||||||
) each [[v1,v4,v3], [v1,v2,v4]]
|
) each [[v1,v4,v3], [v1,v2,v4]]
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
polyhedron(points=pts, faces=faces);
|
size = [2*rr, 2*rr, 2*rr];
|
||||||
|
orient_and_align(size, orient, align, chain=true) {
|
||||||
|
polyhedron(points=pts, faces=faces);
|
||||||
|
children();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1394,10 +1439,12 @@ module teardrop(r=undef, d=undef, l=undef, h=undef, ang=45, cap_h=undef, orient=
|
||||||
{
|
{
|
||||||
r = get_radius(r=r, d=d, dflt=1);
|
r = get_radius(r=r, d=d, dflt=1);
|
||||||
l = first_defined([l, h, 1]);
|
l = first_defined([l, h, 1]);
|
||||||
orient_and_align([r*2,r*2,l], orient, align) {
|
size = [r*2,r*2,l];
|
||||||
|
orient_and_align(size, orient, align, chain=true) {
|
||||||
linear_extrude(height=l, center=true, slices=2) {
|
linear_extrude(height=l, center=true, slices=2) {
|
||||||
teardrop2d(r=r, ang=ang, cap_h=cap_h);
|
teardrop2d(r=r, ang=ang, cap_h=cap_h);
|
||||||
}
|
}
|
||||||
|
children();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1429,13 +1476,15 @@ module onion(cap_h=undef, r=undef, d=undef, maxang=45, h=undef, orient=ORIENT_Z,
|
||||||
r = get_radius(r=r, d=d, dflt=1);
|
r = get_radius(r=r, d=d, dflt=1);
|
||||||
h = first_defined([cap_h, h]);
|
h = first_defined([cap_h, h]);
|
||||||
maxd = 3*r/tan(maxang);
|
maxd = 3*r/tan(maxang);
|
||||||
orient_and_align([r*2,r*2,r*2], orient, align) {
|
size = [r*2,r*2,r*2];
|
||||||
|
orient_and_align(size, orient, align, chain=true) {
|
||||||
rotate_extrude(convexity=2) {
|
rotate_extrude(convexity=2) {
|
||||||
difference() {
|
difference() {
|
||||||
teardrop2d(r=r, ang=maxang, cap_h=h);
|
teardrop2d(r=r, ang=maxang, cap_h=h);
|
||||||
left(r) square(size=[2*r,maxd], center=true);
|
left(r) square(size=[2*r,maxd], center=true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
children();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1464,7 +1513,8 @@ module onion(cap_h=undef, r=undef, d=undef, maxang=45, h=undef, orient=ORIENT_Z,
|
||||||
module narrowing_strut(w=10, l=100, wall=5, ang=30, orient=ORIENT_Y, align=V_UP)
|
module narrowing_strut(w=10, l=100, wall=5, ang=30, orient=ORIENT_Y, align=V_UP)
|
||||||
{
|
{
|
||||||
h = wall + w/2/tan(ang);
|
h = wall + w/2/tan(ang);
|
||||||
orient_and_align([w, h, l], orient, align, orig_orient=ORIENT_Z) {
|
size = [w, h, l];
|
||||||
|
orient_and_align(size, orient, align, chain=true) {
|
||||||
fwd(h/2) {
|
fwd(h/2) {
|
||||||
linear_extrude(height=l, center=true, slices=2) {
|
linear_extrude(height=l, center=true, slices=2) {
|
||||||
back(wall/2) square([w, wall], center=true);
|
back(wall/2) square([w, wall], center=true);
|
||||||
|
@ -1478,6 +1528,7 @@ module narrowing_strut(w=10, l=100, wall=5, ang=30, orient=ORIENT_Y, align=V_UP)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
children();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1505,7 +1556,7 @@ module narrowing_strut(w=10, l=100, wall=5, ang=30, orient=ORIENT_Y, align=V_UP)
|
||||||
// thinning_wall(h=50, l=80, thick=4);
|
// thinning_wall(h=50, l=80, thick=4);
|
||||||
// Example: Trapezoidal
|
// Example: Trapezoidal
|
||||||
// thinning_wall(h=50, l=[80,50], thick=4);
|
// thinning_wall(h=50, l=[80,50], thick=4);
|
||||||
module thinning_wall(h=50, l=100, thick=5, ang=30, strut=5, wall=2, orient=ORIENT_X, align=V_CENTER)
|
module thinning_wall(h=50, l=100, thick=5, ang=30, strut=5, wall=2, orient=ORIENT_Z, align=V_CENTER)
|
||||||
{
|
{
|
||||||
l1 = (l[0] == undef)? l : l[0];
|
l1 = (l[0] == undef)? l : l[0];
|
||||||
l2 = (l[1] == undef)? l : l[1];
|
l2 = (l[1] == undef)? l : l[1];
|
||||||
|
@ -1528,7 +1579,8 @@ module thinning_wall(h=50, l=100, thick=5, ang=30, strut=5, wall=2, orient=ORIEN
|
||||||
y1 = thick/2;
|
y1 = thick/2;
|
||||||
y2 = y1 - min(z2-z3, x2-x3) * sin(ang);
|
y2 = y1 - min(z2-z3, x2-x3) * sin(ang);
|
||||||
|
|
||||||
orient_and_align([l1, thick, h], orient, align, orig_orient=ORIENT_X) {
|
size = [l1, thick, h];
|
||||||
|
orient_and_align(size, orient, align, size2=[l2,thick], chain=true) {
|
||||||
polyhedron(
|
polyhedron(
|
||||||
points=[
|
points=[
|
||||||
[-x4, -y1, -z1],
|
[-x4, -y1, -z1],
|
||||||
|
@ -1620,6 +1672,7 @@ module thinning_wall(h=50, l=100, thick=5, ang=30, strut=5, wall=2, orient=ORIEN
|
||||||
],
|
],
|
||||||
convexity=6
|
convexity=6
|
||||||
);
|
);
|
||||||
|
children();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1649,23 +1702,27 @@ module braced_thinning_wall(h=50, l=100, thick=5, ang=30, strut=5, wall=2, orien
|
||||||
{
|
{
|
||||||
dang = atan((h-2*strut)/(l-2*strut));
|
dang = atan((h-2*strut)/(l-2*strut));
|
||||||
dlen = (h-2*strut)/sin(dang);
|
dlen = (h-2*strut)/sin(dang);
|
||||||
orient_and_align([thick, l, h], orient, align, orig_orient=ORIENT_Y) {
|
size = [l, thick, h];
|
||||||
xrot_copies([0, 180]) {
|
orient_and_align(size, orient, align, orig_orient=ORIENT_Y, chain=true) {
|
||||||
down(h/2) narrowing_strut(w=thick, l=l, wall=strut, ang=ang);
|
union() {
|
||||||
fwd(l/2) xrot(-90) narrowing_strut(w=thick, l=h-0.1, wall=strut, ang=ang);
|
xrot_copies([0, 180]) {
|
||||||
intersection() {
|
down(h/2) narrowing_strut(w=thick, l=l, wall=strut, ang=ang);
|
||||||
cube(size=[thick, l, h], center=true);
|
fwd(l/2) xrot(-90) narrowing_strut(w=thick, l=h-0.1, wall=strut, ang=ang);
|
||||||
xrot_copies([-dang,dang]) {
|
intersection() {
|
||||||
zspread(strut/2) {
|
cube(size=[thick, l, h], center=true);
|
||||||
scale([1,1,1.5]) yrot(45) {
|
xrot_copies([-dang,dang]) {
|
||||||
cube(size=[thick/sqrt(2), dlen, thick/sqrt(2)], center=true);
|
zspread(strut/2) {
|
||||||
|
scale([1,1,1.5]) yrot(45) {
|
||||||
|
cube(size=[thick/sqrt(2), dlen, thick/sqrt(2)], center=true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
cube(size=[thick, dlen, strut/2], center=true);
|
||||||
}
|
}
|
||||||
cube(size=[thick, dlen, strut/2], center=true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
cube(size=[wall, l-0.1, h-0.1], center=true);
|
||||||
}
|
}
|
||||||
cube(size=[wall, l-0.1, h-0.1], center=true);
|
children();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1702,7 +1759,8 @@ module thinning_triangle(h=50, l=100, thick=5, ang=30, strut=5, wall=3, diagonly
|
||||||
{
|
{
|
||||||
dang = atan(h/l);
|
dang = atan(h/l);
|
||||||
dlen = h/sin(dang);
|
dlen = h/sin(dang);
|
||||||
orient_and_align([thick, l, h], orient, align, center=center, noncentered=V_UP+V_BACK, orig_orient=ORIENT_Y) {
|
size = [thick, l, h];
|
||||||
|
orient_and_align(size, orient, align, center=center, noncentered=V_UP+V_BACK, orig_orient=ORIENT_Y, chain=true) {
|
||||||
difference() {
|
difference() {
|
||||||
union() {
|
union() {
|
||||||
if (!diagonly) {
|
if (!diagonly) {
|
||||||
|
@ -1725,6 +1783,7 @@ module thinning_triangle(h=50, l=100, thick=5, ang=30, strut=5, wall=3, diagonly
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
children();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1750,7 +1809,7 @@ module thinning_triangle(h=50, l=100, thick=5, ang=30, strut=5, wall=3, diagonly
|
||||||
module thinning_brace(h=50, l=100, thick=5, ang=30, strut=5, wall=3, center=true)
|
module thinning_brace(h=50, l=100, thick=5, ang=30, strut=5, wall=3, center=true)
|
||||||
{
|
{
|
||||||
deprecate("thinning_brace()", "thinning_triangle(..., diagonly=true)");
|
deprecate("thinning_brace()", "thinning_triangle(..., diagonly=true)");
|
||||||
thinning_triangle(h=h, l=l, thick=thick, ang=ang, strut=strut, wall=wall, diagonly=true, center=center);
|
thinning_triangle(h=h, l=l, thick=thick, ang=ang, strut=strut, wall=wall, diagonly=true, center=center) children();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1801,17 +1860,21 @@ module sparse_strut(h=50, l=100, thick=4, maxang=30, strut=5, max_bridge=20, ori
|
||||||
ang = atan(ystep/zstep);
|
ang = atan(ystep/zstep);
|
||||||
len = zstep / cos(ang);
|
len = zstep / cos(ang);
|
||||||
|
|
||||||
orient_and_align([thick, l, h], orient, align, orig_orient=ORIENT_Y) {
|
size = [thick, l, h];
|
||||||
zspread(zoff*2)
|
orient_and_align(size, orient, align, orig_orient=ORIENT_Y, chain=true) {
|
||||||
cube(size=[thick, l, strut], center=true);
|
union() {
|
||||||
yspread(yoff*2)
|
zspread(zoff*2)
|
||||||
cube(size=[thick, strut, h], center=true);
|
cube(size=[thick, l, strut], center=true);
|
||||||
yspread(ystep, n=yreps) {
|
yspread(yoff*2)
|
||||||
zspread(zstep, n=zreps) {
|
cube(size=[thick, strut, h], center=true);
|
||||||
xrot( ang) cube(size=[thick, strut, len], center=true);
|
yspread(ystep, n=yreps) {
|
||||||
xrot(-ang) cube(size=[thick, strut, len], center=true);
|
zspread(zstep, n=zreps) {
|
||||||
|
xrot( ang) cube(size=[thick, strut, len], center=true);
|
||||||
|
xrot(-ang) cube(size=[thick, strut, len], center=true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
children();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1866,7 +1929,8 @@ module sparse_strut3d(h=50, l=100, w=50, thick=3, maxang=40, strut=3, max_bridge
|
||||||
supp_reps = floor(cross_len/2/(zstep*sin(supp_ang)));
|
supp_reps = floor(cross_len/2/(zstep*sin(supp_ang)));
|
||||||
supp_step = cross_len/2/supp_reps;
|
supp_step = cross_len/2/supp_reps;
|
||||||
|
|
||||||
orient_and_align([w, l, h], orient, align, orig_orient=ORIENT_Y) {
|
size = [w, l, h];
|
||||||
|
orient_and_align(size, orient, align, orig_orient=ORIENT_Y, chain=true) {
|
||||||
intersection() {
|
intersection() {
|
||||||
union() {
|
union() {
|
||||||
ybridge = (l - (yreps+1) * strut) / yreps;
|
ybridge = (l - (yreps+1) * strut) / yreps;
|
||||||
|
@ -1908,6 +1972,7 @@ module sparse_strut3d(h=50, l=100, w=50, thick=3, maxang=40, strut=3, max_bridge
|
||||||
}
|
}
|
||||||
cube([w,l,h], center=true);
|
cube([w,l,h], center=true);
|
||||||
}
|
}
|
||||||
|
children();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1943,20 +2008,23 @@ module corrugated_wall(h=50, l=100, thick=5, strut=5, wall=2, orient=ORIENT_Y, a
|
||||||
steps = quantup(segs(thick/2),4);
|
steps = quantup(segs(thick/2),4);
|
||||||
step = period/steps;
|
step = period/steps;
|
||||||
il = l - 2*strut + 2*step;
|
il = l - 2*strut + 2*step;
|
||||||
orient_and_align([thick, l, h], orient, align, orig_orient=ORIENT_Y) {
|
size = [thick, l, h];
|
||||||
linear_extrude(height=h-2*strut+0.1, slices=2, convexity=ceil(2*il/period), center=true) {
|
orient_and_align(size, orient, align, orig_orient=ORIENT_Y, chain=true) {
|
||||||
polygon(
|
union() {
|
||||||
points=concat(
|
linear_extrude(height=h-2*strut+0.1, slices=2, convexity=ceil(2*il/period), center=true) {
|
||||||
[for (y=[-il/2:step:il/2]) [amplitude*sin(y/period*360)-wall/2, y] ],
|
polygon(
|
||||||
[for (y=[il/2:-step:-il/2]) [amplitude*sin(y/period*360)+wall/2, y] ]
|
points=concat(
|
||||||
)
|
[for (y=[-il/2:step:il/2]) [amplitude*sin(y/period*360)-wall/2, y] ],
|
||||||
);
|
[for (y=[il/2:-step:-il/2]) [amplitude*sin(y/period*360)+wall/2, y] ]
|
||||||
}
|
)
|
||||||
|
);
|
||||||
difference() {
|
}
|
||||||
cube([thick, l, h], center=true);
|
difference() {
|
||||||
cube([thick+0.5, l-2*strut, h-2*strut], center=true);
|
cube([thick, l, h], center=true);
|
||||||
|
cube([thick+0.5, l-2*strut, h-2*strut], center=true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
children();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2016,7 +2084,8 @@ module pie_slice(
|
||||||
r1 = get_radius(r1, r, d1, d, 10);
|
r1 = get_radius(r1, r, d1, d, 10);
|
||||||
r2 = get_radius(r2, r, d2, d, 10);
|
r2 = get_radius(r2, r, d2, d, 10);
|
||||||
maxd = max(r1,r2)+0.1;
|
maxd = max(r1,r2)+0.1;
|
||||||
orient_and_align([2*r1, 2*r1, l], orient, align, center=center) {
|
size = [2*r1, 2*r1, l];
|
||||||
|
orient_and_align(size, orient, align, center=center, chain=true) {
|
||||||
difference() {
|
difference() {
|
||||||
cylinder(r1=r1, r2=r2, h=l, center=true);
|
cylinder(r1=r1, r2=r2, h=l, center=true);
|
||||||
if (ang<180) rotate(ang) back(maxd/2) cube([2*maxd, maxd, l+0.1], center=true);
|
if (ang<180) rotate(ang) back(maxd/2) cube([2*maxd, maxd, l+0.1], center=true);
|
||||||
|
@ -2025,6 +2094,7 @@ module pie_slice(
|
||||||
if (ang>180) rotate(ang-180) back(maxd/2) cube([2*maxd, maxd, l+0.1], center=true);
|
if (ang>180) rotate(ang-180) back(maxd/2) cube([2*maxd, maxd, l+0.1], center=true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
children();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2057,7 +2127,8 @@ module pie_slice(
|
||||||
// interior_fillet(l=40, r=10, orient=ORIENT_Y_90);
|
// interior_fillet(l=40, r=10, orient=ORIENT_Y_90);
|
||||||
module interior_fillet(l=1.0, r=1.0, ang=90, overlap=0.01, orient=ORIENT_X, align=V_CENTER) {
|
module interior_fillet(l=1.0, r=1.0, ang=90, overlap=0.01, orient=ORIENT_X, align=V_CENTER) {
|
||||||
dy = r/tan(ang/2);
|
dy = r/tan(ang/2);
|
||||||
orient_and_align([l,r,r], orient, align, orig_orient=ORIENT_X) {
|
size = [l,r,r];
|
||||||
|
orient_and_align(size, orient, align, orig_orient=ORIENT_X, chain=true) {
|
||||||
difference() {
|
difference() {
|
||||||
translate([0,-overlap/tan(ang/2),-overlap]) {
|
translate([0,-overlap/tan(ang/2),-overlap]) {
|
||||||
if (ang == 90) {
|
if (ang == 90) {
|
||||||
|
@ -2068,6 +2139,7 @@ module interior_fillet(l=1.0, r=1.0, ang=90, overlap=0.01, orient=ORIENT_X, alig
|
||||||
}
|
}
|
||||||
translate([0,dy,r]) xcyl(l=l+0.1, r=r);
|
translate([0,dy,r]) xcyl(l=l+0.1, r=r);
|
||||||
}
|
}
|
||||||
|
children();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2108,6 +2180,8 @@ module slot(
|
||||||
r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=5);
|
r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=5);
|
||||||
r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=5);
|
r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=5);
|
||||||
sides = quantup(segs(max(r1, r2)), 4);
|
sides = quantup(segs(max(r1, r2)), 4);
|
||||||
|
// TODO: implement orient and align.
|
||||||
|
// TODO: implement connectors.
|
||||||
hull() spread(p1=p1, p2=p2, l=l, n=2) cyl(l=h, r1=r1, r2=r2, center=true, $fn=sides);
|
hull() spread(p1=p1, p2=p2, l=l, n=2) cyl(l=h, r1=r1, r2=r2, center=true, $fn=sides);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2156,7 +2230,8 @@ module arced_slot(
|
||||||
sr2 = get_radius(sr2, sr, sd2, sd, 2);
|
sr2 = get_radius(sr2, sr, sd2, sd, 2);
|
||||||
fn_minor = first_defined([$fn2, $fn]);
|
fn_minor = first_defined([$fn2, $fn]);
|
||||||
da = ea - sa;
|
da = ea - sa;
|
||||||
orient_and_align([r+sr1, r+sr1, h], orient, align) {
|
size = [r+sr1, r+sr1, h];
|
||||||
|
orient_and_align(size, orient, align, chain=true) {
|
||||||
translate(cp) {
|
translate(cp) {
|
||||||
zrot(sa) {
|
zrot(sa) {
|
||||||
difference() {
|
difference() {
|
||||||
|
@ -2167,6 +2242,7 @@ module arced_slot(
|
||||||
zrot(da) right(r) cylinder(h=h, r1=sr1, r2=sr2, center=true, $fn=fn_minor);
|
zrot(da) right(r) cylinder(h=h, r1=sr1, r2=sr2, center=true, $fn=fn_minor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
children();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
378
transforms.scad
378
transforms.scad
|
@ -1439,27 +1439,22 @@ module zrot_copies(rots=[], cp=[0,0,0], n=undef, count=undef, sa=0, offset=0, r=
|
||||||
|
|
||||||
|
|
||||||
// Module: xring()
|
// Module: xring()
|
||||||
//
|
|
||||||
// Description:
|
// Description:
|
||||||
// Distributes `n` copies of the given children on a circle of radius `r`
|
// Distributes `n` copies of the given children on a circle of radius `r`
|
||||||
// around the X axis. If `rot` is true, each copy is rotated in place to keep
|
// around the X axis. If `rot` is true, each copy is rotated in place to keep
|
||||||
// the same side towards the center. The first, unrotated copy will be at the
|
// the same side towards the center. The first, unrotated copy will be at the
|
||||||
// starting angle `sa`.
|
// starting angle `sa`.
|
||||||
//
|
|
||||||
// Usage:
|
// Usage:
|
||||||
// xring(n, r, [sa], [cp], [rot]) ...
|
// xring(n, r, [sa], [cp], [rot]) ...
|
||||||
//
|
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// n = Number of copies of children to distribute around the circle. (Default: 2)
|
// n = Number of copies of children to distribute around the circle. (Default: 2)
|
||||||
// r = Radius of ring to distribute children around. (Default: 0)
|
// r = Radius of ring to distribute children around. (Default: 0)
|
||||||
// sa = Start angle for first (unrotated) copy. (Default: 0)
|
// sa = Start angle for first (unrotated) copy. (Default: 0)
|
||||||
// cp = Centerpoint of ring. Default: [0,0,0]
|
// cp = Centerpoint of ring. Default: [0,0,0]
|
||||||
// rot = If true, rotate each copy to keep the same side towards the center of the ring. Default: true.
|
// rot = If true, rotate each copy to keep the same side towards the center of the ring. Default: true.
|
||||||
//
|
|
||||||
// Side Effects:
|
// Side Effects:
|
||||||
// `$ang` is set to the rotation angle of each child copy, and can be used to modify each child individually.
|
// `$ang` is set to the rotation angle of each child copy, and can be used to modify each child individually.
|
||||||
// `$idx` is set to the index value of each child copy.
|
// `$idx` is set to the index value of each child copy.
|
||||||
//
|
|
||||||
// Examples:
|
// Examples:
|
||||||
// xring(n=6, r=10) xrot(-90) cylinder(h=20, r1=5, r2=0);
|
// xring(n=6, r=10) xrot(-90) cylinder(h=20, r1=5, r2=0);
|
||||||
// xring(n=6, r=10, sa=45) xrot(-90) cylinder(h=20, r1=5, r2=0);
|
// xring(n=6, r=10, sa=45) xrot(-90) cylinder(h=20, r1=5, r2=0);
|
||||||
|
@ -1643,7 +1638,7 @@ module ovoid_spread(r=undef, d=undef, n=100, cone_ang=90, scale=[1,1,1], perp=tr
|
||||||
theta_phis = [for (x=[0:n-1]) [180*(1+sqrt(5))*(x+0.5)%360, acos(1-2*(x+0.5)/cnt)]];
|
theta_phis = [for (x=[0:n-1]) [180*(1+sqrt(5))*(x+0.5)%360, acos(1-2*(x+0.5)/cnt)]];
|
||||||
|
|
||||||
for ($idx = [0:len(theta_phis)-1]) {
|
for ($idx = [0:len(theta_phis)-1]) {
|
||||||
tp = theta_phis[$idx];
|
tp = theta_phis[$idx];
|
||||||
xyz = spherical_to_xyz(r, tp[0], tp[1]);
|
xyz = spherical_to_xyz(r, tp[0], tp[1]);
|
||||||
$pos = vmul(xyz,scale);
|
$pos = vmul(xyz,scale);
|
||||||
$theta = tp[0];
|
$theta = tp[0];
|
||||||
|
@ -2274,17 +2269,28 @@ module shell2d(thickness, or=0, ir=0, fill=0, round=0)
|
||||||
// Named alignments, as well as `ALIGN_NEG`/`ALIGN_POS` are aligned pre-rotation.
|
// Named alignments, as well as `ALIGN_NEG`/`ALIGN_POS` are aligned pre-rotation.
|
||||||
//
|
//
|
||||||
// Usage:
|
// Usage:
|
||||||
// orient_and_align(size, [orient], [align], [center], [noncentered], [orig_orient], [orig_align], [alignments]) ...
|
// orient_and_align(size, [orient], [align], [center], [noncentered], [orig_orient], [orig_align], [alignments], [chain]) ...
|
||||||
//
|
//
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// size = The size of the part.
|
// size = The [X,Y,Z] size of the part.
|
||||||
// orient = The axis to align to. Use ORIENT_ constants from constants.scad
|
// size2 = The [X,Y] size of the top of the part.
|
||||||
|
// shift = The [X,Y] offset of the top of the part, compared to the bottom of the part.
|
||||||
|
// orient = The axis to align to. Use `ORIENT_` constants from `constants.scad`.
|
||||||
// align = The side of the origin the part should be aligned with.
|
// align = The side of the origin the part should be aligned with.
|
||||||
// center = If given, overrides `align`. If true, centers vertically. If false, `align` will be set to the value in `noncentered`.
|
// center = If given, overrides `align`. If true, centers vertically. If false, `align` will be set to the value in `noncentered`.
|
||||||
// noncentered = The value to set `align` to if `center` == `false`. Default: `V_UP`.
|
// noncentered = The value to set `align` to if `center` == `false`. Default: `V_UP`.
|
||||||
// orig_orient = The original orientation of the part. Default: `ORIENT_Z`.
|
// orig_orient = The original orientation of the part. Default: `ORIENT_Z`.
|
||||||
// orig_align = The original alignment of the part. Default: `V_CENTER`.
|
// orig_align = The original alignment of the part. Default: `V_CENTER`.
|
||||||
// alignments = A list of `["name", [X,Y,Z]]` alignment-label/offset pairs.
|
// alignments = A list of extra, non-standard connectors that can be aligned to.
|
||||||
|
// chain = If true, allow attachable children.
|
||||||
|
//
|
||||||
|
// Side Effects:
|
||||||
|
// `$parent_size` is set to the parent object's cubical region size.
|
||||||
|
// `$parent_size2` is set to the parent object's top [X,Y] size.
|
||||||
|
// `$parent_shift` is set to the parent object's `shift` value, if any.
|
||||||
|
// `$parent_orient` is set to the parent object's `orient` value.
|
||||||
|
// `$parent_align` is set to the parent object's `align` value.
|
||||||
|
// `$parent_conns` is set to the parent object's list of non-standard extra connectors.
|
||||||
//
|
//
|
||||||
// Example:
|
// Example:
|
||||||
// #cylinder(d=5, h=10);
|
// #cylinder(d=5, h=10);
|
||||||
|
@ -2293,55 +2299,321 @@ module orient_and_align(
|
||||||
size=undef, orient=ORIENT_Z, align=V_CENTER,
|
size=undef, orient=ORIENT_Z, align=V_CENTER,
|
||||||
center=undef, noncentered=ALIGN_POS,
|
center=undef, noncentered=ALIGN_POS,
|
||||||
orig_orient=ORIENT_Z, orig_align=V_CENTER,
|
orig_orient=ORIENT_Z, orig_align=V_CENTER,
|
||||||
alignments=[]
|
size2=undef, shift=[0,0],
|
||||||
|
alignments=[], chain=false
|
||||||
) {
|
) {
|
||||||
algn = is_def(center)? (center? V_CENTER : noncentered) : align;
|
size2 = point2d(default(size2, size));
|
||||||
if (orig_align != V_CENTER) {
|
shift = point2d(shift);
|
||||||
orient_and_align(size=size, orient=orient, align=algn) {
|
align = is_def(center)? (center? V_CENTER : noncentered) : align;
|
||||||
translate(vmul(size/2, -orig_align)) children();
|
m = matrix4_mult(concat(
|
||||||
}
|
(orig_align==V_CENTER)? [] : [
|
||||||
} else if (orig_orient != ORIENT_Z) {
|
// If original alignment is not centered, center it.
|
||||||
rotsize = (
|
matrix4_translate(vmul(size/2, -orig_align))
|
||||||
(orig_orient==ORIENT_X)? [size[1], size[2], size[0]] :
|
],
|
||||||
(orig_orient==ORIENT_Y)? [size[0], size[2], size[1]] :
|
(orig_orient==ORIENT_Z)? [] : [
|
||||||
vabs(rotate_points3d([size], orig_orient, reverse=true)[0])
|
// If original orientation is not upright, rotate it upright.
|
||||||
);
|
matrix4_zrot(-orig_orient.z),
|
||||||
orient_and_align(size=rotsize, orient=orient, align=algn) {
|
matrix4_yrot(-orig_orient.y),
|
||||||
rot(orig_orient,reverse=true) children();
|
matrix4_xrot(-orig_orient.x)
|
||||||
}
|
],
|
||||||
} else if (is_scalar(algn)) {
|
($attach_to!=undef)? (
|
||||||
// If align is a number and not a vector, then translate PRE-rotation.
|
let(
|
||||||
orient_and_align(size=size, orient=orient) {
|
conn = find_connector($attach_to, size.z, size, size2=size2, shift=shift),
|
||||||
translate(vmul(size/2, algn*V_UP)) children();
|
ang = vector_angle(conn[2],V_DOWN),
|
||||||
}
|
axis = vector_axis(conn[2],V_DOWN),
|
||||||
} else if (is_str(algn)) {
|
ang2 = (conn[2]==V_UP || conn[2]==V_DOWN)? 0 : 180-conn[3],
|
||||||
// If align is a string, look for an alignments label that matches.
|
axis2 = rotate_points3d([axis],[0,0,ang2])[0]
|
||||||
found = search([algn], alignments, num_returns_per_match=1);
|
) [
|
||||||
if (found != [[]]) {
|
matrix4_translate(-conn[1]),
|
||||||
orient_and_align(size=size, orient=orient) {
|
matrix4_zrot(ang2),
|
||||||
idx = found[0];
|
matrix4_rot_by_axis(axis2, ang)
|
||||||
delta = alignments[idx][1];
|
]
|
||||||
translate(-delta) children();
|
) : concat(
|
||||||
}
|
(!is_scalar(align) && !is_str(align))? [] : [
|
||||||
|
let(conn = find_connector(align, size.z, size, size2=size2, shift=shift, extra_conns=alignments))
|
||||||
|
matrix4_translate(-conn[1])
|
||||||
|
],
|
||||||
|
(orient==ORIENT_Z)? [] : [
|
||||||
|
matrix4_xrot(orient.x),
|
||||||
|
matrix4_yrot(orient.y),
|
||||||
|
matrix4_zrot(orient.z)
|
||||||
|
],
|
||||||
|
(!is_array(align) || align==[0,0,0])? [] : [
|
||||||
|
let(conn = find_connector(align, size.z, size, size2=size2, shift=shift))
|
||||||
|
matrix4_translate(conn[1])
|
||||||
|
]
|
||||||
|
)
|
||||||
|
));
|
||||||
|
$attach_to = undef;
|
||||||
|
$parent_size = size;
|
||||||
|
$parent_size2 = size2;
|
||||||
|
$parent_shift = shift;
|
||||||
|
$parent_orient = orient;
|
||||||
|
$parent_align = align;
|
||||||
|
$parent_conns = alignments;
|
||||||
|
tags = _str_char_split($tags, " ");
|
||||||
|
s_tags = $tags_shown;
|
||||||
|
h_tags = $tags_hidden;
|
||||||
|
shown = !s_tags || any([for (tag=tags) in_list(tag, s_tags)]);
|
||||||
|
hidden = any([for (tag=tags) in_list(tag, h_tags)]);
|
||||||
|
echo(tags=tags, shown=shown, hidden=hidden, view=shown&&!hidden);
|
||||||
|
multmatrix(m) {
|
||||||
|
if ($children>1 && chain) {
|
||||||
|
if(shown && !hidden) color($color) for (i=[0:$children-2]) children(i);
|
||||||
|
children($children-1);
|
||||||
} else {
|
} else {
|
||||||
assertion(1==0, str("Alignment label '", algn, "' is not known.", (alignments? str(" Try one of ", [for (v=alignments) v[0]], ".") : "")));
|
if(shown && !hidden) color($color) children();
|
||||||
}
|
}
|
||||||
} else if (orient != ORIENT_Z) {
|
|
||||||
rotsize = (
|
|
||||||
(orient==ORIENT_X)? [size[2], size[0], size[1]] :
|
|
||||||
(orient==ORIENT_Y)? [size[0], size[2], size[1]] :
|
|
||||||
vabs(rotate_points3d([size], orient)[0])
|
|
||||||
);
|
|
||||||
orient_and_align(size=rotsize, align=algn) {
|
|
||||||
rotate(orient) children();
|
|
||||||
}
|
|
||||||
} else if (is_def(algn) && algn != [0,0,0]) {
|
|
||||||
translate(vmul(size/2, algn)) children();
|
|
||||||
} else {
|
|
||||||
children();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Internal. Not exposed.
|
||||||
|
function _str_char_split(s,delim,n=0,acc=[],word="") =
|
||||||
|
(n>=len(s))? concat(acc, [word]) :
|
||||||
|
(s[n]==delim)?
|
||||||
|
_str_char_split(s,delim,n+1,concat(acc,[word]),"") :
|
||||||
|
_str_char_split(s,delim,n+1,acc,str(word,s[n]));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Function: connector()
|
||||||
|
// Usage:
|
||||||
|
// connector(name, pos, dir, [rot])
|
||||||
|
// Description:
|
||||||
|
// Creates a connector data structure.
|
||||||
|
// Arguments:
|
||||||
|
// name = The string name of the connector. Lowercase. Words separated by single dashes. No spaces.
|
||||||
|
// pos = The [X,Y,Z] position of the connector.
|
||||||
|
// dir = A vector pointing in the direction parts should project from the connector position.
|
||||||
|
// rot = If needed, the angle to rotate the part around the direction vector.
|
||||||
|
function connector(name, pos=[0,0,0], dir=V_UP, rot=0) = [name, pos, dir, rot];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Function: find_connector()
|
||||||
|
// Usage:
|
||||||
|
// find_connector(align, h, size, [size2], [shift], [edges], [corners]);
|
||||||
|
// Description:
|
||||||
|
// Generates a list of typical connectors for a cubical region of the given size.
|
||||||
|
// Arguments:
|
||||||
|
// align = Named alignment/connector string.
|
||||||
|
// h = Height of the region.
|
||||||
|
// size = The [X,Y] size of the bottom of the cubical region.
|
||||||
|
// size2 = The [X,Y] size of the top of the cubical region.
|
||||||
|
// shift = The [X,Y] amount to shift the center of the top with respect to the center of the bottom.
|
||||||
|
// extra_conns = A list of extra named connectors.
|
||||||
|
function find_connector(align, h, size, size2=undef, shift=[0,0], extra_conns=[]) =
|
||||||
|
let(
|
||||||
|
eps = 1e-9,
|
||||||
|
shift = point3d(shift),
|
||||||
|
size = point3d(point2d(size)),
|
||||||
|
size2 = (size2!=undef)? point3d(point2d(size2)) : size,
|
||||||
|
found = !is_str(align)? [] : search([align], extra_conns, num_returns_per_match=1)[0]
|
||||||
|
) (found!=[])? extra_conns[found] : let(
|
||||||
|
words = is_scalar(align)? (
|
||||||
|
align==ALIGN_NEG? ["top"] :
|
||||||
|
align==ALIGN_POS? ["bottom"] :
|
||||||
|
["center"]
|
||||||
|
) : is_array(align)? align : _str_char_split(align,"-"),
|
||||||
|
ovec = is_array(align)? align :
|
||||||
|
sum([
|
||||||
|
for (word = words)
|
||||||
|
word=="left"? V_LEFT :
|
||||||
|
word=="right"? V_RIGHT :
|
||||||
|
word=="front"? V_FWD :
|
||||||
|
word=="back"? V_BACK :
|
||||||
|
word=="top"? V_UP :
|
||||||
|
word=="bottom"? V_DOWN :
|
||||||
|
word=="center"? V_ZERO :
|
||||||
|
assertion(false,
|
||||||
|
str(
|
||||||
|
"Alignment label '", align, "' is not known.",
|
||||||
|
(!extra_conns? "" : str(
|
||||||
|
" Try one of ", [for (v=extra_conns) v[0]], " or the standard alignments."
|
||||||
|
))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
]),
|
||||||
|
top = [-size2/2+shift, shift, size2/2+shift],
|
||||||
|
bot = [-size/2, V_ZERO, size/2],
|
||||||
|
toppt = [top[ovec.x+1].x, top[ovec.y+1].y, h/2],
|
||||||
|
botpt = [bot[ovec.x+1].x, bot[ovec.y+1].y, -h/2],
|
||||||
|
pos = lerp(botpt, toppt, (ovec.z+1)/2),
|
||||||
|
oang = (
|
||||||
|
ovec == V_UP? 0 :
|
||||||
|
ovec == V_DOWN? 0 :
|
||||||
|
(norm([ovec.x,ovec.y]) < eps)? 0 : atan2(ovec.y, ovec.x)+90
|
||||||
|
),
|
||||||
|
vec = (
|
||||||
|
abs(ovec.z) > eps? ovec :
|
||||||
|
rotate_points3d([ovec], from=V_UP, to=toppt-botpt)[0]
|
||||||
|
)
|
||||||
|
) [align, pos, vec, oang];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Module: attach()
|
||||||
|
// Usage:
|
||||||
|
// attach(name, [overlap], [norot]) ...
|
||||||
|
// attach(name, to, [overlap]) ...
|
||||||
|
// Description:
|
||||||
|
// Attaches children to a parent object at an attachment point and orientation.
|
||||||
|
// Arguments:
|
||||||
|
// name = The name of the parent attachment point to attach to.
|
||||||
|
// to = The name of the child attachment point.
|
||||||
|
// overlap = Amount to sink child into the parent.
|
||||||
|
// norot = If true, don't rotate children when aligning to the attachment point.
|
||||||
|
// Example:
|
||||||
|
// spheroid(d=20) {
|
||||||
|
// attach("top") down(1.5) cyl(l=11.5, d1=10, d2=5, align="bottom");
|
||||||
|
// attach("right", "bottom") down(1.5) cyl(l=11.5, d1=10, d2=5);
|
||||||
|
// attach("front") down(1.5) cyl(l=11.5, d1=10, d2=5, align="bottom");
|
||||||
|
// }
|
||||||
|
module attach(name, to=undef, overlap=undef, norot=false)
|
||||||
|
{
|
||||||
|
assertion($parent_size != undef, "No object to attach to!");
|
||||||
|
overlap = (overlap!=undef)? overlap : $overlap;
|
||||||
|
conn = find_connector(name, $parent_size.z, point2d($parent_size), size2=$parent_size2, shift=$parent_shift, extra_conns=$parent_conns);
|
||||||
|
pos = conn[1];
|
||||||
|
vec = conn[2];
|
||||||
|
ang = conn[3];
|
||||||
|
$attach_to = to;
|
||||||
|
$attach_conn = conn;
|
||||||
|
if (norot || (norm(vec-V_UP)<1e-9 && ang==0)) {
|
||||||
|
translate(pos) translate([0,0,-overlap]) children();
|
||||||
|
} else {
|
||||||
|
translate(pos) rot(ang,from=V_UP,to=vec) translate([0,0,-overlap]) children();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Module: tags()
|
||||||
|
// Usage:
|
||||||
|
// tags(tags) ...
|
||||||
|
// Description:
|
||||||
|
// Marks all children with the given tags.
|
||||||
|
// Arguments:
|
||||||
|
// tags = String containing space delimited set of tags to apply.
|
||||||
|
module tags(tags)
|
||||||
|
{
|
||||||
|
$tags = tags;
|
||||||
|
children();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Module: recolor()
|
||||||
|
// Usage:
|
||||||
|
// recolor(c) ...
|
||||||
|
// Description:
|
||||||
|
// Sets the color for children that can use the $color special variable.
|
||||||
|
// Example:
|
||||||
|
// recolor("red") cyl(l=20, d=10);
|
||||||
|
module recolor(c)
|
||||||
|
{
|
||||||
|
$color = c;
|
||||||
|
children();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Module: hide()
|
||||||
|
// Usage:
|
||||||
|
// hide(tags) ...
|
||||||
|
// Description: Hides all children with the given tags.
|
||||||
|
module hide(tags="")
|
||||||
|
{
|
||||||
|
$tags_hidden = tags==""? [] : _str_char_split(tags, " ");
|
||||||
|
children();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Module: show()
|
||||||
|
// Usage:
|
||||||
|
// show(tags) ...
|
||||||
|
// Description: Shows only children with the given tags.
|
||||||
|
module show(tags="")
|
||||||
|
{
|
||||||
|
$tags_shown = tags==""? [] : _str_char_split(tags, " ");
|
||||||
|
children();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Module: diff()
|
||||||
|
// Usage:
|
||||||
|
// diff(neg, [keep]) ...
|
||||||
|
// diff(neg, pos, [keep]) ...
|
||||||
|
// Description:
|
||||||
|
// If `neg` is given, takes the union of all children with tags
|
||||||
|
// that are in `neg`, and differences them from the union of all
|
||||||
|
// children with tags in `pos`. If `pos` is not given, then all
|
||||||
|
// items in `neg` are differenced from all items not in `neg`. If
|
||||||
|
// `keep` is given, all children with tags in `keep` are then unioned
|
||||||
|
// with the result. If `keep` is not given, all children without
|
||||||
|
// tags in `pos` or `neg` are then unioned with the result.
|
||||||
|
// Arguments:
|
||||||
|
// neg = String containing space delimited set of tag names of children to difference away.
|
||||||
|
// pos = String containing space delimited set of tag names of children to be differenced away from.
|
||||||
|
// keep = String containing space delimited set of tag names of children to keep whole.
|
||||||
|
module diff(neg, pos=undef, keep=undef)
|
||||||
|
{
|
||||||
|
difference() {
|
||||||
|
if (pos != undef) {
|
||||||
|
show(pos) children();
|
||||||
|
} else {
|
||||||
|
if (keep == undef) {
|
||||||
|
hide(neg) children();
|
||||||
|
} else {
|
||||||
|
hide(str(neg," ",keep)) children();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
show(neg) children();
|
||||||
|
}
|
||||||
|
if (keep!=undef) {
|
||||||
|
show(keep) children();
|
||||||
|
} else if (pos!=undef) {
|
||||||
|
hide(str(pos," ",neg)) children();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Module: intersect()
|
||||||
|
// Usage:
|
||||||
|
// intersect(a, [keep]) ...
|
||||||
|
// intersect(a, b, [keep]) ...
|
||||||
|
// Description:
|
||||||
|
// If `a` is given, takes the union of all children with tags that
|
||||||
|
// are in `a`, and intersection()s them with the union of all
|
||||||
|
// children with tags in `b`. If `b` is not given, then the union
|
||||||
|
// of all items with tags in `a` are intersection()ed with the union
|
||||||
|
// of all items without tags in `a`. If `keep` is given, then the
|
||||||
|
// result is unioned with all the children with tags in `keep`. If
|
||||||
|
// `keep` is not given, all children without tags in `a` or `b` are
|
||||||
|
// unioned with the result.
|
||||||
|
// Arguments:
|
||||||
|
// a = String containing space delimited set of tag names of children.
|
||||||
|
// b = String containing space delimited set of tag names of children.
|
||||||
|
// keep = String containing space delimited set of tag names of children to keep whole.
|
||||||
|
module intersect(a, b=undef, keep=undef)
|
||||||
|
{
|
||||||
|
intersection() {
|
||||||
|
if (b != undef) {
|
||||||
|
show(b) children();
|
||||||
|
} else {
|
||||||
|
if (keep == undef) {
|
||||||
|
hide(a) children();
|
||||||
|
} else {
|
||||||
|
hide(str(a," ",keep)) children();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
show(a) children();
|
||||||
|
}
|
||||||
|
if (keep!=undef) {
|
||||||
|
show(keep) children();
|
||||||
|
} else if (b!=undef) {
|
||||||
|
hide(str(a," ",b)) children();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||||
|
|
Loading…
Reference in a new issue