Merge pull request #840 from adrianVmariano/master

usage message fixes
This commit is contained in:
Revar Desmera 2022-04-09 20:35:53 -07:00 committed by GitHub
commit 34873b2915
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 956 additions and 882 deletions

View file

@ -19,7 +19,7 @@ include <rounding.scad>
// Module: pco1810_neck()
// Usage:
// pco1810_neck([wall])
// pco1810_neck([wall]) [ATTACHMENTS];
// Description:
// Creates an approximation of a standard PCO-1810 threaded beverage bottle neck.
// Arguments:
@ -140,7 +140,7 @@ function pco1810_neck(wall=2, anchor="support-ring", spin=0, orient=UP) =
// Module: pco1810_cap()
// Usage:
// pco1810_cap([wall], [texture]);
// pco1810_cap([wall], [texture]) [ATTACHMENTS];
// Description:
// Creates a basic cap for a PCO1810 threaded beverage bottle.
// Arguments:
@ -211,7 +211,7 @@ function pco1810_cap(wall=2, texture="none", anchor=BOTTOM, spin=0, orient=UP) =
// Module: pco1881_neck()
// Usage:
// pco1881_neck([wall])
// pco1881_neck([wall]) [ATTACHMENTS];
// Description:
// Creates an approximation of a standard PCO-1881 threaded beverage bottle neck.
// Arguments:
@ -332,12 +332,13 @@ function pco1881_neck(wall=2, anchor="support-ring", spin=0, orient=UP) =
// Module: pco1881_cap()
// Usage:
// pco1881_cap(wall, [texture]);
// pco1881_cap(wall, [texture]) [ATTACHMENTS];
// Description:
// Creates a basic cap for a PCO1881 threaded beverage bottle.
// Arguments:
// wall = Wall thickness in mm.
// texture = The surface texture of the cap. Valid values are "none", "knurled", or "ribbed". Default: "none"
// ---
// 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`
@ -394,11 +395,12 @@ function pco1881_cap(wall=2, texture="none", anchor=BOTTOM, spin=0, orient=UP) =
// Module: generic_bottle_neck()
// Usage:
// generic_bottle_neck([wall], ...)
// generic_bottle_neck([wall], ...) [ATTACHMENTS];
// Description:
// Creates a bottle neck given specifications.
// Arguments:
// wall = distance between ID and any wall that may be below the support
// ---
// neck_d = Outer diameter of neck without threads
// id = Inner diameter of neck
// thread_od = Outer diameter of thread
@ -406,7 +408,6 @@ function pco1881_cap(wall=2, texture="none", anchor=BOTTOM, spin=0, orient=UP) =
// support_d = Outer diameter of support ring. Set to 0 for no support.
// pitch = Thread pitch
// round_supp = True to round the lower edge of the support ring
// ---
// 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`
@ -519,7 +520,7 @@ function generic_bottle_neck(
// Module: generic_bottle_cap()
// Usage:
// generic_bottle_cap(wall, [texture], ...);
// generic_bottle_cap(wall, [texture], ...) [ATTACHMENTS];
// Description:
// Creates a basic threaded cap given specifications.
// Arguments:
@ -608,7 +609,7 @@ function generic_bottle_cap(
// Module: bottle_adapter_neck_to_cap()
// Usage:
// bottle_adapter_neck_to_cap(wall, [texture]);
// bottle_adapter_neck_to_cap(wall, [texture], ...) [ATTACHMENTS];
// Description:
// Creates a threaded neck to cap adapter
// Arguments:
@ -834,10 +835,11 @@ function bottle_adapter_cap_to_cap(
// Module: bottle_adapter_neck_to_neck()
// Usage:
// bottle_adapter_neck_to_neck();
// bottle_adapter_neck_to_neck(...);
// Description:
// Creates a threaded neck to neck adapter.
// Arguments:
// ---
// d = Distance between bottoms of necks
// neck_od1 = Outer diameter of top neck w/o threads
// neck_id1 = Inner diameter of top neck
@ -868,6 +870,7 @@ module bottle_adapter_neck_to_neck(
support_od2, pitch2,
taper_lead_in = 0, wall
) {
no_children($children);
neck_od2 = (neck_od2 == undef) ? neck_od1 : neck_od2;
neck_id2 = (neck_id2 == undef) ? neck_id1 : neck_id2;
thread_od2 = (thread_od2 == undef) ? thread_od1 : thread_od2;
@ -956,7 +959,7 @@ function bottle_adapter_neck_to_neck(
// Module: sp_neck()
// Usage:
// sp_neck(diam, type, wall|id, [style], [bead], [anchor], [spin], [orient])
// sp_neck(diam, type, wall|id=, [style=], [bead=]) [ATTACHMENTS];
// Description:
// Make a SPI (Society of Plastics Industry) threaded bottle neck. You must
// supply the nominal outer diameter of the threads and the thread type, one of
@ -1150,6 +1153,9 @@ module sp_neck(diam,type,wall,id,style="L",bead=false, anchor, spin, orient)
// true_diam = sp_diameter(diam,type)
// Description:
// Returns the actual base diameter (root of the threads) for a SPI plastic bottle neck given the nominal diameter and type number (400, 410, 415).
// Arguments:
// diam = nominal diameter
// type = closure type number (400, 410 or 415)
function sp_diameter(diam,type) =
let(
table = struct_val(_sp_specs,type)

View file

@ -47,8 +47,8 @@ function approx(a,b,eps=EPSILON) =
// Usage:
// x = all_zero(x, [eps]);
// Description:
// Returns true if the finite number passed to it is approximately zero, to within `eps`.
// If passed a list returns true if all its entries are approximately zero.
// Returns true if its argument is approximately zero, to within `eps`.
// If passed a list returns true if all its entries are approximately equal to zero.
// Otherwise, returns false.
// Arguments:
// x = The value to check.
@ -67,8 +67,8 @@ function all_zero(x, eps=EPSILON) =
// Usage:
// test = all_nonzero(x, [eps]);
// Description:
// Returns true if the finite number passed to it is different from zero by `eps`.
// If passed a list returns true if all the entries of the list are different from zero by `eps`.
// Returns true if its argument is finite and different from zero by `eps`.
// If passed a list returns true if all the entries of the list are finite numbers that are different from zero by `eps`.
// Otherwise, returns false.
// Arguments:
// x = The value to check.
@ -88,8 +88,8 @@ function all_nonzero(x, eps=EPSILON) =
// Usage:
// test = all_positive(x,[eps]);
// Description:
// Returns true if the finite number passed to it is greater than zero.
// If passed a list returns true if all the entries are positive.
// Returns true if the argument is finite and greater than zero, within epsilon tolerance if desired.
// If passed a list returns true if all the entries are finite positive numbers.
// Otherwise, returns false.
// Arguments:
// x = The value to check.
@ -103,7 +103,7 @@ function all_nonzero(x, eps=EPSILON) =
// f = all_positive([3,1,2]); // Returns: true.
// g = all_positive([3,-1,2]); // Returns: false.
function all_positive(x,eps=0) =
is_num(x)? x>eps :
is_finite(x)? x>eps :
is_vector(x) && [for (xx=x) if(xx<=0) 1] == [];
@ -111,8 +111,8 @@ function all_positive(x,eps=0) =
// Usage:
// test = all_negative(x, [eps]);
// Description:
// Returns true if the finite number passed to it is less than zero.
// If passed a list, recursively checks if all items in the list are negative.
// Returns true if the argument is finite and less than zero, within epsilon tolerance if desired.
// If passed a list, returns true if all the elements are finite negative numbers.
// Otherwise, returns false.
// Arguments:
// x = The value to check.
@ -127,7 +127,7 @@ function all_positive(x,eps=0) =
// g = all_negative([3,-1,2]); // Returns: false.
// h = all_negative([-3,-1,-2]); // Returns: true.
function all_negative(x, eps=0) =
is_num(x)? x<-eps :
is_finite(x)? x<-eps :
is_vector(x) && [for (xx=x) if(xx>=-eps) 1] == [];
@ -135,8 +135,8 @@ function all_negative(x, eps=0) =
// Usage:
// all_nonpositive(x, [eps]);
// Description:
// Returns true if the finite number passed to it is less than or equal to zero.
// If passed a list, recursively checks if all items in the list are nonpositive.
// Returns true if its argument is finite and less than or equal to zero.
// If passed a list, returns true if all the elements are finite non-positive numbers.
// Otherwise, returns false.
// Arguments:
// x = The value to check.
@ -160,7 +160,7 @@ function all_nonpositive(x,eps=0) =
// all_nonnegative(x, [eps]);
// Description:
// Returns true if the finite number passed to it is greater than or equal to zero.
// If passed a list, recursively checks if all items in the list are nonnegative.
// If passed a list, returns true if all the elements are finite non-negative numbers.
// Otherwise, returns false.
// Arguments:
// x = The value to check.
@ -196,7 +196,7 @@ function all_equal(vec,eps=0) =
// Function: is_increasing()
// Usage:
// bool = is_increasing(list);
// bool = is_increasing(list, [strict]);
// Topics: List Handling
// See Also: max_index(), min_index(), is_decreasing()
// Description:
@ -205,7 +205,7 @@ function all_equal(vec,eps=0) =
// evaluated character by character.
// Arguments:
// list = list (or string) to check
// strict = set to true to test that list is strictly increasing
// strict = set to true to test that list is strictly increasing. Default: false
// Example:
// a = is_increasing([1,2,3,4]); // Returns: true
// b = is_increasing([1,3,2,4]); // Returns: false
@ -220,7 +220,7 @@ function is_increasing(list,strict=false) =
// Function: is_decreasing()
// Usage:
// bool = is_decreasing(list);
// bool = is_decreasing(list, [strict]);
// Topics: List Handling
// See Also: max_index(), min_index(), is_increasing()
// Description:
@ -229,7 +229,7 @@ function is_increasing(list,strict=false) =
// evaluated character by character.
// Arguments:
// list = list (or string) to check
// strict = set to true to test that list is strictly decreasing
// strict = set to true to test that list is strictly decreasing. Default: false
// Example:
// a = is_decreasing([1,2,3,4]); // Returns: false
// b = is_decreasing([4,2,3,1]); // Returns: false
@ -256,7 +256,7 @@ function _type_num(x) =
// test = compare_vals(a, b);
// Description:
// Compares two values. Lists are compared recursively.
// Returns <0 if a<b. Returns >0 if a>b. Returns 0 if a==b.
// Returns a negative value if a<b. Returns a positive value if a>b. Returns 0 if a==b.
// If types are not the same, then undef < bool < nan < num < str < list < range.
// Arguments:
// a = First value to compare.
@ -274,9 +274,9 @@ function compare_vals(a, b) =
// test = compare_lists(a, b)
// Description:
// Compare contents of two lists using `compare_vals()`.
// Returns <0 if `a`<`b`.
// Returns a negative number if `a`<`b`.
// Returns 0 if `a`==`b`.
// Returns >0 if `a`>`b`.
// Returns a positive number if `a`>`b`.
// Arguments:
// a = First list to compare.
// b = Second list to compare.
@ -312,7 +312,7 @@ function compare_lists(a, b) =
// a = min_index([5,3,9,6,2,7,8,2,1]); // Returns: 8
// b = min_index([5,3,9,6,2,7,8,2,7],all=true); // Returns: [4,7]
function min_index(vals, all=false) =
assert( is_vector(vals) && len(vals)>0 , "Invalid or empty list of numbers.")
assert( is_vector(vals), "Invalid or list of numbers.")
all ? search(min(vals),vals,0) : search(min(vals), vals)[0];
@ -336,11 +336,6 @@ function max_index(vals, all=false) =
all ? search(max(vals),vals,0) : search(max(vals), vals)[0];
// Section: Dealing with duplicate list entries
@ -351,14 +346,20 @@ function max_index(vals, all=false) =
// idx = find_approx(val, list, [start=], [eps=]);
// indices = find_approx(val, list, all=true, [start=], [eps=]);
// Description:
// Finds the first item in `list` that matches `val`, returning the index. Returns `undef` if there is no match.
// Finds the first item in `list` that matches `val` to within `eps` tolerance, returning the index. Returns `undef` if there is no match.
// If `all=true` then returns all the items that agree within `eps` and returns the empty list if no such items exist.
// Arguments:
// val = The value to search for.
// list = The list to search through.
// list = The list to search.
// ---
// start = The index to start searching from. Default: 0
// all = If true, returns a list of all matching item indices.
// eps = The maximum allowed floating point rounding error for numeric comparisons.
// all = If true, returns a list of all matching item indices. Default: false
// eps = The maximum allowed floating point rounding error for numeric comparisons. Default: EPSILON (1e-9)
// Example:
// find_approx(3,[4,5,3.01,2,2.99], eps=0.1); // Returns 2
// find_approx(9,[4,5,3.01,2,2.99], eps=0.1); // Returns undef
// find_approx(3,[4,5,3.01,2,2.99], all=true, eps=0.1); // Returns [2,4]
// find_approx(9,[4,5,3.01,2,2.99], all=true, eps=0.1); // Returns []
function find_approx(val, list, start=0, all=false, eps=EPSILON) =
all ? [for (i=[start:1:len(list)-1]) if (approx(val, list[i], eps=eps)) i]
: __find_approx(val, list, eps=eps, i=start);
@ -373,7 +374,7 @@ function __find_approx(val, list, eps, i=0) =
// Function: deduplicate()
// Usage:
// list = deduplicate(list, [close], [eps]);
// list = deduplicate(list, [closed], [eps]);
// Topics: List Handling
// See Also: deduplicate_indexed()
// Description:
@ -459,7 +460,7 @@ function deduplicate_indexed(list, indices, closed=false, eps=EPSILON) =
// Given a string or a list returns the sorted string or the sorted list with all repeated items removed.
// The sorting order of non homogeneous lists is the function `sort` order.
// Arguments:
// list = The list to uniquify.
// list = The list to process.
// Example:
// sorted = unique([5,2,8,3,1,3,8,7,5]); // Returns: [1,2,3,5,7,8]
// sorted = unique("axdbxxc"); // Returns: "abcdx"
@ -494,7 +495,7 @@ function _unique_sort(l) =
// Function: unique_count()
// Usage:
// counts = unique_count(list);
// sorted_counts = unique_count(list);
// Topics: List Handling
// See Also: shuffle(), sort(), sortidx(), unique()
// Description:
@ -724,7 +725,7 @@ function sort(list, idx=undef) =
// idxs2 = sortidx(lst, idx=0); // Returns: [1,2,0,3]
// idxs3 = sortidx(lst, idx=[1,3]); // Returns: [3,0,2,1]
function sortidx(list, idx=undef) =
assert(is_list(list)||is_string(list), "Invalid input." )
assert(is_list(list)||is_string(list), "Invalid list." )
!is_list(list) || len(list)<=1 ? list :
is_homogeneous(list,1)
? let(
@ -751,26 +752,31 @@ function sortidx(list, idx=undef) =
// Function: group_sort()
// Usage:
// ulist = group_sort(list);
// ulist = group_sort(list,[idx]);
// Topics: List Handling
// See Also: shuffle(), sort(), sortidx(), unique(), unique_count()
// Description:
// Given a list of values, returns the sorted list with all repeated items grouped in a list.
// When the list entries are themselves lists, the sorting may be done based on the `idx` entry
// of those entries, that should be numbers.
// The result is always a list of lists.
// Given a list of numbers, sorts the list into a sequence of lists, where each list contains any repeated values.
// If there are no repeated values the output will be a list of singleton lists.
// If you apply {{flatten()}} to the output, the result will be a simple sorted list.
// .
// When the input is a list of lists, the sorting is done based on index `idx` of the entries in `list`.
// In this case, `list[i][idx]` must be a number for every `i`, and the entries in `list` are grouped
// together in the output if they match at index `idx`. This function can be used to group together
// items that are tagged with the same index.
// Arguments:
// list = The list to sort.
// idx = If given, do the comparison based just on the specified index. Default: zero.
// idx = If input is a list of lists, index to sort on. Default: 0.
// Example:
// sorted = group_sort([5,2,8,3,1,3,8,7,5]); // Returns: [[1],[2],[3,3],[5,5],[7],[8,8]]
// sorted2 = group_sort([[5,"a"],[2,"b"], [5,"c"], [3,"d"], [2,"e"] ], idx=0); // Returns: [[[2,"b"],[2,"e"]], [[5,"a"],[5,"c"]], [[3,"d"]] ]
// // Next example returns: [ [[2,"b"],[2,"e"]], [[3,"d"]], [[5,"a"],[5,"c"]] ]
// sorted2 = group_sort([[5,"a"],[2,"b"], [5,"c"], [3,"d"], [2,"e"] ], idx=0);
function group_sort(list, idx) =
assert(is_list(list), "Input should be a list." )
assert(is_undef(idx) || (is_finite(idx) && idx>=0) , "Invalid index." )
assert(is_undef(idx) || (is_int(idx) && idx>=0) , "Invalid index." )
len(list)<=1 ? [list] :
is_vector(list)? _group_sort(list) :
let( idx = is_undef(idx) ? 0 : idx )
is_vector(list)? assert(is_undef(idx),"Cannot give idx with a vector input") _group_sort(list) :
let( idx = default(idx,0) )
assert( [for(entry=list) if(!is_list(entry) || len(entry)<idx || !is_num(entry[idx]) ) 1]==[],
"Some entry of the list is a list shorter than `idx` or the indexed entry of it is not a number.")
_group_sort_by_index(list,idx);
@ -827,7 +833,7 @@ function group_data(groups, values) =
// k = number of items to return
function list_smallest(list, k) =
assert(is_list(list))
assert(is_finite(k) && k>=0, "k must be nonnegative")
assert(is_int(k) && k>=0, "k must be nonnegative")
let(
v = list[rand_int(0,len(list)-1,1)[0]],
smaller = [for(li=list) if(li<v) li ],

View file

@ -28,8 +28,8 @@
// Function&Module: spur_gear()
// Usage: As a Module
// spur_gear(pitch, teeth, thickness, [shaft_diam=], [hide], [pressure_angle], [clearance], [backlash], [helical], [slices], [interior]);
// spur_gear(mod=, teeth=, thickness=, [shaft_diam=], ...);
// spur_gear(pitch, teeth, thickness, [shaft_diam], [hide=], [pressure_angle=], [clearance=], [backlash=], [helical=], [slices=], [interior=]) [ATTACHMENTS];
// spur_gear(mod=, teeth=, thickness=, [shaft_diam=], ...) [ATTACHMENTS];
// Usage: As a Function
// vnf = spur_gear(pitch, teeth, thickness, [shaft_diam], ...);
// vnf = spur_gear(mod=, teeth=, thickness=, [shaft_diam], ...);
@ -193,9 +193,11 @@ module spur_gear(
// Function&Module: spur_gear2d()
// Usage: As Module
// spur_gear2d(pitch|mod, teeth, [hide], [pressure_angle], [clearance], [backlash], [interior]);
// spur_gear2d(pitch, teeth, [hide=], [pressure_angle=], [clearance=], [backlash=], [interior=]) [ATTACHMENTS];
// spur_gear2d(mod=, teeth=, [hide=], [pressure_angle=], [clearance=], [backlash=], [interior=]) [ATTACHMENTS];
// Usage: As Function
// poly = spur_gear2d(pitch|mod, teeth, [hide], [pressure_angle], [clearance], [backlash], [interior]);
// poly = spur_gear2d(pitch, teeth, [hide=], [pressure_angle=], [clearance=], [backlash=], [interior=]);
// poly = spur_gear2d(mod=, teeth=, [hide=], [pressure_angle=], [clearance=], [backlash=], [interior=]);
// Topics: Gears
// See Also: spur_gear()
// Description:
@ -291,8 +293,8 @@ module spur_gear2d(
// Function&Module: rack()
// Usage: As a Module
// rack(pitch, teeth, thickness, height, [pressure_angle=], [backlash=]);
// rack(mod=, teeth=, thickness=, height=, [pressure_angle=], [backlash]=);
// rack(pitch, teeth, thickness, height, [pressure_angle=], [backlash=]) [ATTACHMENTS];
// rack(mod=, teeth=, thickness=, height=, [pressure_angle=], [backlash]=) [ATTACHMENTS];
// Usage: As a Function
// vnf = rack(pitch, teeth, thickness, height, [pressure_angle=], [backlash=]);
// vnf = rack(mod=, teeth=, thickness=, height=, [pressure_angle=], [backlash=]);
@ -438,10 +440,12 @@ function rack(
// Function&Module: rack2d()
// Usage: As a Function
// path = rack2d(pitch|mod, teeth, height, [pressure_angle], [backlash]);
// Usage: As a Module
// rack2d(pitch|mod, teeth, height, [pressure_angle], [backlash]);
// path = rack2d(pitch, teeth, height, [pressure_angle=], [backlash=]) [ATTACHMENTS];
// path = rack2d(mod=, teeth=, height=, [pressure_angle=], [backlash=]) [ATTACHMENTS];
// Usage: As a Function
// path = rack2d(pitch, teeth, height, [pressure_angle=], [backlash=]);
// path = rack2d(mod=, teeth=, height=, [pressure_angle=], [backlash=]);
// Topics: Gears
// See Also: spur_gear2d()
// Description:
@ -453,6 +457,7 @@ function rack(
// pitch = The circular pitch, or distance between teeth around the pitch circle, in mm.
// teeth = Total number of teeth along the rack
// height = Height of rack in mm, from tooth top to back of rack.
// ---
// pressure_angle = Controls how straight or bulged the tooth sides are. In degrees.
// backlash = Gap between two meshing teeth, in the direction along the circumference of the pitch circle
// mod = The metric module/modulus of the gear.

View file

@ -1358,6 +1358,9 @@ function sphere_line_intersection(r, cp, line, bounded=false, d, eps=EPSILON) =
function polygon_area(poly, signed=false) =
assert(is_path(poly), "Invalid polygon." )
len(poly)<3 ? 0 :
len(poly)==3 ?
let( total= len(poly[0])==2 ? 0.5*cross(poly[2]-poly[0],poly[2]-poly[1]) : 0.5*norm(cross(poly[2]-poly[0],poly[2]-poly[1])))
signed ? total : abs(total) :
len(poly[0])==2
? let( total = sum([for(i=[1:1:len(poly)-2]) cross(poly[i]-poly[0],poly[i+1]-poly[0]) ])/2 )
signed ? total : abs(total)

View file

@ -10,112 +10,11 @@
// Section: Hinges and Snaps
// Module: folding_hinge_mask()
// Usage:
// folding_hinge_mask(l, thick, [layerheight], [foldangle], [hingegap], [anchor], [spin], [orient]);
// Description:
// Creates a mask to be differenced away from a plate to create a foldable hinge.
// Center the mask at the bottom of the plate you want to make a hinge in.
// The mask will leave hinge material two `layerheight`s thick on the bottom of the hinge.
// Arguments:
// l = Length of the hinge in mm.
// thick = Thickness in mm of the material to make the hinge in.
// layerheight = The expected printing layer height in mm.
// foldangle = The interior angle in degrees of the joint to be created with the hinge. Default: 90
// hingegap = Size in mm of the gap at the bottom of the hinge, to make room for folding.
// 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`
// Example:
// folding_hinge_mask(l=100, thick=3, foldangle=60);
module folding_hinge_mask(l, thick, layerheight=0.2, foldangle=90, hingegap=undef, anchor=CENTER, spin=0, orient=UP)
{
hingegap = default(hingegap, layerheight)+2*$slop;
size = [l, hingegap, 2*thick];
size2 = [l, hingegap+2*thick*tan(foldangle/2)];
attachable(anchor,spin,orient, size=size, size2=size2) {
up(layerheight*2) prismoid([l,hingegap], [l, hingegap+2*thick/tan(foldangle/2)], h=thick, anchor=BOT);
children();
}
}
// Module: snap_lock()
// Usage:
// snap_lock(thick, [snaplen], [snapdiam], [layerheight], [foldangle], [hingegap], [anchor], [spin], [orient]);
// Description:
// Creates the central snaplock part.
// Arguments:
// thick = Thickness in mm of the material to make the hinge in.
// snaplen = Length of locking snaps.
// snapdiam = Diameter/width of locking snaps.
// layerheight = The expected printing layer height in mm.
// foldangle = The interior angle in degrees of the joint to be created with the hinge. Default: 90
// hingegap = Size in mm of the gap at the bottom of the hinge, to make room for folding.
// 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`
// Example:
// snap_lock(thick=3, foldangle=60);
module snap_lock(thick, snaplen=5, snapdiam=5, layerheight=0.2, foldangle=90, hingegap=undef, anchor=CENTER, spin=0, orient=UP)
{
hingegap = default(hingegap, layerheight)+2*$slop;
snap_x = (snapdiam/2) / tan(foldangle/2) + (thick-2*layerheight)/tan(foldangle/2) + hingegap/2;
size = [snaplen, snapdiam, 2*thick];
attachable(anchor,spin,orient, size=size) {
back(snap_x) {
cube([snaplen, snapdiam, snapdiam/2+thick], anchor=BOT) {
attach(TOP) xcyl(l=snaplen, d=snapdiam, $fn=16);
attach(TOP) xcopies(snaplen-snapdiam/4/3) xscale(0.333) sphere(d=snapdiam*0.8, $fn=12);
}
}
children();
}
}
// Module: snap_socket()
// Usage:
// snap_socket(thick, [snaplen], [snapdiam], [layerheight], [foldangle], [hingegap], [anchor], [spin], [orient]);
// Description:
// Creates the outside snaplock socketed part.
// Arguments:
// thick = Thickness in mm of the material to make the hinge in.
// snaplen = Length of locking snaps.
// snapdiam = Diameter/width of locking snaps.
// layerheight = The expected printing layer height in mm.
// foldangle = The interior angle in degrees of the joint to be created with the hinge. Default: 90
// hingegap = Size in mm of the gap at the bottom of the hinge, to make room for folding.
// 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`
// Example:
// snap_socket(thick=3, foldangle=60);
module snap_socket(thick, snaplen=5, snapdiam=5, layerheight=0.2, foldangle=90, hingegap=undef, anchor=CENTER, spin=0, orient=UP)
{
hingegap = default(hingegap, layerheight)+2*$slop;
snap_x = (snapdiam/2) / tan(foldangle/2) + (thick-2*layerheight)/tan(foldangle/2) + hingegap/2;
size = [snaplen, snapdiam, 2*thick];
attachable(anchor,spin,orient, size=size) {
fwd(snap_x) {
zrot_copies([0,180], r=snaplen+$slop) {
diff("divot")
cube([snaplen, snapdiam, snapdiam/2+thick], anchor=BOT) {
attach(TOP) xcyl(l=snaplen, d=snapdiam, $fn=16);
attach(TOP) left((snaplen+snapdiam/4/3)/2) xscale(0.333) sphere(d=snapdiam*0.8, $fn=12, $tags="divot");
}
}
}
children();
}
}
// Module: apply_folding_hinges_and_snaps()
// Usage:
// apply_folding_hinges_and_snaps(thick, [foldangle], [hinges], [snaps], [sockets], [snaplen], [snapdiam], [hingegap], [layerheight]) ...
// apply_folding_hinges_and_snaps(thick, [foldangle=], [hinges=], [snaps=], [sockets=], [snaplen=], [snapdiam=], [hingegap=], [layerheight=]) CHILDREN;
// Description:
// Adds snaplocks and removes hinges from children objects at the given positions.
// Adds snaplocks and create hinges in children at the given positions.
// Arguments:
// thick = Thickness in mm of the material to make the hinge in.
// foldangle = The interior angle in degrees of the joint to be created with the hinge. Default: 90
@ -190,4 +89,111 @@ module apply_folding_hinges_and_snaps(thick, foldangle=90, hinges=[], snaps=[],
}
// Module: folding_hinge_mask()
// Usage:
// folding_hinge_mask(l, thick, [layerheight=], [foldangle=], [hingegap=], [anchor=], [spin=], [orient=]) [ATTACHMENTS];
// Description:
// Creates a mask to be differenced away from a plate to create a foldable hinge.
// Center the mask at the bottom of the plate you want to make a hinge in.
// The mask will leave hinge material two `layerheight`s thick on the bottom of the hinge.
// Arguments:
// l = Length of the hinge in mm.
// thick = Thickness in mm of the material to make the hinge in.
// ---
// layerheight = The expected printing layer height in mm.
// foldangle = The interior angle in degrees of the joint to be created with the hinge. Default: 90
// hingegap = Size in mm of the gap at the bottom of the hinge, to make room for folding.
// 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`
// Example:
// folding_hinge_mask(l=100, thick=3, foldangle=60);
module folding_hinge_mask(l, thick, layerheight=0.2, foldangle=90, hingegap=undef, anchor=CENTER, spin=0, orient=UP)
{
hingegap = default(hingegap, layerheight)+2*$slop;
size = [l, hingegap, 2*thick];
size2 = [l, hingegap+2*thick*tan(foldangle/2)];
attachable(anchor,spin,orient, size=size, size2=size2) {
up(layerheight*2) prismoid([l,hingegap], [l, hingegap+2*thick/tan(foldangle/2)], h=thick, anchor=BOT);
children();
}
}
// Module: snap_lock()
// Usage:
// snap_lock(thick, [snaplen=], [snapdiam=], [layerheight=], [foldangle=], [hingegap=], [anchor=], [spin=], [orient=]) [ATTACHMENTS];
// Description:
// Creates the central snaplock part.
// Arguments:
// thick = Thickness in mm of the material to make the hinge in.
// ---
// snaplen = Length of locking snaps.
// snapdiam = Diameter/width of locking snaps.
// layerheight = The expected printing layer height in mm.
// foldangle = The interior angle in degrees of the joint to be created with the hinge. Default: 90
// hingegap = Size in mm of the gap at the bottom of the hinge, to make room for folding.
// 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`
// Example:
// snap_lock(thick=3, foldangle=60);
module snap_lock(thick, snaplen=5, snapdiam=5, layerheight=0.2, foldangle=90, hingegap=undef, anchor=CENTER, spin=0, orient=UP)
{
hingegap = default(hingegap, layerheight)+2*$slop;
snap_x = (snapdiam/2) / tan(foldangle/2) + (thick-2*layerheight)/tan(foldangle/2) + hingegap/2;
size = [snaplen, snapdiam, 2*thick];
attachable(anchor,spin,orient, size=size) {
back(snap_x) {
cube([snaplen, snapdiam, snapdiam/2+thick], anchor=BOT) {
attach(TOP) xcyl(l=snaplen, d=snapdiam, $fn=16);
attach(TOP) xcopies(snaplen-snapdiam/4/3) xscale(0.333) sphere(d=snapdiam*0.8, $fn=12);
}
}
children();
}
}
// Module: snap_socket()
// Usage:
// snap_socket(thick, [snaplen=], [snapdiam=], [layerheight=], [foldangle=], [hingegap=], [anchor=], [spin=], [orient=]) [ATTACHMENTS];
// Description:
// Creates the outside snaplock socketed part.
// Arguments:
// thick = Thickness in mm of the material to make the hinge in.
// ---
// snaplen = Length of locking snaps.
// snapdiam = Diameter/width of locking snaps.
// layerheight = The expected printing layer height in mm.
// foldangle = The interior angle in degrees of the joint to be created with the hinge. Default: 90
// hingegap = Size in mm of the gap at the bottom of the hinge, to make room for folding.
// 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`
// Example:
// snap_socket(thick=3, foldangle=60);
module snap_socket(thick, snaplen=5, snapdiam=5, layerheight=0.2, foldangle=90, hingegap=undef, anchor=CENTER, spin=0, orient=UP)
{
hingegap = default(hingegap, layerheight)+2*$slop;
snap_x = (snapdiam/2) / tan(foldangle/2) + (thick-2*layerheight)/tan(foldangle/2) + hingegap/2;
size = [snaplen, snapdiam, 2*thick];
attachable(anchor,spin,orient, size=size) {
fwd(snap_x) {
zrot_copies([0,180], r=snaplen+$slop) {
diff("divot")
cube([snaplen, snapdiam, snapdiam/2+thick], anchor=BOT) {
attach(TOP) xcyl(l=snaplen, d=snapdiam, $fn=16);
attach(TOP) left((snaplen+snapdiam/4/3)/2) xscale(0.333) sphere(d=snapdiam*0.8, $fn=12, $tags="divot");
}
}
}
children();
}
}
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap

View file

@ -14,22 +14,22 @@
// Module: knurled_cylinder()
// Usage:
// knurled_cylinder(l, r|d, [overage], [count], [profile], [helix]);
// knurled_cylinder(l, r1|d1, r2|d2, [overage], [count], [profile], [helix]);
// knurled_cylinder(l|h|height, r|d=, [count=], [profile=], [helix=]);
// knurled_cylinder(l|h|height, r1=|d1=, r2=|d2=, [count=], [profile=], [helix=]);
// Description:
// Creates a mask to difference from a cylinder to give it a knurled surface.
// Creates a knurled cylinder. The knurling is made from small bumps (pyramids) arranged on the surface.
// The
// Arguments:
// l = The length of the axis of the mask. Default: 10
// overage = Extra backing to the mask. Default: 5
// r = The radius of the cylinder to knurl. Default: 10
// l / h / height = The length/height of the cylinder
// r = The radius of the cylinder to knurl.
// r1 = The radius of the bottom of the conical cylinder to knurl.
// r2 = The radius of the top of the conical cylinder to knurl.
// d = The diameter of the cylinder to knurl.
// d1 = The diameter of the bottom of the conical cylinder to knurl.
// d2 = The diameter of the top of the conical cylinder to knurl.
// count = The number of grooves to have around the surface of the cylinder. Default: 30
// profile = The angle of the bottom of the groove, in degrees. Default 120
// helix = The helical angle of the grooves, in degrees. Default: 30
// count = The number of bumps filling one revolution of the cylinder. Default: 30
// profile = The lower angle between the pyramid-shaped bumps. Smaller angles make the bumps sharper and can lead to bad models if count is small. Default 120
// helix = The helical angle of the bumps, in degrees. Close to zero produces vertical ribbing. Close to 90 degrees produces very thin bumps and is not recommended. Default: 30
// chamfer = The size of the chamfers on the ends of the cylinder. Default: none.
// chamfer1 = The size of the chamfer on the bottom end of the cylinder. Default: none.
// chamfer2 = The size of the chamfer on the top end of the cylinder. Default: none.
@ -48,8 +48,11 @@
// knurled_cylinder(l=30, r=20, count=30, profile=120, helix=30);
// knurled_cylinder(l=30, r=20, count=30, profile=90, helix=30);
// knurled_cylinder(l=30, r=20, count=20, profile=120, helix=30);
// knurled_cylinder(l=30, r=20, count=20, profile=120, helix=0.01);
// knurled_cylinder(l=30, r=20, count=20, profile=140, helix=60);
// knurled_cylinder(l=30, r1=20, r2=12, count=40, profile=90, helix=55);
module knurled_cylinder(
l=20,
l,
r=undef, r1=undef, r2=undef,
d=undef, d1=undef, d2=undef,
count=30, profile=120, helix=30,
@ -57,8 +60,12 @@ module knurled_cylinder(
chamfang=undef, chamfang1=undef, chamfang2=undef,
from_end=false,
rounding=undef, rounding1=undef, rounding2=undef,
anchor=CENTER, spin=0, orient=UP
anchor=CENTER, spin=0, orient=UP,
height, h
) {
assert(is_finite(helix) && helix>0 && helix<90, "Must give helix angle between 0 and 90");
assert(is_finite(profile) && profile>0 && profile<180, "Must give profile between 0 and 180");
l = one_defined([l,h,height],"l,h,height");
r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=10);
r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=10);
inset = r1 * sin(180/count) / tan(profile/2);
@ -73,8 +80,11 @@ module knurled_cylinder(
vertices = concat(
[
for (layer = [0:1:layers], pt=path)
(layer%2)? [pt.x, pt.y, layer*knob_h-layers*knob_h/2] :
rot(180/count, p=[pt.x, pt.y, layer*knob_h-layers*knob_h/2])
let(scale_factor = lerp(1,r2/r1,layer/layers))
scale([scale_factor,scale_factor,1],
(layer%2)? [pt.x, pt.y, layer*knob_h-layers*knob_h/2] :
rot(180/count, p=[pt.x, pt.y, layer*knob_h-layers*knob_h/2])
)
], [
[0,0,-layers*knob_h/2],
[0,0, layers*knob_h/2]
@ -127,22 +137,23 @@ module knurled_cylinder(
// Module: knurled_cylinder_mask()
// Usage:
// knurled_cylinder_mask(l, r|d, [overage], [count], [profile], [helix]);
// knurled_cylinder_mask(l, r1|d1, r2|d2, [overage], [count], [profile], [helix]);
// knurled_cylinder_mask(l|h|height, r|d=, [overage], [count], [profile], [helix]) [ATTACHMENTS];
// knurled_cylinder_mask(l|h|height, r=1|d1=, r2=|d2=, [overage=], [count=], [profile=], [helix=],...) [ATTACHMENTS];
// Description:
// Creates a mask to difference from a cylinder to give it a knurled surface.
// Arguments:
// l = The length of the axis of the mask. Default: 10
// l = The length of the axis of the mask.
// r = The radius of the cylinder to knurl.
// overage = Extra backing to the mask. Default: 5
// r = The radius of the cylinder to knurl. Default: 10
// ---
// r1 = The radius of the bottom of the conical cylinder to knurl.
// r2 = The radius of the top of the conical cylinder to knurl.
// d = The diameter of the cylinder to knurl.
// d1 = The diameter of the bottom of the conical cylinder to knurl.
// d2 = The diameter of the top of the conical cylinder to knurl.
// count = The number of grooves to have around the surface of the cylinder. Default: 30
// profile = The angle of the bottom of the groove, in degrees. Default 120
// helix = The helical angle of the grooves, in degrees. Default: 30
// count = The number of bumps filling one revolution of the cylinder. Default: 30
// profile = The lower angle between the pyramid-shaped bumps. Smaller angles make the bumps sharper and can lead to bad models if count is small. Default 120
// helix = The helical angle of the bumps, in degrees. Close to zero produces vertical ribbing. Close to 90 degrees produces very thin bumps and is not recommended. Default: 30
// 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`
@ -150,18 +161,19 @@ module knurled_cylinder(
// knurled_cylinder_mask(l=30, r=20, overage=5, profile=120, helix=30);
// knurled_cylinder_mask(l=30, r=20, overage=10, profile=120, helix=30);
module knurled_cylinder_mask(
l=10, overage=5,
r=undef, r1=undef, r2=undef,
l, r, overage=5,
r1=undef, r2=undef,
d=undef, d1=undef, d2=undef,
count=30, profile=120, helix=30,
anchor=CENTER, spin=0, orient=UP
anchor=CENTER, spin=0, orient=UP, height,h
) {
l = one_defined([l,h,height],"l,h,height");
r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=10);
r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=10);
attachable(anchor,spin,orient, r1=r1, r2=r2, l=l) {
difference() {
cylinder(r1=r1+overage, r2=r2+overage, h=l, center=true);
knurled_cylinder(r1=r1, r2=r2, l=l+0.01);
knurled_cylinder(r1=r1, r2=r2, l=l+0.01, profile=profile, helix=helix,count=count);
}
children();
}

View file

@ -15,12 +15,10 @@
// Section: 2D Masking Shapes
// Function&Module: mask2d_roundover()
// Usage: As Module
// mask2d_roundover(r|d, [inset], [excess]);
// Usage: With Attachments
// mask2d_roundover(r|d, [inset], [excess]) { attachments }
// Usage: As Module
// path = mask2d_roundover(r|d, [inset], [excess]);
// Usage: As module
// mask2d_roundover(r|d=, [inset], [excess]) [ATTACHMENTS];
// Usage: As function
// path = mask2d_roundover(r|d=, [inset], [excess]);
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable, Masks (2D)
// See Also: corner_profile(), edge_profile(), face_profile()
// Description:
@ -72,12 +70,10 @@ function mask2d_roundover(r, inset=0, excess=0.01, d, anchor=CENTER,spin=0) =
// Function&Module: mask2d_cove()
// Usage: As Module
// mask2d_cove(r|d, [inset], [excess]);
// Usage: With Attachments
// mask2d_cove(r|d, [inset], [excess]) { attachments }
// Usage: As Function
// path = mask2d_cove(r|d, [inset], [excess]);
// Usage: As module
// mask2d_cove(r|d=, [inset], [excess]) [ATTACHMENTS];
// Usage: As function
// path = mask2d_cove(r|d=, [inset], [excess]);
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable, Masks (2D)
// See Also: corner_profile(), edge_profile(), face_profile()
// Description:
@ -130,21 +126,21 @@ function mask2d_cove(r, inset=0, excess=0.01, d, anchor=CENTER,spin=0) =
// Function&Module: mask2d_chamfer()
// Usage: As Module
// mask2d_chamfer(edge, [angle], [inset], [excess]);
// mask2d_chamfer(y, [angle], [inset], [excess]);
// mask2d_chamfer(x, [angle], [inset], [excess]);
// Usage: With Attachments
// mask2d_chamfer(edge, [angle], [inset], [excess]) { attachments }
// mask2d_chamfer(edge, [angle], [inset], [excess]) [ATTACHMENTS];
// mask2d_chamfer(y=, [angle=], [inset=], [excess=]) [ATTACHMENTS];
// mask2d_chamfer(x=, [angle=], [inset=], [excess=]) [ATTACHMENTS];
// Usage: As Function
// path = mask2d_chamfer(edge, [angle], [inset], [excess]);
// path = mask2d_chamfer(y, [angle], [inset], [excess]);
// path = mask2d_chamfer(x, [angle], [inset], [excess]);
// path = mask2d_chamfer(y=, [angle=], [inset=], [excess=]);
// path = mask2d_chamfer(x=, [angle=], [inset=], [excess=]);
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable, Masks (2D)
// See Also: corner_profile(), edge_profile(), face_profile()
// Description:
// Creates a 2D chamfer mask shape that is useful for extruding into a 3D mask for a 90° edge.
// This 2D mask is designed to be differenced away from the edge of a shape that is in the first (X+Y+) quadrant.
// If called as a function, this just returns a 2D path of the outline of the mask shape.
// The edge parameter specifies the length of the chamfer's slanted edge. Alternatively you can give x or y to
// specify the width or height. Only one of x, y, or width is permitted.
// Arguments:
// edge = The length of the edge of the chamfer.
// angle = The angle of the chamfer edge, away from vertical. Default: 45.
@ -177,16 +173,15 @@ module mask2d_chamfer(edge, angle=45, inset=0, excess=0.01, x, y, anchor=CENTER,
}
function mask2d_chamfer(edge, angle=45, inset=0, excess=0.01, x, y, anchor=CENTER,spin=0) =
assert(num_defined([x,y,edge])==1)
assert(is_num(first_defined([x,y,edge])))
let(dummy=one_defined([x,y,edge],["x","y","edge"]))
assert(is_num(angle))
assert(is_undef(excess)||is_num(excess))
assert(is_num(inset)||(is_vector(inset)&&len(inset)==2))
let(
inset = is_list(inset)? inset : [inset,inset],
excess = default(excess,$overlap),
x = !is_undef(x)? x :
!is_undef(y)? adj_ang_to_opp(adj=y,ang=angle) :
x = is_def(x)? x :
is_def(y)? adj_ang_to_opp(adj=y,ang=angle) :
hyp_ang_to_opp(hyp=edge,ang=angle),
y = opp_ang_to_adj(opp=x,ang=angle),
path = [
@ -201,9 +196,7 @@ function mask2d_chamfer(edge, angle=45, inset=0, excess=0.01, x, y, anchor=CENTE
// Function&Module: mask2d_rabbet()
// Usage: As Module
// mask2d_rabbet(size, [excess]);
// Usage: With Attachments
// mask2d_rabbet(size, [excess]) { attachments }
// mask2d_rabbet(size, [excess]) [ATTACHMENTS];
// Usage: As Function
// path = mask2d_rabbet(size, [excess]);
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable, Masks (2D)
@ -252,11 +245,9 @@ function mask2d_rabbet(size, excess=0.01, anchor=CENTER,spin=0) =
// Function&Module: mask2d_dovetail()
// Usage: As Module
// mask2d_dovetail(edge, [angle], [inset], [shelf], [excess], ...);
// mask2d_dovetail(x=, [angle=], [inset=], [shelf=], [excess=], ...);
// mask2d_dovetail(y=, [angle=], [inset=], [shelf=], [excess=], ...);
// Usage: With Attachments
// mask2d_dovetail(edge, [angle], [inset], [shelf], ...) { attachments }
// mask2d_dovetail(edge, [angle], [inset], [shelf], [excess], ...) [ATTACHMENTS];
// mask2d_dovetail(x=, [angle=], [inset=], [shelf=], [excess=], ...) [ATTACHMENTS];
// mask2d_dovetail(y=, [angle=], [inset=], [shelf=], [excess=], ...) [ATTACHMENTS];
// Usage: As Function
// path = mask2d_dovetail(edge, [angle], [inset], [shelf], [excess]);
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable, Masks (2D)
@ -323,11 +314,9 @@ function mask2d_dovetail(edge, angle=30, inset=0, shelf=0, excess=0.01, x, y, an
// Function&Module: mask2d_teardrop()
// Usage: As Module
// mask2d_teardrop(r|d, [angle], [excess]);
// Usage: With Attachments
// mask2d_teardrop(r|d, [angle], [excess]) { attachments }
// mask2d_teardrop(r|d=, [angle], [excess]) [ATTACHMENTS];
// Usage: As Function
// path = mask2d_teardrop(r|d, [angle], [excess]);
// path = mask2d_teardrop(r|d=, [angle], [excess]);
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable, Masks (2D)
// See Also: corner_profile(), edge_profile(), face_profile()
// Description:
@ -379,9 +368,7 @@ module mask2d_teardrop(r, angle=45, excess=0.01, d, anchor=CENTER, spin=0) {
// Function&Module: mask2d_ogee()
// Usage: As Module
// mask2d_ogee(pattern, [excess], ...);
// Usage: With Attachments
// mask2d_ogee(pattern, [excess], ...) { attachments }
// mask2d_ogee(pattern, [excess], ...) [ATTAHCMENTS];
// Usage: As Function
// path = mask2d_ogee(pattern, [excess], ...);
// Topics: Shapes (2D), Paths (2D), Path Generators, Attachable, Masks (2D)

View file

@ -15,7 +15,7 @@
// Module: chamfer_edge_mask()
// Usage:
// chamfer_edge_mask(l, chamfer, [excess]);
// chamfer_edge_mask(l, chamfer, [excess]) [ATTACHMENTS];
// Description:
// Creates a shape that can be used to chamfer a 90 degree edge.
// Difference it from the object to be chamfered. The center of
@ -24,6 +24,7 @@
// l = Length of mask.
// chamfer = Size of chamfer.
// excess = The extra amount to add to the length of the mask so that it differences away from other shapes cleanly. Default: `0.1`
// ---
// 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`
@ -40,6 +41,7 @@
// edge_mask(TOP+RIGHT)
// #chamfer_edge_mask(l=50, chamfer=10);
// }
function chamfer_edge_mask(l=1, chamfer=1, excess=0.1, anchor=CENTER, spin=0, orient=UP) = no_function("chamfer_edge_mask");
module chamfer_edge_mask(l=1, chamfer=1, excess=0.1, anchor=CENTER, spin=0, orient=UP) {
attachable(anchor,spin,orient, size=[chamfer*2, chamfer*2, l]) {
cylinder(r=chamfer, h=l+excess, center=true, $fn=4);
@ -50,7 +52,7 @@ module chamfer_edge_mask(l=1, chamfer=1, excess=0.1, anchor=CENTER, spin=0, orie
// Module: chamfer_corner_mask()
// Usage:
// chamfer_corner_mask(chamfer);
// chamfer_corner_mask(chamfer) [ATTACHMENTS];
// Description:
// Creates a shape that can be used to chamfer a 90 degree corner.
// Difference it from the object to be chamfered. The center of
@ -77,6 +79,7 @@ module chamfer_edge_mask(l=1, chamfer=1, excess=0.1, anchor=CENTER, spin=0, orie
// Example: Anchors
// chamfer_corner_mask(chamfer=20)
// show_anchors();
function chamfer_corner_mask(chamfer=1, anchor=CENTER, spin=0, orient=UP) = no_function("chamfer_corner_mask");
module chamfer_corner_mask(chamfer=1, anchor=CENTER, spin=0, orient=UP) {
octahedron(chamfer*4, anchor=anchor, spin=spin, orient=orient) children();
}
@ -84,7 +87,7 @@ module chamfer_corner_mask(chamfer=1, anchor=CENTER, spin=0, orient=UP) {
// Module: chamfer_cylinder_mask()
// Usage:
// chamfer_cylinder_mask(r|d, chamfer, [ang], [from_end])
// chamfer_cylinder_mask(r|d=, chamfer, [ang], [from_end]) [ATTACHMENTS];
// Description:
// Create a mask that can be used to bevel/chamfer the end of a cylindrical region.
// Difference it from the end of the region to be chamfered. The center of the mask
@ -92,8 +95,9 @@ module chamfer_corner_mask(chamfer=1, anchor=CENTER, spin=0, orient=UP) {
// to be chamfered.
// Arguments:
// r = Radius of cylinder to chamfer.
// chamfer = Size of the edge chamfered, inset from edge.
// ---
// d = Diameter of cylinder to chamfer. Use instead of r.
// chamfer = Size of the edge chamfered, inset from edge. (Default: 0.25)
// ang = Angle of chamfer in degrees from vertical. (Default: 45)
// from_end = If true, chamfer size is measured from end of cylinder. If false, chamfer is measured outset from the radius of the cylinder. (Default: false)
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
@ -110,7 +114,8 @@ module chamfer_corner_mask(chamfer=1, anchor=CENTER, spin=0, orient=UP) {
// up(50) chamfer_cylinder_mask(r=50, chamfer=10);
// }
// Example: Masking by Attachment
module chamfer_cylinder_mask(r, d, chamfer=0.25, ang=45, from_end=false, anchor=CENTER, spin=0, orient=UP)
function chamfer_cylinder_mask(r, chamfer, d, ang=45, from_end=false, anchor=CENTER, spin=0, orient=UP) = no_function("chamfer_cylinder_mask");
module chamfer_cylinder_mask(r, chamfer, d, ang=45, from_end=false, anchor=CENTER, spin=0, orient=UP)
{
r = get_radius(r=r, d=d, dflt=1);
ch = from_end? chamfer : opp_ang_to_adj(chamfer,ang);
@ -129,15 +134,16 @@ module chamfer_cylinder_mask(r, d, chamfer=0.25, ang=45, from_end=false, anchor=
// Module: rounding_edge_mask()
// Usage:
// rounding_edge_mask(l|h, r|d)
// rounding_edge_mask(l|h, r1|d1, r2|d2)
// rounding_edge_mask(l|h, r|d, [excess=]) [ATTACHMENTS];
// rounding_edge_mask(l|h, r1=|d1=, r2=|d2=, [excess=]) [ATTACHMENTS];
// Description:
// Creates a shape that can be used to round a vertical 90 degree edge.
// Difference it from the object to be rounded. The center of the mask
// object should align exactly with the edge to be rounded.
// Arguments:
// l = Length of mask.
// l/h = Length of mask.
// r = Radius of the rounding.
// ---
// r1 = Bottom radius of rounding.
// r2 = Top radius of rounding.
// d = Diameter of the rounding.
@ -172,6 +178,7 @@ module chamfer_cylinder_mask(r, d, chamfer=0.25, ang=45, from_end=false, anchor=
// rounding_edge_mask(l=p.z, r=25);
// }
// }
function rounding_edge_mask(l, r, r1, r2, d, d1, d2, excess=0.1, anchor=CENTER, spin=0, orient=UP, h=undef) = no_function("rounding_edge_mask");
module rounding_edge_mask(l, r, r1, r2, d, d1, d2, excess=0.1, anchor=CENTER, spin=0, orient=UP, h=undef)
{
l = first_defined([l, h, 1]);
@ -203,15 +210,15 @@ module rounding_edge_mask(l, r, r1, r2, d, d1, d2, excess=0.1, anchor=CENTER, sp
// Module: rounding_corner_mask()
// Usage:
// rounding_corner_mask(r|d, [excess=], [style=]);
// rounding_corner_mask(r|d, [excess=], [style=]) [ATTACHMENTS];
// Description:
// Creates a shape that you can use to round 90 degree corners.
// Difference it from the object to be rounded. The center of the mask
// object should align exactly with the corner to be rounded.
// Arguments:
// r = Radius of corner rounding.
// d = Diameter of corner rounding.
// ---
// d = Diameter of corner rounding.
// excess = Extra size for the mask. Defaults: 0.1
// style = The style of the sphere cutout's construction. One of "orig", "aligned", "stagger", "octa", or "icosa". Default: "octa"
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
@ -235,6 +242,7 @@ module rounding_edge_mask(l, r, r1, r2, d, d1, d2, excess=0.1, anchor=CENTER, sp
// corner_mask(TOP)
// #rounding_corner_mask(r=20);
// }
function rounding_corner_mask(r, d, style="octa", excess=0.1, anchor=CENTER, spin=0, orient=UP) = no_function("rounding_corner_mask");
module rounding_corner_mask(r, d, style="octa", excess=0.1, anchor=CENTER, spin=0, orient=UP)
{
r = get_radius(r=r, d=d, dflt=1);
@ -252,8 +260,8 @@ module rounding_corner_mask(r, d, style="octa", excess=0.1, anchor=CENTER, spin=
// Module: rounding_angled_edge_mask()
// Usage:
// rounding_angled_edge_mask(h, r|d, [ang]);
// rounding_angled_edge_mask(h, r1|d1, r2|d2, [ang]);
// rounding_angled_edge_mask(h, r|d=, [ang=]) [ATTACHMENTS];
// rounding_angled_edge_mask(h, r1=|d1=, r2=|d2=, [ang=]) [ATTACHMENTS];
// Description:
// Creates a vertical mask that can be used to round the edge where two face meet, at any arbitrary
// angle. Difference it from the object to be rounded. The center of the mask should align exactly
@ -261,12 +269,13 @@ module rounding_corner_mask(r, d, style="octa", excess=0.1, anchor=CENTER, spin=
// Arguments:
// h = Height of vertical mask.
// r = Radius of the rounding.
// ---
// r1 = Bottom radius of rounding.
// r2 = Top radius of rounding.
// d = Diameter of the rounding.
// d1 = Bottom diameter of rounding.
// d2 = Top diameter of rounding.
// ang = Angle that the planes meet at.
// ang = Angle that the planes meet at. Default: 90
// 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`
@ -280,7 +289,8 @@ module rounding_corner_mask(r, d, style="octa", excess=0.1, anchor=CENTER, spin=
// pie_slice(ang=70, h=50, d=100, center=true);
// #rounding_angled_edge_mask(h=51, r1=10, r2=25, ang=70, $fn=32);
// }
module rounding_angled_edge_mask(h=1.0, r, r1, r2, d, d1, d2, ang=90, anchor=CENTER, spin=0, orient=UP)
function rounding_angled_edge_mask(h, r, r1, r2, d, d1, d2, ang=90, anchor=CENTER, spin=0, orient=UP) = no_function("rounding_angled_edge_mask");
module rounding_angled_edge_mask(h, r, r1, r2, d, d1, d2, ang=90, anchor=CENTER, spin=0, orient=UP)
{
function _mask_shape(r) = [
for (i = [0:1:n]) let (a=90+ang+i*sweep/n) [r*cos(a)+x, r*sin(a)+r],
@ -316,15 +326,16 @@ module rounding_angled_edge_mask(h=1.0, r, r1, r2, d, d1, d2, ang=90, anchor=CEN
// Module: rounding_angled_corner_mask()
// Usage:
// rounding_angled_corner_mask(r|d, ang);
// rounding_angled_corner_mask(r|d=, [ang]) [ATTACHMENTS];
// Description:
// Creates a shape that can be used to round the corner of an angle.
// Difference it from the object to be rounded. The center of the mask
// object should align exactly with the point of the corner to be rounded.
// Arguments:
// r = Radius of the rounding.
// ---
// d = Diameter of the rounding.
// ang = Angle between planes that you need to round the corner of.
// ang = Angle between planes that you need to round the corner of. Default: 90
// 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`
@ -334,6 +345,7 @@ module rounding_angled_edge_mask(h=1.0, r, r1, r2, d, d1, d2, ang=90, anchor=CEN
// pie_slice(ang=ang, h=50, r=200, center=true);
// up(50/2) #rounding_angled_corner_mask(r=20, ang=ang);
// }
function rounding_angled_corner_mask(r, ang=90, d, anchor=CENTER, spin=0, orient=UP) = no_function("rounding_angled_corner_mask");
module rounding_angled_corner_mask(r, ang=90, d, anchor=CENTER, spin=0, orient=UP)
{
r = get_radius(r=r, d=d, dflt=1);
@ -362,16 +374,17 @@ module rounding_angled_corner_mask(r, ang=90, d, anchor=CENTER, spin=0, orient=U
// Module: rounding_cylinder_mask()
// Usage:
// rounding_cylinder_mask(r|d, rounding);
// rounding_cylinder_mask(r|d=, rounding);
// Description:
// Create a mask that can be used to round the end of a cylinder.
// Difference it from the cylinder to be rounded. The center of the
// mask object should align exactly with the center of the end of the
// cylinder to be rounded.
// Arguments:
// r = Radius of cylinder. (Default: 1.0)
// d = Diameter of cylinder. (Default: 1.0)
// rounding = Radius of the edge rounding. (Default: 0.25)
// r = Radius of cylinder.
// rounding = Radius of the edge rounding.
// ---
// d = Diameter of cylinder.
// Example:
// difference() {
// cylinder(r=50, h=50, center=false);
@ -388,8 +401,10 @@ module rounding_angled_corner_mask(r, ang=90, d, anchor=CENTER, spin=0, orient=U
// attach(TOP)
// #rounding_cylinder_mask(d=30, rounding=5, $tags="mask");
// }
module rounding_cylinder_mask(r, rounding=0.25, d)
function rounding_cylinder_mask(r, rounding, d) = no_function("rounding_cylinder_mask");
module rounding_cylinder_mask(r, rounding, d)
{
no_children($children);
r = get_radius(r=r, d=d, dflt=1);
difference() {
cyl(r=r+rounding, l=rounding*2, anchor=CENTER);
@ -401,7 +416,7 @@ module rounding_cylinder_mask(r, rounding=0.25, d)
// Module: rounding_hole_mask()
// Usage:
// rounding_hole_mask(r|d, rounding, [excess]);
// rounding_hole_mask(r|d, rounding, [excess]) [ATTACHMENTS];
// Description:
// Create a mask that can be used to round the edge of a circular hole.
// Difference it from the hole to be rounded. The center of the
@ -410,7 +425,7 @@ module rounding_cylinder_mask(r, rounding=0.25, d)
// Arguments:
// r = Radius of hole.
// d = Diameter of hole to rounding.
// rounding = Radius of the rounding. (Default: 0.25)
// rounding = Radius of the rounding.
// excess = The extra thickness of the mask. Default: `0.1`.
// 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`
@ -429,7 +444,8 @@ module rounding_cylinder_mask(r, rounding=0.25, d)
// cylinder(r=50, h=100.1, center=true);
// up(50) rounding_hole_mask(r=50, rounding=10);
// }
module rounding_hole_mask(r, rounding=0.25, excess=0.1, d, anchor=CENTER, spin=0, orient=UP)
function rounding_hole_mask(r, rounding, excess=0.1, d, anchor=CENTER, spin=0, orient=UP) = no_function("rounding_hole_mask");
module rounding_hole_mask(r, rounding, excess=0.1, d, anchor=CENTER, spin=0, orient=UP)
{
r = get_radius(r=r, d=d, dflt=1);
attachable(anchor,spin,orient, r=r+rounding, l=2*rounding) {
@ -448,7 +464,7 @@ module rounding_hole_mask(r, rounding=0.25, excess=0.1, d, anchor=CENTER, spin=0
// Module: teardrop_edge_mask()
// Usage:
// teardrop_edge_mask(r|d, [angle], [excess]);
// teardrop_edge_mask(r|d=, [angle], [excess]);
// Description:
// Makes an apropriate 3D corner rounding mask that keeps within `angle` degrees of vertical.
// Arguments:
@ -456,9 +472,6 @@ module rounding_hole_mask(r, rounding=0.25, excess=0.1, d, anchor=CENTER, spin=0
// d = Diameter of the mask rounding.
// angle = Maximum angle from vertical. Default: 45
// excess = Excess mask size. Default: 0.1
// 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`
// Example(VPD=50,VPR=[55,0,120]):
// teardrop_edge_mask(l=20, r=10, angle=40);
// Example(VPD=300,VPR=[75,0,25]):
@ -469,7 +482,10 @@ module rounding_hole_mask(r, rounding=0.25, excess=0.1, d, anchor=CENTER, spin=0
// corner_mask(BOT)
// teardrop_corner_mask(r=10, angle=40);
// }
module teardrop_edge_mask(l, r, angle, excess=0.1, d, anchor=CENTER, spin=0, orient=UP) {
function teardrop_edge_mask(l, r, angle, excess=0.1, d) = no_function("teardrop_edge_mask");
module teardrop_edge_mask(l, r, angle, excess=0.1, d)
{
no_children($children);
assert(is_num(l));
assert(is_num(angle));
assert(is_num(excess));
@ -484,17 +500,15 @@ module teardrop_edge_mask(l, r, angle, excess=0.1, d, anchor=CENTER, spin=0, ori
// Module: teardrop_corner_mask()
// Usage:
// teardrop_corner_mask(r|d, [angle], [excess]);
// teardrop_corner_mask(r|d=, [angle], [excess]);
// Description:
// Makes an apropriate 3D corner rounding mask that keeps within `angle` degrees of vertical.
// Arguments:
// r = Radius of the mask rounding.
// d = Diameter of the mask rounding.
// angle = Maximum angle from vertical. Default: 45
// excess = Excess mask size. Default: 0.1
// 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`
// ---
// d = Diameter of the mask rounding.
// Example:
// teardrop_corner_mask(r=20, angle=40);
// Example:
@ -505,7 +519,10 @@ module teardrop_edge_mask(l, r, angle, excess=0.1, d, anchor=CENTER, spin=0, ori
// corner_mask(BOT)
// teardrop_corner_mask(r=10, angle=40);
// }
module teardrop_corner_mask(r, angle, excess=0.1, d, anchor=CENTER, spin=0, orient=UP) {
function teardrop_corner_mask(r, angle, excess=0.1, d) = no_function("teardrop_corner_mask");
module teardrop_corner_mask(r, angle, excess=0.1, d)
{
no_children($children);
assert(is_num(angle));
assert(is_num(excess));
assert(angle>0 && angle<90);

View file

@ -14,11 +14,11 @@
// Module: bounding_box()
// Usage:
// bounding_box() ...
// bounding_box([excess],[planar]) CHILDREN;
// Description:
// Returns the smallest axis-aligned square (or cube) shape that contains all the 2D (or 3D)
// children given. The module children() is supposed to be a 3d shape when planar=false and
// a 2d shape when planar=true otherwise the system will issue a warning of mixing dimension
// children given. The module children() must 3d when planar=false and
// 2d when planar=true, or you will get a warning of mixing dimension
// or scaling by 0.
// Arguments:
// excess = The amount that the bounding box should be larger than needed to bound the children, in each axis.
@ -103,7 +103,7 @@ module bounding_box(excess=0, planar=false) {
// Module: chain_hull()
//
// Usage:
// chain_hull() ...
// chain_hull() CHILDREN;
//
// Description:
// Performs hull operations between consecutive pairs of children,
@ -150,7 +150,7 @@ module chain_hull()
// Module: path_extrude2d()
// Usage:
// path_extrude2d(path, [caps], [closed]) {...}
// path_extrude2d(path, [caps=], [closed=], [s=], [convexity=]) 2D-CHILDREN;
// Description:
// Extrudes 2D children along the given 2D path, with optional rounded endcaps.
// It works by constructing straight sections corresponding to each segment of the path and inserting rounded joints at each corner.
@ -158,6 +158,7 @@ module chain_hull()
// If you set caps to true for asymmetric children then incorrect caps will be generated.
// Arguments:
// path = The 2D path to extrude the geometry along.
// ---
// caps = If true, caps each end of the path with a rounded copy of the children. Children must by symmetric across the Y axis, or results are wrong. Default: false
// closed = If true, connect the starting point of the path to the ending point. Default: false
// convexity = The max number of times a line could pass though a wall. Default: 10
@ -261,13 +262,15 @@ module path_extrude2d(path, caps=false, closed=false, s, convexity=10) {
// Module: cylindrical_extrude()
// Usage:
// cylindrical_extrude(size, ir|id, or|od, [convexity]) ...
// cylindrical_extrude(ir|id=, or|od=, [size=], [convexity=], [spin=], [orient=]) 2D-CHILDREN;
// Description:
// Extrudes all 2D children outwards, curved around a cylindrical shape.
// Extrudes its 2D children outwards, curved around a cylindrical shape. Uses $fn/$fa/$fs to
// control the faceting of the extrusion.
// Arguments:
// or = The outer radius to extrude to.
// od = The outer diameter to extrude to.
// ir = The inner radius to extrude from.
// or = The outer radius to extrude to.
// ---
// od = The outer diameter to extrude to.
// id = The inner diameter to extrude from.
// size = The [X,Y] size of the 2D children to extrude. Default: [1000,1000]
// convexity = The max number of times a line could pass though a wall. Default: 10
@ -282,11 +285,12 @@ module path_extrude2d(path, caps=false, closed=false, s, convexity=10) {
// Example: Orient to the Y Axis.
// cylindrical_extrude(or=40, ir=35, orient=BACK)
// text(text="Hello World!", size=10, halign="center", valign="center");
module cylindrical_extrude(or, ir, od, id, size=1000, convexity=10, spin=0, orient=UP) {
module cylindrical_extrude(ir, or, od, id, size=1000, convexity=10, spin=0, orient=UP) {
assert(is_num(size) || is_vector(size,2));
size = is_num(size)? [size,size] : size;
ir = get_radius(r=ir,d=id);
or = get_radius(r=or,d=od);
assert(all_positive([ir,or]), "Must supply positive inner and outer radius or diameter");
index_r = or;
circumf = 2 * PI * index_r;
width = min(size.x, circumf);
@ -316,11 +320,15 @@ module cylindrical_extrude(or, ir, od, id, size=1000, convexity=10, spin=0, orie
// Module: extrude_from_to()
// Usage:
// extrude_from_to(pt1, pt2, [convexity=], [twist=], [scale=], [slices=]) 2D-CHILDREN;
// Description:
// Extrudes a 2D shape between the 3d points pt1 and pt2. Takes as children a set of 2D shapes to extrude.
// Extrudes the 2D children linearly between the 3d points pt1 and pt2. The origin of the 2D children are placed on
// pt1 and pt2, and oriented perpendicular to the line between the points.
// Arguments:
// pt1 = starting point of extrusion.
// pt2 = ending point of extrusion.
// ---
// convexity = max number of times a line could intersect a wall of the 2D shape being extruded.
// twist = number of degrees to twist the 2D shape over the entire extrusion length.
// scale = scale multiplier for end of extrusion compared the start.
@ -349,8 +357,10 @@ module extrude_from_to(pt1, pt2, convexity, twist, scale, slices) {
// Module: path_extrude()
// Usage: path_extrude(path, [convexity], [clipsize]) 2D-CHILDREN;
// Description:
// Extrudes 2D children along a 3D path. This may be slow.
// Extrudes 2D children along a 3D path. This may be slow and can have problems with twisting.
// See Also: path_sweep()
// Arguments:
// path = Array of points for the bezier path to extrude along.
// convexity = Maximum number of walls a ray can pass through.
@ -407,7 +417,7 @@ module path_extrude(path, convexity=10, clipsize=100) {
// Module: minkowski_difference()
// Usage:
// minkowski_difference() { base_shape(); diff_shape(); ... }
// minkowski_difference() { BASE; DIFF1; DIFF2; ... }
// Description:
// Takes a 3D base shape and one or more 3D diff shapes, carves out the diff shapes from the
// surface of the base shape, in a way complementary to how `minkowski()` unions shapes to the
@ -443,16 +453,16 @@ module minkowski_difference(planar=false) {
// Module: offset3d()
// Usage:
// offset3d(r, [size], [convexity]);
// offset3d(r, [size], [convexity]) CHILDREN;
// Description:
// Expands or contracts the surface of a 3D object by a given amount. This is very, very slow.
// No really, this is unbearably slow. It uses `minkowski()`. Use this as a last resort.
// This is so slow that no example images will be rendered.
// Arguments:
// r = Radius to expand object by. Negative numbers contract the object.
// r = Radius to expand object by. Negative numbers contract the object.
// size = Maximum size of object to be contracted, given as a scalar. Default: 100
// convexity = Max number of times a line could intersect the walls of the object. Default: 10
module offset3d(r=1, size=100, convexity=10) {
module offset3d(r, size=100, convexity=10) {
n = quant(max(8,segs(abs(r))),4);
if (r==0) {
children();
@ -482,10 +492,10 @@ module offset3d(r=1, size=100, convexity=10) {
// Module: round3d()
// Usage:
// round3d(r) ...
// round3d(or) ...
// round3d(ir) ...
// round3d(or, ir) ...
// round3d(r) CHILDREN;
// round3d(or) CHILDREN;
// round3d(ir) CHILDREN;
// round3d(or, ir) CHILDREN;
// Description:
// Rounds arbitrary 3D objects. Giving `r` rounds all concave and convex corners. Giving just `ir`
// rounds just concave corners. Giving just `or` rounds convex corners. Giving both `ir` and `or`

View file

@ -12,6 +12,7 @@
// Section: Phillips Drive
// Module: phillips_mask()
// Usage: phillips_mask(size) [ATTACHMENTS];
// Description:
// Creates a mask for creating a Phillips drive recess given the Phillips size. Each mask can
// be lowered to different depths to create different sizes of recess.
@ -129,7 +130,7 @@ function phillips_diam(size, depth) =
// Module: torx_mask()
// Usage:
// torx_mask(size, l, [center]);
// torx_mask(size, l, [center]) [ATTACHMENTS];
// Description: Creates a torx bit tip.
// Arguments:
// size = Torx size.

File diff suppressed because it is too large Load diff

View file

@ -120,6 +120,10 @@ test_is_decreasing();
module test_find_approx() {
assert(find_approx(1, [2,3,1.05,4,1,2,.99], eps=.1)==2);
assert(find_approx(1, [2,3,1.05,4,1,2,.99], all=true, eps=.1)==[2,4,6]);
assert(find_approx(1, [2,3,4])==undef);
assert(find_approx(1, [2,3,4],all=true)==[]);
assert(find_approx(1, [])==undef);
assert(find_approx(1, [], all=true)==[]);
}
test_find_approx();

View file

@ -768,10 +768,9 @@ module test_polygon_area() {
assert(approx(polygon_area(rot([13,27,75],
p=path3d(circle(r=50,$fn=1000),fill=23)),
signed=true), PI*50*50, eps=0.1));
assert(abs(triangle_area([0,0], [0,10], [10,0]) + 50) < EPSILON);
assert(abs(triangle_area([0,0], [0,10], [0,15])) < EPSILON);
assert(abs(triangle_area([0,0], [10,0], [0,10]) - 50) < EPSILON);
assert(abs(polygon_area([[0,0], [0,10], [10,0]],signed=true) + 50) < EPSILON);
assert(abs(polygon_area([[0,0], [0,10], [0,15]],signed=true)) < EPSILON);
assert(abs(polygon_area([[0,0], [10,0], [0,10]],signed=true) - 50) < EPSILON);
}
*test_polygon_area();

View file

@ -29,6 +29,8 @@ module test_is_vector() {
assert(is_vector([1,1,1],all_nonzero=true) == true);
assert(is_vector([-1,1,1],all_nonzero=true) == true);
assert(is_vector([-1,-1,-1],all_nonzero=true) == true);
assert(!is_vector([3,INF,4]));
assert(!is_vector([3,NAN,4]));
}
test_is_vector();

View file

@ -88,27 +88,6 @@ function law_of_sines(a, A, b, B) =
asin(constrain(b/r, -1, 1));
// Function: triangle_area()
// Usage:
// area = triangle_area(p1,p2,p3);
// Topics: Geometry, Trigonometry, Triangles, Area
// Description:
// Returns the area of a triangle formed between three 2D or 3D vertices.
// Result will be negative if the points are 2D and in clockwise order.
// Arguments:
// p1 = The first vertex of the triangle.
// p2 = The second vertex of the triangle.
// p3 = The third vertex of the triangle.
// Example:
// triangle_area([0,0], [5,10], [10,0]); // Returns -50
// triangle_area([10,0], [5,10], [0,0]); // Returns 50
function triangle_area(p1,p2,p3) =
assert( is_path([p1,p2,p3]), "Invalid points or incompatible dimensions." )
len(p1)==3
? 0.5*norm(cross(p3-p1,p3-p2))
: 0.5*cross(p3-p1,p3-p2);
// Section: 2D Right Triangle Functions
// This is a set of functions to make it easier to perform trig calculations on right triangles.

View file

@ -43,7 +43,7 @@
// is_vector([1,1,1],all_nonzero=false); // Returns true
// is_vector([],zero=false); // Returns false
function is_vector(v, length, zero, all_nonzero=false, eps=EPSILON) =
is_list(v) && len(v)>0 && []==[for(vi=v) if(!is_num(vi)) 0]
is_list(v) && len(v)>0 && []==[for(vi=v) if(!is_finite(vi)) 0]
&& (is_undef(length) || len(v)==length)
&& (is_undef(zero) || ((norm(v) >= eps) == !zero))
&& (!all_nonzero || all_nonzero(v)) ;