mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2024-12-29 00:09:41 +00:00
Fixed corner and top/bottom edge orientations.
This commit is contained in:
parent
cc36235736
commit
7e1598d66d
18 changed files with 550 additions and 465 deletions
397
attachments.scad
Normal file
397
attachments.scad
Normal file
|
@ -0,0 +1,397 @@
|
|||
//////////////////////////////////////////////////////////////////////
|
||||
// LibFile: attachments.scad
|
||||
// This is the file that handles attachments and orientation of children.
|
||||
// To use, add the following lines to the beginning of your file:
|
||||
// ```
|
||||
// include <BOSL2/std.scad>
|
||||
// ```
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2017-2019, 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.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
// Section: Functions
|
||||
|
||||
|
||||
// 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=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.
|
||||
// geometry = One of "cube", "cylinder", or "sphere" to denote the overall geometry of the shape. Cones are "cylinder", and prismoids are "cube" for this purpose. Default: "cube"
|
||||
// extra_conns = A list of extra named connectors.
|
||||
function find_connector(align, h, size, size2=undef, shift=[0,0], extra_conns=[], geometry="cube") =
|
||||
is_string(align)? (
|
||||
let(found = search([align], extra_conns, num_returns_per_match=1)[0])
|
||||
assert(found!=[], str("Unknown alignment: ",align))
|
||||
extra_conns[found]
|
||||
) : (
|
||||
let(
|
||||
size = point2d(size),
|
||||
size2 = (size2!=undef)? point2d(size2) : size,
|
||||
shift = point2d(shift),
|
||||
oang = (
|
||||
align == UP? 0 :
|
||||
align == DOWN? 0 :
|
||||
(norm([align.x,align.y]) < EPSILON)? 0 :
|
||||
atan2(align.y, align.x)+90
|
||||
)
|
||||
)
|
||||
geometry=="sphere"? let(
|
||||
phi = align==UP? 0 : align==DOWN? 180 : 90 + (45 * align.z),
|
||||
theta = atan2(align.y, align.x),
|
||||
vec = spherical_to_xyz(1, theta, phi),
|
||||
pos = vmul(vec, (point3d(size)+h*UP)/2)
|
||||
) [align, pos, vec, oang] : let (
|
||||
xyal = (
|
||||
geometry=="cylinder"? (
|
||||
let(xy = point2d(align))
|
||||
norm(xy)>0? xy/norm(xy) : [0,0]
|
||||
) : point2d(align)
|
||||
),
|
||||
botpt = point3d(vmul(size/2,xyal))+DOWN*h/2,
|
||||
toppt = point3d(vmul(size2/2,xyal)+shift)+UP*h/2,
|
||||
pos = lerp(botpt, toppt, (align.z+1)/2),
|
||||
sidevec = rotate_points3d([point3d(xyal)], from=UP, to=toppt-botpt)[0],
|
||||
vec = (
|
||||
norm([align.x,align.y]) < EPSILON? align :
|
||||
abs(align.z) < EPSILON? sidevec :
|
||||
align.z>0? (UP+sidevec)/2 :
|
||||
(DOWN+sidevec)/2
|
||||
)
|
||||
) [align, pos, vec, oang]
|
||||
);
|
||||
|
||||
|
||||
|
||||
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]));
|
||||
|
||||
|
||||
|
||||
// Section: Modules
|
||||
|
||||
|
||||
// Module: orient_and_align()
|
||||
//
|
||||
// Description:
|
||||
// Takes a vertically oriented shape, and re-orients and aligns it.
|
||||
// This is useful for making a custom shape available in various
|
||||
// orientations and alignments without extra translate()s and rotate()s.
|
||||
// Children should be vertically (Z-axis) oriented, and centered.
|
||||
// Non-extremity alignment points should be named via the `alignments` arg.
|
||||
// Named alignments are aligned pre-rotation.
|
||||
//
|
||||
// Usage:
|
||||
// orient_and_align(size, [orient], [align], [center], [noncentered], [orig_orient], [orig_align], [alignments], [chain]) ...
|
||||
//
|
||||
// Arguments:
|
||||
// size = The [X,Y,Z] size of the part.
|
||||
// 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.
|
||||
// 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: `BOTTOM`.
|
||||
// orig_orient = The original orientation of the part. Default: `ORIENT_Z`.
|
||||
// orig_align = The original alignment of the part. Default: `CENTER`.
|
||||
// geometry = One of "cube", "cylinder", or "sphere" to denote the overall geometry of the shape. Cones are "cylinder", and prismoids are "cube" for this purpose. Default: "cube"
|
||||
// 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_geom` is set to the parent object's `geometry` value.
|
||||
// `$parent_conns` is set to the parent object's list of non-standard extra connectors.
|
||||
//
|
||||
// Example:
|
||||
// #cylinder(d=5, h=10);
|
||||
// orient_and_align([5,5,10], orient=ORIENT_Y, align=BACK, orig_align=UP) cylinder(d=5, h=10);
|
||||
module orient_and_align(
|
||||
size=undef, orient=ORIENT_Z, align=CENTER,
|
||||
center=undef, noncentered=BOTTOM,
|
||||
orig_orient=ORIENT_Z, orig_align=CENTER,
|
||||
size2=undef, shift=[0,0],
|
||||
alignments=[], chain=false,
|
||||
geometry="cube"
|
||||
) {
|
||||
size2 = point2d(default(size2, size));
|
||||
shift = point2d(shift);
|
||||
align = !is_undef(center)? (center? CENTER : noncentered) : align;
|
||||
m = matrix4_mult(concat(
|
||||
(orig_align==CENTER)? [] : [
|
||||
// If original alignment is not centered, center it.
|
||||
matrix4_translate(vmul(size/2, -orig_align))
|
||||
],
|
||||
(orig_orient==ORIENT_Z)? [] : [
|
||||
// If original orientation is not upright, rotate it upright.
|
||||
matrix4_zrot(-orig_orient.z),
|
||||
matrix4_yrot(-orig_orient.y),
|
||||
matrix4_xrot(-orig_orient.x)
|
||||
],
|
||||
($attach_to!=undef)? (
|
||||
let(
|
||||
conn = find_connector($attach_to, size.z, size, size2=size2, shift=shift, geometry=geometry),
|
||||
ang = vector_angle(conn[2], DOWN),
|
||||
axis = vector_axis(conn[2], DOWN),
|
||||
ang2 = (conn[2]==UP || conn[2]==DOWN)? 0 : 180-conn[3],
|
||||
axis2 = rotate_points3d([axis],[0,0,ang2])[0]
|
||||
) [
|
||||
matrix4_translate(-conn[1]),
|
||||
matrix4_zrot(ang2),
|
||||
matrix4_rot_by_axis(axis2, ang)
|
||||
]
|
||||
) : concat(
|
||||
(align==CENTER)? [] : [
|
||||
let(conn = find_connector(align, size.z, size, size2=size2, shift=shift, extra_conns=alignments, geometry=geometry))
|
||||
matrix4_translate(-conn[1])
|
||||
],
|
||||
(orient==ORIENT_Z)? [] : [
|
||||
matrix4_xrot(orient.x),
|
||||
matrix4_yrot(orient.y),
|
||||
matrix4_zrot(orient.z)
|
||||
]
|
||||
)
|
||||
));
|
||||
$attach_to = undef;
|
||||
$parent_size = size;
|
||||
$parent_size2 = size2;
|
||||
$parent_shift = shift;
|
||||
$parent_orient = orient;
|
||||
$parent_align = align;
|
||||
$parent_geom = geometry;
|
||||
$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)]);
|
||||
multmatrix(m) {
|
||||
if ($children>1 && chain) {
|
||||
if(shown && !hidden) color($color) for (i=[0:$children-2]) children(i);
|
||||
children($children-1);
|
||||
} else {
|
||||
if(shown && !hidden) color($color) children();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 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)
|
||||
{
|
||||
assert($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, geometry=$parent_geom);
|
||||
pos = conn[1];
|
||||
vec = conn[2];
|
||||
ang = conn[3];
|
||||
$attach_to = to;
|
||||
$attach_conn = conn;
|
||||
if (norot || (norm(vec-UP)<1e-9 && ang==0)) {
|
||||
translate(pos) translate([0,0,-overlap]) children();
|
||||
} else {
|
||||
translate(pos) rot(ang,from=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
|
|
@ -885,7 +885,7 @@ function patch_scale(patch, v=[1,1,1], cp=[0,0,0]) = [for(row=patch) scale_point
|
|||
// v = Vector axis to rotate round.
|
||||
// cp = Centerpoint to rotate around.
|
||||
function patch_rotate(patch, a=undef, v=undef, cp=[0,0,0]) =
|
||||
[for(row=patch) rotate_points3d(row, v=a, axis=v, cp=cp)] :
|
||||
[for(row=patch) rotate_points3d(row, a=a, v=v, cp=cp)];
|
||||
|
||||
|
||||
// Function: patches_translate()
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// Backwards Compatability library
|
||||
// To use, include this line at the top of your file:
|
||||
// ```
|
||||
// use <compat.scad>
|
||||
// use <BOSL2/std.scad>
|
||||
// ```
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
51
debug.scad
51
debug.scad
|
@ -4,8 +4,6 @@
|
|||
// To use, add the following lines to the beginning of your file:
|
||||
// ```
|
||||
// include <BOSL2/std.scad>
|
||||
// include <BOSL2/paths.scad>
|
||||
// include <BOSL2/beziers.scad>
|
||||
// include <BOSL2/debug.scad>
|
||||
// ```
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
@ -173,25 +171,16 @@ module debug_polyhedron(points, faces, convexity=10, txtsize=1, disabled=false)
|
|||
|
||||
|
||||
|
||||
// Function: all_conns()
|
||||
// Function: all_connectors()
|
||||
// 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) a+b] : [],
|
||||
in_list(type,["cube","cylinder"])? [for (a=zs, b=xs) a+b] : [],
|
||||
in_list(type,["cube"])? [for (a=ys, b=xs) a+b] : [],
|
||||
in_list(type,["cube"])? [for (a=zs, b=ys, c=xs) a+b+c] : []
|
||||
);
|
||||
// Return the vectors for all standard connectors.
|
||||
function all_connectors() = [
|
||||
for (
|
||||
zv = [TOP, CENTER, BOTTOM],
|
||||
yv = [FRONT, CENTER, BACK],
|
||||
xv = [LEFT, CENTER, RIGHT]
|
||||
) xv+yv+zv
|
||||
];
|
||||
|
||||
|
||||
|
||||
|
@ -207,11 +196,12 @@ function all_conns(type="cube") =
|
|||
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=UP)
|
||||
attach(TOP) cyl(h=s/3, d1=s/5, d2=0, align=UP) {
|
||||
recolor(color) cyl(h=s, d=s/15, align=DOWN)
|
||||
attach(TOP) cyl(h=s/3, d1=s/5, d2=0, align=DOWN) {
|
||||
if(flag) {
|
||||
attach(BOTTOM) recolor([1,0.5,0.5]) cuboid([s/50, s/6, s/4], align="front-top");
|
||||
attach(BOTTOM) recolor([1,0.5,0.5]) cuboid([s/50, s/6, s/4], align=FRONT+TOP);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -219,11 +209,9 @@ module connector_arrow(s=10, color=[0.333,0.333,1], flag=true) {
|
|||
|
||||
// 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)) {
|
||||
// Show all standard connectors for the parent object.
|
||||
module show_connectors() {
|
||||
for (conn=all_connectors()) {
|
||||
attach(conn) connector_arrow();
|
||||
}
|
||||
children();
|
||||
|
@ -231,16 +219,17 @@ module show_connectors(type="cube") {
|
|||
|
||||
|
||||
|
||||
// Module: frameref()
|
||||
// Module: frame_ref()
|
||||
// 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) {
|
||||
module frame_ref(s=15) {
|
||||
noop() {
|
||||
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);
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +1,13 @@
|
|||
include <BOSL2/constants.scad>
|
||||
include <BOSL2/transforms.scad>
|
||||
include <BOSL2/primitives.scad>
|
||||
include <BOSL2/shapes.scad>
|
||||
include <BOSL2/debug.scad>
|
||||
include <BOSL2/std.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);
|
||||
cuboid([60,40,40], fillet=5, edges=EDGES_Z_ALL, align=BOTTOM) {
|
||||
attach(TOP, BOTTOM) 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"]) {
|
||||
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]);
|
||||
attach(TOP, LEFT, overlap=5) prismoid([30,20], [20,20], h=10, shift=[-7,0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
include <BOSL2/constants.scad>
|
||||
use <BOSL2/transforms.scad>
|
||||
use <BOSL2/beziers.scad>
|
||||
use <BOSL2/math.scad>
|
||||
include <BOSL2/std.scad>
|
||||
include <BOSL2/paths.scad>
|
||||
include <BOSL2/beziers.scad>
|
||||
|
||||
|
||||
function CR_corner(size, orient=[0,0,0], trans=[0,0,0]) =
|
||||
|
|
8
examples/conical_connectors.scad
Normal file
8
examples/conical_connectors.scad
Normal file
|
@ -0,0 +1,8 @@
|
|||
include <BOSL2/std.scad>
|
||||
include <BOSL2/debug.scad>
|
||||
|
||||
|
||||
cylinder(h=30, d1=50, d2=30) show_connectors();
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
8
examples/cube_connectors.scad
Normal file
8
examples/cube_connectors.scad
Normal file
|
@ -0,0 +1,8 @@
|
|||
include <BOSL2/std.scad>
|
||||
include <BOSL2/debug.scad>
|
||||
|
||||
|
||||
cube(40, center=true) show_connectors();
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
|
@ -1,9 +1,8 @@
|
|||
include <BOSL2/constants.scad>
|
||||
include <BOSL2/primitives.scad>
|
||||
include <BOSL2/std.scad>
|
||||
include <BOSL2/debug.scad>
|
||||
|
||||
|
||||
cylinder(h=30, d1=50, d2=30) show_connectors("cylinder");
|
||||
cylinder(h=30, d=30) show_connectors();
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
include <BOSL2/constants.scad>
|
||||
include <BOSL2/transforms.scad>
|
||||
include <BOSL2/primitives.scad>
|
||||
include <BOSL2/std.scad>
|
||||
include <BOSL2/paths.scad>
|
||||
include <BOSL2/beziers.scad>
|
||||
|
||||
module leaf(s) {
|
||||
|
@ -18,7 +17,7 @@ module leaf(s) {
|
|||
|
||||
module branches(minsize){
|
||||
if($parent_size2.x>minsize) {
|
||||
attach("top")
|
||||
attach(TOP)
|
||||
zrot(gaussian_rand(90,10))
|
||||
zring(n=floor(log_rand(2,5,4)))
|
||||
zrot(gaussian_rand(0,5))
|
||||
|
@ -32,7 +31,7 @@ module branches(minsize){
|
|||
branches(minsize);
|
||||
} else {
|
||||
recolor("springgreen")
|
||||
attach("top") zrot(90)
|
||||
attach(TOP) zrot(90)
|
||||
leaf(gaussian_rand(100,5));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
use <BOSL2/transforms.scad>
|
||||
use <BOSL2/math.scad>
|
||||
include <BOSL2/constants.scad>
|
||||
include <BOSL2/std.scad>
|
||||
|
||||
// Shows all the orientations on cubes in their correct rotations.
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
include <BOSL2/constants.scad>
|
||||
include <BOSL2/shapes.scad>
|
||||
include <BOSL2/std.scad>
|
||||
include <BOSL2/debug.scad>
|
||||
|
||||
|
||||
|
|
8
examples/sphere_connectors.scad
Normal file
8
examples/sphere_connectors.scad
Normal file
|
@ -0,0 +1,8 @@
|
|||
include <BOSL2/std.scad>
|
||||
include <BOSL2/debug.scad>
|
||||
|
||||
|
||||
sphere(d=30) show_connectors();
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
|
@ -1,7 +1,4 @@
|
|||
include <BOSL2/constants.scad>
|
||||
include <BOSL2/transforms.scad>
|
||||
include <BOSL2/primitives.scad>
|
||||
include <BOSL2/shapes.scad>
|
||||
include <BOSL2/std.scad>
|
||||
|
||||
|
||||
diff("hole", "body pole")
|
||||
|
|
|
@ -54,9 +54,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
//
|
||||
// Example: Simple regular cube.
|
||||
// cube(40);
|
||||
// Example: Rectangular cube, with given X, Y, and Z sizes.
|
||||
// Example: Rectangular cube.
|
||||
// cuboid([20,40,50]);
|
||||
module cube(size, center=undef, align=ALLPOS)
|
||||
// Example: Standard Connectors.
|
||||
// cube(40, center=true) show_connectors();
|
||||
module cube(size, center=undef, align=ALLNEG)
|
||||
{
|
||||
size = scalar_vec3(size);
|
||||
orient_and_align(size, ORIENT_Z, align, center, noncentered=ALLPOS, chain=true) {
|
||||
|
@ -96,14 +98,19 @@ module cube(size, center=undef, align=ALLPOS)
|
|||
// 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=UP)
|
||||
// Example: Standard Connectors
|
||||
// xdistribute(40) {
|
||||
// cylinder(h=30, d=25) show_connectors();
|
||||
// cylinder(h=30, d1=25, d2=10) show_connectors();
|
||||
// }
|
||||
module cylinder(r=undef, d=undef, r1=undef, r2=undef, d1=undef, d2=undef, h=undef, l=undef, center=undef, orient=ORIENT_Z, align=BOTTOM)
|
||||
{
|
||||
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=UP, chain=true) {
|
||||
orient_and_align(size, orient, align, center, size2=[r2*2,r2*2], noncentered=UP, geometry="cylinder", chain=true) {
|
||||
linear_extrude(height=l, scale=r2/r1, convexity=2, center=true) {
|
||||
circle(r=r1, $fn=sides);
|
||||
}
|
||||
|
@ -124,14 +131,18 @@ module cylinder(r=undef, d=undef, r1=undef, r2=undef, d1=undef, d2=undef, h=unde
|
|||
// 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 constants from `constants.scad`. Default: `CENTER`.
|
||||
// Example:
|
||||
// staggered_sphere(d=100);
|
||||
// Example: By Radius
|
||||
// sphere(r=50);
|
||||
// Example: By Diameter
|
||||
// sphere(d=100);
|
||||
// Example: Standard Connectors
|
||||
// sphere(d=50) show_connectors();
|
||||
module sphere(r=undef, d=undef, orient=ORIENT_Z, align=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) {
|
||||
orient_and_align(size, orient, align, geometry="sphere", chain=true) {
|
||||
rotate_extrude(convexity=2) {
|
||||
difference() {
|
||||
circle(r=r, $fn=sides);
|
||||
|
|
112
shapes.scad
112
shapes.scad
|
@ -76,6 +76,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
// cuboid([30,40,50], chamfer=5, edges=EDGE_TOP_FR+EDGE_TOP_RT+EDGE_FR_RT, $fn=24);
|
||||
// Example: Rectangular cube with only some edges rounded.
|
||||
// cuboid([30,40,50], fillet=5, edges=EDGE_TOP_FR+EDGE_TOP_RT+EDGE_FR_RT, $fn=24);
|
||||
// Example: Standard Connectors
|
||||
// cuboid(40, chamfer=5) show_connectors();
|
||||
module cuboid(
|
||||
size=[1,1,1],
|
||||
p1=undef, p2=undef,
|
||||
|
@ -90,11 +92,11 @@ module cuboid(
|
|||
if (!is_undef(p1)) {
|
||||
if (!is_undef(p2)) {
|
||||
translate([for (v=array_zip([p1,p2],0)) min(v)]) {
|
||||
cuboid(size=vabs(p2-p1), chamfer=chamfer, fillet=fillet, edges=edges, trimcorners=trimcorners, align=ALLPOS) children();
|
||||
cuboid(size=vabs(p2-p1), chamfer=chamfer, fillet=fillet, edges=edges, trimcorners=trimcorners, align=ALLNEG) children();
|
||||
}
|
||||
} else {
|
||||
translate(p1) {
|
||||
cuboid(size=size, chamfer=chamfer, fillet=fillet, edges=edges, trimcorners=trimcorners, align=ALLPOS) children();
|
||||
cuboid(size=size, chamfer=chamfer, fillet=fillet, edges=edges, trimcorners=trimcorners, align=ALLNEG) children();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -333,15 +335,17 @@ module upcube(size=[1,1,1]) {siz = scalar_vec3(size); up(siz[2]/2) cube(size=siz
|
|||
// prismoid(size1=[30,60], size2=[0,60], shift=[-15,0], h=30);
|
||||
// Example(FlatSpin): Shifting/Skewing
|
||||
// prismoid(size1=[50,30], size2=[20,20], h=20, shift=[15,5]);
|
||||
// Example(Spin): Standard Connectors
|
||||
// prismoid(size1=[50,30], size2=[20,20], h=20, shift=[15,5]) show_connectors();
|
||||
module prismoid(
|
||||
size1=[1,1], size2=[1,1], h=1, shift=[0,0],
|
||||
orient=ORIENT_Z, align=UP, center=undef
|
||||
orient=ORIENT_Z, align=DOWN, center=undef
|
||||
) {
|
||||
eps = 0.001;
|
||||
shiftby = point3d(point2d(shift));
|
||||
s1 = [max(size1.x, eps), max(size1.y, eps)];
|
||||
s2 = [max(size2.x, eps), max(size2.y, eps)];
|
||||
orient_and_align([s1.x,s1.y,h], orient, align, center, size2=s2, shift=shift, noncentered=UP, chain=true) {
|
||||
orient_and_align([s1.x,s1.y,h], orient, align, center, size2=s2, shift=shift, noncentered=DOWN, chain=true) {
|
||||
polyhedron(
|
||||
points=[
|
||||
[+s2.x/2, +s2.y/2, +h/2] + shiftby,
|
||||
|
@ -399,10 +403,12 @@ module prismoid(
|
|||
// rounded_prismoid(size1=[40,60], size2=[40,60], h=20, r1=3, r2=10, $fn=24);
|
||||
// Example(FlatSpin): Shifting/Skewing
|
||||
// rounded_prismoid(size1=[50,30], size2=[20,20], h=20, shift=[15,5], r=5);
|
||||
// Example(Spin): Standard Connectors
|
||||
// rounded_prismoid(size1=[40,60], size2=[40,60], h=20, r1=3, r2=10, $fn=24) show_connectors();
|
||||
module rounded_prismoid(
|
||||
size1, size2, h, shift=[0,0],
|
||||
r=undef, r1=undef, r2=undef,
|
||||
align=UP, orient=ORIENT_Z, center=undef
|
||||
align=DOWN, orient=ORIENT_Z, center=undef
|
||||
) {
|
||||
eps = 0.001;
|
||||
maxrad1 = min(size1.x/2, size1.y/2);
|
||||
|
@ -446,14 +452,16 @@ module rounded_prismoid(
|
|||
// Arguments:
|
||||
// size = [width, thickness, height]
|
||||
// orient = The axis to place the hypotenuse along. Only accepts `ORIENT_X`, `ORIENT_Y`, or `ORIENT_Z` from `constants.scad`. Default: `ORIENT_Y`.
|
||||
// align = The side of the origin to align to. Use constants from `constants.scad`. Default: `UP+BACK+RIGHT`.
|
||||
// center = If given, overrides `align`. A true value sets `align=CENTER`, false sets `align=UP+BACK+RIGHT`.
|
||||
// align = The side of the origin to align to. Use constants from `constants.scad`. Default: `ALLNEG`.
|
||||
// center = If given, overrides `align`. A true value sets `align=CENTER`, false sets `align=ALLNEG`.
|
||||
//
|
||||
// Example: Centered
|
||||
// right_triangle([60, 10, 40], center=true);
|
||||
// Example: *Non*-Centered
|
||||
// right_triangle([60, 10, 40]);
|
||||
module right_triangle(size=[1, 1, 1], orient=ORIENT_Y, align=ALLPOS, center=undef)
|
||||
// Example: Standard Connectors
|
||||
// right_triangle([60, 15, 40]) show_connectors();
|
||||
module right_triangle(size=[1, 1, 1], orient=ORIENT_Y, align=ALLNEG, center=undef)
|
||||
{
|
||||
size = scalar_vec3(size);
|
||||
orient_and_align(size, align=align, center=center, chain=true) {
|
||||
|
@ -542,7 +550,7 @@ module right_triangle(size=[1, 1, 1], orient=ORIENT_Y, align=ALLPOS, center=unde
|
|||
// realign = If true, rotate the cylinder by half the angle of one face.
|
||||
// orient = Orientation of the cylinder. Use the `ORIENT_` constants from `constants.scad`. Default: vertical.
|
||||
// align = Alignment of the cylinder. Use the constants from `constants.scad`. Default: centered.
|
||||
// center = If given, overrides `align`. A true value sets `align=CENTER`, false sets `align=UP`.
|
||||
// center = If given, overrides `align`. A true value sets `align=CENTER`, false sets `align=DOWN`.
|
||||
//
|
||||
// Example: By Radius
|
||||
// xdistribute(30) {
|
||||
|
@ -577,6 +585,13 @@ module right_triangle(size=[1, 1, 1], orient=ORIENT_Y, align=ALLPOS, center=unde
|
|||
//
|
||||
// Example: Putting it all together
|
||||
// cyl(l=40, d1=25, d2=15, chamfer1=10, chamfang1=30, from_end=true, fillet2=5);
|
||||
//
|
||||
// Example: Standard Connectors
|
||||
// xdistribute(40) {
|
||||
// cyl(l=30, d=25) show_connectors();
|
||||
// cyl(l=30, d1=25, d2=10) show_connectors();
|
||||
// }
|
||||
//
|
||||
module cyl(
|
||||
l=undef, h=undef,
|
||||
r=undef, r1=undef, r2=undef,
|
||||
|
@ -595,7 +610,7 @@ module cyl(
|
|||
sides = segs(max(r1,r2));
|
||||
sc = circum? 1/cos(180/sides) : 1;
|
||||
phi = atan2(l, r1-r2);
|
||||
orient_and_align(size1, orient, align, center=center, size2=size2, chain=true) {
|
||||
orient_and_align(size1, orient, align, center=center, size2=size2, geometry="cylinder", chain=true) {
|
||||
zrot(realign? 180/sides : 0) {
|
||||
if (!any_defined([chamfer, chamfer1, chamfer2, fillet, fillet1, fillet2])) {
|
||||
cylinder(h=l, r1=r1*sc, r2=r2*sc, center=true, $fn=sides);
|
||||
|
@ -722,36 +737,6 @@ module cyl(
|
|||
|
||||
|
||||
|
||||
// Module: downcyl()
|
||||
//
|
||||
// Description:
|
||||
// Creates a cylinder aligned below the origin.
|
||||
//
|
||||
// Usage:
|
||||
// downcyl(l|h, r|d);
|
||||
// downcyl(l|h, r1|d1, r2|d2);
|
||||
//
|
||||
// Arguments:
|
||||
// l / h = Length of cylinder. (Default: 1.0)
|
||||
// r = Radius of cylinder.
|
||||
// r1 = Bottom radius of cylinder.
|
||||
// r2 = Top radius of cylinder.
|
||||
// d = Diameter of cylinder. (use instead of r)
|
||||
// d1 = Bottom diameter of cylinder.
|
||||
// d2 = Top diameter of cylinder.
|
||||
//
|
||||
// Example: Cylinder
|
||||
// downcyl(r=20, h=40);
|
||||
// Example: Cone
|
||||
// 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)
|
||||
{
|
||||
l = first_defined([l, h, 1]);
|
||||
cyl(r=r, r1=r1, r2=r2, d=d, d1=d1, d2=d2, l=l, align=DOWN) children();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Module: xcyl()
|
||||
//
|
||||
// Description:
|
||||
|
@ -770,7 +755,7 @@ module downcyl(r=undef, h=undef, l=undef, d=undef, d1=undef, d2=undef, r1=undef,
|
|||
// d1 = Optional diameter of left (X-) end of cylinder.
|
||||
// d2 = Optional diameter of right (X+) end of cylinder.
|
||||
// align = The side of the origin to align to. Use constants from `constants.scad`. Default: `CENTER`
|
||||
// center = If given, overrides `align`. A `true` value sets `align=CENTER`, `false` sets `align=UP`.
|
||||
// center = If given, overrides `align`. A `true` value sets `align=CENTER`, `false` sets `align=BOTTOM`.
|
||||
//
|
||||
// Example: By Radius
|
||||
// ydistribute(50) {
|
||||
|
@ -909,6 +894,8 @@ module zcyl(l=undef, r=undef, d=undef, r1=undef, r2=undef, d1=undef, d2=undef, h
|
|||
// tube(h=30, or1=40, or2=25, ir1=35, ir2=20);
|
||||
// Example: Circular Wedge
|
||||
// tube(h=30, or1=40, or2=30, ir1=20, ir2=30);
|
||||
// Example: Standard Connectors
|
||||
// tube(h=30, or=40, wall=5) show_connectors();
|
||||
module tube(
|
||||
h=1, wall=undef,
|
||||
r=undef, r1=undef, r2=undef,
|
||||
|
@ -929,7 +916,7 @@ module tube(
|
|||
sides = segs(max(r1,r2));
|
||||
size = [r1*2,r1*2,h];
|
||||
size2 = [r2*2,r2*2,h];
|
||||
orient_and_align(size, orient, align, center=center, size2=size2, chain=true) {
|
||||
orient_and_align(size, orient, align, center=center, size2=size2, geometry="cylinder", chain=true) {
|
||||
zrot(realign? 180/sides : 0) {
|
||||
difference() {
|
||||
cyl(h=h, r1=r1, r2=r2, $fn=sides) children();
|
||||
|
@ -968,6 +955,8 @@ module tube(
|
|||
// torus(d=45, d2=15);
|
||||
// torus(or=30, ir=15);
|
||||
// torus(od=60, id=30);
|
||||
// Example: Standard Connectors
|
||||
// torus(od=60, id=30) show_connectors();
|
||||
module torus(
|
||||
r=undef, d=undef,
|
||||
r2=undef, d2=undef,
|
||||
|
@ -980,7 +969,7 @@ module torus(
|
|||
majrad = get_radius(r=r, d=d, dflt=(orr+irr)/2);
|
||||
minrad = get_radius(r=r2, d=d2, dflt=(orr-irr)/2);
|
||||
size = [(majrad+minrad)*2, (majrad+minrad)*2, minrad*2];
|
||||
orient_and_align(size, orient, align, center=center, chain=true) {
|
||||
orient_and_align(size, orient, align, center=center, geometry="cylinder", chain=true) {
|
||||
rotate_extrude(convexity=4) {
|
||||
right(majrad) circle(minrad);
|
||||
}
|
||||
|
@ -1004,8 +993,12 @@ module torus(
|
|||
// 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 constants from `constants.scad`. Default: `CENTER`.
|
||||
// Example:
|
||||
// spheroid(d=100, circum=true, $fn=10);
|
||||
// Example: By Radius
|
||||
// spheroid(r=50, circum=true);
|
||||
// Example: By Diameter
|
||||
// spheroid(d=100, circum=true);
|
||||
// Example: Standard Connectors
|
||||
// spheroid(d=40, circum=true) show_connectors();
|
||||
module spheroid(r=undef, d=undef, circum=false, orient=UP, align=CENTER)
|
||||
{
|
||||
r = get_radius(r=r, d=d, dflt=1);
|
||||
|
@ -1013,7 +1006,7 @@ module spheroid(r=undef, d=undef, circum=false, orient=UP, align=CENTER)
|
|||
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) {
|
||||
orient_and_align(size, orient, align, geometry="sphere", chain=true) {
|
||||
sphere(r=rr);
|
||||
children();
|
||||
}
|
||||
|
@ -1036,8 +1029,12 @@ module spheroid(r=undef, d=undef, circum=false, orient=UP, align=CENTER)
|
|||
// 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 constants from `constants.scad`. Default: `CENTER`.
|
||||
//
|
||||
// Example:
|
||||
// staggered_sphere(d=100, circum=true, $fn=10);
|
||||
// Example: By Radius
|
||||
// staggered_sphere(r=50, circum=true);
|
||||
// Example: By Diameter
|
||||
// staggered_sphere(d=100, circum=true);
|
||||
// Example: Standard Connectors
|
||||
// staggered_sphere(d=40, circum=true) show_connectors();
|
||||
module staggered_sphere(r=undef, d=undef, circum=false, orient=UP, align=CENTER) {
|
||||
r = get_radius(r=r, d=d, dflt=1);
|
||||
sides = segs(r);
|
||||
|
@ -1075,7 +1072,7 @@ module staggered_sphere(r=undef, d=undef, circum=false, orient=UP, align=CENTER)
|
|||
]
|
||||
);
|
||||
size = [2*rr, 2*rr, 2*rr];
|
||||
orient_and_align(size, orient, align, chain=true) {
|
||||
orient_and_align(size, orient, align, geometry="sphere", chain=true) {
|
||||
polyhedron(points=pts, faces=faces);
|
||||
children();
|
||||
}
|
||||
|
@ -1153,7 +1150,7 @@ 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);
|
||||
l = first_defined([l, h, 1]);
|
||||
size = [r*2,r*2,l];
|
||||
orient_and_align(size, orient, align, chain=true) {
|
||||
orient_and_align(size, orient, align, geometry="cylinder", chain=true) {
|
||||
linear_extrude(height=l, center=true, slices=2) {
|
||||
teardrop2d(r=r, ang=ang, cap_h=cap_h);
|
||||
}
|
||||
|
@ -1184,13 +1181,18 @@ module teardrop(r=undef, d=undef, l=undef, h=undef, ang=45, cap_h=undef, orient=
|
|||
// onion(r=30, maxang=30, cap_h=40);
|
||||
// Example: Close Crop
|
||||
// onion(r=30, maxang=30, cap_h=20);
|
||||
// Example: Standard Connectors
|
||||
// onion(r=30, maxang=30, cap_h=40) show_connectors();
|
||||
module onion(cap_h=undef, r=undef, d=undef, maxang=45, h=undef, orient=ORIENT_Z, align=CENTER)
|
||||
{
|
||||
r = get_radius(r=r, d=d, dflt=1);
|
||||
h = first_defined([cap_h, h]);
|
||||
maxd = 3*r/tan(maxang);
|
||||
size = [r*2,r*2,r*2];
|
||||
orient_and_align(size, orient, align, chain=true) {
|
||||
alignments = [
|
||||
["cap", [0,0,h], UP, 0]
|
||||
];
|
||||
orient_and_align(size, orient, align, geometry="sphere", alignments=alignments, chain=true) {
|
||||
rotate_extrude(convexity=2) {
|
||||
difference() {
|
||||
teardrop2d(r=r, ang=maxang, cap_h=h);
|
||||
|
@ -1724,7 +1726,7 @@ module corrugated_wall(h=50, l=100, thick=5, strut=5, wall=2, orient=ORIENT_Y, a
|
|||
//
|
||||
// Description:
|
||||
// Useful when you MUST pass a child to a module, but you want it to be nothing.
|
||||
module nil() union() {}
|
||||
module nil() union(){}
|
||||
|
||||
|
||||
// Module: noop()
|
||||
|
@ -1732,7 +1734,7 @@ module nil() union() {}
|
|||
// Description:
|
||||
// Passes through the children passed to it, with no action at all.
|
||||
// Useful while debugging when you want to replace a command.
|
||||
module noop() children();
|
||||
module noop(orient=ORIENT_Z) orient_and_align([0,0,0], orient, CENTER, chain=true) {nil(); children();}
|
||||
|
||||
|
||||
// Module: pie_slice()
|
||||
|
@ -1773,7 +1775,7 @@ module pie_slice(
|
|||
r2 = get_radius(r2, r, d2, d, 10);
|
||||
maxd = max(r1,r2)+0.1;
|
||||
size = [2*r1, 2*r1, l];
|
||||
orient_and_align(size, orient, align, center=center, chain=true) {
|
||||
orient_and_align(size, orient, align, center=center, geometry="cylinder", chain=true) {
|
||||
difference() {
|
||||
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);
|
||||
|
@ -1919,7 +1921,7 @@ module arced_slot(
|
|||
fn_minor = first_defined([$fn2, $fn]);
|
||||
da = ea - sa;
|
||||
size = [r+sr1, r+sr1, h];
|
||||
orient_and_align(size, orient, align, chain=true) {
|
||||
orient_and_align(size, orient, align, geometry="cylinder", chain=true) {
|
||||
translate(cp) {
|
||||
zrot(sa) {
|
||||
difference() {
|
||||
|
|
25
std.scad
25
std.scad
|
@ -36,18 +36,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
*/
|
||||
|
||||
|
||||
include <BOSL2/constants.scad>
|
||||
include <BOSL2/compat.scad>
|
||||
include <BOSL2/math.scad>
|
||||
include <BOSL2/arrays.scad>
|
||||
include <BOSL2/vector.scad>
|
||||
include <BOSL2/matrices.scad>
|
||||
include <BOSL2/coords.scad>
|
||||
include <BOSL2/geometry.scad>
|
||||
include <BOSL2/transforms.scad>
|
||||
include <BOSL2/primitives.scad>
|
||||
include <BOSL2/shapes.scad>
|
||||
include <BOSL2/masks.scad>
|
||||
include <constants.scad>
|
||||
include <compat.scad>
|
||||
include <math.scad>
|
||||
include <arrays.scad>
|
||||
include <vectors.scad>
|
||||
include <matrices.scad>
|
||||
include <coords.scad>
|
||||
include <geometry.scad>
|
||||
include <attachments.scad>
|
||||
include <transforms.scad>
|
||||
include <primitives.scad>
|
||||
include <shapes.scad>
|
||||
include <masks.scad>
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
|
326
transforms.scad
326
transforms.scad
|
@ -2173,330 +2173,4 @@ module shell2d(thickness, or=0, ir=0, fill=0, round=0)
|
|||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Section: Miscellaneous
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// Module: orient_and_align()
|
||||
//
|
||||
// Description:
|
||||
// Takes a vertically oriented shape, and re-orients and aligns it.
|
||||
// This is useful for making a custom shape available in various
|
||||
// orientations and alignments without extra translate()s and rotate()s.
|
||||
// Children should be vertically (Z-axis) oriented, and centered.
|
||||
// Non-extremity alignment points should be named via the `alignments` arg.
|
||||
// Named alignments are aligned pre-rotation.
|
||||
//
|
||||
// Usage:
|
||||
// orient_and_align(size, [orient], [align], [center], [noncentered], [orig_orient], [orig_align], [alignments], [chain]) ...
|
||||
//
|
||||
// Arguments:
|
||||
// size = The [X,Y,Z] size of the part.
|
||||
// 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.
|
||||
// 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: `UP`.
|
||||
// orig_orient = The original orientation of the part. Default: `ORIENT_Z`.
|
||||
// orig_align = The original alignment of the part. Default: `CENTER`.
|
||||
// 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:
|
||||
// #cylinder(d=5, h=10);
|
||||
// orient_and_align([5,5,10], orient=ORIENT_Y, align=BACK, orig_align=UP) cylinder(d=5, h=10);
|
||||
module orient_and_align(
|
||||
size=undef, orient=ORIENT_Z, align=CENTER,
|
||||
center=undef, noncentered=TOP,
|
||||
orig_orient=ORIENT_Z, orig_align=CENTER,
|
||||
size2=undef, shift=[0,0],
|
||||
alignments=[], chain=false
|
||||
) {
|
||||
size2 = point2d(default(size2, size));
|
||||
shift = point2d(shift);
|
||||
align = !is_undef(center)? (center? CENTER : noncentered) : align;
|
||||
m = matrix4_mult(concat(
|
||||
(orig_align==CENTER)? [] : [
|
||||
// If original alignment is not centered, center it.
|
||||
matrix4_translate(vmul(size/2, -orig_align))
|
||||
],
|
||||
(orig_orient==ORIENT_Z)? [] : [
|
||||
// If original orientation is not upright, rotate it upright.
|
||||
matrix4_zrot(-orig_orient.z),
|
||||
matrix4_yrot(-orig_orient.y),
|
||||
matrix4_xrot(-orig_orient.x)
|
||||
],
|
||||
($attach_to!=undef)? (
|
||||
let(
|
||||
conn = find_connector($attach_to, size.z, size, size2=size2, shift=shift),
|
||||
ang = vector_angle(conn[2], DOWN),
|
||||
axis = vector_axis(conn[2], DOWN),
|
||||
ang2 = (conn[2]==UP || conn[2]==DOWN)? 0 : 180-conn[3],
|
||||
axis2 = rotate_points3d([axis],[0,0,ang2])[0]
|
||||
) [
|
||||
matrix4_translate(-conn[1]),
|
||||
matrix4_zrot(ang2),
|
||||
matrix4_rot_by_axis(axis2, ang)
|
||||
]
|
||||
) : concat(
|
||||
(align==CENTER)? [] : [
|
||||
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)
|
||||
]
|
||||
)
|
||||
));
|
||||
$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 {
|
||||
if(shown && !hidden) color($color) children();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 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=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(
|
||||
shift = point3d(shift),
|
||||
size = point3d(point2d(size)),
|
||||
size2 = (size2!=undef)? point3d(point2d(size2)) : size,
|
||||
found = !is_string(align)? [] : search([align], extra_conns, num_returns_per_match=1)[0]
|
||||
) (found!=[])? extra_conns[found] : let(
|
||||
top = [-size2/2+shift, shift, size2/2+shift],
|
||||
bot = [-size/2, CENTER, size/2],
|
||||
toppt = [top[align.x+1].x, top[align.y+1].y, h/2],
|
||||
botpt = [bot[align.x+1].x, bot[align.y+1].y, -h/2],
|
||||
pos = lerp(botpt, toppt, (align.z+1)/2),
|
||||
oang = (
|
||||
align == UP? 0 :
|
||||
align == DOWN? 0 :
|
||||
(norm([align.x,align.y]) < EPSILON)? 0 :
|
||||
atan2(align.y, align.x)+90
|
||||
),
|
||||
vec = (
|
||||
abs(align.z) > EPSILON? align :
|
||||
rotate_points3d([align], from=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)
|
||||
{
|
||||
assert($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-UP)<1e-9 && ang==0)) {
|
||||
translate(pos) translate([0,0,-overlap]) children();
|
||||
} else {
|
||||
translate(pos) rot(ang,from=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
|
||||
|
|
Loading…
Reference in a new issue