Merge pull request #1429 from adrianVmariano/master

sparse cuboid + doc fixes
This commit is contained in:
Revar Desmera 2024-05-21 14:04:18 -07:00 committed by GitHub
commit 7d69589478
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 463 additions and 133 deletions

View file

@ -69,7 +69,7 @@ PrioritizeFiles:
walls.scad
wiring.scad
DefineHeader(BulletList): Side Effects
DefineHeader(Table;Headers=Anchor Name|Position): Extra Anchors
DefineHeader(Table;Headers=Anchor Name|Position): Named Anchors
DefineHeader(Table;Headers=Anchor Type|What it is): Anchor Types
DefineHeader(Table;Headers=Name|Definition): Terminology
DefineHeader(BulletList): Requirements

View file

@ -3571,7 +3571,7 @@ function _force_anchor_2d(anchor) =
/// geom = The geometry description of the shape.
function _find_anchor(anchor, geom) =
is_string(anchor)? (
anchor=="origin"? [anchor, CENTER, UP, 0]
anchor=="origin"? [anchor, CENTER, UP, 0] // Ok that this returns 3d anchor in the 2d case?
: let(
anchors = last(geom),
found = search([anchor], anchors, num_returns_per_match=1)[0]

View file

@ -31,7 +31,7 @@ include <rounding.scad>
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Extra Anchors:
// Named Anchors:
// "tamper-ring" = Centered at the top of the anti-tamper ring channel.
// "support-ring" = Centered at the bottom of the support ring.
// Example:
@ -160,7 +160,7 @@ function pco1810_neck(wall=2, anchor="support-ring", spin=0, orient=UP) =
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Extra Anchors:
// Named Anchors:
// "inside-top" = Centered on the inside top of the cap.
// Examples:
// pco1810_cap();
@ -236,7 +236,7 @@ function pco1810_cap(h, r, d, wall, texture="none", anchor=BOTTOM, spin=0, orien
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Extra Anchors:
// Named Anchors:
// "tamper-ring" = Centered at the top of the anti-tamper ring channel.
// "support-ring" = Centered at the bottom of the support ring.
// Example:
@ -362,7 +362,7 @@ function pco1881_neck(wall=2, anchor="support-ring", spin=0, orient=UP) =
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Extra Anchors:
// Named Anchors:
// "inside-top" = Centered on the inside top of the cap.
// Examples:
// pco1881_cap();
@ -431,7 +431,7 @@ function pco1881_cap(wall=2, texture="none", anchor=BOTTOM, spin=0, orient=UP) =
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Extra Anchors:
// Named Anchors:
// "support-ring" = Centered at the bottom of the support ring.
// Example:
// generic_bottle_neck();
@ -564,7 +564,7 @@ function generic_bottle_neck(
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Extra Anchors:
// Named Anchors:
// "inside-top" = Centered on the inside top of the cap.
// Examples:
// generic_bottle_cap(thread_depth=2,neck_od=INCH,height=INCH/2);

View file

@ -1643,7 +1643,7 @@ module ring_gear2d(
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Extra Anchors:
// Named Anchors:
// "root" = At the base of the teeth, at the center of rack.
// "root-left" = At the base of the teeth, at the left end of the rack.
// "root-right" = At the base of the teeth, at the right end of the rack.
@ -1912,7 +1912,7 @@ function rack(
// rounding = If true, rack tips and valleys are slightly rounded. Default: true
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// Extra Anchors:
// Named Anchors:
// "root" = At the height of the teeth, at the center of rack.
// "root-left" = At the height of the teeth, at the left end of the rack.
// "root-right" = At the height of the teeth, at the right end of the rack.
@ -2363,7 +2363,7 @@ module crown_gear(
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: "pitchbase"
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Extra Anchors:
// Named Anchors:
// "pitchbase" = With the base of the pitch cone in the XY plane, centered at the origin. This is the natural height for the gear, and the default anchor.
// "apex" = At the pitch cone apex for the bevel gear.
// "flattop" = At the top of the flat top of the bevel gear.

View file

@ -249,20 +249,6 @@ module chamfer_cylinder_mask(r, chamfer, d, ang=45, from_end=false, anchor=CENTE
// rounding_edge_mask(l=p.z, r=25);
// }
// }
// Example: Acute angle
// ang=60;
// difference() {
// pie_slice(ang=ang, h=50, r=100);
// zflip_copy(z=25)
// #rounding_corner_mask(r=20, ang=ang);
// }
// Example: Obtuse angle
// ang=120;
// difference() {
// pie_slice(ang=ang, h=50, r=30);
// zflip_copy(z=25)
// #rounding_corner_mask(r=20, ang=ang);
// }
function rounding_edge_mask(l, r, ang=90, r1, r2, d, d1, d2, excess=0.1, anchor=CENTER, spin=0, orient=UP, h,height,length) = no_function("rounding_edge_mask");
module rounding_edge_mask(l, r, ang=90, r1, r2, excess=0.01, d1, d2,d,r,length, h, height, anchor=CENTER, spin=0, orient=UP,
@ -274,7 +260,7 @@ module rounding_edge_mask(l, r, ang=90, r1, r2, excess=0.01, d1, d2,d,r,length,
dummy = assert(all_nonnegative([r1,r2]), "radius/diameter value(s) must be nonnegative")
assert(all_positive([length]), "length/l/h/height must be a positive value")
assert(is_finite(ang) && ang>0 && ang<180, "ang must be a number between 0 and 180");
steps = ceil(segs(r)*(180-ang)/360);
steps = ceil(segs(max(r1,r2))*(180-ang)/360);
function make_path(r) =
let(
arc = r==0 ? repeat([0,0],steps+1)
@ -383,8 +369,21 @@ module rounding_edge_mask(l, r, ang=90, r1, r2, excess=0.01, d1, d2,d,r,length,
// corner_mask(TOP)
// #rounding_corner_mask(r=20);
// }
// Example: Acute angle mask
//
// Example(VPR=[71.8,0,345.8],VPT=[57.0174,43.8496,24.5863],VPD=263.435,NoScales): Acute angle
// ang=60;
// difference() {
// pie_slice(ang=ang, h=50, r=100);
// zflip_copy(z=25)
// #rounding_corner_mask(r=20, ang=ang);
// }
// Example(VPR=[62.7,0,5.4],VPT=[6.9671,22.7592,20.7513],VPD=192.044): Obtuse angle
// ang=120;
// difference() {
// pie_slice(ang=ang, h=50, r=30);
// zflip_copy(z=25)
// #rounding_corner_mask(r=20, ang=ang);
// }
function rounding_corner_mask(r, ang, d, style="octa", excess=0.1, anchor=CENTER, spin=0, orient=UP) = no_function("rounding_corner_mask");
module rounding_corner_mask(r, ang=90, d, style="octa", excess=0.1, anchor=CENTER, spin=0, orient=UP)
{

View file

@ -1374,7 +1374,7 @@ function quadratic_roots(a,b,c,real=false) =
// Function: polynomial()
// Synopsis: Calculates a polynomial equation at a given value.
// Synopsis: Evaluate a polynomial at a real or complex value.
// Topics: Math, Complex Numbers
// See Also: quadratic_roots(), polynomial(), poly_mult(), poly_div(), poly_add(), poly_roots()
// Usage:
@ -1394,7 +1394,7 @@ function polynomial(p,z,k,total) =
// Function: poly_mult()
// Synopsis: Returns the polynomial result of multiplying two polynomial equations.
// Synopsis: Compute product of two polynomials, returning a polynomial.
// Topics: Math
// See Also: quadratic_roots(), polynomial(), poly_mult(), poly_div(), poly_add(), poly_roots()
// Usage:
@ -1416,7 +1416,7 @@ function poly_mult(p,q) =
// Function: poly_div()
// Synopsis: Returns the polynomial quotient and remainder results of dividing two polynomial equations.
// Synopsis: Returns the polynomial quotient and remainder results of dividing two polynomials.
// Topics: Math
// See Also: quadratic_roots(), polynomial(), poly_mult(), poly_div(), poly_add(), poly_roots()
// Usage:
@ -1457,7 +1457,7 @@ function _poly_trim(p,eps=0) =
// Function: poly_add()
// Synopsis: Returns the polynomial sum of adding two polynomial equations.
// Synopsis: Returns the polynomial sum of adding two polynomials.
// Topics: Math
// See Also: quadratic_roots(), polynomial(), poly_mult(), poly_div(), poly_add(), poly_roots()
// Usage:
@ -1475,7 +1475,7 @@ function poly_add(p,q) =
// Function: poly_roots()
// Synopsis: Returns all complex number roots of the given real polynomial.
// Synopsis: Returns all complex valued roots of the given real polynomial.
// Topics: Math, Complex Numbers
// See Also: quadratic_roots(), polynomial(), poly_mult(), poly_div(), poly_add(), poly_roots()
// Usage:
@ -1563,7 +1563,8 @@ function _poly_roots(p, pderiv, s, z, tol, i=0) =
// parts are zero. You can specify eps, in which case the test is
// z.y/(1+norm(z)) < eps. Because
// of poor convergence and higher error for repeated roots, such roots may
// be missed by the algorithm because their imaginary part is large.
// be missed by the algorithm because error can make their imaginary parts
// large enough to appear non-zero.
// Arguments:
// p = polynomial to solve as coefficient list, highest power term first
// eps = used to determine whether imaginary parts of roots are zero

View file

@ -373,7 +373,7 @@ function get_metric_nut_thickness(size) = lookup(size, [
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Extra Anchors:
// Named Anchors:
// "base" = At the base of the head.
// "countersunk" = At the head height that would be just barely exposed when countersunk.
// Examples:
@ -434,7 +434,7 @@ module generic_screw(
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Extra Anchors:
// Named Anchors:
// "base" = At the base of the head.
// "countersunk" = At the head height that would be just barely exposed when countersunk.
// "shank" = At the bottom start of the unthreaded shank.

View file

@ -314,6 +314,8 @@ function force_region(poly) = is_path(poly) ? [poly] : poly;
// spin = Rotate this many degrees after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// cp = Centerpoint for determining intersection anchors or centering the shape. Determintes the base of the anchor vector. Can be "centroid", "mean", "box" or a 2D point. Default: "centroid"
// atype = Set to "hull" or "intersect" to select anchor type. Default: "hull"
// Named Anchors:
// "origin" = The native position of the region.
// Anchor Types:
// "hull" = Anchors to the virtual convex hull of the region.
// "intersect" = Anchors to the outer edge of the region.
@ -1192,6 +1194,8 @@ function _list_three(a,b,c) =
// When called as a function and given a list of regions or 2D polygons,
// returns the union of all given regions and polygons. Result is a single region.
// When called as the built-in module, makes the union of the given children.
// This function is **much** slower than the native union module acting on geometry,
// so you should only use it when you need a point list for further processing.
// Arguments:
// regions = List of regions to union.
// Example(2D):
@ -1227,6 +1231,8 @@ function union(regions=[],b=undef,c=undef,eps=EPSILON) =
// takes the first region or polygon and differences away all other regions/polygons from it. The resulting
// region is returned.
// When called as the built-in module, makes the set difference of the given children.
// This function is **much** slower than the native difference module acting on geometry,
// so you should only use it when you need a point list for further processing.
// Arguments:
// regions = List of regions or polygons to difference.
// Example(2D):
@ -1299,6 +1305,8 @@ function intersection(regions=[],b=undef,c=undef,eps=EPSILON) =
// When called as a module, performs a Boolean exclusive-or of up to 10 children. Note that when
// the input regions cross each other the exclusive-or operator will produce shapes that
// meet at corners (non-simple regions), which do not render in CGAL.
// This function is **much** slower than the native intersection module acting on geometry,
// so you should only use it when you need a point list for further processing.
// Arguments:
// regions = List of regions or polygons to exclusive_or
// Example(2D): As Function. A linear_sweep of this shape fails to render in CGAL.

View file

@ -951,6 +951,11 @@ function _path_join(paths,joint,k=0.5,i=0,result=[],relocate=true,closed=false)
// spin = Rotate this many degrees after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// cp = Centerpoint for determining intersection anchors or centering the shape. Determintes the base of the anchor vector. Can be "centroid", "mean", "box" or a 2D point. Default: "centroid"
// atype = Set to "hull" or "intersect" to select anchor type. Default: "hull"
// Named Anchors:
// "origin" = The native position of the region.
// Anchor Types:
// "hull" = Anchors to the virtual convex hull of the region.
// "intersect" = Anchors to the outer edge of the region.
// Example(2D): Basic examples illustrating flat, round, and pointed ends, on a finely sampled arc and a path made from 3 segments.
// arc = arc(points=[[1,1],[3,4],[6,3]],n=50);
// path = [[0,0],[6,2],[9,7],[8,10]];
@ -1047,7 +1052,7 @@ function _path_join(paths,joint,k=0.5,i=0,result=[],relocate=true,closed=false)
// right(12)
// offset_stroke(path, width=1, closed=true);
function offset_stroke(path, width=1, rounded=true, start, end, check_valid=true, quality=1, chamfer=false, closed=false,
atype="hull", anchor, spin, cp="centroid") =
atype="hull", anchor="origin", spin, cp="centroid") =
let(path = force_path(path))
assert(is_path(path,2),"path is not a 2d path")
let(
@ -1374,7 +1379,7 @@ module offset_stroke(path, width=1, rounded=true, start, end, check_valid=true,
// intersect = Anchors to the surface of the linear sweep of the path, ignoring any end roundings.
// surf_hull = Anchors to the convex hull of the offset_sweep shape, including end treatments.
// surf_intersect = Anchors to the surface of the offset_sweep shape, including any end treatments.
// Extra Anchors:
// Named Anchors:
// "base" = Anchor to the base of the shape in its native position, ignoring any "extra"
// "top" = Anchor to the top of the shape in its native position, ignoring any "extra"
// "zcenter" = Center shape in the Z direction in the native XY position, ignoring any "extra"
@ -2082,6 +2087,11 @@ function _rp_compute_patches(top, bot, rtop, rsides, ktop, ksides, concave) =
// orient = Vector to rotate top towards after spin (module only)
// atype = Select "hull" or "intersect" anchor types. (module only) Default: "hull"
// cp = Centerpoint for determining "intersect" anchors or centering the shape. Determintes the base of the anchor vector. Can be "centroid", "mean", "box" or a 3D point. (module only) Default: "centroid"
// Named Anchors:
// "origin" = The native position of the prism.
// Anchor Types:
// "hull" = Anchors to the virtual convex hull of the prism.
// "intersect" = Anchors to the surface of the prism.
// Example: Uniformly rounded pentagonal prism
// rounded_prism(pentagon(3), height=3,
// joint_top=0.5, joint_bot=0.5, joint_sides=0.5);
@ -2792,7 +2802,7 @@ Access to the derivative smoothing parameter?
// orient = Vector to rotate top towards after spin (module only)
// atype = Select "hull" or "intersect" anchor types. (module only) Default: "hull"
// cp = Centerpoint for determining "intersect" anchors or centering the shape. Determintes the base of the anchor vector. Can be "centroid", "mean", "box" or a 3D point. (module only) Default: "centroid"
// Extra Anchors:
// Named Anchors:
// "root" = Root point of the joiner prism, pointing out in the direction of the prism axis
// "end" = End point of the joiner prism, pointing out in the direction of the prism axis
// Example(3D,NoScales): Here is the simplest case, a circular prism with a specified length standing vertically on a plane.

View file

@ -277,22 +277,22 @@ Torx values: https://www.stanleyengineeredfastening.com/-/media/web/sef/resourc
// shaft = screw shaft
// shank = unthreaded section of shaft (invalid if screw is fully threaded)
// threads = threaded section of screw
// Extra Anchors:
// top = top of screw
// bot = bottom of screw
// center = center of screw
// head_top = top of head (same as top for headless screws)
// head_bot = bottom of head (same as top for headless screws)
// head_center = center of head (same as top for headless screws)
// shaft_top = top of shaft
// shaft_bot = bottom of shaft
// shaft_center = center of shaft
// shank_top = top of shank (invalid if screw is fully threaded)
// shank_bot = bottom of shank (invalid if screw is fully threaded)
// shank_center = center of shank (invalid if screw is fully threaded)
// threads_top = top of threaded portion of screw (invalid if thread_len=0)
// threads_bot = bottom of threaded portion of screw (invalid if thread_len=0)
// threads_center = center of threaded portion of screw (invalid if thread_len=0)
// Named Anchors:
// "top" = top of screw
// "bot" = bottom of screw
// "center" = center of screw
// "head_top" = top of head (same as top for headless screws)
// "head_bot" = bottom of head (same as top for headless screws)
// "head_center" = center of head (same as top for headless screws)
// "shaft_top" = top of shaft
// "shaft_bot" = bottom of shaft
// "shaft_center" = center of shaft
// "shank_top" = top of shank (invalid if screw is fully threaded)
// "shank_bot" = bottom of shank (invalid if screw is fully threaded)
// "shank_center" = center of shank (invalid if screw is fully threaded)
// "threads_top" = top of threaded portion of screw (invalid if thread_len=0)
// "threads_bot" = bottom of threaded portion of screw (invalid if thread_len=0)
// "threads_center" = center of threaded portion of screw (invalid if thread_len=0)
// Example(Med): Selected UTS (English) screws
// $fn=32;
// xdistribute(spacing=8){
@ -803,22 +803,22 @@ module screw(spec, head, drive, thread, drive_size,
// shaft = screw shaft
// shank = unthreaded section of shaft (invalid if screw is fully threaded)
// threads = threaded section of screw
// Extra Anchors:
// top = top of screw
// bot = bottom of screw
// center = center of screw
// head_top = top of head (invalid for headless screws)
// head_bot = bottom of head (invalid for headless screws)
// head_center = center of head (invalid for headless screws)
// shaft_top = top of shaft
// shaft_bot = bottom of shaft
// shaft_center = center of shaft
// shank_top = top of shank (invalid if screw is fully threaded)
// shank_bot = bottom of shank (invalid if screw is fully threaded)
// shank_center = center of shank (invalid if screw is fully threaded)
// threads_top = top of threaded portion of screw (invalid if thread_len=0)
// threads_bot = bottom of threaded portion of screw (invalid if thread_len=0)
// threads_center = center of threaded portion of screw (invalid if thread_len=0)
// Named Anchors:
// "top" = top of screw
// "bot" = bottom of screw
// "center" = center of screw
// "head_top" = top of head (invalid for headless screws)
// "head_bot" = bottom of head (invalid for headless screws)
// "head_center" = center of head (invalid for headless screws)
// "shaft_top" = top of shaft
// "shaft_bot" = bottom of shaft
// "shaft_center" = center of shaft
// "shank_top" = top of shank (invalid if screw is fully threaded)
// "shank_bot" = bottom of shank (invalid if screw is fully threaded)
// "shank_center" = center of shank (invalid if screw is fully threaded)
// "threads_top" = top of threaded portion of screw (invalid if thread_len=0)
// "threads_bot" = bottom of threaded portion of screw (invalid if thread_len=0)
// "threads_center" = center of threaded portion of screw (invalid if thread_len=0)
// Example: Counterbored clearance hole
// diff()
// cuboid(20)
@ -1037,22 +1037,22 @@ module screw_hole(spec, head, thread, oversize, hole_oversize, head_oversize,
// shoulder = the shoulder
// shaft = screw shaft
// threads = threaded section of screw
// Extra Anchors:
// top = top of screw
// bot = bottom of screw
// center = center of screw
// head_top = top of head (invalid for headless screws)
// head_bot = bottom of head (invalid for headless screws)
// head_center = center of head (invalid for headless screws)
// shoulder_top = top of shoulder
// shoulder_bot = bottom of shoulder
// shoulder_center = center of shoulder
// shaft_top = top of shaft
// shaft_bot = bottom of shaft
// shaft_center = center of shaft
// threads_top = top of threaded portion of screw (invalid if thread_len=0)
// threads_bot = bottom of threaded portion of screw (invalid if thread_len=0)
// threads_center = center of threaded portion of screw (invalid if thread_len=0)
// Named Anchors:
// "top" = top of screw
// "bot" = bottom of screw
// "center" = center of screw
// "head_top" = top of head (invalid for headless screws)
// "head_bot" = bottom of head (invalid for headless screws)
// "head_center" = center of head (invalid for headless screws)
// "shoulder_top" = top of shoulder
// "shoulder_bot" = bottom of shoulder
// "shoulder_center" = center of shoulder
// "shaft_top" = top of shaft
// "shaft_bot" = bottom of shaft
// "shaft_center" = center of shaft
// "threads_top" = top of threaded portion of screw (invalid if thread_len=0)
// "threads_bot" = bottom of threaded portion of screw (invalid if thread_len=0)
// "threads_center" = center of threaded portion of screw (invalid if thread_len=0)
// Example: ISO shoulder screw
// shoulder_screw("iso",10,length=20);
// Example: English shoulder screw

View file

@ -549,7 +549,7 @@ function ellipse(r, d, realign=false, circum=false, uniform=false, anchor=CENTER
// align_side = If given as a 2D vector, rotates the whole shape so that the normal of side0 points in that direction. This occurs before spin.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// Extra Anchors:
// Named Anchors:
// "tip0", "tip1", etc. = Each tip has an anchor, pointing outwards.
// "side0", "side1", etc. = The center of each side has an anchor, pointing outwards.
// Example(2D): by Outer Size
@ -691,7 +691,7 @@ module regular_ngon(n=6, r, d, or, od, ir, id, side, rounding=0, realign=false,
// align_side = If given as a 2D vector, rotates the whole shape so that the normal of side0 points in that direction. This occurs before spin.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// Extra Anchors:
// Named Anchors:
// "tip0" ... "tip4" = Each tip has an anchor, pointing outwards.
// "side0" ... "side4" = The center of each side has an anchor, pointing outwards.
// Example(2D): by Outer Size
@ -752,7 +752,7 @@ module pentagon(r, d, or, od, ir, id, side, rounding=0, realign=false, align_tip
// align_side = If given as a 2D vector, rotates the whole shape so that the normal of side0 points in that direction. This occurs before spin.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// Extra Anchors:
// Named Anchors:
// "tip0" ... "tip5" = Each tip has an anchor, pointing outwards.
// "side0" ... "side5" = The center of each side has an anchor, pointing outwards.
// Example(2D): by Outer Size
@ -812,7 +812,7 @@ module hexagon(r, d, or, od, ir, id, side, rounding=0, realign=false, align_tip,
// align_side = If given as a 2D vector, rotates the whole shape so that the normal of side0 points in that direction. This occurs before spin.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// Extra Anchors:
// Named Anchors:
// "tip0" ... "tip7" = Each tip has an anchor, pointing outwards.
// "side0" ... "side7" = The center of each side has an anchor, pointing outwards.
// Example(2D): by Outer Size
@ -863,8 +863,8 @@ module octagon(r, d, or, od, ir, id, side, rounding=0, realign=false, align_tip,
// ---
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// Extra Anchors:
// hypot = Center of angled side, perpendicular to that side.
// Named Anchors:
// "hypot" = Center of angled side, perpendicular to that side.
// Example(2D):
// right_triangle([40,30]);
// Example(2D): With `center=true`
@ -1144,7 +1144,7 @@ module trapezoid(h, w1, w2, ang, shift, chamfer=0, rounding=0, flip=false, ancho
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// atype = Choose "hull" or "intersect" anchor methods. Default: "hull"
// Extra Anchors:
// Named Anchors:
// "tip0" ... "tip4" = Each tip has an anchor, pointing outwards.
// "pit0" ... "pit4" = The inside corner between each tip has an anchor, pointing outwards.
// "midpt0" ... "midpt4" = The center-point between each pair of tips has an anchor, pointing outwards.
@ -1439,7 +1439,7 @@ function teardrop2d(r, ang=45, cap_h, d, circum=false, realign=false, anchor=CEN
// d1 = diameter of the left-hand circle
// d2 = diameter of the right-hand circle
// D = diameter of the joining arcs
// Extra Anchors:
// Named Anchors:
// "left" = center of the left circle
// "right" = center of the right circle
// Example(2D,NoAxes): This first example shows how the egg is constructed from two circles and two joining arcs.
@ -1930,7 +1930,7 @@ function _superformula(theta,m1,m2,n1,n2=1,n3=1,a=1,b=1) =
// d = Diameter of the shape. Scale shape to fit in a circle of diameter d.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// Extra Anchors:
// Named Anchors:
// "tip0", "tip1", etc. = Each tip has an anchor, pointing outwards.
// Examples(2D):
// reuleaux_polygon(n=3, r=50);
@ -2025,7 +2025,7 @@ function reuleaux_polygon(n=3, r, d, anchor=CENTER, spin=0) =
// script = The script the text is in. Default: `"latin"`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `"baseline"`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#subsection-spin). Default: `0`
// Extra Anchors:
// Named Anchors:
// "baseline" = Anchors at the baseline of the text, at the start of the string.
// str("baseline",VECTOR) = Anchors at the baseline of the text, modified by the X and Z components of the appended vector.
// Examples(2D):

View file

@ -1120,10 +1120,10 @@ function rect_tube(
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
//
// Extra Anchors:
// hypot = Center of angled wedge face, perpendicular to that face.
// hypot_left = Left side of angled wedge face, bisecting the angle between the left side and angled faces.
// hypot_right = Right side of angled wedge face, bisecting the angle between the right side and angled faces.
// Named Anchors:
// "hypot" = Center of angled wedge face, perpendicular to that face.
// "hypot_left" = Left side of angled wedge face, bisecting the angle between the left side and angled faces.
// "hypot_right" = Right side of angled wedge face, bisecting the angle between the right side and angled faces.
//
// Example: Centered
// wedge([20, 40, 15], center=true);
@ -2741,10 +2741,10 @@ function torus(
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
//
// Extra Anchors:
// cap = The center of the top of the cap, oriented with the cap face normal.
// cap_fwd = The front edge of the cap.
// cap_back = The back edge of the cap.
// Named Anchors:
// "cap" = The center of the top of the cap, oriented with the cap face normal.
// "cap_fwd" = The front edge of the cap.
// "cap_back" = The back edge of the cap.
//
// Example: Typical Shape
// teardrop(r=30, h=10, ang=30);
@ -2862,9 +2862,9 @@ function teardrop(h, r, ang=45, cap_h, r1, r2, d, d1, d2, cap_h1, cap_h2, chamf
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
//
// Extra Anchors:
// cap = The center of the top of the cap, oriented with the cap face normal.
// tip = The position where an un-capped onion would come to a point, oriented in the direction the point is from the center.
// Named Anchors:
// "cap" = The center of the top of the cap, oriented with the cap face normal.
// "tip" = The position where an un-capped onion would come to a point, oriented in the direction the point is from the center.
//
// Example: Typical Shape
// onion(r=30, ang=30);
@ -3365,10 +3365,12 @@ module fillet(l, r, ang=90, r1, r2, excess=0.01, d1, d2,d,length, h, height, anc
// surface where the height at any given point is the scalar value for that position.
// One script to convert a grayscale image to a heightfield array in a .scad file can be found at:
// https://raw.githubusercontent.com/BelfrySCAD/BOSL2/master/scripts/img2scad.py
// The bottom value defines a planar base for the resulting shape and it must be strictly less than
// the model data to produce valid geometry, so data which is too small is set to 0.1 units above the bottom value.
// Arguments:
// data = This is either the 2D rectangular array of heights, or a function literal that takes X and Y arguments.
// size = The [X,Y] size of the surface to create. If given as a scalar, use it for both X and Y sizes. Default: `[100,100]`
// bottom = The Z coordinate for the bottom of the heightfield object to create. Any heights lower than this will be truncated to very slightly above this height. Default: -20
// bottom = The Z coordinate for the bottom of the heightfield object to create. Any heights lower than this will be truncated to very slightly (0.1) above this height. Default: -20
// maxz = The maximum height to model. Truncates anything taller to this height. Set to INF for no truncation. Default: 100
// xrange = A range of values to iterate X over when calculating a surface from a function literal. Default: [-1 : 0.01 : 1]
// yrange = A range of values to iterate Y over when calculating a surface from a function literal. Default: [-1 : 0.01 : 1]
@ -3437,7 +3439,7 @@ function heightfield(data, size=[100,100], bottom=-20, maxz=100, xrange=[-1:0.04
for (x = [0:1:xcnt-1]) [
size.x * (x/(xcnt-1)-0.5),
size.y * (y/(ycnt-1)-0.5),
min(data[y][x],maxz)
min(max(data[y][x],bottom+0.1),maxz)
]
]
] : [

View file

@ -21,7 +21,7 @@
// Synopsis: Connect a sequence of arbitrary polygons into a 3D object.
// SynTags: VNF, Geom
// Topics: Extrusion, Skin
// See Also: sweep(), linear_sweep(), rotate_sweep(), spiral_sweep(), path_sweep(), offset_sweep()
// See Also: vnf_vertex_array(), sweep(), linear_sweep(), rotate_sweep(), spiral_sweep(), path_sweep(), offset_sweep()
// Usage: As module:
// skin(profiles, slices, [z=], [refine=], [method=], [sampling=], [caps=], [closed=], [style=], [convexity=], [anchor=],[cp=],[spin=],[orient=],[atype=]) [ATTACHMENTS];
// Usage: As function:
@ -163,6 +163,8 @@
// atype = Select "hull" or "intersect" anchor types. Default: "hull"
// cp = Centerpoint for determining "intersect" anchors or centering the shape. Determintes the base of the anchor vector. Can be "centroid", "mean", "box" or a 3D point. Default: "centroid"
// style = vnf_vertex_array style. Default: "min_edge"
// Named Anchors:
// "origin" = The native position of the shape.
// Anchor Types:
// "hull" = Anchors to the virtual convex hull of the shape.
// "intersect" = Anchors to the surface of the shape.
@ -562,7 +564,7 @@ function skin(profiles, slices, refine=1, method="direct", sampling, caps, close
// "hull" = Anchors to the virtual convex hull of the shape.
// "intersect" = Anchors to the surface of the shape.
// "bbox" = Anchors to the bounding box of the extruded shape.
// Extra Anchors:
// Named Anchors:
// "origin" = Centers the extruded shape vertically only, but keeps the original path positions in the X and Y. Oriented UP.
// "original_base" = Keeps the original path positions in the X and Y, but at the bottom of the extrusion. Oriented UP.
// Example: Extruding a Compound Region.
@ -884,6 +886,8 @@ function linear_sweep(
// anchor = Translate so anchor point is at the origin. Default: "origin"
// spin = Rotate this many degrees around Z axis after anchor. Default: 0
// orient = Vector to rotate top towards after spin (module only)
// Named Anchors:
// "origin" = The native position of the shape.
// Anchor Types:
// "hull" = Anchors to the virtual convex hull of the shape.
// "intersect" = Anchors to the surface of the shape.
@ -1492,11 +1496,12 @@ module spiral_sweep(poly, h, r, turns=1, taper, r1, r2, d, d1, d2, internal=fals
// Anchor Types:
// "hull" = Anchors to the virtual convex hull of the shape.
// "intersect" = Anchors to the surface of the shape.
// Extra Anchors:
// start = When `closed==false`, the origin point of the shape, on the starting face of the object
// end = When `closed==false`, the origin point of the shape, on the ending face of the object
// start-centroid = When `closed==false`, the centroid of the shape, on the starting face of the object
// end-centroid = When `closed==false`, the centroid of the shape, on the ending face of the object
// Named Anchors:
// "origin" = The native position of the shape
// "start" = When `closed==false`, the origin point of the shape, on the starting face of the object
// "end" = When `closed==false`, the origin point of the shape, on the ending face of the object
// "start-centroid" = When `closed==false`, the centroid of the shape, on the starting face of the object
// "end-centroid" = When `closed==false`, the centroid of the shape, on the ending face of the object
// Example(NoScales): A simple sweep of a square along a sine wave:
// path = [for(theta=[-180:5:180]) [theta/10, 10*sin(theta)]];
// sq = square(6,center=true);
@ -1800,11 +1805,14 @@ module path_sweep(shape, path, method="incremental", normal, closed, twist=0, tw
assert(in_list(atype, _ANCHOR_TYPES), "Anchor type must be \"hull\" or \"intersect\"");
trans_scale = path_sweep(shape, path, method, normal, closed, twist, twist_by_length, scale, scale_by_length,
symmetry, last_normal, tangent, uniform, relaxed, caps, style, transforms=true,_return_scales=true);
caps = is_def(caps) ? caps :
closed ? false : true;
fullcaps = is_bool(caps) ? [caps,caps] : caps;
transforms = trans_scale[0];
scales = trans_scale[1];
firstscale = is_num(scales[0]) ? 1/scales[0] : [1/scales[0].x, 1/scales[0].y];
lastscale = is_num(last(scales)) ? 1/last(scales) : [1/last(scales).x, 1/last(scales).y];
vnf = sweep(is_path(shape)?clockwise_polygon(shape):shape, transforms, closed=false, caps=caps,style=style);
vnf = sweep(is_path(shape)?clockwise_polygon(shape):shape, transforms, closed=false, caps=fullcaps,style=style);
shapecent = point3d(centroid(shape));
$sweep_transforms = transforms;
$sweep_scales = scales;
@ -2037,6 +2045,8 @@ function path_sweep(shape, path, method="incremental", normal, closed, twist=0,
// orient = Vector to rotate top towards after spin
// atype = Select "hull" or "intersect" anchor types. Default: "hull"
// cp = Centerpoint for determining "intersect" anchors or centering the shape. Determintes the base of the anchor vector. Can be "centroid", "mean", "box" or a 3D point. Default: "centroid"
// Named Anchors:
// "origin" = The native position of the shape.
// Anchor Types:
// "hull" = Anchors to the virtual convex hull of the shape.
// "intersect" = Anchors to the surface of the shape.
@ -2168,6 +2178,8 @@ function _ofs_face_edge(face,firstlen,second=false) =
// anchor = Translate so anchor point is at the origin. Default: "origin"
// spin = Rotate this many degrees around Z axis after anchor. Default: 0
// orient = Vector to rotate top towards after spin (module only)
// Named Anchors:
// "origin" = The native position of the shape.
// Anchor Types:
// "hull" = Anchors to the virtual convex hull of the shape.
// "intersect" = Anchors to the surface of the shape.
@ -3865,10 +3877,10 @@ function texture(tex, n, border, gap, roughness, inset) =
/// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
/// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
/// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
/// Extra Anchors:
/// centroid_top = The centroid of the top of the shape, oriented UP.
/// centroid = The centroid of the center of the shape, oriented UP.
/// centroid_bot = The centroid of the bottom of the shape, oriented DOWN.
/// Named Anchors:
/// "centroid_top" = The centroid of the top of the shape, oriented UP.
/// "centroid" = The centroid of the center of the shape, oriented UP.
/// "centroid_bot" = The centroid of the bottom of the shape, oriented DOWN.
function _get_vnf_tile_edges(texture) =
let(

View file

@ -1063,7 +1063,7 @@ function _slice_3dpolygons(polys, dir, cuts) =
// Anchor Types:
// "hull" = Anchors to the virtual convex hull of the shape.
// "intersect" = Anchors to the surface of the shape.
// Extra Anchors:
// Named Anchors:
// "origin" = Anchor at the origin, oriented UP.
module vnf_polyhedron(vnf, convexity=2, cp="centroid", anchor="origin", spin=0, orient=UP, atype="hull") {
vnf = is_vnf_list(vnf)? vnf_join(vnf) : vnf;

View file

@ -9,6 +9,8 @@
//////////////////////////////////////////////////////////////////////
include<rounding.scad>
// Section: Walls
@ -16,7 +18,7 @@
// Synopsis: Makes an open cross-braced rectangular wall.
// SynTags: Geom
// Topics: FDM Optimized, Walls
// See Also: sparse_wall(), corrugated_wall(), thinning_wall(), thinning_triangle(), narrowing_strut()
// See Also: corrugated_wall(), thinning_wall(), thinning_triangle(), narrowing_strut()
//
// Usage:
// sparse_wall(h, l, thick, [maxang=], [strut=], [max_bridge=]) [ATTACHMENTS];
@ -30,9 +32,9 @@
// l = length of strut wall.
// thick = thickness of strut wall.
// ---
// maxang = maximum overhang angle of cross-braces.
// strut = the width of the cross-braces.
// max_bridge = maximum bridging distance between cross-braces.
// maxang = maximum overhang angle of cross-braces, measured down from vertical. Default: 30
// strut = the width of the cross-braces. Default: 5
// max_bridge = maximum bridging distance between cross-braces. Default: 20
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
@ -129,7 +131,6 @@ module sparse_wall2d(size=[50,100], maxang=30, strut=5, max_bridge=20, anchor=CE
ang = atan(ystep/zstep);
len = zstep / cos(ang);
attachable(anchor,spin, two_d=true, size=size) {
union() {
difference() {
@ -138,8 +139,8 @@ module sparse_wall2d(size=[50,100], maxang=30, strut=5, max_bridge=20, anchor=CE
}
ycopies(ystep, n=yreps) {
xcopies(zstep, n=zreps) {
skew(syx=tan(-ang)) square([(h-strut)/zreps, strut], center=true);
skew(syx=tan( ang)) square([(h-strut)/zreps, strut], center=true);
skew(syx=tan(-ang)) square([(h-strut)/zreps, strut/cos(ang)], center=true);
skew(syx=tan( ang)) square([(h-strut)/zreps, strut/cos(ang)], center=true);
}
}
}
@ -148,6 +149,303 @@ module sparse_wall2d(size=[50,100], maxang=30, strut=5, max_bridge=20, anchor=CE
}
// Module: sparse_cuboid()
// Synopsis: Makes an open cross-braced cuboid
// SynTags: Geom
// Topics: FDM Optimized, Walls
// See Also: sparse_wall(), corrugated_wall(), thinning_wall(), thinning_triangle(), narrowing_strut(), cuboid()
// Usage:
// sparse_cuboid(size, [dir], [maxang=], [struct=]
// Description:
// Makes an open rectangular cuboid with X-shaped cross-bracing to reduce the need for material in 3d printing.
// The direction of the cross bracing can be aligned with the X, Y or Z axis. This module can be
// used as a drop-in replacement for {{cuboid()}} if you belatedly decide that your model would benefit from
// the sparse construction. Note that for Z aligned bracing the max_bridge parameter contrains the gaps that are parallel
// to the Y axis, and the angle is measured relative to the X direction.
// Arguments:
// size = The size of sparse wall, a number or length 3 vector.
// dir = direction of holes through the cuboid, must be a vector parallel to the X, Y or Z axes, or one of "X", "Y" or "Z". Default: "Y"
// ---
// maxang = maximum overhang angle of cross-braces, measured down from vertical. Default: 30
// strut = the width of the cross-braces. Default: 5
// max_bridge = maximum bridging distance between cross-braces. Default: 20
// chamfer = Size of chamfer, inset from sides. Default: No chamfering.
// rounding = Radius of the edge rounding. Default: No rounding.
// edges = Edges to mask. See [Specifying Edges](attachments.scad#section-specifying-edges). Default: all edges.
// except = Edges to explicitly NOT mask. See [Specifying Edges](attachments.scad#section-specifying-edges). Default: No edges.
// trimcorners = If true, rounds or chamfers corners where three chamfered/rounded edges meet. Default: `true`
// teardrop = If given as a number, rounding around the bottom edge of the cuboid won't exceed this many degrees from vertical. If true, the limit angle is 45 degrees. Default: `false`
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards. See [orient](attachments.scad#subsection-orient). Default: `UP`
// Examples:
// sparse_cuboid([10,20,30], strut=1);
// sparse_cuboid([10,20,30], "Y", strut=1);
// sparse_cuboid([10,20,30], UP, strut=1);
// sparse_cuboid(30, FWD, strut=2, rounding=2, $fn=24);
module sparse_cuboid(size, dir=RIGHT, strut=5, maxang=30, max_bridge=20,
chamfer,
rounding,
edges=EDGES_ALL,
except=[],
except_edges,
trimcorners=true,
teardrop=false,
anchor=CENTER, spin=0, orient=UP)
{
size = scalar_vec3(size);
dummy1=assert(in_list(dir,["X","Y","Z"]) || is_vector(dir,3), "dir must be a 3-vector or one of \"X\", \"Y\", or \"Z\"");
count = len([for(d=dir) if (d!=0) d]);
dummy2=assert(is_string(dir) || (count==1 && len(dir)<=3), "vector valued dir must have exactly one non-zero component");
dir = is_string(dir) ? dir
: dir.x ? "X"
: dir.y ? "Y"
: "Z";
attachable(anchor,spin,orient,size=size){
intersection(){
if (dir=="X")
sparse_wall(size.z,size.y,size.x,strut=strut,maxang=maxang, max_bridge=max_bridge);
else if (dir=="Y")
zrot(90)
sparse_wall(size.z,size.x,size.y,strut=strut,maxang=maxang, max_bridge=max_bridge);
else
yrot(90)
sparse_wall(size.x,size.y,size.z,strut=strut,maxang=maxang, max_bridge=max_bridge);
cuboid(size=size, chamfer=chamfer, rounding=rounding,edges=edges, except=except, except_edges=except_edges,
trimcorners=trimcorners, teardrop=teardrop);
}
children();
}
}
// Module: hex_panel()
// Usage:
// hex_panel(shape, wall, spacing, [frame=], [bevel=], [bevel_frame=], [h=|height=|l=|length=], [anchor=], [orient=], [spin=])
// Description:
// Produces a panel with a honeycomb interior. The panel consists of a frame containing
// a honeycob interior. The frame is laid out in the XY plane with the honeycob interior
// and then extruded to the height h. The shape argument defines the outer bounderies of
// the frame.
// .
// The simplest way to define the frame shape is to give a cuboid size as a 3d vector for
// the shape argument. The h argument is not allowed in this case. With rectangular frames you can supply the
// bevel argument which applies a 45 deg bevel on the specified list of edges. These edges
// can be LEFT, RIGHT, FRONT, or BACK to place a bevel the edge facing upward. You can add
// BOTTOM, as in LEFT+BOT, to get a bevel that faces down. When beveling a separate beveled frame
// is added to the model. You can independently control its thickness by setting `bevel_frame`, which
// defaults to the frame thickness. Note also that `frame` and `bevel_frame` can be set to zero
// to produce just the honeycomb.
// .
// The other option is to provide a 2D path as the shape argument. The path must not intersect
// itself. You must give the height argument in this case and you cannot give the bevel argument.
// The panel is made from a linear extrusion of the specified shape. In this case, anchoring
// is done as usual for linear sweeps. The shape appears by default on its base and you can
// choose "hull" or "intersect" anchor types.
// Arguments:
// shape = 3D size vector or a 2D path
// strut = thickness of hexagonal bracing
// spacing = center-to-center spacing of hex cells in the honeycomb.
// --
// frame = width of the frame around the honeycomb. Default: same as strut
// bevel = list of edges to bevel on rectangular case when shape is a size vector; allowed options are RIGHT, LEFT, BACK, or FRONT, or those directions with BOTTOM added. Default: []
// bevel_frame = width of the frame applied at bevels. Default: same as frame
// h / height / l / length = thickness of the panel when shape is a path
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER` for rectangular panels, `"zcenter"` for extrusions.
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
// atype = Select "hull", "intersect" anchor types. Default: "hull"
// cp = Centerpoint for determining "intersect" anchors or centering the shape. Determintes the base of the anchor vector. Can be "centroid", "mean", "box" or a 3D point. Default: "centroid"
// Named Anchors:
// "base" = Anchor to the base of the shape in its native position
// "top" = Anchor to the top of the shape in its native position
// "zcenter" = Center shape in the Z direction in the native XY position (default)
// Anchor Types:
// hull = Anchors to the convex hull of the linear sweep of the path, ignoring any end roundings.
// intersect = Anchors to the surface of the linear sweep of the path, ignoring any end roundings.
// Examples
// hex_panel([50, 100, 5], strut=1.5, spacing=10);
// hex_panel([50, 100, 5], 1.5, 10, frame = 5);
// hex_panel([50, 100, 5], 5, 10.05);
// hex_panel([50, 100, 5], 1.5, 20, frame = 5);
// hex_panel([50, 100, 5], 1.5, 12, frame = 0);
// hex_panel([50, 100, 5], frame = 10, spacing = 20, strut = 4);
// hex_panel([50, 100, 10], 1.5, 10, frame = 5, bevel = [LEFT, RIGHT]);
// hex_panel([50, 100, 10], 1.5, 10, frame = 5, bevel = [FWD, BACK]);
// hex_panel([50, 100, 10], 1.5, 10, frame = 3, bevel = [LEFT, RIGHT, FWD, BACK]);
// hex_panel([50, 100, 10], 1.5, 10, frame = 1, bevel = [LEFT, RIGHT, FWD+BOTTOM, BACK+BOTTOM]);
// hex_panel([50, 100, 10], 1.5, 10, frame=2, bevel_frame=0, bevel = [FWD, BACK+BOT, RIGHT, LEFT]);
// Example: Triangle
// s = [[0, -40], [0, 40], [60, 0]];
// hex_panel(s, strut=1.5, spacing=10, h = 10, frame = 5);
// Example: Concave polygon
// s = [[0, -40], [0, 70], [60, 0], [80, 20], [70, -20]];
// hex_panel(s, 1.5, 10, h = 10, frame = 5);
// Example: Another concave example
// s = [[0, -40], [0, 40], [30, 20], [60, 40], [60, -40], [30, -20]];
// hex_panel(s, 1.5, 10, h = 10, frame = 5);
// Example: Circular panel
// hex_panel(circle(30), 1.5, 10, h = 10, frame = 5);
// Example: More complicated shape
// s = glued_circles(d=50, spread=50, tangent=30);
// hex_panel(s, 1.5, 10, h = 10, frame = 5);
// Example: Care is required when arranging panels vertically for 3d printability. Setting `orient=RIGHT` produces the correct result.
// hex_panel([50, 100, 10], 1.5, 10, frame = 5, bevel = [FWD, BACK], anchor = BACK + RIGHT + BOTTOM, orient = RIGHT);
// zrot(-90)hex_panel([50, 100, 10], 1.5, 10, frame = 5, bevel = [FWD, BACK], anchor = FWD + RIGHT + BOTTOM, orient = RIGHT);
// Example: In this example panels one of the panels is positioned with `orient=FWD` which produces hexagons with 60 deg overhang edges that may not be 3d printable. This example alsu uses `bevel_frame` to thin the material at the corner.
// hex_panel([50, 100, 10], 1.5, 10, frame = 5, bevel_frame=1, bevel = [FWD, BACK], anchor = BACK + RIGHT + BOTTOM, orient = RIGHT);
// hex_panel([100, 50, 10], 1.5, 10, frame = 5, bevel_frame=1, bevel = [LEFT, RIGHT], anchor = FWD + LEFT + BOTTOM, orient = FWD);
// Example: Joining panels with {{attach()}}. In this case panels were joined front beveled edge to back beveled edge, which means the hex structure doesn't align at the joint
// hex_panel([50, 100, 10], 1.5, 10, frame = 5, bevel_frame=0, bevel = [FWD, BACK], anchor = BACK + RIGHT + BOTTOM, orient = RIGHT)
// attach(BACK,FRONT)
// hex_panel([50, 100, 10], 1.5, 10, frame = 5, bevel_frame=0, bevel = [FWD, BACK]);
// Example: Joining panels with {{attach()}}. Attaching BACK to BACK aligns the hex structure which looks better.
// hex_panel([50, 100, 10], 1.5, 10, frame = 1, bevel = [FWD, BACK], anchor = BACK + RIGHT + BOTTOM, orient = RIGHT)
// attach(BACK,BACK)
// hex_panel([50, 100, 10], 1.5, 10, frame = 1, bevel = [FWD, BACK]);
module hex_panel(
shape,
strut,
spacing,
frame,
bevel_frame,
h, height, l, length,
bevel = [],
anchor,
orient = UP, cp="centroid", atype="hull",
spin = 0)
{
frame = first_defined([frame,strut]);
bevel_frame = first_defined([bevel_frame, frame]);
shape = force_path(shape,"shape");
bevel = is_vector(bevel) ? [bevel] : bevel;
bevOK = len([for(bev=bevel) if (norm([bev.x,bev.y])==1 && (bev.x==0 || bev.y==0) && (bev.z==0 || bev.z==-1)) 1]) == len(bevel);
dummy=
assert(is_finite(strut) && strut > 0, "strut must be positive")
assert(is_finite(frame) && frame >= 0, "frame must be nonnegative")
assert(is_finite(bevel_frame) && bevel_frame >= 0, "bevel_frame must be nonnegative")
assert(is_finite(spacing) && spacing>0, "spacing must be positive")
assert(is_path(shape,2) || is_vector(shape, 3), "shape must be a path or a 3D vector")
assert(len(bevel) == 0 || is_vector(shape, 3), "bevel must be used only on rectangular panels")
assert(is_path(shape) || all_positive(shape), "when shape is a size vector all components must be positive")
assert(bevOK, "bevel list contains an invalid entry")
assert(!(in_list(FRONT, bevel) && in_list(FRONT+BOTTOM, bevel)), "conflicting FRONT bevels")
assert(!(in_list(BACK, bevel) && in_list(BACK+BOTTOM, bevel)), "conflicting BACK bevels")
assert(!(in_list(RIGHT, bevel) && in_list(RIGHT+BOTTOM, bevel)), "conflicting RIGHT bevels")
assert(!(in_list(LEFT, bevel) && in_list(LEFT+BOTTOM, bevel)), "conflicting LEFT bevels")
assert(is_undef(h) || is_path(shape), "cannot give h with a size vector");
shp = is_path(shape) ? shape : square([shape.x, shape.y], center = true);
ht = is_path(shape) ? one_defined([h,l,height,length],"height,length,l,h")
: shape.z;
bounds = pointlist_bounds(shp);
sizes = bounds[1] - bounds[0]; // [xsize, ysize]
assert(frame*2 + spacing < sizes[0], "There must be room for at least 1 cell in the honeycomb");
assert(frame*2 + spacing < sizes[1], "There must be room for at least 1 cell in the honeycomb");
bevpaths = len(bevel)==0 ? []
: _bevelSolid(shape,bevel);
if (len(bevel) > 0) {
size1 = [bevpaths[0][0].x-bevpaths[0][1].x, bevpaths[0][2].y-bevpaths[0][1].y,ht];
size2 = [bevpaths[1][0].x-bevpaths[1][1].x, bevpaths[1][2].y-bevpaths[1][1].y];
shift = point2d(centroid(bevpaths[1])-centroid(bevpaths[0]));
offset = (centroid(bevpaths[0]));
attachable(anchor,spin,orient,size=size1,size2=size2,shift=shift,offset=offset){
down(ht/2)
intersection() {
union() {
linear_extrude(height = ht, convexity=8) {
_honeycomb(shp, spacing = spacing, hex_wall = strut);
offset_stroke(shp, width=[-frame, 0], closed=true);
}
for (b = bevel) _bevelWall(shape, b, bevel_frame);
}
vnf_polyhedron(vnf_vertex_array(bevpaths, col_wrap=true, caps=true));
}
children();
}
}
else if (is_vector(shape)){
attachable(anchor = anchor, spin = spin, orient = orient, size = shape) {
down(ht/2)
linear_extrude(height = ht, convexity=8) {
_honeycomb(shp, spacing = spacing, hex_wall = strut);
offset_stroke(shp, width=[-frame, 0], closed=true);
}
children();
}
}
else {
anchors = [
named_anchor("zcenter", [0,0,0], UP),
named_anchor("base", [0,0,-ht/2], UP),
named_anchor("top", [0,0,ht/2], UP)
];
attachable(anchor = default(anchor,"zcenter"), spin = spin, orient = orient, path=shp, h=ht, cp=cp, extent=atype=="hull",anchors=anchors) {
down(ht/2)
linear_extrude(height = ht, convexity=8) {
_honeycomb(shp, spacing = spacing, hex_wall = strut);
offset_stroke(shp, width=[-frame, 0], closed=true);
}
children();
}
}
}
module _honeycomb(shape, spacing=10, hex_wall=1)
{
hex = hexagon(id=spacing-hex_wall, spin=180/6);
bounds = pointlist_bounds(shape);
size = bounds[1] - bounds[0];
hex_rgn2 = grid_copies(spacing=spacing, size=size, stagger=true, p=hex);
center = (bounds[0] + bounds[1]) / 2;
hex_rgn = move(center, p=hex_rgn2);
difference(){
polygon(shape);
region(hex_rgn);
}
}
function _bevelSolid(shape, bevel) =
let(
tX = in_list(RIGHT, bevel) ? -shape.z : 0,
tx = in_list(LEFT, bevel) ? shape.z : 0,
tY = in_list(BACK, bevel) ? -shape.z : 0,
ty = in_list(FRONT, bevel) ? shape.z : 0,
bX = in_list(RIGHT + BOTTOM, bevel) ? -shape.z : 0,
bx = in_list(LEFT + BOTTOM, bevel) ? shape.z : 0,
bY = in_list(BACK + BOTTOM, bevel) ? -shape.z : 0,
by = in_list(FRONT + BOTTOM, bevel) ? shape.z : 0,
pathB = path3d(rect(select(shape,0,1)) + [[bX,by],[bx,by],[bx,bY],[bX,bY]]),
pathT = path3d(rect(select(shape,0,1)) + [[tX,ty],[tx,ty],[tx,tY],[tX,tY]],shape.z)
)
[pathB,pathT];
module _bevelWall(shape, bevel, thickness) {
l = bevel.y != 0 ? shape.x : shape.y;
d = bevel.y != 0 ? shape.y : shape.x;
zr = bevel.y == -1 ? 180
: bevel.y == 1 ? 0
: bevel.x == -1 ? 90
: bevel.x == 1 ? 270
: undef;
xr = bevel.x != 0 && bevel.z < 0 ? 180 : 0;
yr = bevel.y != 0 && bevel.z < 0 ? 180 : 0;
path = [[-thickness, 0], [0, 0], [-shape.z, -shape.z], [-shape.z-thickness, -shape.z]];
up(shape.z/2)
xrot(xr) yrot(yr) zrot(zr) down(shape.z/2)
back(d/2) right(l/2)
zrot(90) xrot(-90)
linear_extrude(l) polygon(path);
}
// Module: corrugated_wall()
// Synopsis: Makes a corrugated rectangular wall.
// SynTags: Geom
@ -166,7 +464,7 @@ module sparse_wall2d(size=[50,100], maxang=30, strut=5, max_bridge=20, anchor=CE
// l = length of strut wall.
// thick = thickness of strut wall.
// ---
// strut = the width of the cross-braces.
// strut = the width of the frame.
// wall = thickness of corrugations.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`