mirror of
https://github.com/revarbat/BOSL2.git
synced 2025-01-16 13:50:23 +01:00
Standardize indention on spaces, not tabs.
This commit is contained in:
parent
5fe35de963
commit
53c1e25395
264
affine.scad
264
affine.scad
@ -20,13 +20,13 @@ function ident(n) = [for (i = [0:1:n-1]) [for (j = [0:1:n-1]) (i==j)?1:0]];
|
||||
// Function: affine2d_to_3d()
|
||||
// Description: Takes a 3x3 affine2d matrix and returns its 4x4 affine3d equivalent.
|
||||
function affine2d_to_3d(m) = concat(
|
||||
[for (r = [0:2])
|
||||
concat(
|
||||
[for (c = [0:2]) m[r][c]],
|
||||
[0]
|
||||
)
|
||||
],
|
||||
[[0, 0, 0, 1]]
|
||||
[for (r = [0:2])
|
||||
concat(
|
||||
[for (c = [0:2]) m[r][c]],
|
||||
[0]
|
||||
)
|
||||
],
|
||||
[[0, 0, 0, 1]]
|
||||
);
|
||||
|
||||
|
||||
@ -45,9 +45,9 @@ function affine2d_identity() = ident(3);
|
||||
// Arguments:
|
||||
// v = 2D Offset to translate by. [X,Y]
|
||||
function affine2d_translate(v) = [
|
||||
[1, 0, v.x],
|
||||
[0, 1, v.y],
|
||||
[0 ,0, 1]
|
||||
[1, 0, v.x],
|
||||
[0, 1, v.y],
|
||||
[0 ,0, 1]
|
||||
];
|
||||
|
||||
|
||||
@ -57,9 +57,9 @@ function affine2d_translate(v) = [
|
||||
// Arguments:
|
||||
// v = 2D vector of scaling factors. [X,Y]
|
||||
function affine2d_scale(v) = [
|
||||
[v.x, 0, 0],
|
||||
[ 0, v.y, 0],
|
||||
[ 0, 0, 1]
|
||||
[v.x, 0, 0],
|
||||
[ 0, v.y, 0],
|
||||
[ 0, 0, 1]
|
||||
];
|
||||
|
||||
|
||||
@ -69,9 +69,9 @@ function affine2d_scale(v) = [
|
||||
// Arguments:
|
||||
// ang = Number of degrees to rotate.
|
||||
function affine2d_zrot(ang) = [
|
||||
[cos(ang), -sin(ang), 0],
|
||||
[sin(ang), cos(ang), 0],
|
||||
[ 0, 0, 1]
|
||||
[cos(ang), -sin(ang), 0],
|
||||
[sin(ang), cos(ang), 0],
|
||||
[ 0, 0, 1]
|
||||
];
|
||||
|
||||
|
||||
@ -83,12 +83,12 @@ function affine2d_zrot(ang) = [
|
||||
// Arguments:
|
||||
// v = The normal vector of the line to reflect across.
|
||||
function affine2d_mirror(v) =
|
||||
let(v=unit(point2d(v)), a=v.x, b=v.y)
|
||||
[
|
||||
[1-2*a*a, 0-2*a*b, 0],
|
||||
[0-2*a*b, 1-2*b*b, 0],
|
||||
[ 0, 0, 1]
|
||||
];
|
||||
let(v=unit(point2d(v)), a=v.x, b=v.y)
|
||||
[
|
||||
[1-2*a*a, 0-2*a*b, 0],
|
||||
[0-2*a*b, 1-2*b*b, 0],
|
||||
[ 0, 0, 1]
|
||||
];
|
||||
|
||||
|
||||
// Function: affine2d_skew()
|
||||
@ -100,9 +100,9 @@ function affine2d_mirror(v) =
|
||||
// xa = Skew angle, in degrees, in the direction of the X axis.
|
||||
// ya = Skew angle, in degrees, in the direction of the Y axis.
|
||||
function affine2d_skew(xa, ya) = [
|
||||
[1, tan(xa), 0],
|
||||
[tan(ya), 1, 0],
|
||||
[0, 0, 1]
|
||||
[1, tan(xa), 0],
|
||||
[tan(ya), 1, 0],
|
||||
[0, 0, 1]
|
||||
];
|
||||
|
||||
|
||||
@ -114,8 +114,8 @@ function affine2d_skew(xa, ya) = [
|
||||
// Arguments:
|
||||
// affines = A list of 3x3 affine2d matrices.
|
||||
function affine2d_chain(affines, _m=undef, _i=0) =
|
||||
(_i>=len(affines))? (is_undef(_m)? ident(3) : _m) :
|
||||
affine2d_chain(affines, _m=(is_undef(_m)? affines[_i] : affines[_i] * _m), _i=_i+1);
|
||||
(_i>=len(affines))? (is_undef(_m)? ident(3) : _m) :
|
||||
affine2d_chain(affines, _m=(is_undef(_m)? affines[_i] : affines[_i] * _m), _i=_i+1);
|
||||
|
||||
|
||||
|
||||
@ -133,10 +133,10 @@ function affine3d_identity() = ident(4);
|
||||
// Arguments:
|
||||
// v = 3D offset to translate by. [X,Y,Z]
|
||||
function affine3d_translate(v) = [
|
||||
[1, 0, 0, v.x],
|
||||
[0, 1, 0, v.y],
|
||||
[0, 0, 1, v.z],
|
||||
[0 ,0, 0, 1]
|
||||
[1, 0, 0, v.x],
|
||||
[0, 1, 0, v.y],
|
||||
[0, 0, 1, v.z],
|
||||
[0 ,0, 0, 1]
|
||||
];
|
||||
|
||||
|
||||
@ -146,10 +146,10 @@ function affine3d_translate(v) = [
|
||||
// Arguments:
|
||||
// v = 3D vector of scaling factors. [X,Y,Z]
|
||||
function affine3d_scale(v) = [
|
||||
[v.x, 0, 0, 0],
|
||||
[ 0, v.y, 0, 0],
|
||||
[ 0, 0, v.z, 0],
|
||||
[ 0, 0, 0, 1]
|
||||
[v.x, 0, 0, 0],
|
||||
[ 0, v.y, 0, 0],
|
||||
[ 0, 0, v.z, 0],
|
||||
[ 0, 0, 0, 1]
|
||||
];
|
||||
|
||||
|
||||
@ -159,10 +159,10 @@ function affine3d_scale(v) = [
|
||||
// Arguments:
|
||||
// ang = number of degrees to rotate.
|
||||
function affine3d_xrot(ang) = [
|
||||
[1, 0, 0, 0],
|
||||
[0, cos(ang), -sin(ang), 0],
|
||||
[0, sin(ang), cos(ang), 0],
|
||||
[0, 0, 0, 1]
|
||||
[1, 0, 0, 0],
|
||||
[0, cos(ang), -sin(ang), 0],
|
||||
[0, sin(ang), cos(ang), 0],
|
||||
[0, 0, 0, 1]
|
||||
];
|
||||
|
||||
|
||||
@ -172,10 +172,10 @@ function affine3d_xrot(ang) = [
|
||||
// Arguments:
|
||||
// ang = Number of degrees to rotate.
|
||||
function affine3d_yrot(ang) = [
|
||||
[ cos(ang), 0, sin(ang), 0],
|
||||
[ 0, 1, 0, 0],
|
||||
[-sin(ang), 0, cos(ang), 0],
|
||||
[ 0, 0, 0, 1]
|
||||
[ cos(ang), 0, sin(ang), 0],
|
||||
[ 0, 1, 0, 0],
|
||||
[-sin(ang), 0, cos(ang), 0],
|
||||
[ 0, 0, 0, 1]
|
||||
];
|
||||
|
||||
|
||||
@ -187,10 +187,10 @@ function affine3d_yrot(ang) = [
|
||||
// Arguments:
|
||||
// ang = number of degrees to rotate.
|
||||
function affine3d_zrot(ang) = [
|
||||
[cos(ang), -sin(ang), 0, 0],
|
||||
[sin(ang), cos(ang), 0, 0],
|
||||
[ 0, 0, 1, 0],
|
||||
[ 0, 0, 0, 1]
|
||||
[cos(ang), -sin(ang), 0, 0],
|
||||
[sin(ang), cos(ang), 0, 0],
|
||||
[ 0, 0, 1, 0],
|
||||
[ 0, 0, 0, 1]
|
||||
];
|
||||
|
||||
|
||||
@ -203,18 +203,18 @@ function affine3d_zrot(ang) = [
|
||||
// u = 3D axis vector to rotate around.
|
||||
// ang = number of degrees to rotate.
|
||||
function affine3d_rot_by_axis(u, ang) =
|
||||
approx(ang,0)? affine3d_identity() :
|
||||
let(
|
||||
u = unit(u),
|
||||
c = cos(ang),
|
||||
c2 = 1-c,
|
||||
s = sin(ang)
|
||||
) [
|
||||
[u.x*u.x*c2+c , u.x*u.y*c2-u.z*s, u.x*u.z*c2+u.y*s, 0],
|
||||
[u.y*u.x*c2+u.z*s, u.y*u.y*c2+c , u.y*u.z*c2-u.x*s, 0],
|
||||
[u.z*u.x*c2-u.y*s, u.z*u.y*c2+u.x*s, u.z*u.z*c2+c , 0],
|
||||
[ 0, 0, 0, 1]
|
||||
];
|
||||
approx(ang,0)? affine3d_identity() :
|
||||
let(
|
||||
u = unit(u),
|
||||
c = cos(ang),
|
||||
c2 = 1-c,
|
||||
s = sin(ang)
|
||||
) [
|
||||
[u.x*u.x*c2+c , u.x*u.y*c2-u.z*s, u.x*u.z*c2+u.y*s, 0],
|
||||
[u.y*u.x*c2+u.z*s, u.y*u.y*c2+c , u.y*u.z*c2-u.x*s, 0],
|
||||
[u.z*u.x*c2-u.y*s, u.z*u.y*c2+u.x*s, u.z*u.z*c2+c , 0],
|
||||
[ 0, 0, 0, 1]
|
||||
];
|
||||
|
||||
|
||||
// Function: affine3d_rot_from_to()
|
||||
@ -226,22 +226,22 @@ function affine3d_rot_by_axis(u, ang) =
|
||||
// from = 3D axis vector to rotate from.
|
||||
// to = 3D axis vector to rotate to.
|
||||
function affine3d_rot_from_to(from, to) =
|
||||
let(
|
||||
from = unit(point3d(from)),
|
||||
to = unit(point3d(to))
|
||||
) approx(from,to)? affine3d_identity() :
|
||||
let(
|
||||
u = vector_axis(from,to),
|
||||
ang = vector_angle(from,to),
|
||||
c = cos(ang),
|
||||
c2 = 1-c,
|
||||
s = sin(ang)
|
||||
) [
|
||||
[u.x*u.x*c2+c , u.x*u.y*c2-u.z*s, u.x*u.z*c2+u.y*s, 0],
|
||||
[u.y*u.x*c2+u.z*s, u.y*u.y*c2+c , u.y*u.z*c2-u.x*s, 0],
|
||||
[u.z*u.x*c2-u.y*s, u.z*u.y*c2+u.x*s, u.z*u.z*c2+c , 0],
|
||||
[ 0, 0, 0, 1]
|
||||
];
|
||||
let(
|
||||
from = unit(point3d(from)),
|
||||
to = unit(point3d(to))
|
||||
) approx(from,to)? affine3d_identity() :
|
||||
let(
|
||||
u = vector_axis(from,to),
|
||||
ang = vector_angle(from,to),
|
||||
c = cos(ang),
|
||||
c2 = 1-c,
|
||||
s = sin(ang)
|
||||
) [
|
||||
[u.x*u.x*c2+c , u.x*u.y*c2-u.z*s, u.x*u.z*c2+u.y*s, 0],
|
||||
[u.y*u.x*c2+u.z*s, u.y*u.y*c2+c , u.y*u.z*c2-u.x*s, 0],
|
||||
[u.z*u.x*c2-u.y*s, u.z*u.y*c2+u.x*s, u.z*u.z*c2+c , 0],
|
||||
[ 0, 0, 0, 1]
|
||||
];
|
||||
|
||||
|
||||
// Function: affine_frame_map()
|
||||
@ -266,35 +266,35 @@ function affine3d_rot_from_to(from, to) =
|
||||
// // The next map sends [1,1,0] to [0,1,1] and [-1,1,0] to [0,-1,1]
|
||||
// T = affine_frame_map(x=[0,1,1], y=[0,-1,1]) * affine_frame_map(x=[1,1,0], y=[-1,1,0],reverse=true);
|
||||
function affine_frame_map(x,y,z, reverse=false) =
|
||||
assert(num_defined([x,y,z])>=2, "Must define at least two inputs")
|
||||
let(
|
||||
xvalid = is_undef(x) || (is_vector(x) && len(x)==3),
|
||||
yvalid = is_undef(y) || (is_vector(y) && len(y)==3),
|
||||
zvalid = is_undef(z) || (is_vector(z) && len(z)==3)
|
||||
)
|
||||
assert(xvalid,"Input x must be a length 3 vector")
|
||||
assert(yvalid,"Input y must be a length 3 vector")
|
||||
assert(zvalid,"Input z must be a length 3 vector")
|
||||
let(
|
||||
x = is_undef(x)? undef : unit(x),
|
||||
y = is_undef(y)? undef : unit(y),
|
||||
z = is_undef(z)? undef : unit(z),
|
||||
map = is_undef(x)? [cross(y,z), y, z] :
|
||||
is_undef(y)? [x, cross(z,x), z] :
|
||||
is_undef(z)? [x, y, cross(x,y)] :
|
||||
[x, y, z]
|
||||
)
|
||||
reverse? (
|
||||
let(
|
||||
ocheck = (
|
||||
approx(map[0]*map[1],0) &&
|
||||
approx(map[0]*map[2],0) &&
|
||||
approx(map[1]*map[2],0)
|
||||
)
|
||||
)
|
||||
assert(ocheck, "Inputs must be orthogonal when reverse==true")
|
||||
affine2d_to_3d(map)
|
||||
) : affine2d_to_3d(transpose(map));
|
||||
assert(num_defined([x,y,z])>=2, "Must define at least two inputs")
|
||||
let(
|
||||
xvalid = is_undef(x) || (is_vector(x) && len(x)==3),
|
||||
yvalid = is_undef(y) || (is_vector(y) && len(y)==3),
|
||||
zvalid = is_undef(z) || (is_vector(z) && len(z)==3)
|
||||
)
|
||||
assert(xvalid,"Input x must be a length 3 vector")
|
||||
assert(yvalid,"Input y must be a length 3 vector")
|
||||
assert(zvalid,"Input z must be a length 3 vector")
|
||||
let(
|
||||
x = is_undef(x)? undef : unit(x),
|
||||
y = is_undef(y)? undef : unit(y),
|
||||
z = is_undef(z)? undef : unit(z),
|
||||
map = is_undef(x)? [cross(y,z), y, z] :
|
||||
is_undef(y)? [x, cross(z,x), z] :
|
||||
is_undef(z)? [x, y, cross(x,y)] :
|
||||
[x, y, z]
|
||||
)
|
||||
reverse? (
|
||||
let(
|
||||
ocheck = (
|
||||
approx(map[0]*map[1],0) &&
|
||||
approx(map[0]*map[2],0) &&
|
||||
approx(map[1]*map[2],0)
|
||||
)
|
||||
)
|
||||
assert(ocheck, "Inputs must be orthogonal when reverse==true")
|
||||
affine2d_to_3d(map)
|
||||
) : affine2d_to_3d(transpose(map));
|
||||
|
||||
|
||||
|
||||
@ -306,15 +306,15 @@ function affine_frame_map(x,y,z, reverse=false) =
|
||||
// Arguments:
|
||||
// v = The normal vector of the plane to reflect across.
|
||||
function affine3d_mirror(v) =
|
||||
let(
|
||||
v=unit(point3d(v)),
|
||||
a=v.x, b=v.y, c=v.z
|
||||
) [
|
||||
[1-2*a*a, -2*a*b, -2*a*c, 0],
|
||||
[ -2*b*a, 1-2*b*b, -2*b*c, 0],
|
||||
[ -2*c*a, -2*c*b, 1-2*c*c, 0],
|
||||
[ 0, 0, 0, 1]
|
||||
];
|
||||
let(
|
||||
v=unit(point3d(v)),
|
||||
a=v.x, b=v.y, c=v.z
|
||||
) [
|
||||
[1-2*a*a, -2*a*b, -2*a*c, 0],
|
||||
[ -2*b*a, 1-2*b*b, -2*b*c, 0],
|
||||
[ -2*c*a, -2*c*b, 1-2*c*c, 0],
|
||||
[ 0, 0, 0, 1]
|
||||
];
|
||||
|
||||
|
||||
// Function: affine3d_skew()
|
||||
@ -330,10 +330,10 @@ function affine3d_mirror(v) =
|
||||
// szx = Skew factor multiplier for skewing along the Z axis as you get farther from the X axis. Default: 0
|
||||
// szy = Skew factor multiplier for skewing along the Z axis as you get farther from the Y axis. Default: 0
|
||||
function affine3d_skew(sxy=0, sxz=0, syx=0, syz=0, szx=0, szy=0) = [
|
||||
[ 1, sxy, sxz, 0],
|
||||
[syx, 1, syz, 0],
|
||||
[szx, szy, 1, 0],
|
||||
[ 0, 0, 0, 1]
|
||||
[ 1, sxy, sxz, 0],
|
||||
[syx, 1, syz, 0],
|
||||
[szx, szy, 1, 0],
|
||||
[ 0, 0, 0, 1]
|
||||
];
|
||||
|
||||
|
||||
@ -346,10 +346,10 @@ function affine3d_skew(sxy=0, sxz=0, syx=0, syz=0, szx=0, szy=0) = [
|
||||
// xa = Skew angle, in degrees, in the direction of the X axis.
|
||||
// ya = Skew angle, in degrees, in the direction of the Y axis.
|
||||
function affine3d_skew_xy(xa, ya) = [
|
||||
[1, 0, tan(xa), 0],
|
||||
[0, 1, tan(ya), 0],
|
||||
[0, 0, 1, 0],
|
||||
[0, 0, 0, 1]
|
||||
[1, 0, tan(xa), 0],
|
||||
[0, 1, tan(ya), 0],
|
||||
[0, 0, 1, 0],
|
||||
[0, 0, 0, 1]
|
||||
];
|
||||
|
||||
|
||||
@ -362,10 +362,10 @@ function affine3d_skew_xy(xa, ya) = [
|
||||
// xa = Skew angle, in degrees, in the direction of the X axis.
|
||||
// za = Skew angle, in degrees, in the direction of the Z axis.
|
||||
function affine3d_skew_xz(xa, za) = [
|
||||
[1, tan(xa), 0, 0],
|
||||
[0, 1, 0, 0],
|
||||
[0, tan(za), 1, 0],
|
||||
[0, 0, 0, 1]
|
||||
[1, tan(xa), 0, 0],
|
||||
[0, 1, 0, 0],
|
||||
[0, tan(za), 1, 0],
|
||||
[0, 0, 0, 1]
|
||||
];
|
||||
|
||||
|
||||
@ -378,10 +378,10 @@ function affine3d_skew_xz(xa, za) = [
|
||||
// ya = Skew angle, in degrees, in the direction of the Y axis.
|
||||
// za = Skew angle, in degrees, in the direction of the Z axis.
|
||||
function affine3d_skew_yz(ya, za) = [
|
||||
[ 1, 0, 0, 0],
|
||||
[tan(ya), 1, 0, 0],
|
||||
[tan(za), 0, 1, 0],
|
||||
[ 0, 0, 0, 1]
|
||||
[ 1, 0, 0, 0],
|
||||
[tan(ya), 1, 0, 0],
|
||||
[tan(za), 0, 1, 0],
|
||||
[ 0, 0, 0, 1]
|
||||
];
|
||||
|
||||
|
||||
@ -393,8 +393,8 @@ function affine3d_skew_yz(ya, za) = [
|
||||
// Arguments:
|
||||
// affines = A list of 4x4 affine3d matrices.
|
||||
function affine3d_chain(affines, _m=undef, _i=0) =
|
||||
(_i>=len(affines))? (is_undef(_m)? ident(4) : _m) :
|
||||
affine3d_chain(affines, _m=(is_undef(_m)? affines[_i] : affines[_i] * _m), _i=_i+1);
|
||||
(_i>=len(affines))? (is_undef(_m)? ident(4) : _m) :
|
||||
affine3d_chain(affines, _m=(is_undef(_m)? affines[_i] : affines[_i] * _m), _i=_i+1);
|
||||
|
||||
|
||||
// Function: apply()
|
||||
@ -464,4 +464,4 @@ function is_2d_transform(t) = // z-parameters are zero, except we allow t[2][
|
||||
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
784
arrays.scad
784
arrays.scad
File diff suppressed because it is too large
Load Diff
1148
attachments.scad
1148
attachments.scad
File diff suppressed because it is too large
Load Diff
840
beziers.scad
840
beziers.scad
File diff suppressed because it is too large
Load Diff
@ -26,49 +26,49 @@ module offsetcube(size=[1,1,1],v=[0,0,0]) cuboid(size,anchor=-v);
|
||||
module rrect(size=[1,1,1], r=0.25, center=false) cuboid(size,rounding=r,edges="Z",anchor=center?CENTER:BOT);
|
||||
module rcube(size=[1,1,1], r=0.25, center=false) cuboid(size,rounding=r,anchor=center?CENTER:BOT);
|
||||
module chamfcube(size=[1,1,1],chamfer=0.25,chamfaxes=[1,1,1],chamfcorners=false) {
|
||||
cuboid(
|
||||
size=size, chamfer=chamfer,
|
||||
trimcorners=chamfcorners,
|
||||
edges=concat(
|
||||
chamfaxes[0]? ["X"] : [],
|
||||
chamfaxes[1]? ["Y"] : [],
|
||||
chamfaxes[2]? ["Z"] : []
|
||||
)
|
||||
);
|
||||
cuboid(
|
||||
size=size, chamfer=chamfer,
|
||||
trimcorners=chamfcorners,
|
||||
edges=concat(
|
||||
chamfaxes[0]? ["X"] : [],
|
||||
chamfaxes[1]? ["Y"] : [],
|
||||
chamfaxes[2]? ["Z"] : []
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
module trapezoid(size1=[1,1], size2=[1,1], h=1, center=false)
|
||||
prismoid(size1=size1, size2=size2, h=h, anchor=center?CENTER:BOT);
|
||||
prismoid(size1=size1, size2=size2, h=h, anchor=center?CENTER:BOT);
|
||||
|
||||
module pyramid(n=4, h=1, l=1, r, d, circum=false) {
|
||||
radius = get_radius(r=r, d=d, dflt=l/2/sin(180/n));
|
||||
cyl(r1=radius, r2=0, l=h, circum=circum, $fn=n, realign=true, anchor=BOT);
|
||||
radius = get_radius(r=r, d=d, dflt=l/2/sin(180/n));
|
||||
cyl(r1=radius, r2=0, l=h, circum=circum, $fn=n, realign=true, anchor=BOT);
|
||||
}
|
||||
|
||||
module prism(n=3, h=1, l=1, r=undef, d=undef, circum=false, center=false) {
|
||||
radius = get_radius(r=r, d=d, dflt=l/2/sin(180/n));
|
||||
cyl(r=radius, l=h, circum=circum, $fn=n, realign=true, anchor=center?CENTER:BOT);
|
||||
radius = get_radius(r=r, d=d, dflt=l/2/sin(180/n));
|
||||
cyl(r=radius, l=h, circum=circum, $fn=n, realign=true, anchor=center?CENTER:BOT);
|
||||
}
|
||||
|
||||
module chamferred_cylinder(h,r,d,chamfer=0.25,chamfedge,angle=45,top=true,bottom=true,center=false) {
|
||||
chamf = chamfedge!=undef? chamfedge*sin(angle) : chamfer;
|
||||
cyl(h=h, r=r, d=d, chamfer1=(bottom?chamf:0), chamfer2=(top?chamf:0), chamfang=angle, anchor=center?CENTER:BOT);
|
||||
chamf = chamfedge!=undef? chamfedge*sin(angle) : chamfer;
|
||||
cyl(h=h, r=r, d=d, chamfer1=(bottom?chamf:0), chamfer2=(top?chamf:0), chamfang=angle, anchor=center?CENTER:BOT);
|
||||
}
|
||||
|
||||
module chamf_cyl(h=1, r, d, chamfer=0.25, chamfedge, angle=45, center=false, top=true, bottom=true) {
|
||||
chamf = chamfedge!=undef? chamfedge*sin(angle) : chamfer;
|
||||
cyl(h=h, r=r, d=d, chamfer1=(bottom?chamf:0), chamfer2=(top?chamf:0), chamfang=angle, anchor=center?CENTER:BOT);
|
||||
chamf = chamfedge!=undef? chamfedge*sin(angle) : chamfer;
|
||||
cyl(h=h, r=r, d=d, chamfer1=(bottom?chamf:0), chamfer2=(top?chamf:0), chamfang=angle, anchor=center?CENTER:BOT);
|
||||
}
|
||||
|
||||
module filleted_cylinder(h=1, r=undef, d=undef, r1, r2, d1, d2, fillet=0.25, center=false)
|
||||
cyl(l=h, r=r, d=d, r1=r1, r2=r2, d1=d1, d2=d2, rounding=fillet, anchor=center?CENTER:BOT);
|
||||
cyl(l=h, r=r, d=d, r1=r1, r2=r2, d1=d1, d2=d2, rounding=fillet, anchor=center?CENTER:BOT);
|
||||
|
||||
module rcylinder(h=1, r=1, r1, r2, d, d1, d2, fillet=0.25, center=false)
|
||||
cyl(l=h, r=r, d=d, r1=r1, r2=r2, d1=d1, d2=d2, rounding=fillet, anchor=center?CENTER:BOT);
|
||||
cyl(l=h, r=r, d=d, r1=r1, r2=r2, d1=d1, d2=d2, rounding=fillet, anchor=center?CENTER:BOT);
|
||||
|
||||
module thinning_brace(h=50, l=100, thick=5, ang=30, strut=5, wall=3, center=true)
|
||||
thinning_triangle(h=h, l=l, thick=thick, ang=ang, strut=strut, wall=wall, diagonly=true, center=center);
|
||||
thinning_triangle(h=h, l=l, thick=thick, ang=ang, strut=strut, wall=wall, diagonly=true, center=center);
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
||||
|
486
bottlecaps.scad
486
bottlecaps.scad
@ -33,97 +33,97 @@ include <knurling.scad>
|
||||
// pco1810_neck();
|
||||
module pco1810_neck(wall=2, anchor="support-ring", spin=0, orient=UP)
|
||||
{
|
||||
inner_d = 21.74;
|
||||
neck_d = 26.19;
|
||||
neck_h = 5.00;
|
||||
support_d = 33.00;
|
||||
support_width = 1.45;
|
||||
support_rad = 0.40;
|
||||
support_h = 21.00;
|
||||
support_ang = 16;
|
||||
tamper_ring_d = 27.97;
|
||||
tamper_ring_width = 0.50;
|
||||
tamper_ring_r = 1.60;
|
||||
tamper_base_d = 25.71;
|
||||
tamper_base_h = 14.10;
|
||||
threadbase_d = 24.51;
|
||||
thread_pitch = 3.18;
|
||||
thread_angle = 20;
|
||||
thread_od = 27.43;
|
||||
lip_d = 25.07;
|
||||
lip_h = 1.70;
|
||||
lip_leadin_r = 0.20;
|
||||
lip_recess_d = 24.94;
|
||||
lip_recess_h = 1.00;
|
||||
lip_roundover_r = 0.58;
|
||||
inner_d = 21.74;
|
||||
neck_d = 26.19;
|
||||
neck_h = 5.00;
|
||||
support_d = 33.00;
|
||||
support_width = 1.45;
|
||||
support_rad = 0.40;
|
||||
support_h = 21.00;
|
||||
support_ang = 16;
|
||||
tamper_ring_d = 27.97;
|
||||
tamper_ring_width = 0.50;
|
||||
tamper_ring_r = 1.60;
|
||||
tamper_base_d = 25.71;
|
||||
tamper_base_h = 14.10;
|
||||
threadbase_d = 24.51;
|
||||
thread_pitch = 3.18;
|
||||
thread_angle = 20;
|
||||
thread_od = 27.43;
|
||||
lip_d = 25.07;
|
||||
lip_h = 1.70;
|
||||
lip_leadin_r = 0.20;
|
||||
lip_recess_d = 24.94;
|
||||
lip_recess_h = 1.00;
|
||||
lip_roundover_r = 0.58;
|
||||
|
||||
$fn = segs(support_d/2);
|
||||
h = support_h+neck_h;
|
||||
thread_h = (thread_od-threadbase_d)/2;
|
||||
anchors = [
|
||||
anchorpt("support-ring", [0,0,neck_h-h/2]),
|
||||
anchorpt("tamper-ring", [0,0,h/2-tamper_base_h])
|
||||
];
|
||||
attachable(anchor,spin,orient, d=support_d, l=h, anchors=anchors) {
|
||||
down(h/2) {
|
||||
rotate_extrude(convexity=10) {
|
||||
polygon(turtle(
|
||||
state=[inner_d/2,0], [
|
||||
"untilx", neck_d/2,
|
||||
"left", 90,
|
||||
"move", neck_h - 1,
|
||||
"arcright", 1, 90,
|
||||
"untilx", support_d/2-support_rad,
|
||||
"arcleft", support_rad, 90,
|
||||
"move", support_width,
|
||||
"arcleft", support_rad, 90-support_ang,
|
||||
"untilx", tamper_base_d/2,
|
||||
"right", 90-support_ang,
|
||||
"untily", h-tamper_base_h, // Tamper ring holder base.
|
||||
"right", 90,
|
||||
"untilx", tamper_ring_d/2,
|
||||
"left", 90,
|
||||
"move", tamper_ring_width,
|
||||
"arcleft", tamper_ring_r, 90,
|
||||
"untilx", threadbase_d/2,
|
||||
"right", 90,
|
||||
"untily", h-lip_h-lip_leadin_r, // Lip base.
|
||||
"arcright", lip_leadin_r, 90,
|
||||
"untilx", lip_d/2,
|
||||
"left", 90,
|
||||
"untily", h-lip_recess_h,
|
||||
"left", 90,
|
||||
"untilx", lip_recess_d/2,
|
||||
"right", 90,
|
||||
"untily", h-lip_roundover_r,
|
||||
"arcleft", lip_roundover_r, 90,
|
||||
"untilx", inner_d/2
|
||||
]
|
||||
));
|
||||
}
|
||||
up(h-lip_h) {
|
||||
bottom_half() {
|
||||
difference() {
|
||||
thread_helix(
|
||||
base_d=threadbase_d-0.1,
|
||||
pitch=thread_pitch,
|
||||
thread_depth=thread_h+0.1,
|
||||
thread_angle=thread_angle,
|
||||
twist=810,
|
||||
higbee=75,
|
||||
anchor=TOP
|
||||
);
|
||||
zrot_copies(rots=[90,270]) {
|
||||
zrot_copies(rots=[-28,28], r=threadbase_d/2) {
|
||||
prismoid([20,1.82], [20,1.82+2*sin(29)*thread_h], h=thread_h+0.1, anchor=BOT, orient=RIGHT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
$fn = segs(support_d/2);
|
||||
h = support_h+neck_h;
|
||||
thread_h = (thread_od-threadbase_d)/2;
|
||||
anchors = [
|
||||
anchorpt("support-ring", [0,0,neck_h-h/2]),
|
||||
anchorpt("tamper-ring", [0,0,h/2-tamper_base_h])
|
||||
];
|
||||
attachable(anchor,spin,orient, d=support_d, l=h, anchors=anchors) {
|
||||
down(h/2) {
|
||||
rotate_extrude(convexity=10) {
|
||||
polygon(turtle(
|
||||
state=[inner_d/2,0], [
|
||||
"untilx", neck_d/2,
|
||||
"left", 90,
|
||||
"move", neck_h - 1,
|
||||
"arcright", 1, 90,
|
||||
"untilx", support_d/2-support_rad,
|
||||
"arcleft", support_rad, 90,
|
||||
"move", support_width,
|
||||
"arcleft", support_rad, 90-support_ang,
|
||||
"untilx", tamper_base_d/2,
|
||||
"right", 90-support_ang,
|
||||
"untily", h-tamper_base_h, // Tamper ring holder base.
|
||||
"right", 90,
|
||||
"untilx", tamper_ring_d/2,
|
||||
"left", 90,
|
||||
"move", tamper_ring_width,
|
||||
"arcleft", tamper_ring_r, 90,
|
||||
"untilx", threadbase_d/2,
|
||||
"right", 90,
|
||||
"untily", h-lip_h-lip_leadin_r, // Lip base.
|
||||
"arcright", lip_leadin_r, 90,
|
||||
"untilx", lip_d/2,
|
||||
"left", 90,
|
||||
"untily", h-lip_recess_h,
|
||||
"left", 90,
|
||||
"untilx", lip_recess_d/2,
|
||||
"right", 90,
|
||||
"untily", h-lip_roundover_r,
|
||||
"arcleft", lip_roundover_r, 90,
|
||||
"untilx", inner_d/2
|
||||
]
|
||||
));
|
||||
}
|
||||
up(h-lip_h) {
|
||||
bottom_half() {
|
||||
difference() {
|
||||
thread_helix(
|
||||
base_d=threadbase_d-0.1,
|
||||
pitch=thread_pitch,
|
||||
thread_depth=thread_h+0.1,
|
||||
thread_angle=thread_angle,
|
||||
twist=810,
|
||||
higbee=75,
|
||||
anchor=TOP
|
||||
);
|
||||
zrot_copies(rots=[90,270]) {
|
||||
zrot_copies(rots=[-28,28], r=threadbase_d/2) {
|
||||
prismoid([20,1.82], [20,1.82+2*sin(29)*thread_h], h=thread_h+0.1, anchor=BOT, orient=RIGHT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -146,41 +146,41 @@ module pco1810_neck(wall=2, anchor="support-ring", spin=0, orient=UP)
|
||||
// pco1810_cap(texture="ribbed");
|
||||
module pco1810_cap(wall=2, texture="none", anchor=BOTTOM, spin=0, orient=UP)
|
||||
{
|
||||
cap_id = 28.58;
|
||||
tamper_ring_h = 14.10;
|
||||
thread_pitch = 3.18;
|
||||
thread_angle = 20;
|
||||
thread_od = cap_id;
|
||||
thread_depth = 1.6;
|
||||
cap_id = 28.58;
|
||||
tamper_ring_h = 14.10;
|
||||
thread_pitch = 3.18;
|
||||
thread_angle = 20;
|
||||
thread_od = cap_id;
|
||||
thread_depth = 1.6;
|
||||
|
||||
$fn = segs(33/2);
|
||||
w = cap_id + 2*wall;
|
||||
h = tamper_ring_h + wall;
|
||||
anchors = [
|
||||
anchorpt("inside-top", [0,0,-(h/2-wall)])
|
||||
];
|
||||
attachable(anchor,spin,orient, d=w, l=h, anchors=anchors) {
|
||||
down(h/2) zrot(45) {
|
||||
difference() {
|
||||
union() {
|
||||
if (texture == "knurled") {
|
||||
knurled_cylinder(d=w, helix=45, l=tamper_ring_h+wall, anchor=BOTTOM);
|
||||
cyl(d=w-1.5, l=tamper_ring_h+wall, anchor=BOTTOM);
|
||||
} else if (texture == "ribbed") {
|
||||
zrot_copies(n=30, r=(w-1)/2) {
|
||||
cube([1, 1, tamper_ring_h+wall], anchor=BOTTOM);
|
||||
}
|
||||
cyl(d=w-1, l=tamper_ring_h+wall, anchor=BOTTOM);
|
||||
} else {
|
||||
cyl(d=w, l=tamper_ring_h+wall, anchor=BOTTOM);
|
||||
}
|
||||
}
|
||||
up(wall) cyl(d=cap_id, h=tamper_ring_h+wall, anchor=BOTTOM);
|
||||
}
|
||||
up(wall+2) thread_helix(base_d=thread_od-thread_depth*2, pitch=thread_pitch, thread_depth=thread_depth, thread_angle=thread_angle, twist=810, higbee=45, internal=true, anchor=BOTTOM);
|
||||
}
|
||||
children();
|
||||
}
|
||||
$fn = segs(33/2);
|
||||
w = cap_id + 2*wall;
|
||||
h = tamper_ring_h + wall;
|
||||
anchors = [
|
||||
anchorpt("inside-top", [0,0,-(h/2-wall)])
|
||||
];
|
||||
attachable(anchor,spin,orient, d=w, l=h, anchors=anchors) {
|
||||
down(h/2) zrot(45) {
|
||||
difference() {
|
||||
union() {
|
||||
if (texture == "knurled") {
|
||||
knurled_cylinder(d=w, helix=45, l=tamper_ring_h+wall, anchor=BOTTOM);
|
||||
cyl(d=w-1.5, l=tamper_ring_h+wall, anchor=BOTTOM);
|
||||
} else if (texture == "ribbed") {
|
||||
zrot_copies(n=30, r=(w-1)/2) {
|
||||
cube([1, 1, tamper_ring_h+wall], anchor=BOTTOM);
|
||||
}
|
||||
cyl(d=w-1, l=tamper_ring_h+wall, anchor=BOTTOM);
|
||||
} else {
|
||||
cyl(d=w, l=tamper_ring_h+wall, anchor=BOTTOM);
|
||||
}
|
||||
}
|
||||
up(wall) cyl(d=cap_id, h=tamper_ring_h+wall, anchor=BOTTOM);
|
||||
}
|
||||
up(wall+2) thread_helix(base_d=thread_od-thread_depth*2, pitch=thread_pitch, thread_depth=thread_depth, thread_angle=thread_angle, twist=810, higbee=45, internal=true, anchor=BOTTOM);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -204,97 +204,97 @@ module pco1810_cap(wall=2, texture="none", anchor=BOTTOM, spin=0, orient=UP)
|
||||
// pco1881_neck();
|
||||
module pco1881_neck(wall=2, anchor="support-ring", spin=0, orient=UP)
|
||||
{
|
||||
inner_d = 21.74;
|
||||
neck_d = 26.19;
|
||||
neck_h = 5.00;
|
||||
support_d = 33.00;
|
||||
support_width = 0.58;
|
||||
support_rad = 0.30;
|
||||
support_h = 17.00;
|
||||
support_ang = 15;
|
||||
tamper_ring_d = 28.00;
|
||||
tamper_ring_width = 0.30;
|
||||
tamper_ring_ang = 45;
|
||||
tamper_base_d = 25.71;
|
||||
tamper_base_h = 11.20;
|
||||
tamper_divot_r = 1.08;
|
||||
threadbase_d = 24.20;
|
||||
thread_pitch = 2.70;
|
||||
thread_angle = 15;
|
||||
thread_od = 27.4;
|
||||
lip_d = 25.07;
|
||||
lip_h = 1.70;
|
||||
lip_leadin_r = 0.30;
|
||||
lip_recess_d = 24.94;
|
||||
lip_recess_h = 1.00;
|
||||
lip_roundover_r = 0.58;
|
||||
inner_d = 21.74;
|
||||
neck_d = 26.19;
|
||||
neck_h = 5.00;
|
||||
support_d = 33.00;
|
||||
support_width = 0.58;
|
||||
support_rad = 0.30;
|
||||
support_h = 17.00;
|
||||
support_ang = 15;
|
||||
tamper_ring_d = 28.00;
|
||||
tamper_ring_width = 0.30;
|
||||
tamper_ring_ang = 45;
|
||||
tamper_base_d = 25.71;
|
||||
tamper_base_h = 11.20;
|
||||
tamper_divot_r = 1.08;
|
||||
threadbase_d = 24.20;
|
||||
thread_pitch = 2.70;
|
||||
thread_angle = 15;
|
||||
thread_od = 27.4;
|
||||
lip_d = 25.07;
|
||||
lip_h = 1.70;
|
||||
lip_leadin_r = 0.30;
|
||||
lip_recess_d = 24.94;
|
||||
lip_recess_h = 1.00;
|
||||
lip_roundover_r = 0.58;
|
||||
|
||||
$fn = segs(support_d/2);
|
||||
h = support_h+neck_h;
|
||||
thread_h = (thread_od-threadbase_d)/2;
|
||||
anchors = [
|
||||
anchorpt("support-ring", [0,0,neck_h-h/2]),
|
||||
anchorpt("tamper-ring", [0,0,h/2-tamper_base_h])
|
||||
];
|
||||
attachable(anchor,spin,orient, d=support_d, l=h, anchors=anchors) {
|
||||
down(h/2) {
|
||||
rotate_extrude(convexity=10) {
|
||||
polygon(turtle(
|
||||
state=[inner_d/2,0], [
|
||||
"untilx", neck_d/2,
|
||||
"left", 90,
|
||||
"move", neck_h - 1,
|
||||
"arcright", 1, 90,
|
||||
"untilx", support_d/2-support_rad,
|
||||
"arcleft", support_rad, 90,
|
||||
"move", support_width,
|
||||
"arcleft", support_rad, 90-support_ang,
|
||||
"untilx", tamper_base_d/2,
|
||||
"arcright", tamper_divot_r, 180-support_ang*2,
|
||||
"left", 90-support_ang,
|
||||
"untily", h-tamper_base_h, // Tamper ring holder base.
|
||||
"right", 90,
|
||||
"untilx", tamper_ring_d/2,
|
||||
"left", 90,
|
||||
"move", tamper_ring_width,
|
||||
"left", tamper_ring_ang,
|
||||
"untilx", threadbase_d/2,
|
||||
"right", tamper_ring_ang,
|
||||
"untily", h-lip_h-lip_leadin_r, // Lip base.
|
||||
"arcright", lip_leadin_r, 90,
|
||||
"untilx", lip_d/2,
|
||||
"left", 90,
|
||||
"untily", h-lip_recess_h,
|
||||
"left", 90,
|
||||
"untilx", lip_recess_d/2,
|
||||
"right", 90,
|
||||
"untily", h-lip_roundover_r,
|
||||
"arcleft", lip_roundover_r, 90,
|
||||
"untilx", inner_d/2
|
||||
]
|
||||
));
|
||||
}
|
||||
up(h-lip_h) {
|
||||
difference() {
|
||||
thread_helix(
|
||||
base_d=threadbase_d-0.1,
|
||||
pitch=thread_pitch,
|
||||
thread_depth=thread_h+0.1,
|
||||
thread_angle=thread_angle,
|
||||
twist=650,
|
||||
higbee=75,
|
||||
anchor=TOP
|
||||
);
|
||||
zrot_copies(rots=[90,270]) {
|
||||
zrot_copies(rots=[-28,28], r=threadbase_d/2) {
|
||||
prismoid([20,1.82], [20,1.82+2*sin(29)*thread_h], h=thread_h+0.1, anchor=BOT, orient=RIGHT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
$fn = segs(support_d/2);
|
||||
h = support_h+neck_h;
|
||||
thread_h = (thread_od-threadbase_d)/2;
|
||||
anchors = [
|
||||
anchorpt("support-ring", [0,0,neck_h-h/2]),
|
||||
anchorpt("tamper-ring", [0,0,h/2-tamper_base_h])
|
||||
];
|
||||
attachable(anchor,spin,orient, d=support_d, l=h, anchors=anchors) {
|
||||
down(h/2) {
|
||||
rotate_extrude(convexity=10) {
|
||||
polygon(turtle(
|
||||
state=[inner_d/2,0], [
|
||||
"untilx", neck_d/2,
|
||||
"left", 90,
|
||||
"move", neck_h - 1,
|
||||
"arcright", 1, 90,
|
||||
"untilx", support_d/2-support_rad,
|
||||
"arcleft", support_rad, 90,
|
||||
"move", support_width,
|
||||
"arcleft", support_rad, 90-support_ang,
|
||||
"untilx", tamper_base_d/2,
|
||||
"arcright", tamper_divot_r, 180-support_ang*2,
|
||||
"left", 90-support_ang,
|
||||
"untily", h-tamper_base_h, // Tamper ring holder base.
|
||||
"right", 90,
|
||||
"untilx", tamper_ring_d/2,
|
||||
"left", 90,
|
||||
"move", tamper_ring_width,
|
||||
"left", tamper_ring_ang,
|
||||
"untilx", threadbase_d/2,
|
||||
"right", tamper_ring_ang,
|
||||
"untily", h-lip_h-lip_leadin_r, // Lip base.
|
||||
"arcright", lip_leadin_r, 90,
|
||||
"untilx", lip_d/2,
|
||||
"left", 90,
|
||||
"untily", h-lip_recess_h,
|
||||
"left", 90,
|
||||
"untilx", lip_recess_d/2,
|
||||
"right", 90,
|
||||
"untily", h-lip_roundover_r,
|
||||
"arcleft", lip_roundover_r, 90,
|
||||
"untilx", inner_d/2
|
||||
]
|
||||
));
|
||||
}
|
||||
up(h-lip_h) {
|
||||
difference() {
|
||||
thread_helix(
|
||||
base_d=threadbase_d-0.1,
|
||||
pitch=thread_pitch,
|
||||
thread_depth=thread_h+0.1,
|
||||
thread_angle=thread_angle,
|
||||
twist=650,
|
||||
higbee=75,
|
||||
anchor=TOP
|
||||
);
|
||||
zrot_copies(rots=[90,270]) {
|
||||
zrot_copies(rots=[-28,28], r=threadbase_d/2) {
|
||||
prismoid([20,1.82], [20,1.82+2*sin(29)*thread_h], h=thread_h+0.1, anchor=BOT, orient=RIGHT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -317,36 +317,36 @@ module pco1881_neck(wall=2, anchor="support-ring", spin=0, orient=UP)
|
||||
// pco1881_cap(texture="ribbed");
|
||||
module pco1881_cap(wall=2, texture="none", anchor=BOTTOM, spin=0, orient=UP)
|
||||
{
|
||||
$fn = segs(33/2);
|
||||
w = 28.58 + 2*wall;
|
||||
h = 11.2 + wall;
|
||||
anchors = [
|
||||
anchorpt("inside-top", [0,0,-(h/2-wall)])
|
||||
];
|
||||
attachable(anchor,spin,orient, d=w, l=h, anchors=anchors) {
|
||||
down(h/2) zrot(45) {
|
||||
difference() {
|
||||
union() {
|
||||
if (texture == "knurled") {
|
||||
knurled_cylinder(d=w, helix=45, l=11.2+wall, anchor=BOTTOM);
|
||||
cyl(d=w-1.5, l=11.2+wall, anchor=BOTTOM);
|
||||
} else if (texture == "ribbed") {
|
||||
zrot_copies(n=30, r=(w-1)/2) {
|
||||
cube([1, 1, 11.2+wall], anchor=BOTTOM);
|
||||
}
|
||||
cyl(d=w-1, l=11.2+wall, anchor=BOTTOM);
|
||||
} else {
|
||||
cyl(d=w, l=11.2+wall, anchor=BOTTOM);
|
||||
}
|
||||
}
|
||||
up(wall) cyl(d=28.58, h=11.2+wall, anchor=BOTTOM);
|
||||
}
|
||||
up(wall+2) thread_helix(base_d=25.5, pitch=2.7, thread_depth=1.6, thread_angle=15, twist=650, higbee=45, internal=true, anchor=BOTTOM);
|
||||
}
|
||||
children();
|
||||
}
|
||||
$fn = segs(33/2);
|
||||
w = 28.58 + 2*wall;
|
||||
h = 11.2 + wall;
|
||||
anchors = [
|
||||
anchorpt("inside-top", [0,0,-(h/2-wall)])
|
||||
];
|
||||
attachable(anchor,spin,orient, d=w, l=h, anchors=anchors) {
|
||||
down(h/2) zrot(45) {
|
||||
difference() {
|
||||
union() {
|
||||
if (texture == "knurled") {
|
||||
knurled_cylinder(d=w, helix=45, l=11.2+wall, anchor=BOTTOM);
|
||||
cyl(d=w-1.5, l=11.2+wall, anchor=BOTTOM);
|
||||
} else if (texture == "ribbed") {
|
||||
zrot_copies(n=30, r=(w-1)/2) {
|
||||
cube([1, 1, 11.2+wall], anchor=BOTTOM);
|
||||
}
|
||||
cyl(d=w-1, l=11.2+wall, anchor=BOTTOM);
|
||||
} else {
|
||||
cyl(d=w, l=11.2+wall, anchor=BOTTOM);
|
||||
}
|
||||
}
|
||||
up(wall) cyl(d=28.58, h=11.2+wall, anchor=BOTTOM);
|
||||
}
|
||||
up(wall+2) thread_helix(base_d=25.5, pitch=2.7, thread_depth=1.6, thread_angle=15, twist=650, higbee=45, internal=true, anchor=BOTTOM);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
70
common.scad
70
common.scad
@ -17,12 +17,12 @@
|
||||
// Description:
|
||||
// Returns a string representing the type of the value. One of "undef", "boolean", "number", "string", "list", or "range"
|
||||
function typeof(x) =
|
||||
is_undef(x)? "undef" :
|
||||
is_bool(x)? "boolean" :
|
||||
is_num(x)? "number" :
|
||||
is_string(x)? "string" :
|
||||
is_list(x)? "list" :
|
||||
"range";
|
||||
is_undef(x)? "undef" :
|
||||
is_bool(x)? "boolean" :
|
||||
is_num(x)? "number" :
|
||||
is_string(x)? "string" :
|
||||
is_list(x)? "list" :
|
||||
"range";
|
||||
|
||||
|
||||
// Function: is_type()
|
||||
@ -43,9 +43,9 @@ function typeof(x) =
|
||||
// is_str3 = is_type(["foo"], "string"); // Returns: false
|
||||
// is_str4 = is_type(3, "string"); // Returns: false
|
||||
function is_type(x,types) =
|
||||
is_list(types)? in_list(typeof(x),types) :
|
||||
is_string(types)? typeof(x) == types :
|
||||
assert(is_list(types)||is_string(types));
|
||||
is_list(types)? in_list(typeof(x),types) :
|
||||
is_string(types)? typeof(x) == types :
|
||||
assert(is_list(types)||is_string(types));
|
||||
|
||||
|
||||
// Function: is_def()
|
||||
@ -100,9 +100,9 @@ function is_range(x) = is_num(x[0]) && !is_list(x);
|
||||
// is_list_of([[1,[3,4]], [4,[5,6]]], [1,[2,3]]); // Returne true
|
||||
// is_list_of([[1,[3,INF]], [4,[5,6]]], [1,[2,3]]); // Returne false
|
||||
function is_list_of(list,pattern) =
|
||||
let(pattern = 0*pattern)
|
||||
is_list(list) &&
|
||||
[]==[for(entry=list) if (entry*0 != pattern) entry];
|
||||
let(pattern = 0*pattern)
|
||||
is_list(list) &&
|
||||
[]==[for(entry=list) if (entry*0 != pattern) entry];
|
||||
|
||||
|
||||
// Function: is_consistent()
|
||||
@ -153,13 +153,13 @@ function default(v,dflt=undef) = is_undef(v)? dflt : v;
|
||||
// v = The list whose items are being checked.
|
||||
// recursive = If true, sublists are checked recursively for defined values. The first sublist that has a defined item is returned.
|
||||
function first_defined(v,recursive=false,_i=0) =
|
||||
_i<len(v) && (
|
||||
is_undef(v[_i]) || (
|
||||
recursive &&
|
||||
is_list(v[_i]) &&
|
||||
is_undef(first_defined(v[_i],recursive=recursive))
|
||||
)
|
||||
)? first_defined(v,recursive=recursive,_i=_i+1) : v[_i];
|
||||
_i<len(v) && (
|
||||
is_undef(v[_i]) || (
|
||||
recursive &&
|
||||
is_list(v[_i]) &&
|
||||
is_undef(first_defined(v[_i],recursive=recursive))
|
||||
)
|
||||
)? first_defined(v,recursive=recursive,_i=_i+1) : v[_i];
|
||||
|
||||
|
||||
// Function: one_defined()
|
||||
@ -225,9 +225,9 @@ function all_defined(v,recursive=false) = max([for (x=v) is_undef(x)||(recursive
|
||||
// uncentered = The value to return if `center` is not `undef` and evaluates as false. Default: ALLNEG
|
||||
// dflt = The default value to return if both `anchor` and `center` are `undef`. Default: `CENTER`
|
||||
function get_anchor(anchor,center,uncentered=BOT,dflt=CENTER) =
|
||||
!is_undef(center)? (center? CENTER : uncentered) :
|
||||
!is_undef(anchor)? anchor :
|
||||
dflt;
|
||||
!is_undef(center)? (center? CENTER : uncentered) :
|
||||
!is_undef(anchor)? anchor :
|
||||
dflt;
|
||||
|
||||
|
||||
// Function: get_radius()
|
||||
@ -251,13 +251,13 @@ function get_anchor(anchor,center,uncentered=BOT,dflt=CENTER) =
|
||||
// d = Most general diameter.
|
||||
// dflt = Value to return if all other values given are `undef`.
|
||||
function get_radius(r1=undef, r2=undef, r=undef, d1=undef, d2=undef, d=undef, dflt=undef) = (
|
||||
!is_undef(r1)? assert(is_undef(r2)&&is_undef(d1)&&is_undef(d2), "Conflicting or redundant radius/diameter arguments given.") r1 :
|
||||
!is_undef(r2)? assert(is_undef(d1)&&is_undef(d2), "Conflicting or redundant radius/diameter arguments given.") r2 :
|
||||
!is_undef(d1)? d1/2 :
|
||||
!is_undef(d2)? d2/2 :
|
||||
!is_undef(r)? assert(is_undef(d), "Conflicting or redundant radius/diameter arguments given.") r :
|
||||
!is_undef(d)? d/2 :
|
||||
dflt
|
||||
!is_undef(r1)? assert(is_undef(r2)&&is_undef(d1)&&is_undef(d2), "Conflicting or redundant radius/diameter arguments given.") r1 :
|
||||
!is_undef(r2)? assert(is_undef(d1)&&is_undef(d2), "Conflicting or redundant radius/diameter arguments given.") r2 :
|
||||
!is_undef(d1)? d1/2 :
|
||||
!is_undef(d2)? d2/2 :
|
||||
!is_undef(r)? assert(is_undef(d), "Conflicting or redundant radius/diameter arguments given.") r :
|
||||
!is_undef(d)? d/2 :
|
||||
dflt
|
||||
);
|
||||
|
||||
// Function: get_height()
|
||||
@ -289,9 +289,9 @@ function get_height(h=undef,l=undef,height=undef,dflt=undef) =
|
||||
// v = Value to return vector from.
|
||||
// dflt = Default value to set empty vector parts from.
|
||||
function scalar_vec3(v, dflt=undef) =
|
||||
is_undef(v)? undef :
|
||||
is_list(v)? [for (i=[0:2]) default(v[i], default(dflt, 0))] :
|
||||
!is_undef(dflt)? [v,dflt,dflt] : [v,v,v];
|
||||
is_undef(v)? undef :
|
||||
is_list(v)? [for (i=[0:2]) default(v[i], default(dflt, 0))] :
|
||||
!is_undef(dflt)? [v,dflt,dflt] : [v,v,v];
|
||||
|
||||
|
||||
// Function: segs()
|
||||
@ -302,8 +302,8 @@ function scalar_vec3(v, dflt=undef) =
|
||||
// Arguments:
|
||||
// r = Radius of circle to get the number of segments for.
|
||||
function segs(r) =
|
||||
$fn>0? ($fn>3? $fn : 3) :
|
||||
ceil(max(5, min(360/$fa, abs(r)*2*PI/$fs)));
|
||||
$fn>0? ($fn>3? $fn : 3) :
|
||||
ceil(max(5, min(360/$fa, abs(r)*2*PI/$fs)));
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -118,4 +118,4 @@ FORWARD = FRONT; // Vector pointing forward, alias to `FRONT`.
|
||||
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
160
coords.scad
160
coords.scad
@ -30,10 +30,10 @@ function point2d(p, fill=0) = [for (i=[0:1]) (p[i]==undef)? fill : p[i]];
|
||||
// points = A list of 2D or 3D points/vectors.
|
||||
// fill = Value to fill missing values in vectors with.
|
||||
function path2d(points) =
|
||||
assert(is_path(points,dim=undef,fast=true),"Input to path2d is not a path")
|
||||
let (result = points * concat(ident(2), repeat([0,0], len(points[0])-2)))
|
||||
assert(is_def(result), "Invalid input to path2d")
|
||||
result;
|
||||
assert(is_path(points,dim=undef,fast=true),"Input to path2d is not a path")
|
||||
let (result = points * concat(ident(2), repeat([0,0], len(points[0])-2)))
|
||||
assert(is_def(result), "Invalid input to path2d")
|
||||
result;
|
||||
|
||||
|
||||
// Function: point3d()
|
||||
@ -53,16 +53,16 @@ function point3d(p, fill=0) = [for (i=[0:2]) (p[i]==undef)? fill : p[i]];
|
||||
// points = A list of 2D, 3D or higher dimensional points/vectors.
|
||||
// fill = Value to fill missing values in vectors with (in the 2D case)
|
||||
function path3d(points, fill=0) =
|
||||
assert(is_num(fill))
|
||||
assert(is_path(points, dim=undef, fast=true), "Input to path3d is not a path")
|
||||
let (
|
||||
change = len(points[0])-3,
|
||||
M = change < 0? [[1,0,0],[0,1,0]] :
|
||||
concat(ident(3), repeat([0,0,0],change)),
|
||||
result = points*M
|
||||
)
|
||||
assert(is_def(result), "Input to path3d is invalid")
|
||||
fill == 0 || change>=0 ? result : result + repeat([0,0,fill], len(result));
|
||||
assert(is_num(fill))
|
||||
assert(is_path(points, dim=undef, fast=true), "Input to path3d is not a path")
|
||||
let (
|
||||
change = len(points[0])-3,
|
||||
M = change < 0? [[1,0,0],[0,1,0]] :
|
||||
concat(ident(3), repeat([0,0,0],change)),
|
||||
result = points*M
|
||||
)
|
||||
assert(is_def(result), "Input to path3d is invalid")
|
||||
fill == 0 || change>=0 ? result : result + repeat([0,0,fill], len(result));
|
||||
|
||||
|
||||
// Function: point4d()
|
||||
@ -118,9 +118,9 @@ function path4d(points, fill=0) =
|
||||
// xy = polar_to_xy(40,30); // Returns: ~[34.6410162, 15]
|
||||
// xy = polar_to_xy([40,30]); // Returns: ~[34.6410162, 15]
|
||||
function polar_to_xy(r,theta=undef) = let(
|
||||
rad = theta==undef? r[0] : r,
|
||||
t = theta==undef? r[1] : theta
|
||||
) rad*[cos(t), sin(t)];
|
||||
rad = theta==undef? r[0] : r,
|
||||
t = theta==undef? r[1] : theta
|
||||
) rad*[cos(t), sin(t)];
|
||||
|
||||
|
||||
// Function: xy_to_polar()
|
||||
@ -137,9 +137,9 @@ function polar_to_xy(r,theta=undef) = let(
|
||||
// plr = xy_to_polar(20,30);
|
||||
// plr = xy_to_polar([40,60]);
|
||||
function xy_to_polar(x,y=undef) = let(
|
||||
xx = y==undef? x[0] : x,
|
||||
yy = y==undef? x[1] : y
|
||||
) [norm([xx,yy]), atan2(yy,xx)];
|
||||
xx = y==undef? x[0] : x,
|
||||
yy = y==undef? x[1] : y
|
||||
) [norm([xx,yy]), atan2(yy,xx)];
|
||||
|
||||
|
||||
// Function: project_plane()
|
||||
@ -169,26 +169,26 @@ function xy_to_polar(x,y=undef) = let(
|
||||
// xy = project_plane(pt, a, b, c);
|
||||
// xy2 = project_plane(pt, [a,b,c]);
|
||||
function project_plane(point, a, b, c) =
|
||||
is_undef(b) && is_undef(c) && is_list(a)? let(
|
||||
mat = is_vector(a,4)? plane_transform(a) :
|
||||
assert(is_path(a) && len(a)>=3)
|
||||
plane_transform(plane_from_points(a)),
|
||||
pts = is_vector(point)? point2d(apply(mat,point)) :
|
||||
is_path(point)? path2d(apply(mat,point)) :
|
||||
is_region(point)? [for (x=point) path2d(apply(mat,x))] :
|
||||
assert(false, "point must be a 3D point, path, or region.")
|
||||
) pts :
|
||||
assert(is_vector(a))
|
||||
assert(is_vector(b))
|
||||
assert(is_vector(c))
|
||||
assert(is_vector(point)||is_path(point))
|
||||
let(
|
||||
u = unit(b-a),
|
||||
v = unit(c-a),
|
||||
n = unit(cross(u,v)),
|
||||
w = unit(cross(n,u)),
|
||||
relpoint = apply(move(-a),point)
|
||||
) relpoint * transpose([w,u]);
|
||||
is_undef(b) && is_undef(c) && is_list(a)? let(
|
||||
mat = is_vector(a,4)? plane_transform(a) :
|
||||
assert(is_path(a) && len(a)>=3)
|
||||
plane_transform(plane_from_points(a)),
|
||||
pts = is_vector(point)? point2d(apply(mat,point)) :
|
||||
is_path(point)? path2d(apply(mat,point)) :
|
||||
is_region(point)? [for (x=point) path2d(apply(mat,x))] :
|
||||
assert(false, "point must be a 3D point, path, or region.")
|
||||
) pts :
|
||||
assert(is_vector(a))
|
||||
assert(is_vector(b))
|
||||
assert(is_vector(c))
|
||||
assert(is_vector(point)||is_path(point))
|
||||
let(
|
||||
u = unit(b-a),
|
||||
v = unit(c-a),
|
||||
n = unit(cross(u,v)),
|
||||
w = unit(cross(n,u)),
|
||||
relpoint = apply(move(-a),point)
|
||||
) relpoint * transpose([w,u]);
|
||||
|
||||
|
||||
// Function: lift_plane()
|
||||
@ -210,27 +210,27 @@ function project_plane(point, a, b, c) =
|
||||
// b = A 3D point that the plane passes through. Used to define the plane.
|
||||
// c = A 3D point that the plane passes through. Used to define the plane.
|
||||
function lift_plane(point, a, b, c) =
|
||||
is_undef(b) && is_undef(c) && is_list(a)? let(
|
||||
mat = is_vector(a,4)? plane_transform(a) :
|
||||
assert(is_path(a) && len(a)>=3)
|
||||
plane_transform(plane_from_points(a)),
|
||||
imat = matrix_inverse(mat),
|
||||
pts = is_vector(point)? apply(imat,point3d(point)) :
|
||||
is_path(point)? apply(imat,path3d(point)) :
|
||||
is_region(point)? [for (x=point) apply(imat,path3d(x))] :
|
||||
assert(false, "point must be a 2D point, path, or region.")
|
||||
) pts :
|
||||
assert(is_vector(a))
|
||||
assert(is_vector(b))
|
||||
assert(is_vector(c))
|
||||
assert(is_vector(point)||is_path(point))
|
||||
let(
|
||||
u = unit(b-a),
|
||||
v = unit(c-a),
|
||||
n = unit(cross(u,v)),
|
||||
w = unit(cross(n,u)),
|
||||
remapped = point*[w,u]
|
||||
) apply(move(a),remapped);
|
||||
is_undef(b) && is_undef(c) && is_list(a)? let(
|
||||
mat = is_vector(a,4)? plane_transform(a) :
|
||||
assert(is_path(a) && len(a)>=3)
|
||||
plane_transform(plane_from_points(a)),
|
||||
imat = matrix_inverse(mat),
|
||||
pts = is_vector(point)? apply(imat,point3d(point)) :
|
||||
is_path(point)? apply(imat,path3d(point)) :
|
||||
is_region(point)? [for (x=point) apply(imat,path3d(x))] :
|
||||
assert(false, "point must be a 2D point, path, or region.")
|
||||
) pts :
|
||||
assert(is_vector(a))
|
||||
assert(is_vector(b))
|
||||
assert(is_vector(c))
|
||||
assert(is_vector(point)||is_path(point))
|
||||
let(
|
||||
u = unit(b-a),
|
||||
v = unit(c-a),
|
||||
n = unit(cross(u,v)),
|
||||
w = unit(cross(n,u)),
|
||||
remapped = point*[w,u]
|
||||
) apply(move(a),remapped);
|
||||
|
||||
|
||||
// Function: cylindrical_to_xyz()
|
||||
@ -247,10 +247,10 @@ function lift_plane(point, a, b, c) =
|
||||
// xyz = cylindrical_to_xyz(20,30,40);
|
||||
// xyz = cylindrical_to_xyz([40,60,50]);
|
||||
function cylindrical_to_xyz(r,theta=undef,z=undef) = let(
|
||||
rad = theta==undef? r[0] : r,
|
||||
t = theta==undef? r[1] : theta,
|
||||
zed = theta==undef? r[2] : z
|
||||
) [rad*cos(t), rad*sin(t), zed];
|
||||
rad = theta==undef? r[0] : r,
|
||||
t = theta==undef? r[1] : theta,
|
||||
zed = theta==undef? r[2] : z
|
||||
) [rad*cos(t), rad*sin(t), zed];
|
||||
|
||||
|
||||
// Function: xyz_to_cylindrical()
|
||||
@ -269,8 +269,8 @@ function cylindrical_to_xyz(r,theta=undef,z=undef) = let(
|
||||
// cyl = xyz_to_cylindrical(20,30,40);
|
||||
// cyl = xyz_to_cylindrical([40,50,70]);
|
||||
function xyz_to_cylindrical(x,y=undef,z=undef) = let(
|
||||
p = is_num(x)? [x, default(y,0), default(z,0)] : point3d(x)
|
||||
) [norm([p.x,p.y]), atan2(p.y,p.x), p.z];
|
||||
p = is_num(x)? [x, default(y,0), default(z,0)] : point3d(x)
|
||||
) [norm([p.x,p.y]), atan2(p.y,p.x), p.z];
|
||||
|
||||
|
||||
// Function: spherical_to_xyz()
|
||||
@ -288,10 +288,10 @@ function xyz_to_cylindrical(x,y=undef,z=undef) = let(
|
||||
// xyz = spherical_to_xyz(20,30,40);
|
||||
// xyz = spherical_to_xyz([40,60,50]);
|
||||
function spherical_to_xyz(r,theta=undef,phi=undef) = let(
|
||||
rad = theta==undef? r[0] : r,
|
||||
t = theta==undef? r[1] : theta,
|
||||
p = theta==undef? r[2] : phi
|
||||
) rad*[sin(p)*cos(t), sin(p)*sin(t), cos(p)];
|
||||
rad = theta==undef? r[0] : r,
|
||||
t = theta==undef? r[1] : theta,
|
||||
p = theta==undef? r[2] : phi
|
||||
) rad*[sin(p)*cos(t), sin(p)*sin(t), cos(p)];
|
||||
|
||||
|
||||
// Function: xyz_to_spherical()
|
||||
@ -310,8 +310,8 @@ function spherical_to_xyz(r,theta=undef,phi=undef) = let(
|
||||
// sph = xyz_to_spherical(20,30,40);
|
||||
// sph = xyz_to_spherical([40,50,70]);
|
||||
function xyz_to_spherical(x,y=undef,z=undef) = let(
|
||||
p = is_num(x)? [x, default(y,0), default(z,0)] : point3d(x)
|
||||
) [norm(p), atan2(p.y,p.x), atan2(norm([p.x,p.y]),p.z)];
|
||||
p = is_num(x)? [x, default(y,0), default(z,0)] : point3d(x)
|
||||
) [norm(p), atan2(p.y,p.x), atan2(norm([p.x,p.y]),p.z)];
|
||||
|
||||
|
||||
// Function: altaz_to_xyz()
|
||||
@ -329,10 +329,10 @@ function xyz_to_spherical(x,y=undef,z=undef) = let(
|
||||
// xyz = altaz_to_xyz(20,30,40);
|
||||
// xyz = altaz_to_xyz([40,60,50]);
|
||||
function altaz_to_xyz(alt,az=undef,r=undef) = let(
|
||||
p = az==undef? alt[0] : alt,
|
||||
t = 90 - (az==undef? alt[1] : az),
|
||||
rad = az==undef? alt[2] : r
|
||||
) rad*[cos(p)*cos(t), cos(p)*sin(t), sin(p)];
|
||||
p = az==undef? alt[0] : alt,
|
||||
t = 90 - (az==undef? alt[1] : az),
|
||||
rad = az==undef? alt[2] : r
|
||||
) rad*[cos(p)*cos(t), cos(p)*sin(t), sin(p)];
|
||||
|
||||
|
||||
// Function: xyz_to_altaz()
|
||||
@ -352,9 +352,9 @@ function altaz_to_xyz(alt,az=undef,r=undef) = let(
|
||||
// aa = xyz_to_altaz(20,30,40);
|
||||
// aa = xyz_to_altaz([40,50,70]);
|
||||
function xyz_to_altaz(x,y=undef,z=undef) = let(
|
||||
p = is_num(x)? [x, default(y,0), default(z,0)] : point3d(x)
|
||||
) [atan2(p.z,norm([p.x,p.y])), atan2(p.x,p.y), norm(p)];
|
||||
p = is_num(x)? [x, default(y,0), default(z,0)] : point3d(x)
|
||||
) [atan2(p.z,norm([p.x,p.y])), atan2(p.x,p.y), norm(p)];
|
||||
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
572
cubetruss.scad
572
cubetruss.scad
@ -25,10 +25,10 @@ $cubetruss_clip_thickness = 1.6;
|
||||
// size = The length of each side of the cubetruss cubes. Default: `$cubetruss_size` (usually 30)
|
||||
// strut = The width of the struts on the cubetruss cubes. Default: `$cubetruss_strut_size` (usually 3)
|
||||
function cubetruss_dist(cubes=0, gaps=0, size=undef, strut=undef) =
|
||||
let(
|
||||
size = is_undef(size)? $cubetruss_size : size,
|
||||
strut = is_undef(strut)? $cubetruss_strut_size : strut
|
||||
) cubes*(size-strut)+gaps*strut;
|
||||
let(
|
||||
size = is_undef(size)? $cubetruss_size : size,
|
||||
strut = is_undef(strut)? $cubetruss_strut_size : strut
|
||||
) cubes*(size-strut)+gaps*strut;
|
||||
|
||||
|
||||
// Module: cubetruss_segment()
|
||||
@ -49,52 +49,52 @@ function cubetruss_dist(cubes=0, gaps=0, size=undef, strut=undef) =
|
||||
// cubetruss_segment(strut=4);
|
||||
// cubetruss_segment(size=40);
|
||||
module cubetruss_segment(size=undef, strut=undef, bracing=undef, anchor=CENTER, spin=0, orient=UP) {
|
||||
size = is_undef(size)? $cubetruss_size : size;
|
||||
strut = is_undef(strut)? $cubetruss_strut_size : strut;
|
||||
bracing = is_undef(bracing)? $cubetruss_bracing : bracing;
|
||||
h = size;
|
||||
crossthick = strut/sqrt(2);
|
||||
voffset = 0.333;
|
||||
attachable(anchor,spin,orient, size=[size,size,size]) {
|
||||
render(convexity=10)
|
||||
union() {
|
||||
difference() {
|
||||
// Start with a cube.
|
||||
cube([size, size, h], center=true);
|
||||
size = is_undef(size)? $cubetruss_size : size;
|
||||
strut = is_undef(strut)? $cubetruss_strut_size : strut;
|
||||
bracing = is_undef(bracing)? $cubetruss_bracing : bracing;
|
||||
h = size;
|
||||
crossthick = strut/sqrt(2);
|
||||
voffset = 0.333;
|
||||
attachable(anchor,spin,orient, size=[size,size,size]) {
|
||||
render(convexity=10)
|
||||
union() {
|
||||
difference() {
|
||||
// Start with a cube.
|
||||
cube([size, size, h], center=true);
|
||||
|
||||
cube([size-strut*2, size-strut*2, h-strut*2], center=true);
|
||||
cube([size-strut*2, size-strut*2, h-strut*2], center=true);
|
||||
|
||||
// Hollow out octogons in X and Y axes.
|
||||
zrot_copies([0,90]) {
|
||||
xrot(90) zrot(180/8) cylinder(h=max(h,size)+1, d=(min(h,size)-2*strut)/cos(180/8), center=true, $fn=8);
|
||||
}
|
||||
// Hollow out octogons in X and Y axes.
|
||||
zrot_copies([0,90]) {
|
||||
xrot(90) zrot(180/8) cylinder(h=max(h,size)+1, d=(min(h,size)-2*strut)/cos(180/8), center=true, $fn=8);
|
||||
}
|
||||
|
||||
// Hollow out octogon vertically.
|
||||
zrot(180/8) cylinder(h=max(h,size)+1, d=(min(h,size)-2*strut)/cos(180/8), center=true, $fn=8);
|
||||
}
|
||||
// Hollow out octogon vertically.
|
||||
zrot(180/8) cylinder(h=max(h,size)+1, d=(min(h,size)-2*strut)/cos(180/8), center=true, $fn=8);
|
||||
}
|
||||
|
||||
// Interior cross-supports
|
||||
if (bracing) {
|
||||
for (i = [-1,1]) {
|
||||
zrot(i*45) {
|
||||
difference() {
|
||||
cube([crossthick, (size-strut)*sqrt(2), h], center=true);
|
||||
up(i*voffset) {
|
||||
yscale(1.3) {
|
||||
yrot(90) {
|
||||
zrot(180/6) {
|
||||
cylinder(h=crossthick+1, d=(min(h,size)-2*strut)/cos(180/6)-2*voffset, center=true, $fn=6);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
// Interior cross-supports
|
||||
if (bracing) {
|
||||
for (i = [-1,1]) {
|
||||
zrot(i*45) {
|
||||
difference() {
|
||||
cube([crossthick, (size-strut)*sqrt(2), h], center=true);
|
||||
up(i*voffset) {
|
||||
yscale(1.3) {
|
||||
yrot(90) {
|
||||
zrot(180/6) {
|
||||
cylinder(h=crossthick+1, d=(min(h,size)-2*strut)/cos(180/6)-2*voffset, center=true, $fn=6);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -116,47 +116,47 @@ module cubetruss_segment(size=undef, strut=undef, bracing=undef, anchor=CENTER,
|
||||
// cubetruss_clip(extents=1);
|
||||
// cubetruss_clip(clipthick=2.5);
|
||||
module cubetruss_clip(extents=1, size=undef, strut=undef, clipthick=undef, anchor=CENTER, spin=0, orient=UP) {
|
||||
size = is_undef(size)? $cubetruss_size : size;
|
||||
strut = is_undef(strut)? $cubetruss_strut_size : strut;
|
||||
clipthick = is_undef(clipthick)? $cubetruss_clip_thickness : clipthick;
|
||||
cliplen = strut * 2.6;
|
||||
clipheight = min(size+strut, size/3+2*strut*2.6);
|
||||
clipsize = 0.5;
|
||||
s = [extents*(size-strut)+strut+2*clipthick, strut*2, clipheight-2*strut];
|
||||
attachable(anchor,spin,orient, size=s) {
|
||||
xflip_copy(offset=(extents*(size-strut)+strut)/2) {
|
||||
difference() {
|
||||
union() {
|
||||
difference() {
|
||||
right(clipthick/2-0.01) {
|
||||
back(strut) {
|
||||
difference() {
|
||||
xrot(90) prismoid([clipthick, clipheight], [clipthick, clipheight-cliplen*2], h=cliplen);
|
||||
right(clipthick/2) chamfer_mask_z(l=clipheight+0.1, chamfer=clipthick);
|
||||
}
|
||||
}
|
||||
}
|
||||
fwd(strut*3/2) {
|
||||
cube([$slop, strut*3, size], center=true);
|
||||
}
|
||||
}
|
||||
right($slop/2+0.01) {
|
||||
fwd(strut*1.25+$slop) {
|
||||
yrot(-90) prismoid([clipheight-cliplen*2, strut/2], [clipheight-cliplen*2-2*clipsize, strut/2], h=clipsize+0.01);
|
||||
}
|
||||
}
|
||||
}
|
||||
fwd(strut*1.6) {
|
||||
left(clipsize) {
|
||||
yscale(1.5) chamfer_mask_z(l=size+1, chamfer=clipsize+clipthick/3);
|
||||
}
|
||||
}
|
||||
zcopies(clipheight-strut) cube([clipthick*3, cliplen*2, strut], center=true);
|
||||
zcopies(clipheight-2*strut) right(clipthick) chamfer_mask_y(l=cliplen*2, chamfer=clipthick);
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
size = is_undef(size)? $cubetruss_size : size;
|
||||
strut = is_undef(strut)? $cubetruss_strut_size : strut;
|
||||
clipthick = is_undef(clipthick)? $cubetruss_clip_thickness : clipthick;
|
||||
cliplen = strut * 2.6;
|
||||
clipheight = min(size+strut, size/3+2*strut*2.6);
|
||||
clipsize = 0.5;
|
||||
s = [extents*(size-strut)+strut+2*clipthick, strut*2, clipheight-2*strut];
|
||||
attachable(anchor,spin,orient, size=s) {
|
||||
xflip_copy(offset=(extents*(size-strut)+strut)/2) {
|
||||
difference() {
|
||||
union() {
|
||||
difference() {
|
||||
right(clipthick/2-0.01) {
|
||||
back(strut) {
|
||||
difference() {
|
||||
xrot(90) prismoid([clipthick, clipheight], [clipthick, clipheight-cliplen*2], h=cliplen);
|
||||
right(clipthick/2) chamfer_mask_z(l=clipheight+0.1, chamfer=clipthick);
|
||||
}
|
||||
}
|
||||
}
|
||||
fwd(strut*3/2) {
|
||||
cube([$slop, strut*3, size], center=true);
|
||||
}
|
||||
}
|
||||
right($slop/2+0.01) {
|
||||
fwd(strut*1.25+$slop) {
|
||||
yrot(-90) prismoid([clipheight-cliplen*2, strut/2], [clipheight-cliplen*2-2*clipsize, strut/2], h=clipsize+0.01);
|
||||
}
|
||||
}
|
||||
}
|
||||
fwd(strut*1.6) {
|
||||
left(clipsize) {
|
||||
yscale(1.5) chamfer_mask_z(l=size+1, chamfer=clipsize+clipthick/3);
|
||||
}
|
||||
}
|
||||
zcopies(clipheight-strut) cube([clipthick*3, cliplen*2, strut], center=true);
|
||||
zcopies(clipheight-2*strut) right(clipthick) chamfer_mask_y(l=cliplen*2, chamfer=clipthick);
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -177,60 +177,60 @@ module cubetruss_clip(extents=1, size=undef, strut=undef, clipthick=undef, ancho
|
||||
// cubetruss_foot(w=1);
|
||||
// cubetruss_foot(w=3);
|
||||
module cubetruss_foot(w=1, size=undef, strut=undef, clipthick=undef, anchor=CENTER, spin=0, orient=UP) {
|
||||
size = is_undef(size)? $cubetruss_size : size;
|
||||
strut = is_undef(strut)? $cubetruss_strut_size : strut;
|
||||
clipthick = is_undef(clipthick)? $cubetruss_clip_thickness : clipthick;
|
||||
clipsize = 0.5;
|
||||
wall_h = strut+clipthick*1.5;
|
||||
cyld = (size-2*strut)/cos(180/8);
|
||||
s = [w*(size-strut)+strut+2*clipthick, size-2*strut, strut+clipthick];
|
||||
attachable(anchor,spin,orient, size=s, offset=[0,0,(strut-clipthick)/2]) {
|
||||
down(clipthick) {
|
||||
// Base
|
||||
up(clipthick/2) {
|
||||
cuboid([w*(size-strut)+strut+2*clipthick, size-2*strut, clipthick], chamfer=strut, edges=edges("Z"));
|
||||
}
|
||||
size = is_undef(size)? $cubetruss_size : size;
|
||||
strut = is_undef(strut)? $cubetruss_strut_size : strut;
|
||||
clipthick = is_undef(clipthick)? $cubetruss_clip_thickness : clipthick;
|
||||
clipsize = 0.5;
|
||||
wall_h = strut+clipthick*1.5;
|
||||
cyld = (size-2*strut)/cos(180/8);
|
||||
s = [w*(size-strut)+strut+2*clipthick, size-2*strut, strut+clipthick];
|
||||
attachable(anchor,spin,orient, size=s, offset=[0,0,(strut-clipthick)/2]) {
|
||||
down(clipthick) {
|
||||
// Base
|
||||
up(clipthick/2) {
|
||||
cuboid([w*(size-strut)+strut+2*clipthick, size-2*strut, clipthick], chamfer=strut, edges=edges("Z"));
|
||||
}
|
||||
|
||||
// Walls
|
||||
xcopies(w*(size-strut)+strut+clipthick) {
|
||||
up(clipthick-0.01) {
|
||||
prismoid([clipthick, (size-4*strut)], [clipthick, size/3.5], h=wall_h, anchor=BOT);
|
||||
}
|
||||
}
|
||||
// Walls
|
||||
xcopies(w*(size-strut)+strut+clipthick) {
|
||||
up(clipthick-0.01) {
|
||||
prismoid([clipthick, (size-4*strut)], [clipthick, size/3.5], h=wall_h, anchor=BOT);
|
||||
}
|
||||
}
|
||||
|
||||
// Horiz Wall Clips
|
||||
up(clipthick+strut+$slop*2) {
|
||||
xcopies(w*(size-strut)+strut) {
|
||||
prismoid([clipsize*2, size/3.5], [0.1, size/3.5], h=clipsize*3, anchor=BOT);
|
||||
}
|
||||
}
|
||||
// Horiz Wall Clips
|
||||
up(clipthick+strut+$slop*2) {
|
||||
xcopies(w*(size-strut)+strut) {
|
||||
prismoid([clipsize*2, size/3.5], [0.1, size/3.5], h=clipsize*3, anchor=BOT);
|
||||
}
|
||||
}
|
||||
|
||||
// Middle plugs
|
||||
for (xcol = [0:w-1]) {
|
||||
right((xcol-(w-1)/2)*(size-strut)) {
|
||||
difference() {
|
||||
// Start with octagon to fit sides.
|
||||
up(clipthick-0.01) {
|
||||
zrot(180/8) cylinder(h=strut, d1=cyld-4*$slop, d2=cyld-4*$slop-1, center=false, $fn=8);
|
||||
}
|
||||
// Middle plugs
|
||||
for (xcol = [0:w-1]) {
|
||||
right((xcol-(w-1)/2)*(size-strut)) {
|
||||
difference() {
|
||||
// Start with octagon to fit sides.
|
||||
up(clipthick-0.01) {
|
||||
zrot(180/8) cylinder(h=strut, d1=cyld-4*$slop, d2=cyld-4*$slop-1, center=false, $fn=8);
|
||||
}
|
||||
|
||||
// Bevel to fit.
|
||||
up(clipthick+strut) {
|
||||
ycopies(size-2*strut-4*$slop) {
|
||||
chamfer_mask_x(l=size-strut, chamfer=strut*2/3);
|
||||
}
|
||||
}
|
||||
// Bevel to fit.
|
||||
up(clipthick+strut) {
|
||||
ycopies(size-2*strut-4*$slop) {
|
||||
chamfer_mask_x(l=size-strut, chamfer=strut*2/3);
|
||||
}
|
||||
}
|
||||
|
||||
// Cut out X for possible top mount.
|
||||
zrot_copies([-45, 45]) {
|
||||
cube([size*3, strut/sqrt(2)+2*$slop, size*3], center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
// Cut out X for possible top mount.
|
||||
zrot_copies([-45, 45]) {
|
||||
cube([size*3, strut/sqrt(2)+2*$slop, size*3], center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -253,49 +253,49 @@ module cubetruss_foot(w=1, size=undef, strut=undef, clipthick=undef, anchor=CENT
|
||||
// cubetruss_joiner(w=1, vert=true);
|
||||
// cubetruss_joiner(w=2, vert=true, anchor=BOT);
|
||||
module cubetruss_joiner(w=1, vert=true, size=undef, strut=undef, clipthick=undef, anchor=CENTER, spin=0, orient=UP) {
|
||||
size = is_undef(size)? $cubetruss_size : size;
|
||||
strut = is_undef(strut)? $cubetruss_strut_size : strut;
|
||||
clipthick = is_undef(clipthick)? $cubetruss_clip_thickness : clipthick;
|
||||
clipsize = 0.5;
|
||||
s = [cubetruss_dist(w,1)+2*clipthick, cubetruss_dist(2,0)-0.1, strut+clipthick];
|
||||
attachable(anchor,spin,orient, size=s, offset=[0,0,-(clipthick-strut)/2]) {
|
||||
down(clipthick) {
|
||||
// Base
|
||||
cube([w*(size-strut)+strut+2*clipthick, size, clipthick], anchor=BOT);
|
||||
size = is_undef(size)? $cubetruss_size : size;
|
||||
strut = is_undef(strut)? $cubetruss_strut_size : strut;
|
||||
clipthick = is_undef(clipthick)? $cubetruss_clip_thickness : clipthick;
|
||||
clipsize = 0.5;
|
||||
s = [cubetruss_dist(w,1)+2*clipthick, cubetruss_dist(2,0)-0.1, strut+clipthick];
|
||||
attachable(anchor,spin,orient, size=s, offset=[0,0,-(clipthick-strut)/2]) {
|
||||
down(clipthick) {
|
||||
// Base
|
||||
cube([w*(size-strut)+strut+2*clipthick, size, clipthick], anchor=BOT);
|
||||
|
||||
xcopies(w*(size-strut)+strut+clipthick) {
|
||||
cube([clipthick, size, clipthick+strut*3/4], anchor=BOT);
|
||||
}
|
||||
xcopies(w*(size-strut)+strut+clipthick) {
|
||||
cube([clipthick, size, clipthick+strut*3/4], anchor=BOT);
|
||||
}
|
||||
|
||||
// Use feet
|
||||
ycopies(size) {
|
||||
cubetruss_foot(w=w, size=size, strut=strut, clipthick=clipthick, anchor=BOT);
|
||||
}
|
||||
// Use feet
|
||||
ycopies(size) {
|
||||
cubetruss_foot(w=w, size=size, strut=strut, clipthick=clipthick, anchor=BOT);
|
||||
}
|
||||
|
||||
if (vert) {
|
||||
// Vert Walls
|
||||
xcopies(w*(size-strut)+strut+clipthick) {
|
||||
up(clipthick-0.01) {
|
||||
prismoid([clipthick, size], [clipthick, 2*strut+2*clipthick], h=size*0.6, anchor=BOT);
|
||||
}
|
||||
}
|
||||
if (vert) {
|
||||
// Vert Walls
|
||||
xcopies(w*(size-strut)+strut+clipthick) {
|
||||
up(clipthick-0.01) {
|
||||
prismoid([clipthick, size], [clipthick, 2*strut+2*clipthick], h=size*0.6, anchor=BOT);
|
||||
}
|
||||
}
|
||||
|
||||
// Vert Wall Clips
|
||||
up(size/2) {
|
||||
xflip_copy(offset=(w*(size-strut)+strut+0.02)/2) {
|
||||
yflip_copy(offset=strut+$slop/2) {
|
||||
yrot(-90) {
|
||||
back_half() {
|
||||
prismoid([size/3.5, clipthick*2], [size/3.5-4*2*clipsize, 0.1], h=2*clipsize, anchor=BOT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
// Vert Wall Clips
|
||||
up(size/2) {
|
||||
xflip_copy(offset=(w*(size-strut)+strut+0.02)/2) {
|
||||
yflip_copy(offset=strut+$slop/2) {
|
||||
yrot(-90) {
|
||||
back_half() {
|
||||
prismoid([size/3.5, clipthick*2], [size/3.5-4*2*clipsize, 0.1], h=2*clipsize, anchor=BOT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -314,29 +314,29 @@ module cubetruss_joiner(w=1, vert=true, size=undef, strut=undef, clipthick=undef
|
||||
// cubetruss_uclip(dual=false);
|
||||
// cubetruss_uclip(dual=true);
|
||||
module cubetruss_uclip(dual=true, size=undef, strut=undef, clipthick=undef, anchor=CENTER, spin=0, orient=UP) {
|
||||
size = is_undef(size)? $cubetruss_size : size;
|
||||
strut = is_undef(strut)? $cubetruss_strut_size : strut;
|
||||
clipthick = is_undef(clipthick)? $cubetruss_clip_thickness : clipthick;
|
||||
clipsize = 0.5;
|
||||
s = [(dual?2:1)*strut+2*clipthick+$slop, strut+2*clipthick, size/3.5];
|
||||
attachable(anchor,spin,orient, size=s) {
|
||||
union() {
|
||||
difference() {
|
||||
cube(s, center=true);
|
||||
back(clipthick) cube([(dual?2:1)*strut+$slop, strut+2*clipthick, size+1], center=true);
|
||||
}
|
||||
back((strut+$slop)/2) {
|
||||
xflip_copy(offset=(dual?1:0.5)*strut+$slop/2) {
|
||||
yrot(-90) {
|
||||
back_half() {
|
||||
prismoid([size/3.5, clipthick*1.87], [size/3.5, 0.1], h=clipsize, anchor=BOT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
size = is_undef(size)? $cubetruss_size : size;
|
||||
strut = is_undef(strut)? $cubetruss_strut_size : strut;
|
||||
clipthick = is_undef(clipthick)? $cubetruss_clip_thickness : clipthick;
|
||||
clipsize = 0.5;
|
||||
s = [(dual?2:1)*strut+2*clipthick+$slop, strut+2*clipthick, size/3.5];
|
||||
attachable(anchor,spin,orient, size=s) {
|
||||
union() {
|
||||
difference() {
|
||||
cube(s, center=true);
|
||||
back(clipthick) cube([(dual?2:1)*strut+$slop, strut+2*clipthick, size+1], center=true);
|
||||
}
|
||||
back((strut+$slop)/2) {
|
||||
xflip_copy(offset=(dual?1:0.5)*strut+$slop/2) {
|
||||
yrot(-90) {
|
||||
back_half() {
|
||||
prismoid([size/3.5, clipthick*1.87], [size/3.5, 0.1], h=clipsize, anchor=BOT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -363,48 +363,48 @@ module cubetruss_uclip(dual=true, size=undef, strut=undef, clipthick=undef, anch
|
||||
// cubetruss(extents=[1,4,2]);
|
||||
// cubetruss(extents=[1,4,2], bracing=false);
|
||||
module cubetruss(extents=6, clips=[], bracing=undef, size=undef, strut=undef, clipthick=undef, anchor=CENTER, spin=0, orient=UP) {
|
||||
clips = is_vector(clips)? [clips] : clips;
|
||||
size = is_undef(size)? $cubetruss_size : size;
|
||||
strut = is_undef(strut)? $cubetruss_strut_size : strut;
|
||||
bracing = is_undef(bracing)? $cubetruss_bracing : bracing;
|
||||
clipthick = is_undef(clipthick)? $cubetruss_clip_thickness : clipthick;
|
||||
extents = is_vector(extents)? point3d(extents,fill=1) : [1,extents,1];
|
||||
w = extents[0];
|
||||
l = extents[1];
|
||||
h = extents[2];
|
||||
s = [cubetruss_dist(w,1), cubetruss_dist(l,1), cubetruss_dist(h,1)];
|
||||
attachable(anchor,spin,orient, size=s) {
|
||||
union() {
|
||||
for (zrow = [0:h-1]) {
|
||||
up((zrow-(h-1)/2)*(size-strut)) {
|
||||
for (xcol = [0:w-1]) {
|
||||
right((xcol-(w-1)/2)*(size-strut)) {
|
||||
for (ycol = [0:l-1]) {
|
||||
back((ycol-(l-1)/2)*(size-strut)) {
|
||||
cubetruss_segment(size=size, strut=strut, bracing=bracing);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (clipthick > 0) {
|
||||
for (vec = clips) {
|
||||
exts = vabs(rot(from=FWD, to=vec, p=extents));
|
||||
rot(from=FWD,to=vec) {
|
||||
for (zrow = [0:1:exts.z-1]) {
|
||||
up((zrow-(exts.z-1)/2)*(size-strut)) {
|
||||
fwd((exts.y*(size-strut)+strut)/2) {
|
||||
cubetruss_clip(size=size, strut=strut, extents=exts.x, clipthick=clipthick);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
clips = is_vector(clips)? [clips] : clips;
|
||||
size = is_undef(size)? $cubetruss_size : size;
|
||||
strut = is_undef(strut)? $cubetruss_strut_size : strut;
|
||||
bracing = is_undef(bracing)? $cubetruss_bracing : bracing;
|
||||
clipthick = is_undef(clipthick)? $cubetruss_clip_thickness : clipthick;
|
||||
extents = is_vector(extents)? point3d(extents,fill=1) : [1,extents,1];
|
||||
w = extents[0];
|
||||
l = extents[1];
|
||||
h = extents[2];
|
||||
s = [cubetruss_dist(w,1), cubetruss_dist(l,1), cubetruss_dist(h,1)];
|
||||
attachable(anchor,spin,orient, size=s) {
|
||||
union() {
|
||||
for (zrow = [0:h-1]) {
|
||||
up((zrow-(h-1)/2)*(size-strut)) {
|
||||
for (xcol = [0:w-1]) {
|
||||
right((xcol-(w-1)/2)*(size-strut)) {
|
||||
for (ycol = [0:l-1]) {
|
||||
back((ycol-(l-1)/2)*(size-strut)) {
|
||||
cubetruss_segment(size=size, strut=strut, bracing=bracing);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (clipthick > 0) {
|
||||
for (vec = clips) {
|
||||
exts = vabs(rot(from=FWD, to=vec, p=extents));
|
||||
rot(from=FWD,to=vec) {
|
||||
for (zrow = [0:1:exts.z-1]) {
|
||||
up((zrow-(exts.z-1)/2)*(size-strut)) {
|
||||
fwd((exts.y*(size-strut)+strut)/2) {
|
||||
cubetruss_clip(size=size, strut=strut, extents=exts.x, clipthick=clipthick);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -430,53 +430,53 @@ module cubetruss(extents=6, clips=[], bracing=undef, size=undef, strut=undef, cl
|
||||
// cubetruss_corner(extents=[3,0,3,0,2]);
|
||||
// cubetruss_corner(extents=[3,3,3,3,2]);
|
||||
module cubetruss_corner(h=1, extents=[1,1,0,0,1], bracing=undef, size=undef, strut=undef, clipthick=undef, anchor=CENTER, spin=0, orient=UP) {
|
||||
size = is_undef(size)? $cubetruss_size : size;
|
||||
strut = is_undef(strut)? $cubetruss_strut_size : strut;
|
||||
bracing = is_undef(bracing)? $cubetruss_bracing : bracing;
|
||||
clipthick = is_undef(clipthick)? $cubetruss_clip_thickness : clipthick;
|
||||
exts = is_vector(extents)? list_fit(extents,5,fill=0) : [extents, extents, 0, 0, extents];
|
||||
s = [cubetruss_dist(1+exts[0]+exts[2],1), cubetruss_dist(1+exts[1]+exts[3],1), cubetruss_dist(h+exts[4],1)];
|
||||
offset = [cubetruss_dist(exts[0]-exts[2],0), cubetruss_dist(exts[1]-exts[3],0), cubetruss_dist(exts[4],0)]/2;
|
||||
attachable(anchor,spin,orient, size=s, offset=offset) {
|
||||
union() {
|
||||
for (zcol = [0:h-1]) {
|
||||
up((size-strut+0.01)*zcol) {
|
||||
cubetruss_segment(size=size, strut=strut, bracing=bracing);
|
||||
}
|
||||
}
|
||||
for (dir = [0:3]) {
|
||||
if (exts[dir] != undef && exts[dir] > 0) {
|
||||
zrot(dir*90) {
|
||||
for (zcol = [0:h-1]) {
|
||||
up((size-strut+0.01)*zcol) {
|
||||
for (i = [1:exts[dir]]) {
|
||||
right((size-strut+0.01)*i) cubetruss_segment(size=size, strut=strut, bracing=bracing);
|
||||
}
|
||||
if (clipthick > 0) {
|
||||
right(exts[dir]*(size-strut)+size/2) {
|
||||
zrot(90) cubetruss_clip(size=size, strut=strut, clipthick=clipthick);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (exts[4] != undef && exts[4] > 0) {
|
||||
for (i = [1:exts[4]]) {
|
||||
up((size-strut+0.01)*(i+h-1)) cubetruss_segment(size=size, strut=strut, bracing=bracing);
|
||||
}
|
||||
if (clipthick > 0) {
|
||||
up((exts[4]+h-1)*(size-strut)+size/2) {
|
||||
xrot(-90) cubetruss_clip(size=size, strut=strut, clipthick=clipthick);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
size = is_undef(size)? $cubetruss_size : size;
|
||||
strut = is_undef(strut)? $cubetruss_strut_size : strut;
|
||||
bracing = is_undef(bracing)? $cubetruss_bracing : bracing;
|
||||
clipthick = is_undef(clipthick)? $cubetruss_clip_thickness : clipthick;
|
||||
exts = is_vector(extents)? list_fit(extents,5,fill=0) : [extents, extents, 0, 0, extents];
|
||||
s = [cubetruss_dist(1+exts[0]+exts[2],1), cubetruss_dist(1+exts[1]+exts[3],1), cubetruss_dist(h+exts[4],1)];
|
||||
offset = [cubetruss_dist(exts[0]-exts[2],0), cubetruss_dist(exts[1]-exts[3],0), cubetruss_dist(exts[4],0)]/2;
|
||||
attachable(anchor,spin,orient, size=s, offset=offset) {
|
||||
union() {
|
||||
for (zcol = [0:h-1]) {
|
||||
up((size-strut+0.01)*zcol) {
|
||||
cubetruss_segment(size=size, strut=strut, bracing=bracing);
|
||||
}
|
||||
}
|
||||
for (dir = [0:3]) {
|
||||
if (exts[dir] != undef && exts[dir] > 0) {
|
||||
zrot(dir*90) {
|
||||
for (zcol = [0:h-1]) {
|
||||
up((size-strut+0.01)*zcol) {
|
||||
for (i = [1:exts[dir]]) {
|
||||
right((size-strut+0.01)*i) cubetruss_segment(size=size, strut=strut, bracing=bracing);
|
||||
}
|
||||
if (clipthick > 0) {
|
||||
right(exts[dir]*(size-strut)+size/2) {
|
||||
zrot(90) cubetruss_clip(size=size, strut=strut, clipthick=clipthick);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (exts[4] != undef && exts[4] > 0) {
|
||||
for (i = [1:exts[4]]) {
|
||||
up((size-strut+0.01)*(i+h-1)) cubetruss_segment(size=size, strut=strut, bracing=bracing);
|
||||
}
|
||||
if (clipthick > 0) {
|
||||
up((exts[4]+h-1)*(size-strut)+size/2) {
|
||||
xrot(-90) cubetruss_clip(size=size, strut=strut, clipthick=clipthick);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
470
debug.scad
470
debug.scad
@ -28,33 +28,33 @@ include <skin.scad>
|
||||
// polyline = [for (a=[0:30:210]) 10*[cos(a), sin(a), sin(a)]];
|
||||
// trace_polyline(polyline, showpts=true, size=0.5, color="lightgreen");
|
||||
module trace_polyline(pline, closed=false, showpts=false, N=1, size=1, color="yellow") {
|
||||
assert(is_path(pline),"Input pline is not a path");
|
||||
sides = segs(size/2);
|
||||
pline = closed? close_path(pline) : pline;
|
||||
if (showpts) {
|
||||
for (i = [0:1:len(pline)-1]) {
|
||||
translate(pline[i]) {
|
||||
if (i%N == 0) {
|
||||
color("blue") sphere(d=size*2.5, $fn=8);
|
||||
} else {
|
||||
color("red") {
|
||||
cylinder(d=size/2, h=size*3, center=true, $fn=8);
|
||||
xrot(90) cylinder(d=size/2, h=size*3, center=true, $fn=8);
|
||||
yrot(90) cylinder(d=size/2, h=size*3, center=true, $fn=8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (N!=3) {
|
||||
color(color) stroke(path3d(pline), width=size, $fn=8);
|
||||
} else {
|
||||
for (i = [0:1:len(pline)-2]) {
|
||||
if (N!=3 || (i%N) != 1) {
|
||||
color(color) extrude_from_to(pline[i], pline[i+1]) circle(d=size, $fn=sides);
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(is_path(pline),"Input pline is not a path");
|
||||
sides = segs(size/2);
|
||||
pline = closed? close_path(pline) : pline;
|
||||
if (showpts) {
|
||||
for (i = [0:1:len(pline)-1]) {
|
||||
translate(pline[i]) {
|
||||
if (i%N == 0) {
|
||||
color("blue") sphere(d=size*2.5, $fn=8);
|
||||
} else {
|
||||
color("red") {
|
||||
cylinder(d=size/2, h=size*3, center=true, $fn=8);
|
||||
xrot(90) cylinder(d=size/2, h=size*3, center=true, $fn=8);
|
||||
yrot(90) cylinder(d=size/2, h=size*3, center=true, $fn=8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (N!=3) {
|
||||
color(color) stroke(path3d(pline), width=size, $fn=8);
|
||||
} else {
|
||||
for (i = [0:1:len(pline)-2]) {
|
||||
if (N!=3 || (i%N) != 1) {
|
||||
color(color) extrude_from_to(pline[i], pline[i+1]) circle(d=size, $fn=sides);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -77,44 +77,44 @@ module trace_polyline(pline, closed=false, showpts=false, N=1, size=1, color="ye
|
||||
// );
|
||||
module debug_polygon(points, paths=undef, convexity=2, size=1)
|
||||
{
|
||||
pths = is_undef(paths)? [for (i=[0:1:len(points)-1]) i] : is_num(paths[0])? [paths] : paths;
|
||||
echo(points=points);
|
||||
echo(paths=paths);
|
||||
linear_extrude(height=0.01, convexity=convexity, center=true) {
|
||||
polygon(points=points, paths=paths, convexity=convexity);
|
||||
}
|
||||
for (i = [0:1:len(points)-1]) {
|
||||
color("red") {
|
||||
up(0.2) {
|
||||
translate(points[i]) {
|
||||
linear_extrude(height=0.1, convexity=10, center=true) {
|
||||
text(text=str(i), size=size, halign="center", valign="center");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (j = [0:1:len(paths)-1]) {
|
||||
path = paths[j];
|
||||
translate(points[path[0]]) {
|
||||
color("cyan") up(0.1) cylinder(d=size*1.5, h=0.01, center=false, $fn=12);
|
||||
}
|
||||
translate(points[path[len(path)-1]]) {
|
||||
color("pink") up(0.11) cylinder(d=size*1.5, h=0.01, center=false, $fn=4);
|
||||
}
|
||||
for (i = [0:1:len(path)-1]) {
|
||||
midpt = (points[path[i]] + points[path[(i+1)%len(path)]])/2;
|
||||
color("blue") {
|
||||
up(0.2) {
|
||||
translate(midpt) {
|
||||
linear_extrude(height=0.1, convexity=10, center=true) {
|
||||
text(text=str(chr(65+j),i), size=size/2, halign="center", valign="center");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pths = is_undef(paths)? [for (i=[0:1:len(points)-1]) i] : is_num(paths[0])? [paths] : paths;
|
||||
echo(points=points);
|
||||
echo(paths=paths);
|
||||
linear_extrude(height=0.01, convexity=convexity, center=true) {
|
||||
polygon(points=points, paths=paths, convexity=convexity);
|
||||
}
|
||||
for (i = [0:1:len(points)-1]) {
|
||||
color("red") {
|
||||
up(0.2) {
|
||||
translate(points[i]) {
|
||||
linear_extrude(height=0.1, convexity=10, center=true) {
|
||||
text(text=str(i), size=size, halign="center", valign="center");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (j = [0:1:len(paths)-1]) {
|
||||
path = paths[j];
|
||||
translate(points[path[0]]) {
|
||||
color("cyan") up(0.1) cylinder(d=size*1.5, h=0.01, center=false, $fn=12);
|
||||
}
|
||||
translate(points[path[len(path)-1]]) {
|
||||
color("pink") up(0.11) cylinder(d=size*1.5, h=0.01, center=false, $fn=4);
|
||||
}
|
||||
for (i = [0:1:len(path)-1]) {
|
||||
midpt = (points[path[i]] + points[path[(i+1)%len(path)]])/2;
|
||||
color("blue") {
|
||||
up(0.2) {
|
||||
translate(midpt) {
|
||||
linear_extrude(height=0.1, convexity=10, center=true) {
|
||||
text(text=str(chr(65+j),i), size=size/2, halign="center", valign="center");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -138,29 +138,29 @@ module debug_polygon(points, paths=undef, convexity=2, size=1)
|
||||
// polyhedron(points=verts, faces=faces);
|
||||
// }
|
||||
module debug_vertices(vertices, size=1, disabled=false) {
|
||||
if (!disabled) {
|
||||
echo(vertices=vertices);
|
||||
color("blue") {
|
||||
for (i = [0:1:len(vertices)-1]) {
|
||||
v = vertices[i];
|
||||
translate(v) {
|
||||
up(size/8) zrot($vpr[2]) xrot(90) {
|
||||
linear_extrude(height=size/10, center=true, convexity=10) {
|
||||
text(text=str(i), size=size, halign="center");
|
||||
}
|
||||
}
|
||||
sphere(size/10);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($children > 0) {
|
||||
if (!disabled) {
|
||||
color([0.2, 1.0, 0, 0.5]) children();
|
||||
} else {
|
||||
children();
|
||||
}
|
||||
}
|
||||
if (!disabled) {
|
||||
echo(vertices=vertices);
|
||||
color("blue") {
|
||||
for (i = [0:1:len(vertices)-1]) {
|
||||
v = vertices[i];
|
||||
translate(v) {
|
||||
up(size/8) zrot($vpr[2]) xrot(90) {
|
||||
linear_extrude(height=size/10, center=true, convexity=10) {
|
||||
text(text=str(i), size=size, halign="center");
|
||||
}
|
||||
}
|
||||
sphere(size/10);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($children > 0) {
|
||||
if (!disabled) {
|
||||
color([0.2, 1.0, 0, 0.5]) children();
|
||||
} else {
|
||||
children();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -183,46 +183,46 @@ module debug_vertices(vertices, size=1, disabled=false) {
|
||||
// polyhedron(points=verts, faces=faces);
|
||||
// }
|
||||
module debug_faces(vertices, faces, size=1, disabled=false) {
|
||||
if (!disabled) {
|
||||
vlen = len(vertices);
|
||||
color("red") {
|
||||
for (i = [0:1:len(faces)-1]) {
|
||||
face = faces[i];
|
||||
if (face[0] < 0 || face[1] < 0 || face[2] < 0 || face[0] >= vlen || face[1] >= vlen || face[2] >= vlen) {
|
||||
echo("BAD FACE: ", vlen=vlen, face=face);
|
||||
} else {
|
||||
v0 = vertices[face[0]];
|
||||
v1 = vertices[face[1]];
|
||||
v2 = vertices[face[2]];
|
||||
c = mean(select(vertices,face));
|
||||
dv0 = unit(v1 - v0);
|
||||
dv1 = unit(v2 - v0);
|
||||
nrm0 = unit(cross(dv0, dv1));
|
||||
nrm1 = [0, 0, 1];
|
||||
axis = unit(cross(nrm0, nrm1));
|
||||
ang = vector_angle(nrm0, nrm1);
|
||||
theta = atan2(nrm0[1], nrm0[0]);
|
||||
translate(c) {
|
||||
rotate(a=180-ang, v=axis) {
|
||||
zrot(theta-90)
|
||||
linear_extrude(height=size/10, center=true, convexity=10) {
|
||||
union() {
|
||||
text(text=str(i), size=size, halign="center");
|
||||
text(text=str("_"), size=size, halign="center");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
debug_vertices(vertices, size=size, disabled=disabled) {
|
||||
children();
|
||||
}
|
||||
if (!disabled) {
|
||||
echo(faces=faces);
|
||||
}
|
||||
if (!disabled) {
|
||||
vlen = len(vertices);
|
||||
color("red") {
|
||||
for (i = [0:1:len(faces)-1]) {
|
||||
face = faces[i];
|
||||
if (face[0] < 0 || face[1] < 0 || face[2] < 0 || face[0] >= vlen || face[1] >= vlen || face[2] >= vlen) {
|
||||
echo("BAD FACE: ", vlen=vlen, face=face);
|
||||
} else {
|
||||
v0 = vertices[face[0]];
|
||||
v1 = vertices[face[1]];
|
||||
v2 = vertices[face[2]];
|
||||
c = mean(select(vertices,face));
|
||||
dv0 = unit(v1 - v0);
|
||||
dv1 = unit(v2 - v0);
|
||||
nrm0 = unit(cross(dv0, dv1));
|
||||
nrm1 = [0, 0, 1];
|
||||
axis = unit(cross(nrm0, nrm1));
|
||||
ang = vector_angle(nrm0, nrm1);
|
||||
theta = atan2(nrm0[1], nrm0[0]);
|
||||
translate(c) {
|
||||
rotate(a=180-ang, v=axis) {
|
||||
zrot(theta-90)
|
||||
linear_extrude(height=size/10, center=true, convexity=10) {
|
||||
union() {
|
||||
text(text=str(i), size=size, halign="center");
|
||||
text(text=str("_"), size=size, halign="center");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
debug_vertices(vertices, size=size, disabled=disabled) {
|
||||
children();
|
||||
}
|
||||
if (!disabled) {
|
||||
echo(faces=faces);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -245,9 +245,9 @@ module debug_faces(vertices, faces, size=1, disabled=false) {
|
||||
// faces = [[0,1,2], [5,4,3], [0,3,4], [0,4,1], [1,4,5], [1,5,2], [2,5,3], [2,3,0]];
|
||||
// debug_polyhedron(points=verts, faces=faces, txtsize=1);
|
||||
module debug_polyhedron(points, faces, convexity=10, txtsize=1, disabled=false) {
|
||||
debug_faces(vertices=points, faces=faces, size=txtsize, disabled=disabled) {
|
||||
polyhedron(points=points, faces=faces, convexity=convexity);
|
||||
}
|
||||
debug_faces(vertices=points, faces=faces, size=txtsize, disabled=disabled) {
|
||||
polyhedron(points=points, faces=faces, convexity=convexity);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -256,11 +256,11 @@ module debug_polyhedron(points, faces, convexity=10, txtsize=1, disabled=false)
|
||||
// Description:
|
||||
// Return the vectors for all standard anchors.
|
||||
function standard_anchors() = [
|
||||
for (
|
||||
zv = [TOP, CENTER, BOTTOM],
|
||||
yv = [FRONT, CENTER, BACK],
|
||||
xv = [LEFT, CENTER, RIGHT]
|
||||
) xv+yv+zv
|
||||
for (
|
||||
zv = [TOP, CENTER, BOTTOM],
|
||||
yv = [FRONT, CENTER, BACK],
|
||||
xv = [LEFT, CENTER, RIGHT]
|
||||
) xv+yv+zv
|
||||
];
|
||||
|
||||
|
||||
@ -277,19 +277,19 @@ function standard_anchors() = [
|
||||
// Example:
|
||||
// anchor_arrow(s=20);
|
||||
module anchor_arrow(s=10, color=[0.333,0.333,1], flag=true, $tags="anchor-arrow") {
|
||||
$fn=12;
|
||||
recolor("gray") spheroid(d=s/6) {
|
||||
attach(CENTER,BOT) recolor(color) cyl(h=s*2/3, d=s/15) {
|
||||
attach(TOP,BOT) cyl(h=s/3, d1=s/5, d2=0) {
|
||||
if(flag) {
|
||||
position(BOT)
|
||||
recolor([1,0.5,0.5])
|
||||
cuboid([s/100, s/6, s/4], anchor=FRONT+BOT);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
}
|
||||
$fn=12;
|
||||
recolor("gray") spheroid(d=s/6) {
|
||||
attach(CENTER,BOT) recolor(color) cyl(h=s*2/3, d=s/15) {
|
||||
attach(TOP,BOT) cyl(h=s/3, d1=s/5, d2=0) {
|
||||
if(flag) {
|
||||
position(BOT)
|
||||
recolor([1,0.5,0.5])
|
||||
cuboid([s/100, s/6, s/4], anchor=FRONT+BOT);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -303,8 +303,8 @@ module anchor_arrow(s=10, color=[0.333,0.333,1], flag=true, $tags="anchor-arrow"
|
||||
// Example(FlatSpin):
|
||||
// show_internal_anchors() cube(50, center=true) show_anchors();
|
||||
module show_internal_anchors(opacity=0.2) {
|
||||
show("anchor-arrow") children() show_anchors();
|
||||
hide("anchor-arrow") recolor(list_pad(point3d($color),4,fill=opacity)) children();
|
||||
show("anchor-arrow") children() show_anchors();
|
||||
hide("anchor-arrow") recolor(list_pad(point3d($color),4,fill=opacity)) children();
|
||||
}
|
||||
|
||||
|
||||
@ -318,29 +318,29 @@ module show_internal_anchors(opacity=0.2) {
|
||||
// Example(FlatSpin):
|
||||
// cube(50, center=true) show_anchors();
|
||||
module show_anchors(s=10, std=true, custom=true) {
|
||||
if (std) {
|
||||
for (anchor=standard_anchors()) {
|
||||
attach(anchor) anchor_arrow(s);
|
||||
}
|
||||
}
|
||||
if (custom) {
|
||||
for (anchor=select($parent_geom,-1)) {
|
||||
attach(anchor[0]) {
|
||||
anchor_arrow(s, color="cyan");
|
||||
recolor("black")
|
||||
noop($tags="anchor-arrow") {
|
||||
xrot(90) {
|
||||
up(s/10) {
|
||||
linear_extrude(height=0.01, convexity=12, center=true) {
|
||||
text(text=anchor[0], size=s/4, halign="center", valign="center");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
if (std) {
|
||||
for (anchor=standard_anchors()) {
|
||||
attach(anchor) anchor_arrow(s);
|
||||
}
|
||||
}
|
||||
if (custom) {
|
||||
for (anchor=select($parent_geom,-1)) {
|
||||
attach(anchor[0]) {
|
||||
anchor_arrow(s, color="cyan");
|
||||
recolor("black")
|
||||
noop($tags="anchor-arrow") {
|
||||
xrot(90) {
|
||||
up(s/10) {
|
||||
linear_extrude(height=0.01, convexity=12, center=true) {
|
||||
text(text=anchor[0], size=s/4, halign="center", valign="center");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
|
||||
|
||||
@ -353,12 +353,12 @@ module show_anchors(s=10, std=true, custom=true) {
|
||||
// Examples:
|
||||
// frame_ref(25);
|
||||
module frame_ref(s=15) {
|
||||
cube(0.01, center=true) {
|
||||
attach(RIGHT) anchor_arrow(s=s, flag=false, color="red");
|
||||
attach(BACK) anchor_arrow(s=s, flag=false, color="green");
|
||||
attach(TOP) anchor_arrow(s=s, flag=false, color="blue");
|
||||
children();
|
||||
}
|
||||
cube(0.01, center=true) {
|
||||
attach(RIGHT) anchor_arrow(s=s, flag=false, color="red");
|
||||
attach(BACK) anchor_arrow(s=s, flag=false, color="green");
|
||||
attach(TOP) anchor_arrow(s=s, flag=false, color="blue");
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -389,63 +389,63 @@ module frame_ref(s=15) {
|
||||
// fwd(50)ruler(300,width=50,labels=true);
|
||||
module ruler(length=100, width=undef, thickness=1, depth=3, labels=false, pipscale=1/3, maxscale=undef, colors=["black","white"], alpha=1.0, unit=1, inch=false, anchor=LEFT+BACK+TOP, spin=0, orient=UP)
|
||||
{
|
||||
inchfactor = 25.4;
|
||||
assert(depth<=5, "Cannot render scales smaller than depth=5");
|
||||
assert(len(colors)==2, "colors must contain a list of exactly two colors.");
|
||||
length = inch ? inchfactor * length : length;
|
||||
unit = inch ? inchfactor*unit : unit;
|
||||
maxscale = is_def(maxscale)? maxscale : floor(log(length/unit-EPSILON));
|
||||
scales = unit * [for(logsize = [maxscale:-1:maxscale-depth+1]) pow(10,logsize)];
|
||||
widthfactor = (1-pipscale) / (1-pow(pipscale,depth));
|
||||
width = default(width, scales[0]);
|
||||
widths = width * widthfactor * [for(logsize = [0:-1:-depth+1]) pow(pipscale,-logsize)];
|
||||
offsets = concat([0],cumsum(widths));
|
||||
attachable(anchor,spin,orient, size=[length,width,thickness]) {
|
||||
translate([-length/2, -width/2, 0])
|
||||
for(i=[0:1:len(scales)-1]) {
|
||||
count = ceil(length/scales[i]);
|
||||
fontsize = 0.5*min(widths[i], scales[i]/ceil(log(count*scales[i]/unit)));
|
||||
back(offsets[i]) {
|
||||
xcopies(scales[i], n=count, sp=[0,0,0]) union() {
|
||||
actlen = ($idx<count-1) || approx(length%scales[i],0) ? scales[i] : length % scales[i];
|
||||
color(colors[$idx%2], alpha=alpha) {
|
||||
w = i>0 ? quantup(widths[i],1/1024) : widths[i]; // What is the i>0 test supposed to do here?
|
||||
cube([quantup(actlen,1/1024),quantup(w,1/1024),thickness], anchor=FRONT+LEFT);
|
||||
}
|
||||
mark =
|
||||
i == 0 && $idx % 10 == 0 && $idx != 0 ? 0 :
|
||||
i == 0 && $idx % 10 == 9 && $idx != count-1 ? 1 :
|
||||
$idx % 10 == 4 ? 1 :
|
||||
$idx % 10 == 5 ? 0 : -1;
|
||||
flip = 1-mark*2;
|
||||
if (mark >= 0) {
|
||||
marklength = min(widths[i]/2, scales[i]*2);
|
||||
markwidth = marklength*0.4;
|
||||
translate([mark*scales[i], widths[i], 0]) {
|
||||
color(colors[1-$idx%2], alpha=alpha) {
|
||||
linear_extrude(height=thickness+scales[i]/100, convexity=2, center=true) {
|
||||
polygon(scale([flip*markwidth, marklength],p=[[0,0], [1, -1], [0,-0.9]]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (labels && scales[i]/unit+EPSILON >= 1) {
|
||||
color(colors[($idx+1)%2], alpha=alpha) {
|
||||
linear_extrude(height=thickness+scales[i]/100, convexity=2, center=true) {
|
||||
back(scales[i]*.02) {
|
||||
text(text=str( $idx * scales[i] / unit), size=fontsize, halign="left", valign="baseline");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
inchfactor = 25.4;
|
||||
assert(depth<=5, "Cannot render scales smaller than depth=5");
|
||||
assert(len(colors)==2, "colors must contain a list of exactly two colors.");
|
||||
length = inch ? inchfactor * length : length;
|
||||
unit = inch ? inchfactor*unit : unit;
|
||||
maxscale = is_def(maxscale)? maxscale : floor(log(length/unit-EPSILON));
|
||||
scales = unit * [for(logsize = [maxscale:-1:maxscale-depth+1]) pow(10,logsize)];
|
||||
widthfactor = (1-pipscale) / (1-pow(pipscale,depth));
|
||||
width = default(width, scales[0]);
|
||||
widths = width * widthfactor * [for(logsize = [0:-1:-depth+1]) pow(pipscale,-logsize)];
|
||||
offsets = concat([0],cumsum(widths));
|
||||
attachable(anchor,spin,orient, size=[length,width,thickness]) {
|
||||
translate([-length/2, -width/2, 0])
|
||||
for(i=[0:1:len(scales)-1]) {
|
||||
count = ceil(length/scales[i]);
|
||||
fontsize = 0.5*min(widths[i], scales[i]/ceil(log(count*scales[i]/unit)));
|
||||
back(offsets[i]) {
|
||||
xcopies(scales[i], n=count, sp=[0,0,0]) union() {
|
||||
actlen = ($idx<count-1) || approx(length%scales[i],0) ? scales[i] : length % scales[i];
|
||||
color(colors[$idx%2], alpha=alpha) {
|
||||
w = i>0 ? quantup(widths[i],1/1024) : widths[i]; // What is the i>0 test supposed to do here?
|
||||
cube([quantup(actlen,1/1024),quantup(w,1/1024),thickness], anchor=FRONT+LEFT);
|
||||
}
|
||||
mark =
|
||||
i == 0 && $idx % 10 == 0 && $idx != 0 ? 0 :
|
||||
i == 0 && $idx % 10 == 9 && $idx != count-1 ? 1 :
|
||||
$idx % 10 == 4 ? 1 :
|
||||
$idx % 10 == 5 ? 0 : -1;
|
||||
flip = 1-mark*2;
|
||||
if (mark >= 0) {
|
||||
marklength = min(widths[i]/2, scales[i]*2);
|
||||
markwidth = marklength*0.4;
|
||||
translate([mark*scales[i], widths[i], 0]) {
|
||||
color(colors[1-$idx%2], alpha=alpha) {
|
||||
linear_extrude(height=thickness+scales[i]/100, convexity=2, center=true) {
|
||||
polygon(scale([flip*markwidth, marklength],p=[[0,0], [1, -1], [0,-0.9]]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (labels && scales[i]/unit+EPSILON >= 1) {
|
||||
color(colors[($idx+1)%2], alpha=alpha) {
|
||||
linear_extrude(height=thickness+scales[i]/100, convexity=2, center=true) {
|
||||
back(scales[i]*.02) {
|
||||
text(text=str( $idx * scales[i] / unit), size=fontsize, halign="left", valign="baseline");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -33,12 +33,12 @@
|
||||
// move_copies([[-25,-25,0], [25,-25,0], [0,0,50], [0,25,0]]) sphere(r=10);
|
||||
module move_copies(a=[[0,0,0]])
|
||||
{
|
||||
assert(is_list(a));
|
||||
for ($idx = idx(a)) {
|
||||
$pos = a[$idx];
|
||||
assert(is_vector($pos));
|
||||
translate($pos) children();
|
||||
}
|
||||
assert(is_list(a));
|
||||
for ($idx = idx(a)) {
|
||||
$pos = a[$idx];
|
||||
assert(is_vector($pos));
|
||||
translate($pos) children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -80,30 +80,30 @@ module move_copies(a=[[0,0,0]])
|
||||
// }
|
||||
module line_of(p1, p2, spacing, l, n)
|
||||
{
|
||||
ll = (
|
||||
!is_undef(l)? scalar_vec3(l, 0) :
|
||||
(!is_undef(spacing) && !is_undef(n))? (n * scalar_vec3(spacing, 0)) :
|
||||
(!is_undef(p1) && !is_undef(p2))? point3d(p2-p1) :
|
||||
undef
|
||||
);
|
||||
cnt = (
|
||||
!is_undef(n)? n :
|
||||
(!is_undef(spacing) && !is_undef(ll))? floor(norm(ll) / norm(scalar_vec3(spacing, 0)) + 1.000001) :
|
||||
2
|
||||
);
|
||||
spc = (
|
||||
is_undef(spacing)? (ll/(cnt-1)) :
|
||||
is_num(spacing) && !is_undef(ll)? (ll/(cnt-1)) :
|
||||
scalar_vec3(spacing, 0)
|
||||
);
|
||||
assert(!is_undef(cnt), "Need two of `spacing`, 'l', 'n', or `p1`/`p2` arguments in `line_of()`.");
|
||||
spos = !is_undef(p1)? point3d(p1) : -(cnt-1)/2 * spc;
|
||||
for (i=[0:1:cnt-1]) {
|
||||
pos = i * spc + spos;
|
||||
$pos = pos;
|
||||
$idx = i;
|
||||
translate(pos) children();
|
||||
}
|
||||
ll = (
|
||||
!is_undef(l)? scalar_vec3(l, 0) :
|
||||
(!is_undef(spacing) && !is_undef(n))? (n * scalar_vec3(spacing, 0)) :
|
||||
(!is_undef(p1) && !is_undef(p2))? point3d(p2-p1) :
|
||||
undef
|
||||
);
|
||||
cnt = (
|
||||
!is_undef(n)? n :
|
||||
(!is_undef(spacing) && !is_undef(ll))? floor(norm(ll) / norm(scalar_vec3(spacing, 0)) + 1.000001) :
|
||||
2
|
||||
);
|
||||
spc = (
|
||||
is_undef(spacing)? (ll/(cnt-1)) :
|
||||
is_num(spacing) && !is_undef(ll)? (ll/(cnt-1)) :
|
||||
scalar_vec3(spacing, 0)
|
||||
);
|
||||
assert(!is_undef(cnt), "Need two of `spacing`, 'l', 'n', or `p1`/`p2` arguments in `line_of()`.");
|
||||
spos = !is_undef(p1)? point3d(p1) : -(cnt-1)/2 * spc;
|
||||
for (i=[0:1:cnt-1]) {
|
||||
pos = i * spc + spos;
|
||||
$pos = pos;
|
||||
$idx = i;
|
||||
translate(pos) children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -138,7 +138,7 @@ module line_of(p1, p2, spacing, l, n)
|
||||
// }
|
||||
module xcopies(spacing, n, l, sp)
|
||||
{
|
||||
line_of(l=l*RIGHT, spacing=spacing*RIGHT, n=n, p1=sp) children();
|
||||
line_of(l=l*RIGHT, spacing=spacing*RIGHT, n=n, p1=sp) children();
|
||||
}
|
||||
|
||||
|
||||
@ -173,7 +173,7 @@ module xcopies(spacing, n, l, sp)
|
||||
// }
|
||||
module ycopies(spacing, n, l, sp)
|
||||
{
|
||||
line_of(l=l*BACK, spacing=spacing*BACK, n=n, p1=sp) children();
|
||||
line_of(l=l*BACK, spacing=spacing*BACK, n=n, p1=sp) children();
|
||||
}
|
||||
|
||||
|
||||
@ -208,7 +208,7 @@ module ycopies(spacing, n, l, sp)
|
||||
// }
|
||||
module zcopies(spacing, n, l, sp)
|
||||
{
|
||||
line_of(l=l*UP, spacing=spacing*UP, n=n, p1=sp) children();
|
||||
line_of(l=l*UP, spacing=spacing*UP, n=n, p1=sp) children();
|
||||
}
|
||||
|
||||
|
||||
@ -243,18 +243,18 @@ module zcopies(spacing, n, l, sp)
|
||||
// }
|
||||
module distribute(spacing=undef, sizes=undef, dir=RIGHT, l=undef)
|
||||
{
|
||||
gaps = ($children < 2)? [0] :
|
||||
!is_undef(sizes)? [for (i=[0:1:$children-2]) sizes[i]/2 + sizes[i+1]/2] :
|
||||
[for (i=[0:1:$children-2]) 0];
|
||||
spc = !is_undef(l)? ((l - sum(gaps)) / ($children-1)) : default(spacing, 10);
|
||||
gaps2 = [for (gap = gaps) gap+spc];
|
||||
spos = dir * -sum(gaps2)/2;
|
||||
for (i=[0:1:$children-1]) {
|
||||
totspc = sum(concat([0], slice(gaps2, 0, i)));
|
||||
$pos = spos + totspc * dir;
|
||||
$idx = i;
|
||||
translate($pos) children(i);
|
||||
}
|
||||
gaps = ($children < 2)? [0] :
|
||||
!is_undef(sizes)? [for (i=[0:1:$children-2]) sizes[i]/2 + sizes[i+1]/2] :
|
||||
[for (i=[0:1:$children-2]) 0];
|
||||
spc = !is_undef(l)? ((l - sum(gaps)) / ($children-1)) : default(spacing, 10);
|
||||
gaps2 = [for (gap = gaps) gap+spc];
|
||||
spos = dir * -sum(gaps2)/2;
|
||||
for (i=[0:1:$children-1]) {
|
||||
totspc = sum(concat([0], slice(gaps2, 0, i)));
|
||||
$pos = spos + totspc * dir;
|
||||
$idx = i;
|
||||
translate($pos) children(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -287,19 +287,19 @@ module distribute(spacing=undef, sizes=undef, dir=RIGHT, l=undef)
|
||||
// }
|
||||
module xdistribute(spacing=10, sizes=undef, l=undef)
|
||||
{
|
||||
dir = RIGHT;
|
||||
gaps = ($children < 2)? [0] :
|
||||
!is_undef(sizes)? [for (i=[0:1:$children-2]) sizes[i]/2 + sizes[i+1]/2] :
|
||||
[for (i=[0:1:$children-2]) 0];
|
||||
spc = !is_undef(l)? ((l - sum(gaps)) / ($children-1)) : default(spacing, 10);
|
||||
gaps2 = [for (gap = gaps) gap+spc];
|
||||
spos = dir * -sum(gaps2)/2;
|
||||
for (i=[0:1:$children-1]) {
|
||||
totspc = sum(concat([0], slice(gaps2, 0, i)));
|
||||
$pos = spos + totspc * dir;
|
||||
$idx = i;
|
||||
translate($pos) children(i);
|
||||
}
|
||||
dir = RIGHT;
|
||||
gaps = ($children < 2)? [0] :
|
||||
!is_undef(sizes)? [for (i=[0:1:$children-2]) sizes[i]/2 + sizes[i+1]/2] :
|
||||
[for (i=[0:1:$children-2]) 0];
|
||||
spc = !is_undef(l)? ((l - sum(gaps)) / ($children-1)) : default(spacing, 10);
|
||||
gaps2 = [for (gap = gaps) gap+spc];
|
||||
spos = dir * -sum(gaps2)/2;
|
||||
for (i=[0:1:$children-1]) {
|
||||
totspc = sum(concat([0], slice(gaps2, 0, i)));
|
||||
$pos = spos + totspc * dir;
|
||||
$idx = i;
|
||||
translate($pos) children(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -332,19 +332,19 @@ module xdistribute(spacing=10, sizes=undef, l=undef)
|
||||
// }
|
||||
module ydistribute(spacing=10, sizes=undef, l=undef)
|
||||
{
|
||||
dir = BACK;
|
||||
gaps = ($children < 2)? [0] :
|
||||
!is_undef(sizes)? [for (i=[0:1:$children-2]) sizes[i]/2 + sizes[i+1]/2] :
|
||||
[for (i=[0:1:$children-2]) 0];
|
||||
spc = !is_undef(l)? ((l - sum(gaps)) / ($children-1)) : default(spacing, 10);
|
||||
gaps2 = [for (gap = gaps) gap+spc];
|
||||
spos = dir * -sum(gaps2)/2;
|
||||
for (i=[0:1:$children-1]) {
|
||||
totspc = sum(concat([0], slice(gaps2, 0, i)));
|
||||
$pos = spos + totspc * dir;
|
||||
$idx = i;
|
||||
translate($pos) children(i);
|
||||
}
|
||||
dir = BACK;
|
||||
gaps = ($children < 2)? [0] :
|
||||
!is_undef(sizes)? [for (i=[0:1:$children-2]) sizes[i]/2 + sizes[i+1]/2] :
|
||||
[for (i=[0:1:$children-2]) 0];
|
||||
spc = !is_undef(l)? ((l - sum(gaps)) / ($children-1)) : default(spacing, 10);
|
||||
gaps2 = [for (gap = gaps) gap+spc];
|
||||
spos = dir * -sum(gaps2)/2;
|
||||
for (i=[0:1:$children-1]) {
|
||||
totspc = sum(concat([0], slice(gaps2, 0, i)));
|
||||
$pos = spos + totspc * dir;
|
||||
$idx = i;
|
||||
translate($pos) children(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -377,19 +377,19 @@ module ydistribute(spacing=10, sizes=undef, l=undef)
|
||||
// }
|
||||
module zdistribute(spacing=10, sizes=undef, l=undef)
|
||||
{
|
||||
dir = UP;
|
||||
gaps = ($children < 2)? [0] :
|
||||
!is_undef(sizes)? [for (i=[0:1:$children-2]) sizes[i]/2 + sizes[i+1]/2] :
|
||||
[for (i=[0:1:$children-2]) 0];
|
||||
spc = !is_undef(l)? ((l - sum(gaps)) / ($children-1)) : default(spacing, 10);
|
||||
gaps2 = [for (gap = gaps) gap+spc];
|
||||
spos = dir * -sum(gaps2)/2;
|
||||
for (i=[0:1:$children-1]) {
|
||||
totspc = sum(concat([0], slice(gaps2, 0, i)));
|
||||
$pos = spos + totspc * dir;
|
||||
$idx = i;
|
||||
translate($pos) children(i);
|
||||
}
|
||||
dir = UP;
|
||||
gaps = ($children < 2)? [0] :
|
||||
!is_undef(sizes)? [for (i=[0:1:$children-2]) sizes[i]/2 + sizes[i+1]/2] :
|
||||
[for (i=[0:1:$children-2]) 0];
|
||||
spc = !is_undef(l)? ((l - sum(gaps)) / ($children-1)) : default(spacing, 10);
|
||||
gaps2 = [for (gap = gaps) gap+spc];
|
||||
spos = dir * -sum(gaps2)/2;
|
||||
for (i=[0:1:$children-1]) {
|
||||
totspc = sum(concat([0], slice(gaps2, 0, i)));
|
||||
$pos = spos + totspc * dir;
|
||||
$idx = i;
|
||||
translate($pos) children(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -450,73 +450,73 @@ module zdistribute(spacing=10, sizes=undef, l=undef)
|
||||
// }
|
||||
module grid2d(spacing, n, size, stagger=false, inside=undef)
|
||||
{
|
||||
assert(in_list(stagger, [false, true, "alt"]));
|
||||
bounds = is_undef(inside)? undef :
|
||||
is_path(inside)? pointlist_bounds(inside) :
|
||||
assert(is_region(inside))
|
||||
pointlist_bounds(flatten(inside));
|
||||
size = is_num(size)? [size, size] :
|
||||
is_vector(size)? assert(len(size)==2) size :
|
||||
bounds!=undef? [
|
||||
for (i=[0:1]) 2*max(abs(bounds[0][i]),bounds[1][i])
|
||||
] : undef;
|
||||
spacing = is_num(spacing)? (
|
||||
stagger!=false? polar_to_xy(spacing,60) :
|
||||
[spacing,spacing]
|
||||
) :
|
||||
is_vector(spacing)? assert(len(spacing)==2) spacing :
|
||||
size!=undef? (
|
||||
is_num(n)? vdiv(size,(n-1)*[1,1]) :
|
||||
is_vector(n)? assert(len(n)==2) vdiv(size,n-[1,1]) :
|
||||
vdiv(size,(stagger==false? [1,1] : [2,2]))
|
||||
) :
|
||||
undef;
|
||||
n = is_num(n)? [n,n] :
|
||||
is_vector(n)? assert(len(n)==2) n :
|
||||
size!=undef && spacing!=undef? vfloor(vdiv(size,spacing))+[1,1] :
|
||||
[2,2];
|
||||
offset = vmul(spacing, n-[1,1])/2;
|
||||
if (stagger == false) {
|
||||
for (row = [0:1:n.y-1]) {
|
||||
for (col = [0:1:n.x-1]) {
|
||||
pos = vmul([col,row],spacing) - offset;
|
||||
if (
|
||||
is_undef(inside) ||
|
||||
(is_path(inside) && point_in_polygon(pos, inside)>=0) ||
|
||||
(is_region(inside) && point_in_region(pos, inside)>=0)
|
||||
) {
|
||||
$col = col;
|
||||
$row = row;
|
||||
$pos = pos;
|
||||
translate(pos) children();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// stagger == true or stagger == "alt"
|
||||
staggermod = (stagger == "alt")? 1 : 0;
|
||||
cols1 = ceil(n.x/2);
|
||||
cols2 = n.x - cols1;
|
||||
for (row = [0:1:n.y-1]) {
|
||||
rowcols = ((row%2) == staggermod)? cols1 : cols2;
|
||||
if (rowcols > 0) {
|
||||
for (col = [0:1:rowcols-1]) {
|
||||
rowdx = (row%2 != staggermod)? spacing.x : 0;
|
||||
pos = vmul([2*col,row],spacing) + [rowdx,0] - offset;
|
||||
if (
|
||||
is_undef(inside) ||
|
||||
(is_path(inside) && point_in_polygon(pos, inside)>=0) ||
|
||||
(is_region(inside) && point_in_region(pos, inside)>=0)
|
||||
) {
|
||||
$col = col * 2 + ((row%2!=staggermod)? 1 : 0);
|
||||
$row = row;
|
||||
$pos = pos;
|
||||
translate(pos) children();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(in_list(stagger, [false, true, "alt"]));
|
||||
bounds = is_undef(inside)? undef :
|
||||
is_path(inside)? pointlist_bounds(inside) :
|
||||
assert(is_region(inside))
|
||||
pointlist_bounds(flatten(inside));
|
||||
size = is_num(size)? [size, size] :
|
||||
is_vector(size)? assert(len(size)==2) size :
|
||||
bounds!=undef? [
|
||||
for (i=[0:1]) 2*max(abs(bounds[0][i]),bounds[1][i])
|
||||
] : undef;
|
||||
spacing = is_num(spacing)? (
|
||||
stagger!=false? polar_to_xy(spacing,60) :
|
||||
[spacing,spacing]
|
||||
) :
|
||||
is_vector(spacing)? assert(len(spacing)==2) spacing :
|
||||
size!=undef? (
|
||||
is_num(n)? vdiv(size,(n-1)*[1,1]) :
|
||||
is_vector(n)? assert(len(n)==2) vdiv(size,n-[1,1]) :
|
||||
vdiv(size,(stagger==false? [1,1] : [2,2]))
|
||||
) :
|
||||
undef;
|
||||
n = is_num(n)? [n,n] :
|
||||
is_vector(n)? assert(len(n)==2) n :
|
||||
size!=undef && spacing!=undef? vfloor(vdiv(size,spacing))+[1,1] :
|
||||
[2,2];
|
||||
offset = vmul(spacing, n-[1,1])/2;
|
||||
if (stagger == false) {
|
||||
for (row = [0:1:n.y-1]) {
|
||||
for (col = [0:1:n.x-1]) {
|
||||
pos = vmul([col,row],spacing) - offset;
|
||||
if (
|
||||
is_undef(inside) ||
|
||||
(is_path(inside) && point_in_polygon(pos, inside)>=0) ||
|
||||
(is_region(inside) && point_in_region(pos, inside)>=0)
|
||||
) {
|
||||
$col = col;
|
||||
$row = row;
|
||||
$pos = pos;
|
||||
translate(pos) children();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// stagger == true or stagger == "alt"
|
||||
staggermod = (stagger == "alt")? 1 : 0;
|
||||
cols1 = ceil(n.x/2);
|
||||
cols2 = n.x - cols1;
|
||||
for (row = [0:1:n.y-1]) {
|
||||
rowcols = ((row%2) == staggermod)? cols1 : cols2;
|
||||
if (rowcols > 0) {
|
||||
for (col = [0:1:rowcols-1]) {
|
||||
rowdx = (row%2 != staggermod)? spacing.x : 0;
|
||||
pos = vmul([2*col,row],spacing) + [rowdx,0] - offset;
|
||||
if (
|
||||
is_undef(inside) ||
|
||||
(is_path(inside) && point_in_polygon(pos, inside)>=0) ||
|
||||
(is_region(inside) && point_in_region(pos, inside)>=0)
|
||||
) {
|
||||
$col = col * 2 + ((row%2!=staggermod)? 1 : 0);
|
||||
$row = row;
|
||||
$pos = pos;
|
||||
translate(pos) children();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -554,24 +554,24 @@ module grid2d(spacing, n, size, stagger=false, inside=undef)
|
||||
// grid3d(n=[10, 10, 10], spacing=50) color($idx/9) cube(50, center=true);
|
||||
module grid3d(xa=[0], ya=[0], za=[0], n=undef, spacing=undef)
|
||||
{
|
||||
n = scalar_vec3(n, 1);
|
||||
spacing = scalar_vec3(spacing, undef);
|
||||
if (!is_undef(n) && !is_undef(spacing)) {
|
||||
for (xi = [0:1:n.x-1]) {
|
||||
for (yi = [0:1:n.y-1]) {
|
||||
for (zi = [0:1:n.z-1]) {
|
||||
$idx = [xi,yi,zi];
|
||||
$pos = vmul(spacing, $idx - (n-[1,1,1])/2);
|
||||
translate($pos) children();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (xoff = xa, yoff = ya, zoff = za) {
|
||||
$pos = [xoff, yoff, zoff];
|
||||
translate($pos) children();
|
||||
}
|
||||
}
|
||||
n = scalar_vec3(n, 1);
|
||||
spacing = scalar_vec3(spacing, undef);
|
||||
if (!is_undef(n) && !is_undef(spacing)) {
|
||||
for (xi = [0:1:n.x-1]) {
|
||||
for (yi = [0:1:n.y-1]) {
|
||||
for (zi = [0:1:n.z-1]) {
|
||||
$idx = [xi,yi,zi];
|
||||
$pos = vmul(spacing, $idx - (n-[1,1,1])/2);
|
||||
translate($pos) children();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (xoff = xa, yoff = ya, zoff = za) {
|
||||
$pos = [xoff, yoff, zoff];
|
||||
translate($pos) children();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -642,28 +642,28 @@ module grid3d(xa=[0], ya=[0], za=[0], n=undef, spacing=undef)
|
||||
// color("red",0.333) yrot(90) cylinder(h=20, r1=5, r2=0);
|
||||
module rot_copies(rots=[], v=undef, cp=[0,0,0], n=undef, sa=0, offset=0, delta=[0,0,0], subrot=true)
|
||||
{
|
||||
sang = sa + offset;
|
||||
angs = !is_undef(n)?
|
||||
(n<=0? [] : [for (i=[0:1:n-1]) i/n*360+sang]) :
|
||||
rots==[]? [] :
|
||||
assert(!is_string(rots), "Argument rots must be an angle, a list of angles, or a range of angles.")
|
||||
assert(!is_undef(rots[0]), "Argument rots must be an angle, a list of angles, or a range of angles.")
|
||||
[for (a=rots) a];
|
||||
for ($idx = idx(angs)) {
|
||||
$ang = angs[$idx];
|
||||
$axis = v;
|
||||
translate(cp) {
|
||||
rotate(a=$ang, v=v) {
|
||||
translate(delta) {
|
||||
rot(a=(subrot? sang : $ang), v=v, reverse=true) {
|
||||
translate(-cp) {
|
||||
children();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sang = sa + offset;
|
||||
angs = !is_undef(n)?
|
||||
(n<=0? [] : [for (i=[0:1:n-1]) i/n*360+sang]) :
|
||||
rots==[]? [] :
|
||||
assert(!is_string(rots), "Argument rots must be an angle, a list of angles, or a range of angles.")
|
||||
assert(!is_undef(rots[0]), "Argument rots must be an angle, a list of angles, or a range of angles.")
|
||||
[for (a=rots) a];
|
||||
for ($idx = idx(angs)) {
|
||||
$ang = angs[$idx];
|
||||
$axis = v;
|
||||
translate(cp) {
|
||||
rotate(a=$ang, v=v) {
|
||||
translate(delta) {
|
||||
rot(a=(subrot? sang : $ang), v=v, reverse=true) {
|
||||
translate(-cp) {
|
||||
children();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -720,7 +720,7 @@ module rot_copies(rots=[], v=undef, cp=[0,0,0], n=undef, sa=0, offset=0, delta=[
|
||||
// color("red",0.333) xrot(-90) cylinder(h=20, r1=5, r2=0, center=true);
|
||||
module xrot_copies(rots=[], cp=[0,0,0], n=undef, sa=0, r=0, subrot=true)
|
||||
{
|
||||
rot_copies(rots=rots, v=RIGHT, cp=cp, n=n, sa=sa, delta=[0, r, 0], subrot=subrot) children();
|
||||
rot_copies(rots=rots, v=RIGHT, cp=cp, n=n, sa=sa, delta=[0, r, 0], subrot=subrot) children();
|
||||
}
|
||||
|
||||
|
||||
@ -777,7 +777,7 @@ module xrot_copies(rots=[], cp=[0,0,0], n=undef, sa=0, r=0, subrot=true)
|
||||
// color("red",0.333) yrot(-90) cylinder(h=20, r1=5, r2=0, center=true);
|
||||
module yrot_copies(rots=[], cp=[0,0,0], n=undef, sa=0, r=0, subrot=true)
|
||||
{
|
||||
rot_copies(rots=rots, v=BACK, cp=cp, n=n, sa=sa, delta=[-r, 0, 0], subrot=subrot) children();
|
||||
rot_copies(rots=rots, v=BACK, cp=cp, n=n, sa=sa, delta=[-r, 0, 0], subrot=subrot) children();
|
||||
}
|
||||
|
||||
|
||||
@ -834,7 +834,7 @@ module yrot_copies(rots=[], cp=[0,0,0], n=undef, sa=0, r=0, subrot=true)
|
||||
// color("red",0.333) yrot(-90) cylinder(h=20, r1=5, r2=0, center=true);
|
||||
module zrot_copies(rots=[], cp=[0,0,0], n=undef, sa=0, r=0, subrot=true)
|
||||
{
|
||||
rot_copies(rots=rots, v=UP, cp=cp, n=n, sa=sa, delta=[r, 0, 0], subrot=subrot) children();
|
||||
rot_copies(rots=rots, v=UP, cp=cp, n=n, sa=sa, delta=[r, 0, 0], subrot=subrot) children();
|
||||
}
|
||||
|
||||
|
||||
@ -880,27 +880,27 @@ module zrot_copies(rots=[], cp=[0,0,0], n=undef, sa=0, r=0, subrot=true)
|
||||
// #cube(size=[10,3,3],center=true);
|
||||
// arc_of(rx=20, ry=10, n=8) cube(size=[10,3,3],center=true);
|
||||
module arc_of(
|
||||
n=6,
|
||||
r=undef, rx=undef, ry=undef,
|
||||
d=undef, dx=undef, dy=undef,
|
||||
sa=0, ea=360,
|
||||
rot=true
|
||||
n=6,
|
||||
r=undef, rx=undef, ry=undef,
|
||||
d=undef, dx=undef, dy=undef,
|
||||
sa=0, ea=360,
|
||||
rot=true
|
||||
) {
|
||||
rx = get_radius(r1=rx, r=r, d1=dx, d=d, dflt=1);
|
||||
ry = get_radius(r1=ry, r=r, d1=dy, d=d, dflt=1);
|
||||
sa = posmod(sa, 360);
|
||||
ea = posmod(ea, 360);
|
||||
n = (abs(ea-sa)<0.01)?(n+1):n;
|
||||
delt = (((ea<=sa)?360.0:0)+ea-sa)/(n-1);
|
||||
for ($idx = [0:1:n-1]) {
|
||||
$ang = sa + ($idx * delt);
|
||||
$pos =[rx*cos($ang), ry*sin($ang), 0];
|
||||
translate($pos) {
|
||||
zrot(rot? atan2(ry*sin($ang), rx*cos($ang)) : 0) {
|
||||
children();
|
||||
}
|
||||
}
|
||||
}
|
||||
rx = get_radius(r1=rx, r=r, d1=dx, d=d, dflt=1);
|
||||
ry = get_radius(r1=ry, r=r, d1=dy, d=d, dflt=1);
|
||||
sa = posmod(sa, 360);
|
||||
ea = posmod(ea, 360);
|
||||
n = (abs(ea-sa)<0.01)?(n+1):n;
|
||||
delt = (((ea<=sa)?360.0:0)+ea-sa)/(n-1);
|
||||
for ($idx = [0:1:n-1]) {
|
||||
$ang = sa + ($idx * delt);
|
||||
$pos =[rx*cos($ang), ry*sin($ang), 0];
|
||||
translate($pos) {
|
||||
zrot(rot? atan2(ry*sin($ang), rx*cos($ang)) : 0) {
|
||||
children();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -938,29 +938,29 @@ module arc_of(
|
||||
// cylinder(d=8, h=10, center=false);
|
||||
module ovoid_spread(r=undef, d=undef, n=100, cone_ang=90, scale=[1,1,1], perp=true)
|
||||
{
|
||||
r = get_radius(r=r, d=d, dflt=50);
|
||||
cnt = ceil(n / (cone_ang/180));
|
||||
r = get_radius(r=r, d=d, dflt=50);
|
||||
cnt = ceil(n / (cone_ang/180));
|
||||
|
||||
// Calculate an array of [theta,phi] angles for `n` number of
|
||||
// points, almost evenly spaced across the surface of a sphere.
|
||||
// This approximation is based on the golden spiral method.
|
||||
theta_phis = [for (x=[0:1:n-1]) [180*(1+sqrt(5))*(x+0.5)%360, acos(1-2*(x+0.5)/cnt)]];
|
||||
// Calculate an array of [theta,phi] angles for `n` number of
|
||||
// points, almost evenly spaced across the surface of a sphere.
|
||||
// This approximation is based on the golden spiral method.
|
||||
theta_phis = [for (x=[0:1:n-1]) [180*(1+sqrt(5))*(x+0.5)%360, acos(1-2*(x+0.5)/cnt)]];
|
||||
|
||||
for ($idx = idx(theta_phis)) {
|
||||
tp = theta_phis[$idx];
|
||||
xyz = spherical_to_xyz(r, tp[0], tp[1]);
|
||||
$pos = vmul(xyz,scale);
|
||||
$theta = tp[0];
|
||||
$phi = tp[1];
|
||||
$rad = r;
|
||||
translate($pos) {
|
||||
if (perp) {
|
||||
rot(from=UP, to=xyz) children();
|
||||
} else {
|
||||
children();
|
||||
}
|
||||
}
|
||||
}
|
||||
for ($idx = idx(theta_phis)) {
|
||||
tp = theta_phis[$idx];
|
||||
xyz = spherical_to_xyz(r, tp[0], tp[1]);
|
||||
$pos = vmul(xyz,scale);
|
||||
$theta = tp[0];
|
||||
$phi = tp[1];
|
||||
$rad = r;
|
||||
translate($pos) {
|
||||
if (perp) {
|
||||
rot(from=UP, to=xyz) children();
|
||||
} else {
|
||||
children();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1000,27 +1000,27 @@ module ovoid_spread(r=undef, d=undef, n=100, cone_ang=90, scale=[1,1,1], perp=tr
|
||||
// color("blue",0.25) translate([0,-5,-5]) rot(from=UP, to=BACK+UP) cube([15,15,0.01], center=true);
|
||||
module mirror_copy(v=[0,0,1], offset=0, cp)
|
||||
{
|
||||
cp = is_vector(v,4)? plane_normal(v) * v[3] :
|
||||
is_vector(cp)? cp :
|
||||
is_num(cp)? cp*unit(v) :
|
||||
[0,0,0];
|
||||
nv = is_vector(v,4)? plane_normal(v) : unit(v);
|
||||
off = nv*offset;
|
||||
if (cp == [0,0,0]) {
|
||||
translate(off) {
|
||||
$orig = true;
|
||||
$idx = 0;
|
||||
children();
|
||||
}
|
||||
mirror(nv) translate(off) {
|
||||
$orig = false;
|
||||
$idx = 1;
|
||||
children();
|
||||
}
|
||||
} else {
|
||||
translate(off) children();
|
||||
translate(cp) mirror(nv) translate(-cp) translate(off) children();
|
||||
}
|
||||
cp = is_vector(v,4)? plane_normal(v) * v[3] :
|
||||
is_vector(cp)? cp :
|
||||
is_num(cp)? cp*unit(v) :
|
||||
[0,0,0];
|
||||
nv = is_vector(v,4)? plane_normal(v) : unit(v);
|
||||
off = nv*offset;
|
||||
if (cp == [0,0,0]) {
|
||||
translate(off) {
|
||||
$orig = true;
|
||||
$idx = 0;
|
||||
children();
|
||||
}
|
||||
mirror(nv) translate(off) {
|
||||
$orig = false;
|
||||
$idx = 1;
|
||||
children();
|
||||
}
|
||||
} else {
|
||||
translate(off) children();
|
||||
translate(cp) mirror(nv) translate(-cp) translate(off) children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1053,7 +1053,7 @@ module mirror_copy(v=[0,0,1], offset=0, cp)
|
||||
// color("blue",0.25) left(5) cube([0.01,15,15], center=true);
|
||||
module xflip_copy(offset=0, x=0)
|
||||
{
|
||||
mirror_copy(v=[1,0,0], offset=offset, cp=[x,0,0]) children();
|
||||
mirror_copy(v=[1,0,0], offset=offset, cp=[x,0,0]) children();
|
||||
}
|
||||
|
||||
|
||||
@ -1086,7 +1086,7 @@ module xflip_copy(offset=0, x=0)
|
||||
// color("blue",0.25) fwd(5) cube([15,0.01,15], center=true);
|
||||
module yflip_copy(offset=0, y=0)
|
||||
{
|
||||
mirror_copy(v=[0,1,0], offset=offset, cp=[0,y,0]) children();
|
||||
mirror_copy(v=[0,1,0], offset=offset, cp=[0,y,0]) children();
|
||||
}
|
||||
|
||||
|
||||
@ -1119,9 +1119,9 @@ module yflip_copy(offset=0, y=0)
|
||||
// color("blue",0.25) down(5) cube([15,15,0.01], center=true);
|
||||
module zflip_copy(offset=0, z=0)
|
||||
{
|
||||
mirror_copy(v=[0,0,1], offset=offset, cp=[0,0,z]) children();
|
||||
mirror_copy(v=[0,0,1], offset=offset, cp=[0,0,z]) children();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
154
edges.scad
154
edges.scad
@ -68,34 +68,34 @@ function is_edge_array(v) = is_list(v) && is_vector(v[0]) && len(v)==3 && len(v[
|
||||
|
||||
|
||||
function _edge_set(v) =
|
||||
is_edge_array(v)? v : [
|
||||
for (ax=[0:2]) [
|
||||
for (b=[-1,1], a=[-1,1]) let(
|
||||
v2=[[0,a,b],[a,0,b],[a,b,0]][ax]
|
||||
) (
|
||||
is_string(v)? (
|
||||
v=="X"? (ax==0) : // Return all X axis aligned edges.
|
||||
v=="Y"? (ax==1) : // Return all Y axis aligned edges.
|
||||
v=="Z"? (ax==2) : // Return all Z axis aligned edges.
|
||||
v=="ALL"? true : // Return all edges.
|
||||
v=="NONE"? false : // Return no edges.
|
||||
let(valid_values = ["X", "Y", "Z", "ALL", "NONE"])
|
||||
assert(
|
||||
in_list(v, valid_values),
|
||||
str(v, " must be a vector, edge array, or one of ", valid_values)
|
||||
) v
|
||||
) :
|
||||
let(nonz = sum(vabs(v)))
|
||||
nonz==2? (v==v2) : // Edge: return matching edge.
|
||||
let(
|
||||
matches = count_true([
|
||||
for (i=[0:2]) v[i] && (v[i]==v2[i])
|
||||
])
|
||||
)
|
||||
nonz==1? (matches==1) : // Face: return surrounding edges.
|
||||
(matches==2) // Corner: return touching edges.
|
||||
)? 1 : 0
|
||||
]
|
||||
is_edge_array(v)? v : [
|
||||
for (ax=[0:2]) [
|
||||
for (b=[-1,1], a=[-1,1]) let(
|
||||
v2=[[0,a,b],[a,0,b],[a,b,0]][ax]
|
||||
) (
|
||||
is_string(v)? (
|
||||
v=="X"? (ax==0) : // Return all X axis aligned edges.
|
||||
v=="Y"? (ax==1) : // Return all Y axis aligned edges.
|
||||
v=="Z"? (ax==2) : // Return all Z axis aligned edges.
|
||||
v=="ALL"? true : // Return all edges.
|
||||
v=="NONE"? false : // Return no edges.
|
||||
let(valid_values = ["X", "Y", "Z", "ALL", "NONE"])
|
||||
assert(
|
||||
in_list(v, valid_values),
|
||||
str(v, " must be a vector, edge array, or one of ", valid_values)
|
||||
) v
|
||||
) :
|
||||
let(nonz = sum(vabs(v)))
|
||||
nonz==2? (v==v2) : // Edge: return matching edge.
|
||||
let(
|
||||
matches = count_true([
|
||||
for (i=[0:2]) v[i] && (v[i]==v2[i])
|
||||
])
|
||||
)
|
||||
nonz==1? (matches==1) : // Face: return surrounding edges.
|
||||
(matches==2) // Corner: return touching edges.
|
||||
)? 1 : 0
|
||||
]
|
||||
];
|
||||
|
||||
|
||||
@ -211,32 +211,32 @@ function normalize_edges(v) = [for (ax=v) [for (edge=ax) edge>0? 1 : 0]];
|
||||
// Example: All edges, except Z-aligned edges on the front.
|
||||
// edges("ALL", except=edges("Z", except=BACK))
|
||||
function edges(v, except=[]) =
|
||||
(is_string(v) || is_vector(v) || is_edge_array(v))? edges([v], except=except) :
|
||||
(is_string(except) || is_vector(except) || is_edge_array(except))? edges(v, except=[except]) :
|
||||
except==[]? normalize_edges(sum([for (x=v) _edge_set(x)])) :
|
||||
normalize_edges(
|
||||
normalize_edges(sum([for (x=v) _edge_set(x)])) -
|
||||
sum([for (x=except) _edge_set(x)])
|
||||
);
|
||||
(is_string(v) || is_vector(v) || is_edge_array(v))? edges([v], except=except) :
|
||||
(is_string(except) || is_vector(except) || is_edge_array(except))? edges(v, except=[except]) :
|
||||
except==[]? normalize_edges(sum([for (x=v) _edge_set(x)])) :
|
||||
normalize_edges(
|
||||
normalize_edges(sum([for (x=v) _edge_set(x)])) -
|
||||
sum([for (x=except) _edge_set(x)])
|
||||
);
|
||||
|
||||
|
||||
EDGE_OFFSETS = [ // Array of XYZ offsets to the center of each edge.
|
||||
[
|
||||
[ 0,-1,-1],
|
||||
[ 0, 1,-1],
|
||||
[ 0,-1, 1],
|
||||
[ 0, 1, 1]
|
||||
], [
|
||||
[-1, 0,-1],
|
||||
[ 1, 0,-1],
|
||||
[-1, 0, 1],
|
||||
[ 1, 0, 1]
|
||||
], [
|
||||
[-1,-1, 0],
|
||||
[ 1,-1, 0],
|
||||
[-1, 1, 0],
|
||||
[ 1, 1, 0]
|
||||
]
|
||||
[
|
||||
[ 0,-1,-1],
|
||||
[ 0, 1,-1],
|
||||
[ 0,-1, 1],
|
||||
[ 0, 1, 1]
|
||||
], [
|
||||
[-1, 0,-1],
|
||||
[ 1, 0,-1],
|
||||
[-1, 0, 1],
|
||||
[ 1, 0, 1]
|
||||
], [
|
||||
[-1,-1, 0],
|
||||
[ 1,-1, 0],
|
||||
[-1, 1, 0],
|
||||
[ 1, 1, 0]
|
||||
]
|
||||
];
|
||||
|
||||
|
||||
@ -267,21 +267,21 @@ function normalize_corners(v) = [for (x=v) x>0? 1 : 0];
|
||||
|
||||
|
||||
function _corner_set(v) =
|
||||
is_corner_array(v)? v : [
|
||||
for (i=[0:7]) let(
|
||||
v2 = CORNER_OFFSETS[i]
|
||||
) (
|
||||
is_string(v)? (
|
||||
v=="ALL"? true : // Return all corners.
|
||||
v=="NONE"? false : // Return no corners.
|
||||
let(valid_values = ["ALL", "NONE"])
|
||||
assert(
|
||||
in_list(v, valid_values),
|
||||
str(v, " must be a vector, corner array, or one of ", valid_values)
|
||||
) v
|
||||
) :
|
||||
all([for (i=[0:2]) !v[i] || (v[i]==v2[i])])
|
||||
)? 1 : 0
|
||||
is_corner_array(v)? v : [
|
||||
for (i=[0:7]) let(
|
||||
v2 = CORNER_OFFSETS[i]
|
||||
) (
|
||||
is_string(v)? (
|
||||
v=="ALL"? true : // Return all corners.
|
||||
v=="NONE"? false : // Return no corners.
|
||||
let(valid_values = ["ALL", "NONE"])
|
||||
assert(
|
||||
in_list(v, valid_values),
|
||||
str(v, " must be a vector, corner array, or one of ", valid_values)
|
||||
) v
|
||||
) :
|
||||
all([for (i=[0:2]) !v[i] || (v[i]==v2[i])])
|
||||
)? 1 : 0
|
||||
];
|
||||
|
||||
|
||||
@ -370,18 +370,18 @@ function _corner_set(v) =
|
||||
// Example: All corners around the bottom or front faces, except those on the bottom-front edge.
|
||||
// corners([BOTTOM,FRONT], except=BOTTOM+FRONT)
|
||||
function corners(v, except=[]) =
|
||||
(is_string(v) || is_vector(v) || is_corner_array(v))? corners([v], except=except) :
|
||||
(is_string(except) || is_vector(except) || is_corner_array(except))? corners(v, except=[except]) :
|
||||
except==[]? normalize_corners(sum([for (x=v) _corner_set(x)])) :
|
||||
let(
|
||||
a = normalize_corners(sum([for (x=v) _corner_set(x)])),
|
||||
b = normalize_corners(sum([for (x=except) _corner_set(x)]))
|
||||
) normalize_corners(a - b);
|
||||
(is_string(v) || is_vector(v) || is_corner_array(v))? corners([v], except=except) :
|
||||
(is_string(except) || is_vector(except) || is_corner_array(except))? corners(v, except=[except]) :
|
||||
except==[]? normalize_corners(sum([for (x=v) _corner_set(x)])) :
|
||||
let(
|
||||
a = normalize_corners(sum([for (x=v) _corner_set(x)])),
|
||||
b = normalize_corners(sum([for (x=except) _corner_set(x)]))
|
||||
) normalize_corners(a - b);
|
||||
|
||||
|
||||
CORNER_OFFSETS = [ // Array of XYZ offsets to each corner.
|
||||
[-1,-1,-1], [ 1,-1,-1], [-1, 1,-1], [ 1, 1,-1],
|
||||
[-1,-1, 1], [ 1,-1, 1], [-1, 1, 1], [ 1, 1, 1]
|
||||
[-1,-1,-1], [ 1,-1,-1], [-1, 1,-1], [ 1, 1,-1],
|
||||
[-1,-1, 1], [ 1,-1, 1], [-1, 1, 1], [ 1, 1, 1]
|
||||
];
|
||||
|
||||
|
||||
@ -391,7 +391,7 @@ CORNER_OFFSETS = [ // Array of XYZ offsets to each corner.
|
||||
// edges = Standard edges array.
|
||||
// v = Vector pointing to the corner to count edge intersections at.
|
||||
function corner_edge_count(edges, v) =
|
||||
let(u = (v+[1,1,1])/2) edges[0][u.y+u.z*2] + edges[1][u.x+u.z*2] + edges[2][u.x+u.y*2];
|
||||
let(u = (v+[1,1,1])/2) edges[0][u.y+u.z*2] + edges[1][u.x+u.z*2] + edges[2][u.x+u.y*2];
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
74
errors.scad
74
errors.scad
@ -35,11 +35,11 @@ module no_children(count) {
|
||||
// msg = The message to print.
|
||||
// pfx = The prefix to print before `msg`. Default: `ERROR`
|
||||
module echo_error(msg, pfx="ERROR") {
|
||||
echo(str("<p style=\"background-color: #ffb0b0\"><b>", pfx, ":</b> ", msg, "</p>"));
|
||||
echo(str("<p style=\"background-color: #ffb0b0\"><b>", pfx, ":</b> ", msg, "</p>"));
|
||||
}
|
||||
|
||||
function echo_error(msg, pfx="ERROR") =
|
||||
echo(str("<p style=\"background-color: #ffb0b0\"><b>", pfx, ":</b> ", msg, "</p>"));
|
||||
echo(str("<p style=\"background-color: #ffb0b0\"><b>", pfx, ":</b> ", msg, "</p>"));
|
||||
|
||||
|
||||
// Function&Module: echo_warning()
|
||||
@ -52,11 +52,11 @@ function echo_error(msg, pfx="ERROR") =
|
||||
// msg = The message to print.
|
||||
// pfx = The prefix to print before `msg`. Default: `WARNING`
|
||||
module echo_warning(msg, pfx="WARNING") {
|
||||
echo(str("<p style=\"background-color: #ffffb0\"><b>", pfx, ":</b> ", msg, "</p>"));
|
||||
echo(str("<p style=\"background-color: #ffffb0\"><b>", pfx, ":</b> ", msg, "</p>"));
|
||||
}
|
||||
|
||||
function echo_warning(msg, pfx="WARNING") =
|
||||
echo(str("<p style=\"background-color: #ffffb0\"><b>", pfx, ":</b> ", msg, "</p>"));
|
||||
echo(str("<p style=\"background-color: #ffffb0\"><b>", pfx, ":</b> ", msg, "</p>"));
|
||||
|
||||
|
||||
// Function&Module: deprecate()
|
||||
@ -69,25 +69,25 @@ function echo_warning(msg, pfx="WARNING") =
|
||||
// name = The name of the module that is deprecated.
|
||||
// suggest = If given, the module to recommend using instead.
|
||||
module deprecate(name, suggest=undef) {
|
||||
echo_warning(pfx="DEPRECATED",
|
||||
str(
|
||||
"`<code>", name, "</code>` is deprecated and should not be used.",
|
||||
is_undef(suggest)? "" : str(
|
||||
" You should use `<code>", suggest, "</code>` instead."
|
||||
)
|
||||
)
|
||||
);
|
||||
echo_warning(pfx="DEPRECATED",
|
||||
str(
|
||||
"`<code>", name, "</code>` is deprecated and should not be used.",
|
||||
is_undef(suggest)? "" : str(
|
||||
" You should use `<code>", suggest, "</code>` instead."
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function deprecate(name, suggest=undef) =
|
||||
echo_warning(pfx="DEPRECATED",
|
||||
str(
|
||||
"`<code>", name, "</code>` is deprecated and should not be used.",
|
||||
is_undef(suggest)? "" : str(
|
||||
" You should use `<code>", suggest, "</code>` instead."
|
||||
)
|
||||
)
|
||||
);
|
||||
echo_warning(pfx="DEPRECATED",
|
||||
str(
|
||||
"`<code>", name, "</code>` is deprecated and should not be used.",
|
||||
is_undef(suggest)? "" : str(
|
||||
" You should use `<code>", suggest, "</code>` instead."
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
// Function&Module: deprecate_argument()
|
||||
@ -101,26 +101,26 @@ function deprecate(name, suggest=undef) =
|
||||
// arg = The name of the deprecated argument.
|
||||
// suggest = If given, the argument to recommend using instead.
|
||||
module deprecate_argument(name, arg, suggest=undef) {
|
||||
echo_warning(pfx="DEPRECATED ARG", str(
|
||||
"In `<code>", name, "</code>`, ",
|
||||
"the argument `<code>", arg, "</code>` ",
|
||||
"is deprecated and should not be used.",
|
||||
is_undef(suggest)? "" : str(
|
||||
" You should use `<code>", suggest, "</code>` instead."
|
||||
)
|
||||
));
|
||||
echo_warning(pfx="DEPRECATED ARG", str(
|
||||
"In `<code>", name, "</code>`, ",
|
||||
"the argument `<code>", arg, "</code>` ",
|
||||
"is deprecated and should not be used.",
|
||||
is_undef(suggest)? "" : str(
|
||||
" You should use `<code>", suggest, "</code>` instead."
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
function deprecate_argument(name, arg, suggest=undef) =
|
||||
echo_warning(pfx="DEPRECATED ARG", str(
|
||||
"In `<code>", name, "</code>`, ",
|
||||
"the argument `<code>", arg, "</code>` ",
|
||||
"is deprecated and should not be used.",
|
||||
is_undef(suggest)? "" : str(
|
||||
" You should use `<code>", suggest, "</code>` instead."
|
||||
)
|
||||
));
|
||||
echo_warning(pfx="DEPRECATED ARG", str(
|
||||
"In `<code>", name, "</code>`, ",
|
||||
"the argument `<code>", arg, "</code>` ",
|
||||
"is deprecated and should not be used.",
|
||||
is_undef(suggest)? "" : str(
|
||||
" You should use `<code>", suggest, "</code>` instead."
|
||||
)
|
||||
));
|
||||
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -4,15 +4,15 @@ include <BOSL2/hull.scad>
|
||||
$fn=32;
|
||||
|
||||
cuboid([60,40,40], rounding=5, edges=edges("Z"), anchor=BOTTOM) {
|
||||
attach(TOP, BOTTOM) prismoid([60,40],[20,20], h=50, rounding1=5, rounding2=10) {
|
||||
attach(TOP) cylinder(d=20, h=30, center=false) {
|
||||
attach(TOP) cylinder(d1=50, d2=30, h=12, center=false);
|
||||
}
|
||||
attach([FRONT, BACK, LEFT, RIGHT]) cylinder(d1=14, d2=5, h=20) {
|
||||
attach(TOP, LEFT, overlap=5) prismoid([30,20], [20,20], h=10, shift=[-7,0]);
|
||||
}
|
||||
}
|
||||
attach(TOP, BOTTOM) prismoid([60,40],[20,20], h=50, rounding1=5, rounding2=10) {
|
||||
attach(TOP) cylinder(d=20, h=30, center=false) {
|
||||
attach(TOP) cylinder(d1=50, d2=30, h=12, center=false);
|
||||
}
|
||||
attach([FRONT, BACK, LEFT, RIGHT]) cylinder(d1=14, d2=5, h=20) {
|
||||
attach(TOP, LEFT, overlap=5) prismoid([30,20], [20,20], h=10, shift=[-7,0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -3,75 +3,75 @@ include <BOSL2/beziers.scad>
|
||||
|
||||
|
||||
function CR_corner(size, spin=0, orient=UP, trans=[0,0,0]) =
|
||||
let (
|
||||
// This patch might not yet correct for continuous rounding,
|
||||
// but it's a first approximation proof of concept.
|
||||
a = 0.68,
|
||||
b = 0.60,
|
||||
c = 0.24,
|
||||
patch = [
|
||||
[[0,1,1], [0,a,1], [0,c,1], [c,0,1], [a,0,1], [1,0,1]],
|
||||
[[0,1,a], [0,b,b], [0,0,b], [b,0,b], [1,0,a]],
|
||||
[[0,1,c], [0,b,0], [b,0,0], [1,0,c]],
|
||||
[[c,1,0], [b,b,0], [1,c,0]],
|
||||
[[a,1,0], [1,a,0]],
|
||||
[[1,1,0]],
|
||||
]
|
||||
)
|
||||
translate(trans,
|
||||
p=rot(a=spin, from=UP, to=orient,
|
||||
p=scale(size, patch)
|
||||
)
|
||||
);
|
||||
let (
|
||||
// This patch might not yet correct for continuous rounding,
|
||||
// but it's a first approximation proof of concept.
|
||||
a = 0.68,
|
||||
b = 0.60,
|
||||
c = 0.24,
|
||||
patch = [
|
||||
[[0,1,1], [0,a,1], [0,c,1], [c,0,1], [a,0,1], [1,0,1]],
|
||||
[[0,1,a], [0,b,b], [0,0,b], [b,0,b], [1,0,a]],
|
||||
[[0,1,c], [0,b,0], [b,0,0], [1,0,c]],
|
||||
[[c,1,0], [b,b,0], [1,c,0]],
|
||||
[[a,1,0], [1,a,0]],
|
||||
[[1,1,0]],
|
||||
]
|
||||
)
|
||||
translate(trans,
|
||||
p=rot(a=spin, from=UP, to=orient,
|
||||
p=scale(size, patch)
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
function CR_edge(size, spin=0, orient=UP, trans=[0,0,0]) =
|
||||
let (
|
||||
// This patch might not be correct for continuous rounding,
|
||||
// but it's a first approximation proof of concept.
|
||||
vvals = [1.00, 0.68, 0.24],
|
||||
xyvals = [
|
||||
for (x=vvals) [x,0],
|
||||
for (y=reverse(vvals)) [0,y]
|
||||
],
|
||||
zvals = [-0.5:0.2:0.5],
|
||||
patch = [for (xy=xyvals) [for (z=zvals) [each xy, z]]]
|
||||
)
|
||||
translate(trans,
|
||||
p=rot(a=spin, from=UP, to=orient,
|
||||
p=scale(size, p=patch)
|
||||
)
|
||||
);
|
||||
let (
|
||||
// This patch might not be correct for continuous rounding,
|
||||
// but it's a first approximation proof of concept.
|
||||
vvals = [1.00, 0.68, 0.24],
|
||||
xyvals = [
|
||||
for (x=vvals) [x,0],
|
||||
for (y=reverse(vvals)) [0,y]
|
||||
],
|
||||
zvals = [-0.5:0.2:0.5],
|
||||
patch = [for (xy=xyvals) [for (z=zvals) [each xy, z]]]
|
||||
)
|
||||
translate(trans,
|
||||
p=rot(a=spin, from=UP, to=orient,
|
||||
p=scale(size, p=patch)
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
module CR_cube(size=[100,100,100], r=10, splinesteps=8, debug=false)
|
||||
{
|
||||
s = size-2*[r,r,r];
|
||||
h = size/2;
|
||||
corner_pat = CR_corner([r,r,r], trans=[-size.x/2, -size.y/2, -size.z/2]);
|
||||
edge_pat = CR_edge([r, r, s.z], trans=[-h.x, -h.y, 0]);
|
||||
face_pat = bezier_patch_flat([s.x, s.z], N=1, orient=FRONT, trans=[0, -h.y, 0]);
|
||||
corners = bezier_surface([
|
||||
for (yr=[0,180], zr=[0:90:270]) let(
|
||||
m = yrot(yr) * zrot(zr)
|
||||
) [for (row=corner_pat) apply(m, row)]
|
||||
], splinesteps=splinesteps);
|
||||
edges = bezier_surface([
|
||||
for (axr=[[0,0,0],[90,0,0],[0,90,0]],zr=[0:90:270]) let(
|
||||
m = rot(axr) * zrot(zr)
|
||||
) [for (row=edge_pat) apply(m, row)]
|
||||
], splinesteps=[splinesteps,1]);
|
||||
faces = bezier_surface([
|
||||
for (axr=[0,90,180,270,[-90,0,0],[90,0,0]]) let(
|
||||
m = rot(axr)
|
||||
) [for (row=face_pat) apply(m, row)]
|
||||
], splinesteps=1);
|
||||
s = size-2*[r,r,r];
|
||||
h = size/2;
|
||||
corner_pat = CR_corner([r,r,r], trans=[-size.x/2, -size.y/2, -size.z/2]);
|
||||
edge_pat = CR_edge([r, r, s.z], trans=[-h.x, -h.y, 0]);
|
||||
face_pat = bezier_patch_flat([s.x, s.z], N=1, orient=FRONT, trans=[0, -h.y, 0]);
|
||||
corners = bezier_surface([
|
||||
for (yr=[0,180], zr=[0:90:270]) let(
|
||||
m = yrot(yr) * zrot(zr)
|
||||
) [for (row=corner_pat) apply(m, row)]
|
||||
], splinesteps=splinesteps);
|
||||
edges = bezier_surface([
|
||||
for (axr=[[0,0,0],[90,0,0],[0,90,0]],zr=[0:90:270]) let(
|
||||
m = rot(axr) * zrot(zr)
|
||||
) [for (row=edge_pat) apply(m, row)]
|
||||
], splinesteps=[splinesteps,1]);
|
||||
faces = bezier_surface([
|
||||
for (axr=[0,90,180,270,[-90,0,0],[90,0,0]]) let(
|
||||
m = rot(axr)
|
||||
) [for (row=face_pat) apply(m, row)]
|
||||
], splinesteps=1);
|
||||
|
||||
if (debug) {
|
||||
vnf_validate([edges, faces, corners], convexity=4);
|
||||
} else {
|
||||
vnf_polyhedron([edges, faces, corners], convexity=4);
|
||||
}
|
||||
if (debug) {
|
||||
vnf_validate([edges, faces, corners], convexity=4);
|
||||
} else {
|
||||
vnf_polyhedron([edges, faces, corners], convexity=4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -80,4 +80,4 @@ cube(1);
|
||||
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -4,15 +4,15 @@ include <BOSL2/debug.scad>
|
||||
$fn = 36;
|
||||
|
||||
rgn1 = [
|
||||
square(100),
|
||||
move([50,50], p=circle(d=60)),
|
||||
[[35,35],[35,65],[65,65]]
|
||||
square(100),
|
||||
move([50,50], p=circle(d=60)),
|
||||
[[35,35],[35,65],[65,65]]
|
||||
];
|
||||
|
||||
rgn2 = [
|
||||
[[0,0], [100,100], [100,0]],
|
||||
[[27,10], [90,73], [90,10]],
|
||||
move([70,30], p=circle(d=25))
|
||||
[[0,0], [100,100], [100,0]],
|
||||
[[27,10], [90,73], [90,10]],
|
||||
move([70,30], p=circle(d=25))
|
||||
];
|
||||
|
||||
|
||||
@ -21,29 +21,29 @@ outlinecolor="black";
|
||||
|
||||
|
||||
module showit(label, rgn, poly=polycolor, outline=outlinecolor, width=0.5) {
|
||||
move([-50,-50]) {
|
||||
if(outline) color(outline) linear_extrude(height=max(0.1,1-width)) for(path=rgn) stroke(path, width=width, closed=true);
|
||||
if(poly) color(poly) linear_extrude(height=0.1) region(rgn);
|
||||
color("black") right(50) fwd(7) linear_extrude(height=0.1) text(text=label, size=8, halign="center", valign="center");
|
||||
}
|
||||
move([-50,-50]) {
|
||||
if(outline) color(outline) linear_extrude(height=max(0.1,1-width)) for(path=rgn) stroke(path, width=width, closed=true);
|
||||
if(poly) color(poly) linear_extrude(height=0.1) region(rgn);
|
||||
color("black") right(50) fwd(7) linear_extrude(height=0.1) text(text=label, size=8, halign="center", valign="center");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ydistribute(-125) {
|
||||
xdistribute(120) {
|
||||
showit("Region A", rgn1, poly=[1,0,0,0.5]);
|
||||
showit("Region B", rgn2, poly=[0,0,1,0.5]);
|
||||
union() {
|
||||
showit("A and B Overlaid", rgn1, poly=[1,0,0,0.5]);
|
||||
showit("", rgn2, poly=[0,0,1,0.5]);
|
||||
}
|
||||
}
|
||||
xdistribute(120) {
|
||||
showit("Union A+B", union(rgn1, rgn2));
|
||||
showit("Difference A-B", difference(rgn1, rgn2));
|
||||
showit("Intersection A&B", intersection(rgn1, rgn2));
|
||||
showit("Exclusive OR A^B", exclusive_or(rgn1, rgn2));
|
||||
}
|
||||
xdistribute(120) {
|
||||
showit("Region A", rgn1, poly=[1,0,0,0.5]);
|
||||
showit("Region B", rgn2, poly=[0,0,1,0.5]);
|
||||
union() {
|
||||
showit("A and B Overlaid", rgn1, poly=[1,0,0,0.5]);
|
||||
showit("", rgn2, poly=[0,0,1,0.5]);
|
||||
}
|
||||
}
|
||||
xdistribute(120) {
|
||||
showit("Union A+B", union(rgn1, rgn2));
|
||||
showit("Difference A-B", difference(rgn1, rgn2));
|
||||
showit("Intersection A&B", intersection(rgn1, rgn2));
|
||||
showit("Exclusive OR A^B", exclusive_or(rgn1, rgn2));
|
||||
}
|
||||
}
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -5,4 +5,4 @@ include <BOSL2/debug.scad>
|
||||
cylinder(h=30, d1=50, d2=30) show_anchors();
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -5,4 +5,4 @@ include <BOSL2/debug.scad>
|
||||
cube(40, center=true) show_anchors();
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -6,8 +6,8 @@ include <BOSL2/std.scad>
|
||||
s = 20;
|
||||
s2 = s * sin(45);
|
||||
zcopies(s2,n=8) union()
|
||||
grid2d([s2,s2],n=8,stagger=($idx%2)? true : "alt")
|
||||
sphere(d=s);
|
||||
grid2d([s2,s2],n=8,stagger=($idx%2)? true : "alt")
|
||||
sphere(d=s);
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -5,4 +5,4 @@ include <BOSL2/debug.scad>
|
||||
cylinder(h=30, d=30) show_anchors();
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -1,17 +1,17 @@
|
||||
include <BOSL2/std.scad>
|
||||
module tree(l=1500, sc=0.7, depth=10)
|
||||
recolor("lightgray")
|
||||
cylinder(l=l, d1=l/5, d2=l/5*sc)
|
||||
attach(TOP)
|
||||
if (depth>0)
|
||||
zrot(90)
|
||||
zrot_copies(n=2)
|
||||
yrot(30) tree(depth=depth-1, l=l*sc, sc=sc);
|
||||
else
|
||||
recolor("springgreen")
|
||||
yscale(0.67)
|
||||
teardrop(d=l*3, l=1, anchor=BOT, spin=90);
|
||||
recolor("lightgray")
|
||||
cylinder(l=l, d1=l/5, d2=l/5*sc)
|
||||
attach(TOP)
|
||||
if (depth>0)
|
||||
zrot(90)
|
||||
zrot_copies(n=2)
|
||||
yrot(30) tree(depth=depth-1, l=l*sc, sc=sc);
|
||||
else
|
||||
recolor("springgreen")
|
||||
yscale(0.67)
|
||||
teardrop(d=l*3, l=1, anchor=BOT, spin=90);
|
||||
tree();
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -7,9 +7,9 @@ s = 20;
|
||||
xyr = adj_ang_to_hyp(s/2,30);
|
||||
h = hyp_adj_to_opp(s,xyr);
|
||||
zcopies(h,n=8) union()
|
||||
back(($idx%2)*xyr*cos(60))
|
||||
grid2d(s,n=[12,7],stagger=($idx%2)? "alt" : true)
|
||||
sphere(d=s);
|
||||
back(($idx%2)*xyr*cos(60))
|
||||
grid2d(s,n=[12,7],stagger=($idx%2)? "alt" : true)
|
||||
sphere(d=s);
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -1,46 +1,46 @@
|
||||
include <BOSL2/std.scad>
|
||||
|
||||
function _lsystem_recurse(s, rules, lev) =
|
||||
lev<=0? s : _lsystem_recurse([
|
||||
for (
|
||||
i = 0,
|
||||
slen = len(s),
|
||||
sout = "";
|
||||
lev<=0? s : _lsystem_recurse([
|
||||
for (
|
||||
i = 0,
|
||||
slen = len(s),
|
||||
sout = "";
|
||||
|
||||
i <= slen;
|
||||
i <= slen;
|
||||
|
||||
ch = s[i],
|
||||
found = search([ch], rules)[0],
|
||||
sout = str(sout, i==slen? "" : found==[]? ch : rules[found][1]),
|
||||
i = i + 1
|
||||
) if (i==slen) sout
|
||||
][0], rules, lev-1);
|
||||
ch = s[i],
|
||||
found = search([ch], rules)[0],
|
||||
sout = str(sout, i==slen? "" : found==[]? ch : rules[found][1]),
|
||||
i = i + 1
|
||||
) if (i==slen) sout
|
||||
][0], rules, lev-1);
|
||||
|
||||
|
||||
function _lsystem_to_turtle(s, step=1, angle=90, startang=0) =
|
||||
concat(
|
||||
startang? ["left", startang] : [],
|
||||
["angle", angle, "length", step],
|
||||
[
|
||||
for (
|
||||
i = 0,
|
||||
slen = len(s);
|
||||
concat(
|
||||
startang? ["left", startang] : [],
|
||||
["angle", angle, "length", step],
|
||||
[
|
||||
for (
|
||||
i = 0,
|
||||
slen = len(s);
|
||||
|
||||
i <= slen;
|
||||
i <= slen;
|
||||
|
||||
ch = s[i],
|
||||
cmd = (ch=="A" || ch=="B" || ch=="F")? ["move"] :
|
||||
(ch=="+")? ["left"] :
|
||||
(ch=="-")? ["right"] :
|
||||
[],
|
||||
i=i+1
|
||||
) if(i>0 && cmd!=[]) each cmd
|
||||
]
|
||||
);
|
||||
ch = s[i],
|
||||
cmd = (ch=="A" || ch=="B" || ch=="F")? ["move"] :
|
||||
(ch=="+")? ["left"] :
|
||||
(ch=="-")? ["right"] :
|
||||
[],
|
||||
i=i+1
|
||||
) if(i>0 && cmd!=[]) each cmd
|
||||
]
|
||||
);
|
||||
|
||||
|
||||
function lsystem_turtle(basis, rules, levels=5, step=1, angle=90, startang=0) =
|
||||
turtle(_lsystem_to_turtle(_lsystem_recurse(basis, rules, levels), step=step, angle=angle, startang=startang));
|
||||
turtle(_lsystem_to_turtle(_lsystem_recurse(basis, rules, levels), step=step, angle=angle, startang=startang));
|
||||
|
||||
|
||||
function dragon_curve (levels=9, step=1) = lsystem_turtle(levels=levels, step=step, angle=90, "FX", [["X", "X+YF+"], ["Y", "-FX-Y"]]);
|
||||
@ -67,4 +67,4 @@ points = hilbert_curve(levels=5, step=100/pow(2,5));
|
||||
stroke(points, width=1);
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -18,10 +18,10 @@ module orient_cube(ang) {
|
||||
color(axiscolors.z) back((20-1)/2+0.01) right((20-1)/2+0.01) cube([1,1,18], center=true);
|
||||
for (axis=[0:2], neg=[0:1]) {
|
||||
idx = axis + 3*neg;
|
||||
labels = [
|
||||
"RIGHT", "BACK", "UP",
|
||||
"LEFT", "FWD", "DOWN"
|
||||
];
|
||||
labels = [
|
||||
"RIGHT", "BACK", "UP",
|
||||
"LEFT", "FWD", "DOWN"
|
||||
];
|
||||
rot(ang, from=UP, to=orientations[idx]) {
|
||||
up(10) {
|
||||
back(4) color("black") text3d(text=str("spin=",ang), size=2.5);
|
||||
@ -42,34 +42,34 @@ module text3d(text, h=0.01, size=3) {
|
||||
module dottedline(l, d) for(y = [0:d*3:l]) up(y) sphere(d=d);
|
||||
|
||||
module orient_cubes() {
|
||||
// X axis
|
||||
color(axiscolors[0]) {
|
||||
yrot( 90) cylinder(h=axislen, d=axisdiam, center=false);
|
||||
right(axislbllen) rot([90,0,0]) text3d(text="X+");
|
||||
yrot(-90) dottedline(l=axislen, d=axisdiam);
|
||||
left(axislbllen) rot([90,0,180]) text3d(text="X-");
|
||||
}
|
||||
// Y axis
|
||||
color(axiscolors[1]) {
|
||||
xrot(-90) cylinder(h=axislen, d=axisdiam, center=false);
|
||||
back(axislbllen) rot([90,0,90]) text3d(text="Y+");
|
||||
xrot( 90) dottedline(l=axislen, d=axisdiam);
|
||||
fwd(axislbllen) rot([90,0,-90]) text3d(text="Y-");
|
||||
}
|
||||
// Z axis
|
||||
color(axiscolors[2]) {
|
||||
cylinder(h=axislen, d=axisdiam, center=false);
|
||||
up(axislbllen) rot([0,-90,90+$vpr[2]]) text3d(text="Z+");
|
||||
xrot(180) dottedline(l=axislen, d=axisdiam);
|
||||
down(axislbllen) rot([0,90,-90+$vpr[2]]) text3d(text="Z-");
|
||||
}
|
||||
// X axis
|
||||
color(axiscolors[0]) {
|
||||
yrot( 90) cylinder(h=axislen, d=axisdiam, center=false);
|
||||
right(axislbllen) rot([90,0,0]) text3d(text="X+");
|
||||
yrot(-90) dottedline(l=axislen, d=axisdiam);
|
||||
left(axislbllen) rot([90,0,180]) text3d(text="X-");
|
||||
}
|
||||
// Y axis
|
||||
color(axiscolors[1]) {
|
||||
xrot(-90) cylinder(h=axislen, d=axisdiam, center=false);
|
||||
back(axislbllen) rot([90,0,90]) text3d(text="Y+");
|
||||
xrot( 90) dottedline(l=axislen, d=axisdiam);
|
||||
fwd(axislbllen) rot([90,0,-90]) text3d(text="Y-");
|
||||
}
|
||||
// Z axis
|
||||
color(axiscolors[2]) {
|
||||
cylinder(h=axislen, d=axisdiam, center=false);
|
||||
up(axislbllen) rot([0,-90,90+$vpr[2]]) text3d(text="Z+");
|
||||
xrot(180) dottedline(l=axislen, d=axisdiam);
|
||||
down(axislbllen) rot([0,90,-90+$vpr[2]]) text3d(text="Z-");
|
||||
}
|
||||
|
||||
for (ang = [0:90:270]) {
|
||||
off = rot(p=40*BACK,ang);
|
||||
translate(off) {
|
||||
orient_cube(ang);
|
||||
}
|
||||
}
|
||||
for (ang = [0:90:270]) {
|
||||
off = rot(p=40*BACK,ang);
|
||||
translate(off) {
|
||||
orient_cube(ang);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -77,4 +77,4 @@ orient_cubes();
|
||||
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -5,4 +5,4 @@ include <BOSL2/debug.scad>
|
||||
prismoid([60,40], [30,20], h=40) show_anchors();
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -3,46 +3,46 @@ include <BOSL2/paths.scad>
|
||||
include <BOSL2/beziers.scad>
|
||||
|
||||
module leaf(s) {
|
||||
path = [
|
||||
[0,0], [1.5,-1],
|
||||
[2,1], [0,3], [-2,1],
|
||||
[-1.5,-1], [0,0]
|
||||
];
|
||||
xrot(90)
|
||||
linear_sweep_bezier(
|
||||
path * s/2,
|
||||
height=0.02
|
||||
);
|
||||
path = [
|
||||
[0,0], [1.5,-1],
|
||||
[2,1], [0,3], [-2,1],
|
||||
[-1.5,-1], [0,0]
|
||||
];
|
||||
xrot(90)
|
||||
linear_sweep_bezier(
|
||||
path * s/2,
|
||||
height=0.02
|
||||
);
|
||||
}
|
||||
|
||||
module branches(minsize, s1, s2){
|
||||
if(s2>minsize) {
|
||||
attach(TOP)
|
||||
zrot(gaussian_rands(90,20)[0])
|
||||
zrot_copies(n=floor(log_rands(2,5,4)[0]))
|
||||
zrot(gaussian_rands(0,5)[0])
|
||||
yrot(gaussian_rands(30,10)[0]) {
|
||||
sc = gaussian_rands(0.7,0.05)[0];
|
||||
cylinder(d1=s2, d2=s2*sc, l=s1)
|
||||
branches(minsize, s1*sc, s2*sc);
|
||||
}
|
||||
} else {
|
||||
recolor("springgreen")
|
||||
attach(TOP) zrot(90)
|
||||
leaf(gaussian_rands(100,5)[0]);
|
||||
}
|
||||
attach(TOP)
|
||||
zrot(gaussian_rands(90,20)[0])
|
||||
zrot_copies(n=floor(log_rands(2,5,4)[0]))
|
||||
zrot(gaussian_rands(0,5)[0])
|
||||
yrot(gaussian_rands(30,10)[0]) {
|
||||
sc = gaussian_rands(0.7,0.05)[0];
|
||||
cylinder(d1=s2, d2=s2*sc, l=s1)
|
||||
branches(minsize, s1*sc, s2*sc);
|
||||
}
|
||||
} else {
|
||||
recolor("springgreen")
|
||||
attach(TOP) zrot(90)
|
||||
leaf(gaussian_rands(100,5)[0]);
|
||||
}
|
||||
}
|
||||
|
||||
module tree(h, d, minsize) {
|
||||
sc = gaussian_rands(0.7,0.05)[0];
|
||||
recolor("lightgray") {
|
||||
cylinder(d1=d, d2=d*sc, l=h) {
|
||||
branches(minsize, h, d*sc);
|
||||
}
|
||||
}
|
||||
sc = gaussian_rands(0.7,0.05)[0];
|
||||
recolor("lightgray") {
|
||||
cylinder(d1=d, d2=d*sc, l=h) {
|
||||
branches(minsize, h, d*sc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tree(d=300, h=1500, minsize=10);
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -10,4 +10,4 @@ metric_bolt(headtype="oval", size=10, l=15, shank=5, details=true, phillips="#2"
|
||||
show_anchors(5, std=false);
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -5,4 +5,4 @@ include <BOSL2/debug.scad>
|
||||
spheroid(d=30) show_anchors();
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -8,13 +8,13 @@ p = s * d;
|
||||
q = s * 0.55 * d;
|
||||
u = s * 2.5 * UP;
|
||||
patch1 = [
|
||||
[p[2], p[2]+q[3], p[3]+q[2], p[3] ],
|
||||
[p[2]+q[1], p[2]+q[2]+u, p[3]+q[3]+u, p[3]+q[0]],
|
||||
[p[1]+q[2], p[1]+q[1]+u, p[0]+q[0]+u, p[0]+q[3]],
|
||||
[p[1], p[1]+q[0], p[0]+q[1], p[0] ],
|
||||
[p[2], p[2]+q[3], p[3]+q[2], p[3] ],
|
||||
[p[2]+q[1], p[2]+q[2]+u, p[3]+q[3]+u, p[3]+q[0]],
|
||||
[p[1]+q[2], p[1]+q[1]+u, p[0]+q[0]+u, p[0]+q[3]],
|
||||
[p[1], p[1]+q[0], p[0]+q[1], p[0] ],
|
||||
];
|
||||
patch2 = patch_reverse(zflip(p=patch1));
|
||||
trace_bezier_patches([patch1, patch2], splinesteps=16, style="quincunx");
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -3,13 +3,13 @@ include <BOSL2/std.scad>
|
||||
|
||||
diff("hole", "body pole")
|
||||
sphere(d=100, $tags="body") {
|
||||
zcyl(d=55, h=100, $tags="pole"); // attach() not needed for center-to-center.
|
||||
tags("hole") {
|
||||
xcyl(d=55, h=101);
|
||||
ycyl(d=55, h=101);
|
||||
}
|
||||
zcyl(d=15, h=140, $tags="axle");
|
||||
zcyl(d=55, h=100, $tags="pole"); // attach() not needed for center-to-center.
|
||||
tags("hole") {
|
||||
xcyl(d=55, h=101);
|
||||
ycyl(d=55, h=101);
|
||||
}
|
||||
zcyl(d=15, h=140, $tags="axle");
|
||||
}
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
1072
geometry.scad
1072
geometry.scad
File diff suppressed because it is too large
Load Diff
130
hingesnaps.scad
130
hingesnaps.scad
@ -29,13 +29,13 @@
|
||||
// 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();
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -58,18 +58,18 @@ module folding_hinge_mask(l, thick, layerheight=0.2, foldangle=90, hingegap=unde
|
||||
// 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();
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -92,21 +92,21 @@ module snap_lock(thick, snaplen=5, snapdiam=5, layerheight=0.2, foldangle=90, hi
|
||||
// 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();
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -157,37 +157,37 @@ module snap_socket(thick, snaplen=5, snapdiam=5, layerheight=0.2, foldangle=90,
|
||||
// }
|
||||
module apply_folding_hinges_and_snaps(thick, foldangle=90, hinges=[], snaps=[], sockets=[], snaplen=5, snapdiam=5, hingegap=undef, layerheight=0.2)
|
||||
{
|
||||
hingegap = default(hingegap, layerheight)+2*$slop;
|
||||
difference() {
|
||||
children();
|
||||
for (hinge = hinges) {
|
||||
translate(hinge[1]) {
|
||||
folding_hinge_mask(
|
||||
l=hinge[0], thick=thick, layerheight=layerheight,
|
||||
foldangle=foldangle, hingegap=hingegap, spin=hinge[2]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (snap = snaps) {
|
||||
translate(snap[0]) {
|
||||
snap_lock(
|
||||
thick=thick, snaplen=snaplen, snapdiam=snapdiam,
|
||||
layerheight=layerheight, foldangle=foldangle,
|
||||
hingegap=hingegap, spin=snap[1]
|
||||
);
|
||||
}
|
||||
}
|
||||
for (socket = sockets) {
|
||||
translate(socket[0]) {
|
||||
snap_socket(
|
||||
thick=thick, snaplen=snaplen, snapdiam=snapdiam,
|
||||
layerheight=layerheight, foldangle=foldangle,
|
||||
hingegap=hingegap, spin=socket[1]
|
||||
);
|
||||
}
|
||||
}
|
||||
hingegap = default(hingegap, layerheight)+2*$slop;
|
||||
difference() {
|
||||
children();
|
||||
for (hinge = hinges) {
|
||||
translate(hinge[1]) {
|
||||
folding_hinge_mask(
|
||||
l=hinge[0], thick=thick, layerheight=layerheight,
|
||||
foldangle=foldangle, hingegap=hingegap, spin=hinge[2]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (snap = snaps) {
|
||||
translate(snap[0]) {
|
||||
snap_lock(
|
||||
thick=thick, snaplen=snaplen, snapdiam=snapdiam,
|
||||
layerheight=layerheight, foldangle=foldangle,
|
||||
hingegap=hingegap, spin=snap[1]
|
||||
);
|
||||
}
|
||||
}
|
||||
for (socket = sockets) {
|
||||
translate(socket[0]) {
|
||||
snap_socket(
|
||||
thick=thick, snaplen=snaplen, snapdiam=snapdiam,
|
||||
layerheight=layerheight, foldangle=foldangle,
|
||||
hingegap=hingegap, spin=socket[1]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
254
hull.scad
254
hull.scad
@ -48,29 +48,29 @@ function hull(points) = let(two_d = len(points[0]) == 2) two_d? hull2d_path(poin
|
||||
// pts = [for (phi = [30:60:150], theta = [0:60:359]) spherical_to_xyz(10, theta, phi)];
|
||||
// hull_points(pts);
|
||||
module hull_points(points, fast=false) {
|
||||
assert(is_list(points));
|
||||
if (points) {
|
||||
assert(is_list(points[0]));
|
||||
if (fast) {
|
||||
if (len(points[0]) == 2) {
|
||||
hull() polygon(points=points);
|
||||
} else {
|
||||
extra = len(points)%3;
|
||||
faces = concat(
|
||||
[[for(i=[0:1:extra+2])i]],
|
||||
[for(i=[extra+3:3:len(points)-3])[i,i+1,i+2]]
|
||||
);
|
||||
hull() polyhedron(points=points, faces=faces);
|
||||
}
|
||||
} else {
|
||||
perim = hull(points);
|
||||
if (is_num(perim[0])) {
|
||||
polygon(points=points, paths=[perim]);
|
||||
} else {
|
||||
polyhedron(points=points, faces=perim);
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(is_list(points));
|
||||
if (points) {
|
||||
assert(is_list(points[0]));
|
||||
if (fast) {
|
||||
if (len(points[0]) == 2) {
|
||||
hull() polygon(points=points);
|
||||
} else {
|
||||
extra = len(points)%3;
|
||||
faces = concat(
|
||||
[[for(i=[0:1:extra+2])i]],
|
||||
[for(i=[extra+3:3:len(points)-3])[i,i+1,i+2]]
|
||||
);
|
||||
hull() polyhedron(points=points, faces=faces);
|
||||
}
|
||||
} else {
|
||||
perim = hull(points);
|
||||
if (is_num(perim[0])) {
|
||||
polygon(points=points, paths=[perim]);
|
||||
} else {
|
||||
polyhedron(points=points, faces=perim);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -86,62 +86,62 @@ module hull_points(points, fast=false) {
|
||||
// move_copies(pts) color("red") sphere(1);
|
||||
// polygon(points=pts, paths=[path]);
|
||||
function hull2d_path(points) =
|
||||
(len(points) < 3)? [] : let(
|
||||
a=0, b=1,
|
||||
c = first_noncollinear(a, b, points)
|
||||
) (c == len(points))? _hull2d_collinear(points) : let(
|
||||
remaining = [ for (i = [2:1:len(points)-1]) if (i != c) i ],
|
||||
ccw = triangle_area(points[a], points[b], points[c]) > 0,
|
||||
polygon = ccw? [a,b,c] : [a,c,b]
|
||||
) _hull2d_iterative(points, polygon, remaining);
|
||||
(len(points) < 3)? [] : let(
|
||||
a=0, b=1,
|
||||
c = first_noncollinear(a, b, points)
|
||||
) (c == len(points))? _hull2d_collinear(points) : let(
|
||||
remaining = [ for (i = [2:1:len(points)-1]) if (i != c) i ],
|
||||
ccw = triangle_area(points[a], points[b], points[c]) > 0,
|
||||
polygon = ccw? [a,b,c] : [a,c,b]
|
||||
) _hull2d_iterative(points, polygon, remaining);
|
||||
|
||||
|
||||
// Adds the remaining points one by one to the convex hull
|
||||
function _hull2d_iterative(points, polygon, remaining, _i=0) =
|
||||
(_i >= len(remaining))? polygon : let (
|
||||
// pick a point
|
||||
i = remaining[_i],
|
||||
// find the segments that are in conflict with the point (point not inside)
|
||||
conflicts = _find_conflicting_segments(points, polygon, points[i])
|
||||
// no conflicts, skip point and move on
|
||||
) (len(conflicts) == 0)? _hull2d_iterative(points, polygon, remaining, _i+1) : let(
|
||||
// find the first conflicting segment and the first not conflicting
|
||||
// conflict will be sorted, if not wrapping around, do it the easy way
|
||||
polygon = _remove_conflicts_and_insert_point(polygon, conflicts, i)
|
||||
) _hull2d_iterative(points, polygon, remaining, _i+1);
|
||||
(_i >= len(remaining))? polygon : let (
|
||||
// pick a point
|
||||
i = remaining[_i],
|
||||
// find the segments that are in conflict with the point (point not inside)
|
||||
conflicts = _find_conflicting_segments(points, polygon, points[i])
|
||||
// no conflicts, skip point and move on
|
||||
) (len(conflicts) == 0)? _hull2d_iterative(points, polygon, remaining, _i+1) : let(
|
||||
// find the first conflicting segment and the first not conflicting
|
||||
// conflict will be sorted, if not wrapping around, do it the easy way
|
||||
polygon = _remove_conflicts_and_insert_point(polygon, conflicts, i)
|
||||
) _hull2d_iterative(points, polygon, remaining, _i+1);
|
||||
|
||||
|
||||
function _hull2d_collinear(points) =
|
||||
let(
|
||||
a = points[0],
|
||||
n = points[1] - a,
|
||||
points1d = [ for(p = points) (p-a)*n ],
|
||||
min_i = min_index(points1d),
|
||||
max_i = max_index(points1d)
|
||||
) [min_i, max_i];
|
||||
let(
|
||||
a = points[0],
|
||||
n = points[1] - a,
|
||||
points1d = [ for(p = points) (p-a)*n ],
|
||||
min_i = min_index(points1d),
|
||||
max_i = max_index(points1d)
|
||||
) [min_i, max_i];
|
||||
|
||||
|
||||
function _find_conflicting_segments(points, polygon, point) = [
|
||||
for (i = [0:1:len(polygon)-1]) let(
|
||||
j = (i+1) % len(polygon),
|
||||
p1 = points[polygon[i]],
|
||||
p2 = points[polygon[j]],
|
||||
area = triangle_area(p1, p2, point)
|
||||
) if (area < 0) i
|
||||
for (i = [0:1:len(polygon)-1]) let(
|
||||
j = (i+1) % len(polygon),
|
||||
p1 = points[polygon[i]],
|
||||
p2 = points[polygon[j]],
|
||||
area = triangle_area(p1, p2, point)
|
||||
) if (area < 0) i
|
||||
];
|
||||
|
||||
|
||||
// remove the conflicting segments from the polygon
|
||||
function _remove_conflicts_and_insert_point(polygon, conflicts, point) =
|
||||
(conflicts[0] == 0)? let(
|
||||
nonconflicting = [ for(i = [0:1:len(polygon)-1]) if (!in_list(i, conflicts)) i ],
|
||||
new_indices = concat(nonconflicting, (nonconflicting[len(nonconflicting)-1]+1) % len(polygon)),
|
||||
polygon = concat([ for (i = new_indices) polygon[i] ], point)
|
||||
) polygon : let(
|
||||
before_conflicts = [ for(i = [0:1:min(conflicts)]) polygon[i] ],
|
||||
after_conflicts = (max(conflicts) >= (len(polygon)-1))? [] : [ for(i = [max(conflicts)+1:1:len(polygon)-1]) polygon[i] ],
|
||||
polygon = concat(before_conflicts, point, after_conflicts)
|
||||
) polygon;
|
||||
(conflicts[0] == 0)? let(
|
||||
nonconflicting = [ for(i = [0:1:len(polygon)-1]) if (!in_list(i, conflicts)) i ],
|
||||
new_indices = concat(nonconflicting, (nonconflicting[len(nonconflicting)-1]+1) % len(polygon)),
|
||||
polygon = concat([ for (i = new_indices) polygon[i] ], point)
|
||||
) polygon : let(
|
||||
before_conflicts = [ for(i = [0:1:min(conflicts)]) polygon[i] ],
|
||||
after_conflicts = (max(conflicts) >= (len(polygon)-1))? [] : [ for(i = [max(conflicts)+1:1:len(polygon)-1]) polygon[i] ],
|
||||
polygon = concat(before_conflicts, point, after_conflicts)
|
||||
) polygon;
|
||||
|
||||
|
||||
|
||||
@ -159,83 +159,83 @@ function _remove_conflicts_and_insert_point(polygon, conflicts, point) =
|
||||
// move_copies(pts) color("red") sphere(1);
|
||||
// %polyhedron(points=pts, faces=faces);
|
||||
function hull3d_faces(points) =
|
||||
(len(points) < 3)? list_range(len(points)) : let (
|
||||
// start with a single non-collinear triangle
|
||||
a = 0,
|
||||
b = 1,
|
||||
c = first_noncollinear(a, b, points)
|
||||
) (c == len(points))? _hull2d_collinear(points) : let(
|
||||
plane = plane3pt_indexed(points, a, b, c),
|
||||
d = _find_first_noncoplanar(plane, points, 3)
|
||||
) (d == len(points))? /* all coplanar*/ let (
|
||||
pts2d = [ for (p = points) project_plane(p, points[a], points[b], points[c]) ],
|
||||
hull2d = hull2d_path(pts2d)
|
||||
) hull2d : let(
|
||||
remaining = [for (i = [3:1:len(points)-1]) if (i != d) i],
|
||||
// Build an initial tetrahedron.
|
||||
// Swap b, c if d is in front of triangle t.
|
||||
ifop = in_front_of_plane(plane, points[d]),
|
||||
bc = ifop? [c,b] : [b,c],
|
||||
b = bc[0],
|
||||
c = bc[1],
|
||||
triangles = [
|
||||
[a,b,c],
|
||||
[d,b,a],
|
||||
[c,d,a],
|
||||
[b,d,c]
|
||||
],
|
||||
// calculate the plane equations
|
||||
planes = [ for (t = triangles) plane3pt_indexed(points, t[0], t[1], t[2]) ]
|
||||
) _hull3d_iterative(points, triangles, planes, remaining);
|
||||
(len(points) < 3)? list_range(len(points)) : let (
|
||||
// start with a single non-collinear triangle
|
||||
a = 0,
|
||||
b = 1,
|
||||
c = first_noncollinear(a, b, points)
|
||||
) (c == len(points))? _hull2d_collinear(points) : let(
|
||||
plane = plane3pt_indexed(points, a, b, c),
|
||||
d = _find_first_noncoplanar(plane, points, 3)
|
||||
) (d == len(points))? /* all coplanar*/ let (
|
||||
pts2d = [ for (p = points) project_plane(p, points[a], points[b], points[c]) ],
|
||||
hull2d = hull2d_path(pts2d)
|
||||
) hull2d : let(
|
||||
remaining = [for (i = [3:1:len(points)-1]) if (i != d) i],
|
||||
// Build an initial tetrahedron.
|
||||
// Swap b, c if d is in front of triangle t.
|
||||
ifop = in_front_of_plane(plane, points[d]),
|
||||
bc = ifop? [c,b] : [b,c],
|
||||
b = bc[0],
|
||||
c = bc[1],
|
||||
triangles = [
|
||||
[a,b,c],
|
||||
[d,b,a],
|
||||
[c,d,a],
|
||||
[b,d,c]
|
||||
],
|
||||
// calculate the plane equations
|
||||
planes = [ for (t = triangles) plane3pt_indexed(points, t[0], t[1], t[2]) ]
|
||||
) _hull3d_iterative(points, triangles, planes, remaining);
|
||||
|
||||
|
||||
// Adds the remaining points one by one to the convex hull
|
||||
function _hull3d_iterative(points, triangles, planes, remaining, _i=0) =
|
||||
_i >= len(remaining) ? triangles :
|
||||
let (
|
||||
// pick a point
|
||||
i = remaining[_i],
|
||||
// find the triangles that are in conflict with the point (point not inside)
|
||||
conflicts = _find_conflicts(points[i], planes),
|
||||
// for all triangles that are in conflict, collect their halfedges
|
||||
halfedges = [
|
||||
for(c = conflicts, i = [0:2]) let(
|
||||
j = (i+1)%3
|
||||
) [triangles[c][i], triangles[c][j]]
|
||||
],
|
||||
// find the outer perimeter of the set of conflicting triangles
|
||||
horizon = _remove_internal_edges(halfedges),
|
||||
// generate a new triangle for each horizon halfedge together with the picked point i
|
||||
new_triangles = [ for (h = horizon) concat(h,i) ],
|
||||
// calculate the corresponding plane equations
|
||||
new_planes = [ for (t = new_triangles) plane3pt_indexed(points, t[0], t[1], t[2]) ]
|
||||
) _hull3d_iterative(
|
||||
points,
|
||||
// remove the conflicting triangles and add the new ones
|
||||
concat(list_remove(triangles, conflicts), new_triangles),
|
||||
concat(list_remove(planes, conflicts), new_planes),
|
||||
remaining,
|
||||
_i+1
|
||||
);
|
||||
_i >= len(remaining) ? triangles :
|
||||
let (
|
||||
// pick a point
|
||||
i = remaining[_i],
|
||||
// find the triangles that are in conflict with the point (point not inside)
|
||||
conflicts = _find_conflicts(points[i], planes),
|
||||
// for all triangles that are in conflict, collect their halfedges
|
||||
halfedges = [
|
||||
for(c = conflicts, i = [0:2]) let(
|
||||
j = (i+1)%3
|
||||
) [triangles[c][i], triangles[c][j]]
|
||||
],
|
||||
// find the outer perimeter of the set of conflicting triangles
|
||||
horizon = _remove_internal_edges(halfedges),
|
||||
// generate a new triangle for each horizon halfedge together with the picked point i
|
||||
new_triangles = [ for (h = horizon) concat(h,i) ],
|
||||
// calculate the corresponding plane equations
|
||||
new_planes = [ for (t = new_triangles) plane3pt_indexed(points, t[0], t[1], t[2]) ]
|
||||
) _hull3d_iterative(
|
||||
points,
|
||||
// remove the conflicting triangles and add the new ones
|
||||
concat(list_remove(triangles, conflicts), new_triangles),
|
||||
concat(list_remove(planes, conflicts), new_planes),
|
||||
remaining,
|
||||
_i+1
|
||||
);
|
||||
|
||||
|
||||
function _remove_internal_edges(halfedges) = [
|
||||
for (h = halfedges)
|
||||
if (!in_list(reverse(h), halfedges))
|
||||
h
|
||||
for (h = halfedges)
|
||||
if (!in_list(reverse(h), halfedges))
|
||||
h
|
||||
];
|
||||
|
||||
|
||||
function _find_conflicts(point, planes) = [
|
||||
for (i = [0:1:len(planes)-1])
|
||||
if (in_front_of_plane(planes[i], point))
|
||||
i
|
||||
for (i = [0:1:len(planes)-1])
|
||||
if (in_front_of_plane(planes[i], point))
|
||||
i
|
||||
];
|
||||
|
||||
|
||||
function _find_first_noncoplanar(plane, points, i) =
|
||||
(i >= len(points) || !coplanar(plane, points[i]))? i :
|
||||
_find_first_noncoplanar(plane, points, i+1);
|
||||
(i >= len(points) || !coplanar(plane, points[i]))? i :
|
||||
_find_first_noncoplanar(plane, points, i+1);
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -78,7 +78,7 @@ function adendum(pitch=5) = module_value(pitch);
|
||||
// pitch = The circular pitch, or distance between teeth around the pitch circle, in mm.
|
||||
// clearance = If given, sets the clearance between meshing teeth.
|
||||
function dedendum(pitch=5, clearance=undef) =
|
||||
(clearance==undef)? (1.25 * module_value(pitch)) : (module_value(pitch) + clearance);
|
||||
(clearance==undef)? (1.25 * module_value(pitch)) : (module_value(pitch) + clearance);
|
||||
|
||||
|
||||
// Function: pitch_radius()
|
||||
@ -87,7 +87,7 @@ function dedendum(pitch=5, clearance=undef) =
|
||||
// pitch = The circular pitch, or distance between teeth around the pitch circle, in mm.
|
||||
// teeth = The number of teeth on the gear.
|
||||
function pitch_radius(pitch=5, teeth=11) =
|
||||
pitch * teeth / PI / 2;
|
||||
pitch * teeth / PI / 2;
|
||||
|
||||
|
||||
// Function: outer_radius()
|
||||
@ -99,8 +99,8 @@ function pitch_radius(pitch=5, teeth=11) =
|
||||
// clearance = If given, sets the clearance between meshing teeth.
|
||||
// interior = If true, calculate for an interior gear.
|
||||
function outer_radius(pitch=5, teeth=11, clearance=undef, interior=false) =
|
||||
pitch_radius(pitch, teeth) +
|
||||
(interior? dedendum(pitch, clearance) : adendum(pitch));
|
||||
pitch_radius(pitch, teeth) +
|
||||
(interior? dedendum(pitch, clearance) : adendum(pitch));
|
||||
|
||||
|
||||
// Function: root_radius()
|
||||
@ -112,8 +112,8 @@ function outer_radius(pitch=5, teeth=11, clearance=undef, interior=false) =
|
||||
// clearance = If given, sets the clearance between meshing teeth.
|
||||
// interior = If true, calculate for an interior gear.
|
||||
function root_radius(pitch=5, teeth=11, clearance=undef, interior=false) =
|
||||
pitch_radius(pitch, teeth) -
|
||||
(interior? adendum(pitch) : dedendum(pitch, clearance));
|
||||
pitch_radius(pitch, teeth) -
|
||||
(interior? adendum(pitch) : dedendum(pitch, clearance));
|
||||
|
||||
|
||||
// Function: base_radius()
|
||||
@ -123,7 +123,7 @@ function root_radius(pitch=5, teeth=11, clearance=undef, interior=false) =
|
||||
// teeth = The number of teeth on the gear.
|
||||
// PA = Pressure angle in degrees. Controls how straight or bulged the tooth sides are.
|
||||
function base_radius(pitch=5, teeth=11, PA=28) =
|
||||
pitch_radius(pitch, teeth) * cos(PA);
|
||||
pitch_radius(pitch, teeth) * cos(PA);
|
||||
|
||||
|
||||
// Function bevel_pitch_angle()
|
||||
@ -137,7 +137,7 @@ function base_radius(pitch=5, teeth=11, PA=28) =
|
||||
// mate_teeth = Number of teeth that the matching gear has.
|
||||
// drive_angle = Angle between the drive shafts of each gear. Usually 90º.
|
||||
function bevel_pitch_angle(teeth, mate_teeth, drive_angle=90) =
|
||||
atan(sin(drive_angle)/((mate_teeth/teeth)+cos(drive_angle)));
|
||||
atan(sin(drive_angle)/((mate_teeth/teeth)+cos(drive_angle)));
|
||||
|
||||
|
||||
function _gear_polar(r,t) = r*[sin(t),cos(t)];
|
||||
@ -166,63 +166,63 @@ function _gear_q7(f,r,b,r2,t,s) = _gear_q6(b,s,t,(1-f)*max(b,r)+f*r2); //
|
||||
// Example(2D):
|
||||
// gear_tooth_profile(pitch=5, teeth=20, PA=20, valleys=true);
|
||||
function gear_tooth_profile(
|
||||
pitch = 3,
|
||||
teeth = 11,
|
||||
PA = 28,
|
||||
backlash = 0.0,
|
||||
clearance = undef,
|
||||
interior = false,
|
||||
valleys = true
|
||||
pitch = 3,
|
||||
teeth = 11,
|
||||
PA = 28,
|
||||
backlash = 0.0,
|
||||
clearance = undef,
|
||||
interior = false,
|
||||
valleys = true
|
||||
) = let(
|
||||
p = pitch_radius(pitch, teeth),
|
||||
c = outer_radius(pitch, teeth, clearance, interior),
|
||||
r = root_radius(pitch, teeth, clearance, interior),
|
||||
b = base_radius(pitch, teeth, PA),
|
||||
t = pitch/2-backlash/2, //tooth thickness at pitch circle
|
||||
k = -_gear_iang(b, p) - t/2/p/PI*180, //angle to where involute meets base circle on each side of tooth
|
||||
kk = r<b? k : -180/teeth,
|
||||
isteps = 5,
|
||||
pts = concat(
|
||||
valleys? [
|
||||
_gear_polar(r-1, -180.1/teeth),
|
||||
_gear_polar(r, -180.1/teeth),
|
||||
] : [
|
||||
],
|
||||
[_gear_polar(r, kk)],
|
||||
[for (i=[0: 1:isteps]) _gear_q7(i/isteps,r,b,c,k, 1)],
|
||||
[for (i=[isteps:-1:0]) _gear_q7(i/isteps,r,b,c,k,-1)],
|
||||
[_gear_polar(r, -kk)],
|
||||
valleys? [
|
||||
_gear_polar(r, 180.1/teeth),
|
||||
_gear_polar(r-1, 180.1/teeth),
|
||||
] : [
|
||||
]
|
||||
)
|
||||
p = pitch_radius(pitch, teeth),
|
||||
c = outer_radius(pitch, teeth, clearance, interior),
|
||||
r = root_radius(pitch, teeth, clearance, interior),
|
||||
b = base_radius(pitch, teeth, PA),
|
||||
t = pitch/2-backlash/2, //tooth thickness at pitch circle
|
||||
k = -_gear_iang(b, p) - t/2/p/PI*180, //angle to where involute meets base circle on each side of tooth
|
||||
kk = r<b? k : -180/teeth,
|
||||
isteps = 5,
|
||||
pts = concat(
|
||||
valleys? [
|
||||
_gear_polar(r-1, -180.1/teeth),
|
||||
_gear_polar(r, -180.1/teeth),
|
||||
] : [
|
||||
],
|
||||
[_gear_polar(r, kk)],
|
||||
[for (i=[0: 1:isteps]) _gear_q7(i/isteps,r,b,c,k, 1)],
|
||||
[for (i=[isteps:-1:0]) _gear_q7(i/isteps,r,b,c,k,-1)],
|
||||
[_gear_polar(r, -kk)],
|
||||
valleys? [
|
||||
_gear_polar(r, 180.1/teeth),
|
||||
_gear_polar(r-1, 180.1/teeth),
|
||||
] : [
|
||||
]
|
||||
)
|
||||
) reverse(pts);
|
||||
|
||||
|
||||
module gear_tooth_profile(
|
||||
pitch = 3,
|
||||
teeth = 11,
|
||||
PA = 28,
|
||||
backlash = 0.0,
|
||||
clearance = undef,
|
||||
interior = false,
|
||||
valleys = true
|
||||
pitch = 3,
|
||||
teeth = 11,
|
||||
PA = 28,
|
||||
backlash = 0.0,
|
||||
clearance = undef,
|
||||
interior = false,
|
||||
valleys = true
|
||||
) {
|
||||
r = root_radius(pitch, teeth, clearance, interior);
|
||||
translate([0,-r,0])
|
||||
polygon(
|
||||
points=gear_tooth_profile(
|
||||
pitch = pitch,
|
||||
teeth = teeth,
|
||||
PA = PA,
|
||||
backlash = backlash,
|
||||
clearance = clearance,
|
||||
interior = interior,
|
||||
valleys = valleys
|
||||
)
|
||||
);
|
||||
r = root_radius(pitch, teeth, clearance, interior);
|
||||
translate([0,-r,0])
|
||||
polygon(
|
||||
points=gear_tooth_profile(
|
||||
pitch = pitch,
|
||||
teeth = teeth,
|
||||
PA = PA,
|
||||
backlash = backlash,
|
||||
clearance = clearance,
|
||||
interior = interior,
|
||||
valleys = valleys
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -250,62 +250,62 @@ module gear_tooth_profile(
|
||||
// Example(2D): Partial Gear
|
||||
// gear2d(pitch=5, teeth=20, hide=15, PA=20);
|
||||
function gear2d(
|
||||
pitch = 3,
|
||||
teeth = 11,
|
||||
hide = 0,
|
||||
PA = 28,
|
||||
clearance = undef,
|
||||
backlash = 0.0,
|
||||
interior = false,
|
||||
anchor = CENTER,
|
||||
spin = 0
|
||||
pitch = 3,
|
||||
teeth = 11,
|
||||
hide = 0,
|
||||
PA = 28,
|
||||
clearance = undef,
|
||||
backlash = 0.0,
|
||||
interior = false,
|
||||
anchor = CENTER,
|
||||
spin = 0
|
||||
) = let(
|
||||
pr = pitch_radius(pitch=pitch, teeth=teeth),
|
||||
pts = concat(
|
||||
[for (tooth = [0:1:teeth-hide-1])
|
||||
each rot(tooth*360/teeth,
|
||||
planar=true,
|
||||
p=gear_tooth_profile(
|
||||
pitch = pitch,
|
||||
teeth = teeth,
|
||||
PA = PA,
|
||||
clearance = clearance,
|
||||
backlash = backlash,
|
||||
interior = interior,
|
||||
valleys = false
|
||||
)
|
||||
)
|
||||
],
|
||||
hide>0? [[0,0]] : []
|
||||
)
|
||||
pr = pitch_radius(pitch=pitch, teeth=teeth),
|
||||
pts = concat(
|
||||
[for (tooth = [0:1:teeth-hide-1])
|
||||
each rot(tooth*360/teeth,
|
||||
planar=true,
|
||||
p=gear_tooth_profile(
|
||||
pitch = pitch,
|
||||
teeth = teeth,
|
||||
PA = PA,
|
||||
clearance = clearance,
|
||||
backlash = backlash,
|
||||
interior = interior,
|
||||
valleys = false
|
||||
)
|
||||
)
|
||||
],
|
||||
hide>0? [[0,0]] : []
|
||||
)
|
||||
) reorient(anchor,spin, two_d=true, r=pr, p=pts);
|
||||
|
||||
|
||||
module gear2d(
|
||||
pitch = 3,
|
||||
teeth = 11,
|
||||
hide = 0,
|
||||
PA = 28,
|
||||
clearance = undef,
|
||||
backlash = 0.0,
|
||||
interior = false,
|
||||
anchor = CENTER,
|
||||
spin = 0
|
||||
pitch = 3,
|
||||
teeth = 11,
|
||||
hide = 0,
|
||||
PA = 28,
|
||||
clearance = undef,
|
||||
backlash = 0.0,
|
||||
interior = false,
|
||||
anchor = CENTER,
|
||||
spin = 0
|
||||
) {
|
||||
path = gear2d(
|
||||
pitch = pitch,
|
||||
teeth = teeth,
|
||||
hide = hide,
|
||||
PA = PA,
|
||||
clearance = clearance,
|
||||
backlash = backlash,
|
||||
interior = interior
|
||||
);
|
||||
pr = pitch_radius(pitch=pitch, teeth=teeth);
|
||||
attachable(anchor,spin, two_d=true, r=pr) {
|
||||
polygon(path);
|
||||
children();
|
||||
}
|
||||
path = gear2d(
|
||||
pitch = pitch,
|
||||
teeth = teeth,
|
||||
hide = hide,
|
||||
PA = PA,
|
||||
clearance = clearance,
|
||||
backlash = backlash,
|
||||
interior = interior
|
||||
);
|
||||
pr = pitch_radius(pitch=pitch, teeth=teeth);
|
||||
attachable(anchor,spin, two_d=true, r=pr) {
|
||||
polygon(path);
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -362,44 +362,44 @@ module gear2d(
|
||||
// Example: Beveled Gear
|
||||
// gear(pitch=5, teeth=20, thickness=10, shaft_diam=5, helical=-30, slices=12, $fa=1, $fs=1);
|
||||
module gear(
|
||||
pitch = 3,
|
||||
teeth = 11,
|
||||
PA = 28,
|
||||
thickness = 6,
|
||||
hide = 0,
|
||||
shaft_diam = 3,
|
||||
clearance = undef,
|
||||
backlash = 0.0,
|
||||
helical = 0,
|
||||
slices = 2,
|
||||
interior = false,
|
||||
anchor = CENTER,
|
||||
spin = 0,
|
||||
orient = UP
|
||||
pitch = 3,
|
||||
teeth = 11,
|
||||
PA = 28,
|
||||
thickness = 6,
|
||||
hide = 0,
|
||||
shaft_diam = 3,
|
||||
clearance = undef,
|
||||
backlash = 0.0,
|
||||
helical = 0,
|
||||
slices = 2,
|
||||
interior = false,
|
||||
anchor = CENTER,
|
||||
spin = 0,
|
||||
orient = UP
|
||||
) {
|
||||
p = pitch_radius(pitch, teeth);
|
||||
c = outer_radius(pitch, teeth, clearance, interior);
|
||||
r = root_radius(pitch, teeth, clearance, interior);
|
||||
twist = atan2(thickness*tan(helical),p);
|
||||
attachable(anchor,spin,orient, r=p, l=thickness) {
|
||||
difference() {
|
||||
linear_extrude(height=thickness, center=true, convexity=10, twist=twist) {
|
||||
gear2d(
|
||||
pitch = pitch,
|
||||
teeth = teeth,
|
||||
PA = PA,
|
||||
hide = hide,
|
||||
clearance = clearance,
|
||||
backlash = backlash,
|
||||
interior = interior
|
||||
);
|
||||
}
|
||||
if (shaft_diam > 0) {
|
||||
cylinder(h=2*thickness+1, r=shaft_diam/2, center=true, $fn=max(12,segs(shaft_diam/2)));
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
p = pitch_radius(pitch, teeth);
|
||||
c = outer_radius(pitch, teeth, clearance, interior);
|
||||
r = root_radius(pitch, teeth, clearance, interior);
|
||||
twist = atan2(thickness*tan(helical),p);
|
||||
attachable(anchor,spin,orient, r=p, l=thickness) {
|
||||
difference() {
|
||||
linear_extrude(height=thickness, center=true, convexity=10, twist=twist) {
|
||||
gear2d(
|
||||
pitch = pitch,
|
||||
teeth = teeth,
|
||||
PA = PA,
|
||||
hide = hide,
|
||||
clearance = clearance,
|
||||
backlash = backlash,
|
||||
interior = interior
|
||||
);
|
||||
}
|
||||
if (shaft_diam > 0) {
|
||||
cylinder(h=2*thickness+1, r=shaft_diam/2, center=true, $fn=max(12,segs(shaft_diam/2)));
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -457,131 +457,131 @@ module gear(
|
||||
// Example: Beveled Gear
|
||||
// bevel_gear(pitch=5, teeth=36, face_width=10, shaft_diam=5, spiral_rad=-20, spiral_ang=35, bevelang=45, slices=12, $fa=1, $fs=1);
|
||||
module bevel_gear(
|
||||
pitch = 3,
|
||||
teeth = 11,
|
||||
PA = 20,
|
||||
face_width = 6,
|
||||
bevelang = 45,
|
||||
hide = 0,
|
||||
shaft_diam = 3,
|
||||
clearance = undef,
|
||||
backlash = 0.0,
|
||||
spiral_rad = 0,
|
||||
spiral_ang = 0,
|
||||
slices = 2,
|
||||
interior = false,
|
||||
anchor = CENTER,
|
||||
spin = 0,
|
||||
orient = UP
|
||||
pitch = 3,
|
||||
teeth = 11,
|
||||
PA = 20,
|
||||
face_width = 6,
|
||||
bevelang = 45,
|
||||
hide = 0,
|
||||
shaft_diam = 3,
|
||||
clearance = undef,
|
||||
backlash = 0.0,
|
||||
spiral_rad = 0,
|
||||
spiral_ang = 0,
|
||||
slices = 2,
|
||||
interior = false,
|
||||
anchor = CENTER,
|
||||
spin = 0,
|
||||
orient = UP
|
||||
) {
|
||||
thickness = face_width * cos(bevelang);
|
||||
slices = spiral_rad==0? 1 : slices;
|
||||
spiral_rad = spiral_rad==0? 10000 : spiral_rad;
|
||||
p1 = pitch_radius(pitch, teeth);
|
||||
r1 = root_radius(pitch, teeth, clearance, interior);
|
||||
c1 = outer_radius(pitch, teeth, clearance, interior);
|
||||
dx = thickness * tan(bevelang);
|
||||
dy = (p1-r1) * sin(bevelang);
|
||||
scl = (p1-dx)/p1;
|
||||
p2 = pitch_radius(pitch*scl, teeth);
|
||||
r2 = root_radius(pitch*scl, teeth, clearance, interior);
|
||||
c2 = outer_radius(pitch*scl, teeth, clearance, interior);
|
||||
slice_u = 1/slices;
|
||||
Rm = (p1+p2)/2;
|
||||
H = spiral_rad * cos(spiral_ang);
|
||||
V = Rm - abs(spiral_rad) * sin(spiral_ang);
|
||||
spiral_cp = [H,V,0];
|
||||
S = norm(spiral_cp);
|
||||
theta_r = acos((S*S+spiral_rad*spiral_rad-p1*p1)/(2*S*spiral_rad)) - acos((S*S+spiral_rad*spiral_rad-p2*p2)/(2*S*spiral_rad));
|
||||
theta_ro = acos((S*S+spiral_rad*spiral_rad-p1*p1)/(2*S*spiral_rad)) - acos((S*S+spiral_rad*spiral_rad-Rm*Rm)/(2*S*spiral_rad));
|
||||
theta_ri = theta_r - theta_ro;
|
||||
extent_u = 2*(p2-r2)*tan(bevelang) / thickness;
|
||||
slice_us = concat(
|
||||
[for (u = [0:slice_u:1+extent_u]) u]
|
||||
);
|
||||
lsus = len(slice_us);
|
||||
vertices = concat(
|
||||
[
|
||||
for (u=slice_us, tooth=[0:1:teeth-1]) let(
|
||||
p = lerp(p1,p2,u),
|
||||
r = lerp(r1,r2,u),
|
||||
theta = lerp(-theta_ro, theta_ri, u),
|
||||
profile = gear_tooth_profile(
|
||||
pitch = pitch*(p/p1),
|
||||
teeth = teeth,
|
||||
PA = PA,
|
||||
clearance = clearance,
|
||||
backlash = backlash,
|
||||
interior = interior,
|
||||
valleys = false
|
||||
),
|
||||
pp = rot(theta, cp=spiral_cp, p=[0,Rm,0]),
|
||||
ang = atan2(pp.y,pp.x)-90,
|
||||
pts = apply_list(
|
||||
path3d(profile), [
|
||||
move([0,-p,0]),
|
||||
rot([0,ang,0]),
|
||||
rot([bevelang,0,0]),
|
||||
move(pp),
|
||||
rot(tooth*360/teeth),
|
||||
move([0,0,thickness*u])
|
||||
]
|
||||
)
|
||||
) each pts
|
||||
], [
|
||||
[0,0,-dy], [0,0,thickness]
|
||||
]
|
||||
);
|
||||
lcnt = (len(vertices)-2)/lsus/teeth;
|
||||
function _gv(layer,tooth,i) = ((layer*teeth)+(tooth%teeth))*lcnt+(i%lcnt);
|
||||
function _lv(layer,i) = layer*teeth*lcnt+(i%(teeth*lcnt));
|
||||
faces = concat(
|
||||
[
|
||||
for (sl=[0:1:lsus-2], i=[0:1:lcnt*teeth-1]) each [
|
||||
[_lv(sl,i), _lv(sl+1,i), _lv(sl,i+1)],
|
||||
[_lv(sl+1,i), _lv(sl+1,i+1), _lv(sl,i+1)]
|
||||
]
|
||||
], [
|
||||
for (tooth=[0:1:teeth-1], i=[0:1:lcnt/2-1]) each [
|
||||
[_gv(0,tooth,i), _gv(0,tooth,i+1), _gv(0,tooth,lcnt-1-(i+1))],
|
||||
[_gv(0,tooth,i), _gv(0,tooth,lcnt-1-(i+1)), _gv(0,tooth,lcnt-1-i)],
|
||||
[_gv(lsus-1,tooth,i), _gv(lsus-1,tooth,lcnt-1-(i+1)), _gv(lsus-1,tooth,i+1)],
|
||||
[_gv(lsus-1,tooth,i), _gv(lsus-1,tooth,lcnt-1-i), _gv(lsus-1,tooth,lcnt-1-(i+1))],
|
||||
]
|
||||
], [
|
||||
for (tooth=[0:1:teeth-1]) each [
|
||||
[len(vertices)-2, _gv(0,tooth,0), _gv(0,tooth,lcnt-1)],
|
||||
[len(vertices)-2, _gv(0,tooth,lcnt-1), _gv(0,tooth+1,0)],
|
||||
[len(vertices)-1, _gv(lsus-1,tooth,lcnt-1), _gv(lsus-1,tooth,0)],
|
||||
[len(vertices)-1, _gv(lsus-1,tooth+1,0), _gv(lsus-1,tooth,lcnt-1)],
|
||||
]
|
||||
]
|
||||
);
|
||||
attachable(anchor,spin,orient, r1=p1, r2=p2, l=thickness) {
|
||||
union() {
|
||||
difference() {
|
||||
down(thickness/2) {
|
||||
polyhedron(points=vertices, faces=faces, convexity=floor(teeth/2));
|
||||
}
|
||||
if (shaft_diam > 0) {
|
||||
cylinder(h=2*thickness+1, r=shaft_diam/2, center=true, $fn=max(12,segs(shaft_diam/2)));
|
||||
}
|
||||
if (bevelang != 0) {
|
||||
h = (c1-r1)/tan(45);
|
||||
down(thickness/2+dy) {
|
||||
difference() {
|
||||
cube([2*c1/cos(45),2*c1/cos(45),2*h], center=true);
|
||||
cylinder(h=h, r1=r1-0.5, r2=c1-0.5, center=false, $fn=teeth*4);
|
||||
}
|
||||
}
|
||||
up(thickness/2-0.01) {
|
||||
cylinder(h=(c2-r2)/tan(45)*5, r1=r2-0.5, r2=lerp(r2-0.5,c2-0.5,5), center=false, $fn=teeth*4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
thickness = face_width * cos(bevelang);
|
||||
slices = spiral_rad==0? 1 : slices;
|
||||
spiral_rad = spiral_rad==0? 10000 : spiral_rad;
|
||||
p1 = pitch_radius(pitch, teeth);
|
||||
r1 = root_radius(pitch, teeth, clearance, interior);
|
||||
c1 = outer_radius(pitch, teeth, clearance, interior);
|
||||
dx = thickness * tan(bevelang);
|
||||
dy = (p1-r1) * sin(bevelang);
|
||||
scl = (p1-dx)/p1;
|
||||
p2 = pitch_radius(pitch*scl, teeth);
|
||||
r2 = root_radius(pitch*scl, teeth, clearance, interior);
|
||||
c2 = outer_radius(pitch*scl, teeth, clearance, interior);
|
||||
slice_u = 1/slices;
|
||||
Rm = (p1+p2)/2;
|
||||
H = spiral_rad * cos(spiral_ang);
|
||||
V = Rm - abs(spiral_rad) * sin(spiral_ang);
|
||||
spiral_cp = [H,V,0];
|
||||
S = norm(spiral_cp);
|
||||
theta_r = acos((S*S+spiral_rad*spiral_rad-p1*p1)/(2*S*spiral_rad)) - acos((S*S+spiral_rad*spiral_rad-p2*p2)/(2*S*spiral_rad));
|
||||
theta_ro = acos((S*S+spiral_rad*spiral_rad-p1*p1)/(2*S*spiral_rad)) - acos((S*S+spiral_rad*spiral_rad-Rm*Rm)/(2*S*spiral_rad));
|
||||
theta_ri = theta_r - theta_ro;
|
||||
extent_u = 2*(p2-r2)*tan(bevelang) / thickness;
|
||||
slice_us = concat(
|
||||
[for (u = [0:slice_u:1+extent_u]) u]
|
||||
);
|
||||
lsus = len(slice_us);
|
||||
vertices = concat(
|
||||
[
|
||||
for (u=slice_us, tooth=[0:1:teeth-1]) let(
|
||||
p = lerp(p1,p2,u),
|
||||
r = lerp(r1,r2,u),
|
||||
theta = lerp(-theta_ro, theta_ri, u),
|
||||
profile = gear_tooth_profile(
|
||||
pitch = pitch*(p/p1),
|
||||
teeth = teeth,
|
||||
PA = PA,
|
||||
clearance = clearance,
|
||||
backlash = backlash,
|
||||
interior = interior,
|
||||
valleys = false
|
||||
),
|
||||
pp = rot(theta, cp=spiral_cp, p=[0,Rm,0]),
|
||||
ang = atan2(pp.y,pp.x)-90,
|
||||
pts = apply_list(
|
||||
path3d(profile), [
|
||||
move([0,-p,0]),
|
||||
rot([0,ang,0]),
|
||||
rot([bevelang,0,0]),
|
||||
move(pp),
|
||||
rot(tooth*360/teeth),
|
||||
move([0,0,thickness*u])
|
||||
]
|
||||
)
|
||||
) each pts
|
||||
], [
|
||||
[0,0,-dy], [0,0,thickness]
|
||||
]
|
||||
);
|
||||
lcnt = (len(vertices)-2)/lsus/teeth;
|
||||
function _gv(layer,tooth,i) = ((layer*teeth)+(tooth%teeth))*lcnt+(i%lcnt);
|
||||
function _lv(layer,i) = layer*teeth*lcnt+(i%(teeth*lcnt));
|
||||
faces = concat(
|
||||
[
|
||||
for (sl=[0:1:lsus-2], i=[0:1:lcnt*teeth-1]) each [
|
||||
[_lv(sl,i), _lv(sl+1,i), _lv(sl,i+1)],
|
||||
[_lv(sl+1,i), _lv(sl+1,i+1), _lv(sl,i+1)]
|
||||
]
|
||||
], [
|
||||
for (tooth=[0:1:teeth-1], i=[0:1:lcnt/2-1]) each [
|
||||
[_gv(0,tooth,i), _gv(0,tooth,i+1), _gv(0,tooth,lcnt-1-(i+1))],
|
||||
[_gv(0,tooth,i), _gv(0,tooth,lcnt-1-(i+1)), _gv(0,tooth,lcnt-1-i)],
|
||||
[_gv(lsus-1,tooth,i), _gv(lsus-1,tooth,lcnt-1-(i+1)), _gv(lsus-1,tooth,i+1)],
|
||||
[_gv(lsus-1,tooth,i), _gv(lsus-1,tooth,lcnt-1-i), _gv(lsus-1,tooth,lcnt-1-(i+1))],
|
||||
]
|
||||
], [
|
||||
for (tooth=[0:1:teeth-1]) each [
|
||||
[len(vertices)-2, _gv(0,tooth,0), _gv(0,tooth,lcnt-1)],
|
||||
[len(vertices)-2, _gv(0,tooth,lcnt-1), _gv(0,tooth+1,0)],
|
||||
[len(vertices)-1, _gv(lsus-1,tooth,lcnt-1), _gv(lsus-1,tooth,0)],
|
||||
[len(vertices)-1, _gv(lsus-1,tooth+1,0), _gv(lsus-1,tooth,lcnt-1)],
|
||||
]
|
||||
]
|
||||
);
|
||||
attachable(anchor,spin,orient, r1=p1, r2=p2, l=thickness) {
|
||||
union() {
|
||||
difference() {
|
||||
down(thickness/2) {
|
||||
polyhedron(points=vertices, faces=faces, convexity=floor(teeth/2));
|
||||
}
|
||||
if (shaft_diam > 0) {
|
||||
cylinder(h=2*thickness+1, r=shaft_diam/2, center=true, $fn=max(12,segs(shaft_diam/2)));
|
||||
}
|
||||
if (bevelang != 0) {
|
||||
h = (c1-r1)/tan(45);
|
||||
down(thickness/2+dy) {
|
||||
difference() {
|
||||
cube([2*c1/cos(45),2*c1/cos(45),2*h], center=true);
|
||||
cylinder(h=h, r1=r1-0.5, r2=c1-0.5, center=false, $fn=teeth*4);
|
||||
}
|
||||
}
|
||||
up(thickness/2-0.01) {
|
||||
cylinder(h=(c2-r2)/tan(45)*5, r1=r2-0.5, r2=lerp(r2-0.5,c2-0.5,5), center=false, $fn=teeth*4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -614,57 +614,57 @@ module bevel_gear(
|
||||
// Example:
|
||||
// rack(pitch=5, teeth=10, thickness=5, height=5, PA=20);
|
||||
module rack(
|
||||
pitch = 5,
|
||||
teeth = 20,
|
||||
thickness = 5,
|
||||
height = 10,
|
||||
PA = 28,
|
||||
backlash = 0.0,
|
||||
clearance = undef,
|
||||
anchor = CENTER,
|
||||
spin = 0,
|
||||
orient = UP
|
||||
pitch = 5,
|
||||
teeth = 20,
|
||||
thickness = 5,
|
||||
height = 10,
|
||||
PA = 28,
|
||||
backlash = 0.0,
|
||||
clearance = undef,
|
||||
anchor = CENTER,
|
||||
spin = 0,
|
||||
orient = UP
|
||||
) {
|
||||
a = adendum(pitch);
|
||||
d = dedendum(pitch, clearance);
|
||||
xa = a * sin(PA);
|
||||
xd = d * sin(PA);
|
||||
l = teeth * pitch;
|
||||
anchors = [
|
||||
anchorpt("adendum", [0,a,0], BACK),
|
||||
anchorpt("adendum-left", [-l/2,a,0], LEFT),
|
||||
anchorpt("adendum-right", [l/2,a,0], RIGHT),
|
||||
anchorpt("adendum-top", [0,a,thickness/2], UP),
|
||||
anchorpt("adendum-bottom", [0,a,-thickness/2], DOWN),
|
||||
anchorpt("dedendum", [0,-d,0], BACK),
|
||||
anchorpt("dedendum-left", [-l/2,-d,0], LEFT),
|
||||
anchorpt("dedendum-right", [l/2,-d,0], RIGHT),
|
||||
anchorpt("dedendum-top", [0,-d,thickness/2], UP),
|
||||
anchorpt("dedendum-bottom", [0,-d,-thickness/2], DOWN),
|
||||
];
|
||||
attachable(anchor,spin,orient, size=[l, 2*abs(a-height), thickness], anchors=anchors) {
|
||||
left((teeth-1)*pitch/2) {
|
||||
linear_extrude(height = thickness, center = true, convexity = 10) {
|
||||
for (i = [0:1:teeth-1] ) {
|
||||
translate([i*pitch,0,0]) {
|
||||
polygon(
|
||||
points=[
|
||||
[-1/2 * pitch - 0.01, a-height],
|
||||
[-1/2 * pitch, -d],
|
||||
[-1/4 * pitch + backlash - xd, -d],
|
||||
[-1/4 * pitch + backlash + xa, a],
|
||||
[ 1/4 * pitch - backlash - xa, a],
|
||||
[ 1/4 * pitch - backlash + xd, -d],
|
||||
[ 1/2 * pitch, -d],
|
||||
[ 1/2 * pitch + 0.01, a-height],
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
a = adendum(pitch);
|
||||
d = dedendum(pitch, clearance);
|
||||
xa = a * sin(PA);
|
||||
xd = d * sin(PA);
|
||||
l = teeth * pitch;
|
||||
anchors = [
|
||||
anchorpt("adendum", [0,a,0], BACK),
|
||||
anchorpt("adendum-left", [-l/2,a,0], LEFT),
|
||||
anchorpt("adendum-right", [l/2,a,0], RIGHT),
|
||||
anchorpt("adendum-top", [0,a,thickness/2], UP),
|
||||
anchorpt("adendum-bottom", [0,a,-thickness/2], DOWN),
|
||||
anchorpt("dedendum", [0,-d,0], BACK),
|
||||
anchorpt("dedendum-left", [-l/2,-d,0], LEFT),
|
||||
anchorpt("dedendum-right", [l/2,-d,0], RIGHT),
|
||||
anchorpt("dedendum-top", [0,-d,thickness/2], UP),
|
||||
anchorpt("dedendum-bottom", [0,-d,-thickness/2], DOWN),
|
||||
];
|
||||
attachable(anchor,spin,orient, size=[l, 2*abs(a-height), thickness], anchors=anchors) {
|
||||
left((teeth-1)*pitch/2) {
|
||||
linear_extrude(height = thickness, center = true, convexity = 10) {
|
||||
for (i = [0:1:teeth-1] ) {
|
||||
translate([i*pitch,0,0]) {
|
||||
polygon(
|
||||
points=[
|
||||
[-1/2 * pitch - 0.01, a-height],
|
||||
[-1/2 * pitch, -d],
|
||||
[-1/4 * pitch + backlash - xd, -d],
|
||||
[-1/4 * pitch + backlash + xa, a],
|
||||
[ 1/4 * pitch - backlash - xa, a],
|
||||
[ 1/4 * pitch - backlash + xd, -d],
|
||||
[ 1/2 * pitch, -d],
|
||||
[ 1/2 * pitch + 0.01, a-height],
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -698,5 +698,5 @@ translate([(-floor(n5/2)-floor(n1/2)+$t+n1/2-1/2)*9, -d1+0.0, 0]) rotate([0,0,0]
|
||||
*/
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
||||
|
414
joiners.scad
414
joiners.scad
@ -34,29 +34,29 @@ include <skin.scad>
|
||||
// half_joiner_clear(spin=-90);
|
||||
module half_joiner_clear(h=20, w=10, a=30, clearance=0, overlap=0.01, anchor=CENTER, spin=0, orient=UP)
|
||||
{
|
||||
dmnd_height = h*1.0;
|
||||
dmnd_width = dmnd_height*tan(a);
|
||||
guide_size = w/3;
|
||||
guide_width = 2*(dmnd_height/2-guide_size)*tan(a);
|
||||
dmnd_height = h*1.0;
|
||||
dmnd_width = dmnd_height*tan(a);
|
||||
guide_size = w/3;
|
||||
guide_width = 2*(dmnd_height/2-guide_size)*tan(a);
|
||||
|
||||
attachable(anchor,spin,orient, size=[w, guide_width, h]) {
|
||||
union() {
|
||||
ycopies(overlap, n=overlap>0? 2 : 1) {
|
||||
difference() {
|
||||
// Diamonds.
|
||||
scale([w+clearance, dmnd_width/2, dmnd_height/2]) {
|
||||
xrot(45) cube(size=[1,sqrt(2),sqrt(2)], center=true);
|
||||
}
|
||||
// Blunt point of tab.
|
||||
ycopies(guide_width+4) {
|
||||
cube(size=[(w+clearance)*1.05, 4, h*0.99], center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (overlap>0) cube([w+clearance, overlap+0.001, h], center=true);
|
||||
}
|
||||
children();
|
||||
}
|
||||
attachable(anchor,spin,orient, size=[w, guide_width, h]) {
|
||||
union() {
|
||||
ycopies(overlap, n=overlap>0? 2 : 1) {
|
||||
difference() {
|
||||
// Diamonds.
|
||||
scale([w+clearance, dmnd_width/2, dmnd_height/2]) {
|
||||
xrot(45) cube(size=[1,sqrt(2),sqrt(2)], center=true);
|
||||
}
|
||||
// Blunt point of tab.
|
||||
ycopies(guide_width+4) {
|
||||
cube(size=[(w+clearance)*1.05, 4, h*0.99], center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (overlap>0) cube([w+clearance, overlap+0.001, h], center=true);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -81,60 +81,60 @@ module half_joiner_clear(h=20, w=10, a=30, clearance=0, overlap=0.01, anchor=CEN
|
||||
// half_joiner(screwsize=3, spin=-90);
|
||||
module half_joiner(h=20, w=10, l=10, a=30, screwsize=undef, guides=true, anchor=CENTER, spin=0, orient=UP)
|
||||
{
|
||||
dmnd_height = h*1.0;
|
||||
dmnd_width = dmnd_height*tan(a);
|
||||
guide_size = w/3;
|
||||
guide_width = 2*(dmnd_height/2-guide_size)*tan(a);
|
||||
dmnd_height = h*1.0;
|
||||
dmnd_width = dmnd_height*tan(a);
|
||||
guide_size = w/3;
|
||||
guide_width = 2*(dmnd_height/2-guide_size)*tan(a);
|
||||
|
||||
render(convexity=12)
|
||||
attachable(anchor,spin,orient, size=[w, 2*l, h]) {
|
||||
difference() {
|
||||
union() {
|
||||
// Make base.
|
||||
difference() {
|
||||
// Solid backing base.
|
||||
fwd(l/2) cube(size=[w, l, h], center=true);
|
||||
render(convexity=12)
|
||||
attachable(anchor,spin,orient, size=[w, 2*l, h]) {
|
||||
difference() {
|
||||
union() {
|
||||
// Make base.
|
||||
difference() {
|
||||
// Solid backing base.
|
||||
fwd(l/2) cube(size=[w, l, h], center=true);
|
||||
|
||||
// Clear diamond for tab
|
||||
xcopies(2*w*2/3) {
|
||||
half_joiner_clear(h=h+0.01, w=w, clearance=$slop*2, a=a);
|
||||
}
|
||||
}
|
||||
// Clear diamond for tab
|
||||
xcopies(2*w*2/3) {
|
||||
half_joiner_clear(h=h+0.01, w=w, clearance=$slop*2, a=a);
|
||||
}
|
||||
}
|
||||
|
||||
difference() {
|
||||
// Make tab
|
||||
scale([w/3-$slop*2, dmnd_width/2, dmnd_height/2]) xrot(45)
|
||||
cube(size=[1,sqrt(2),sqrt(2)], center=true);
|
||||
difference() {
|
||||
// Make tab
|
||||
scale([w/3-$slop*2, dmnd_width/2, dmnd_height/2]) xrot(45)
|
||||
cube(size=[1,sqrt(2),sqrt(2)], center=true);
|
||||
|
||||
// Blunt point of tab.
|
||||
back(guide_width/2+2)
|
||||
cube(size=[w*0.99,4,guide_size*2], center=true);
|
||||
}
|
||||
// Blunt point of tab.
|
||||
back(guide_width/2+2)
|
||||
cube(size=[w*0.99,4,guide_size*2], center=true);
|
||||
}
|
||||
|
||||
|
||||
// Guide ridges.
|
||||
if (guides == true) {
|
||||
xcopies(w/3-$slop*2) {
|
||||
// Guide ridge.
|
||||
fwd(0.05/2) {
|
||||
scale([0.75, 1, 2]) yrot(45)
|
||||
cube(size=[guide_size/sqrt(2), guide_width+0.05, guide_size/sqrt(2)], center=true);
|
||||
}
|
||||
// Guide ridges.
|
||||
if (guides == true) {
|
||||
xcopies(w/3-$slop*2) {
|
||||
// Guide ridge.
|
||||
fwd(0.05/2) {
|
||||
scale([0.75, 1, 2]) yrot(45)
|
||||
cube(size=[guide_size/sqrt(2), guide_width+0.05, guide_size/sqrt(2)], center=true);
|
||||
}
|
||||
|
||||
// Snap ridge.
|
||||
scale([0.25, 0.5, 1]) zrot(45)
|
||||
cube(size=[guide_size/sqrt(2), guide_size/sqrt(2), dmnd_width], center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Snap ridge.
|
||||
scale([0.25, 0.5, 1]) zrot(45)
|
||||
cube(size=[guide_size/sqrt(2), guide_size/sqrt(2), dmnd_width], center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make screwholes, if needed.
|
||||
if (screwsize != undef) {
|
||||
yrot(90) cylinder(r=screwsize*1.1/2, h=w+1, center=true, $fn=12);
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
// Make screwholes, if needed.
|
||||
if (screwsize != undef) {
|
||||
yrot(90) cylinder(r=screwsize*1.1/2, h=w+1, center=true, $fn=12);
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
//half_joiner(screwsize=3);
|
||||
|
||||
@ -159,29 +159,29 @@ module half_joiner(h=20, w=10, l=10, a=30, screwsize=undef, guides=true, anchor=
|
||||
// half_joiner2(screwsize=3, spin=-90);
|
||||
module half_joiner2(h=20, w=10, l=10, a=30, screwsize=undef, guides=true, anchor=CENTER, spin=0, orient=UP)
|
||||
{
|
||||
dmnd_height = h*1.0;
|
||||
dmnd_width = dmnd_height*tan(a);
|
||||
guide_size = w/3;
|
||||
guide_width = 2*(dmnd_height/2-guide_size)*tan(a);
|
||||
dmnd_height = h*1.0;
|
||||
dmnd_width = dmnd_height*tan(a);
|
||||
guide_size = w/3;
|
||||
guide_width = 2*(dmnd_height/2-guide_size)*tan(a);
|
||||
|
||||
render(convexity=12)
|
||||
attachable(anchor,spin,orient, size=[w, 2*l, h]) {
|
||||
difference() {
|
||||
union () {
|
||||
fwd(l/2) cube(size=[w, l, h], center=true);
|
||||
cube([w, guide_width, h], center=true);
|
||||
}
|
||||
render(convexity=12)
|
||||
attachable(anchor,spin,orient, size=[w, 2*l, h]) {
|
||||
difference() {
|
||||
union () {
|
||||
fwd(l/2) cube(size=[w, l, h], center=true);
|
||||
cube([w, guide_width, h], center=true);
|
||||
}
|
||||
|
||||
// Subtract mated half_joiner.
|
||||
zrot(180) half_joiner(h=h+0.01, w=w+0.01, l=guide_width+0.01, a=a, screwsize=undef, guides=guides, $slop=0.0);
|
||||
// Subtract mated half_joiner.
|
||||
zrot(180) half_joiner(h=h+0.01, w=w+0.01, l=guide_width+0.01, a=a, screwsize=undef, guides=guides, $slop=0.0);
|
||||
|
||||
// Make screwholes, if needed.
|
||||
if (screwsize != undef) {
|
||||
xcyl(r=screwsize*1.1/2, l=w+1, $fn=12);
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
// Make screwholes, if needed.
|
||||
if (screwsize != undef) {
|
||||
xcyl(r=screwsize*1.1/2, l=w+1, $fn=12);
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -207,18 +207,18 @@ module half_joiner2(h=20, w=10, l=10, a=30, screwsize=undef, guides=true, anchor
|
||||
// joiner_clear(spin=-90);
|
||||
module joiner_clear(h=40, w=10, a=30, clearance=0, overlap=0.01, anchor=CENTER, spin=0, orient=UP)
|
||||
{
|
||||
dmnd_height = h*0.5;
|
||||
dmnd_width = dmnd_height*tan(a);
|
||||
guide_size = w/3;
|
||||
guide_width = 2*(dmnd_height/2-guide_size)*tan(a);
|
||||
dmnd_height = h*0.5;
|
||||
dmnd_width = dmnd_height*tan(a);
|
||||
guide_size = w/3;
|
||||
guide_width = 2*(dmnd_height/2-guide_size)*tan(a);
|
||||
|
||||
attachable(anchor,spin,orient, size=[w, guide_width, h]) {
|
||||
union() {
|
||||
up(h/4) half_joiner_clear(h=h/2.0-0.01, w=w, a=a, overlap=overlap, clearance=clearance);
|
||||
down(h/4) half_joiner_clear(h=h/2.0-0.01, w=w, a=a, overlap=overlap, clearance=-0.01);
|
||||
}
|
||||
children();
|
||||
}
|
||||
attachable(anchor,spin,orient, size=[w, guide_width, h]) {
|
||||
union() {
|
||||
up(h/4) half_joiner_clear(h=h/2.0-0.01, w=w, a=a, overlap=overlap, clearance=clearance);
|
||||
down(h/4) half_joiner_clear(h=h/2.0-0.01, w=w, a=a, overlap=overlap, clearance=-0.01);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -244,13 +244,13 @@ module joiner_clear(h=40, w=10, a=30, clearance=0, overlap=0.01, anchor=CENTER,
|
||||
// joiner(w=10, l=10, h=40, spin=-90) cuboid([10, 10*2, 40], anchor=RIGHT);
|
||||
module joiner(h=40, w=10, l=10, a=30, screwsize=undef, guides=true, anchor=CENTER, spin=0, orient=UP)
|
||||
{
|
||||
attachable(anchor,spin,orient, size=[w, 2*l, h]) {
|
||||
union() {
|
||||
up(h/4) half_joiner(h=h/2, w=w, l=l, a=a, screwsize=screwsize, guides=guides);
|
||||
down(h/4) half_joiner2(h=h/2, w=w, l=l, a=a, screwsize=screwsize, guides=guides);
|
||||
}
|
||||
children();
|
||||
}
|
||||
attachable(anchor,spin,orient, size=[w, 2*l, h]) {
|
||||
union() {
|
||||
up(h/4) half_joiner(h=h/2, w=w, l=l, a=a, screwsize=screwsize, guides=guides);
|
||||
down(h/4) half_joiner2(h=h/2, w=w, l=l, a=a, screwsize=screwsize, guides=guides);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -279,17 +279,17 @@ module joiner(h=40, w=10, l=10, a=30, screwsize=undef, guides=true, anchor=CENTE
|
||||
// joiner_pair_clear(spacing=50, n=3);
|
||||
module joiner_pair_clear(spacing=100, h=40, w=10, a=30, n=2, clearance=0, overlap=0.01, anchor=CENTER, spin=0, orient=UP)
|
||||
{
|
||||
dmnd_height = h*0.5;
|
||||
dmnd_width = dmnd_height*tan(a);
|
||||
guide_size = w/3;
|
||||
guide_width = 2*(dmnd_height/2-guide_size)*tan(a);
|
||||
dmnd_height = h*0.5;
|
||||
dmnd_width = dmnd_height*tan(a);
|
||||
guide_size = w/3;
|
||||
guide_width = 2*(dmnd_height/2-guide_size)*tan(a);
|
||||
|
||||
attachable(anchor,spin,orient, size=[spacing+w, guide_width, h]) {
|
||||
xcopies(spacing, n=n) {
|
||||
joiner_clear(h=h, w=w, a=a, clearance=clearance, overlap=overlap);
|
||||
}
|
||||
children();
|
||||
}
|
||||
attachable(anchor,spin,orient, size=[spacing+w, guide_width, h]) {
|
||||
xcopies(spacing, n=n) {
|
||||
joiner_clear(h=h, w=w, a=a, clearance=clearance, overlap=overlap);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -321,18 +321,18 @@ module joiner_pair_clear(spacing=100, h=40, w=10, a=30, n=2, clearance=0, overla
|
||||
// joiner_pair(spacing=50, l=10, n=3, alternate="alt", spin=-90);
|
||||
module joiner_pair(spacing=100, h=40, w=10, l=10, a=30, n=2, alternate=true, screwsize=undef, guides=true, anchor=CENTER, spin=0, orient=UP)
|
||||
{
|
||||
attachable(anchor,spin,orient, size=[spacing+w, 2*l, h]) {
|
||||
left((n-1)*spacing/2) {
|
||||
for (i=[0:1:n-1]) {
|
||||
right(i*spacing) {
|
||||
yrot(180 + (alternate? (i*180+(alternate=="alt"?180:0))%360 : 0)) {
|
||||
joiner(h=h, w=w, l=l, a=a, screwsize=screwsize, guides=guides);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
attachable(anchor,spin,orient, size=[spacing+w, 2*l, h]) {
|
||||
left((n-1)*spacing/2) {
|
||||
for (i=[0:1:n-1]) {
|
||||
right(i*spacing) {
|
||||
yrot(180 + (alternate? (i*180+(alternate=="alt"?180:0))%360 : 0)) {
|
||||
joiner(h=h, w=w, l=l, a=a, screwsize=screwsize, guides=guides);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -362,16 +362,16 @@ module joiner_pair(spacing=100, h=40, w=10, l=10, a=30, n=2, alternate=true, scr
|
||||
// joiner_quad_clear(spacing1=50, spacing2=50, n=3);
|
||||
module joiner_quad_clear(xspacing=undef, yspacing=undef, spacing1=undef, spacing2=undef, n=2, h=40, w=10, a=30, clearance=0, overlap=0.01, anchor=CENTER, spin=0, orient=UP)
|
||||
{
|
||||
spacing1 = first_defined([spacing1, xspacing, 100]);
|
||||
spacing2 = first_defined([spacing2, yspacing, 50]);
|
||||
attachable(anchor,spin,orient, size=[w+spacing1, spacing2, h]) {
|
||||
zrot_copies(n=2) {
|
||||
back(spacing2/2) {
|
||||
joiner_pair_clear(spacing=spacing1, n=n, h=h, w=w, a=a, clearance=clearance, overlap=overlap);
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
spacing1 = first_defined([spacing1, xspacing, 100]);
|
||||
spacing2 = first_defined([spacing2, yspacing, 50]);
|
||||
attachable(anchor,spin,orient, size=[w+spacing1, spacing2, h]) {
|
||||
zrot_copies(n=2) {
|
||||
back(spacing2/2) {
|
||||
joiner_pair_clear(spacing=spacing1, n=n, h=h, w=w, a=a, clearance=clearance, overlap=overlap);
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -403,16 +403,16 @@ module joiner_quad_clear(xspacing=undef, yspacing=undef, spacing1=undef, spacing
|
||||
// joiner_quad(spacing1=50, spacing2=50, l=10, n=3, alternate="alt", spin=-90);
|
||||
module joiner_quad(spacing1=undef, spacing2=undef, xspacing=undef, yspacing=undef, h=40, w=10, l=10, a=30, n=2, alternate=true, screwsize=undef, guides=true, anchor=CENTER, spin=0, orient=UP)
|
||||
{
|
||||
spacing1 = first_defined([spacing1, xspacing, 100]);
|
||||
spacing2 = first_defined([spacing2, yspacing, 50]);
|
||||
attachable(anchor,spin,orient, size=[w+spacing1, spacing2, h]) {
|
||||
zrot_copies(n=2) {
|
||||
back(spacing2/2) {
|
||||
joiner_pair(spacing=spacing1, n=n, h=h, w=w, l=l, a=a, screwsize=screwsize, guides=guides);
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
spacing1 = first_defined([spacing1, xspacing, 100]);
|
||||
spacing2 = first_defined([spacing2, yspacing, 50]);
|
||||
attachable(anchor,spin,orient, size=[w+spacing1, spacing2, h]) {
|
||||
zrot_copies(n=2) {
|
||||
back(spacing2/2) {
|
||||
joiner_pair(spacing=spacing1, n=n, h=h, w=w, l=l, a=a, screwsize=screwsize, guides=guides);
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -497,70 +497,70 @@ module joiner_quad(spacing1=undef, spacing2=undef, xspacing=undef, yspacing=unde
|
||||
// position(TOP+BACK) xcopies(10,5) dovetail("female", length=10, width=7, taper=4, height=4, $tags="remove",anchor=BOTTOM+FRONT,spin=180);
|
||||
module dovetail(gender, length, l, width, w, height, h, angle, slope, taper, back_width, chamfer, extra=0.01, r, radius, round=false, anchor=BOTTOM, spin=0, orient)
|
||||
{
|
||||
radius = get_radius(r1=radius,r2=r);
|
||||
lcount = num_defined([l,length]);
|
||||
hcount = num_defined([h,height]);
|
||||
wcount = num_defined([w,width]);
|
||||
assert(lcount==1, "Must define exactly one of l and length");
|
||||
assert(wcount==1, "Must define exactly one of w and width");
|
||||
assert(hcount==1, "Must define exactly one of h and height");
|
||||
h = first_defined([h,height]);
|
||||
w = first_defined([w,width]);
|
||||
length = first_defined([l,length]);
|
||||
orient = is_def(orient) ? orient :
|
||||
gender == "female" ? DOWN : UP;
|
||||
count = num_defined([angle,slope]);
|
||||
assert(count<=1, "Do not specify both angle and slope");
|
||||
count2 = num_defined([taper,back_width]);
|
||||
assert(count2<=1, "Do not specify both taper and back_width");
|
||||
count3 = num_defined([chamfer, radius]);
|
||||
assert(count3<=1 || (radius==0 && chamfer==0), "Do not specify both chamfer and radius");
|
||||
slope = is_def(slope) ? slope :
|
||||
is_def(angle) ? 1/tan(angle) : 6;
|
||||
width = gender == "male" ? w : w + 2*$slop;
|
||||
height = h + (gender == "female" ? 2*$slop : 0);
|
||||
radius = get_radius(r1=radius,r2=r);
|
||||
lcount = num_defined([l,length]);
|
||||
hcount = num_defined([h,height]);
|
||||
wcount = num_defined([w,width]);
|
||||
assert(lcount==1, "Must define exactly one of l and length");
|
||||
assert(wcount==1, "Must define exactly one of w and width");
|
||||
assert(hcount==1, "Must define exactly one of h and height");
|
||||
h = first_defined([h,height]);
|
||||
w = first_defined([w,width]);
|
||||
length = first_defined([l,length]);
|
||||
orient = is_def(orient) ? orient :
|
||||
gender == "female" ? DOWN : UP;
|
||||
count = num_defined([angle,slope]);
|
||||
assert(count<=1, "Do not specify both angle and slope");
|
||||
count2 = num_defined([taper,back_width]);
|
||||
assert(count2<=1, "Do not specify both taper and back_width");
|
||||
count3 = num_defined([chamfer, radius]);
|
||||
assert(count3<=1 || (radius==0 && chamfer==0), "Do not specify both chamfer and radius");
|
||||
slope = is_def(slope) ? slope :
|
||||
is_def(angle) ? 1/tan(angle) : 6;
|
||||
width = gender == "male" ? w : w + 2*$slop;
|
||||
height = h + (gender == "female" ? 2*$slop : 0);
|
||||
|
||||
front_offset = is_def(taper) ? -extra * tan(taper) :
|
||||
is_def(back_width) ? extra * (back_width-width)/length/2 : 0;
|
||||
front_offset = is_def(taper) ? -extra * tan(taper) :
|
||||
is_def(back_width) ? extra * (back_width-width)/length/2 : 0;
|
||||
|
||||
size = is_def(chamfer) && chamfer>0 ? chamfer :
|
||||
is_def(radius) && radius>0 ? radius : 0;
|
||||
type = is_def(chamfer) && chamfer>0 ? "chamfer" : "circle";
|
||||
size = is_def(chamfer) && chamfer>0 ? chamfer :
|
||||
is_def(radius) && radius>0 ? radius : 0;
|
||||
type = is_def(chamfer) && chamfer>0 ? "chamfer" : "circle";
|
||||
|
||||
fullsize = round ? [size,size] :
|
||||
gender == "male" ? [size,0] : [0,size];
|
||||
fullsize = round ? [size,size] :
|
||||
gender == "male" ? [size,0] : [0,size];
|
||||
|
||||
smallend_half = round_corners(
|
||||
move(
|
||||
[0,-length/2-extra,0],
|
||||
p=[
|
||||
[0 , 0, height],
|
||||
[width/2-front_offset , 0, height],
|
||||
[width/2 - height/slope - front_offset, 0, 0 ],
|
||||
[width/2 - front_offset + height, 0, 0]
|
||||
]
|
||||
),
|
||||
method=type, cut = fullsize, closed=false
|
||||
);
|
||||
smallend_points = concat(select(smallend_half, 1, -2), [down(extra,p=select(smallend_half, -2))]);
|
||||
offset = is_def(taper) ? -(length+extra) * tan(taper) :
|
||||
is_def(back_width) ? (back_width-width) / 2 : 0;
|
||||
bigend_points = move([offset,length+2*extra,0], p=smallend_points);
|
||||
smallend_half = round_corners(
|
||||
move(
|
||||
[0,-length/2-extra,0],
|
||||
p=[
|
||||
[0 , 0, height],
|
||||
[width/2-front_offset , 0, height],
|
||||
[width/2 - height/slope - front_offset, 0, 0 ],
|
||||
[width/2 - front_offset + height, 0, 0]
|
||||
]
|
||||
),
|
||||
method=type, cut = fullsize, closed=false
|
||||
);
|
||||
smallend_points = concat(select(smallend_half, 1, -2), [down(extra,p=select(smallend_half, -2))]);
|
||||
offset = is_def(taper) ? -(length+extra) * tan(taper) :
|
||||
is_def(back_width) ? (back_width-width) / 2 : 0;
|
||||
bigend_points = move([offset,length+2*extra,0], p=smallend_points);
|
||||
|
||||
adjustment = gender == "male" ? -0.01 : 0.01; // Adjustment for default overlap in attach()
|
||||
adjustment = gender == "male" ? -0.01 : 0.01; // Adjustment for default overlap in attach()
|
||||
|
||||
attachable(anchor,spin,orient, size=[width+2*offset, length, height]) {
|
||||
down(height/2+adjustment) {
|
||||
skin(
|
||||
[
|
||||
reverse(concat(smallend_points, xflip(p=reverse(smallend_points)))),
|
||||
reverse(concat(bigend_points, xflip(p=reverse(bigend_points))))
|
||||
],
|
||||
slices=0, convexity=4
|
||||
);
|
||||
}
|
||||
children();
|
||||
}
|
||||
attachable(anchor,spin,orient, size=[width+2*offset, length, height]) {
|
||||
down(height/2+adjustment) {
|
||||
skin(
|
||||
[
|
||||
reverse(concat(smallend_points, xflip(p=reverse(smallend_points)))),
|
||||
reverse(concat(bigend_points, xflip(p=reverse(bigend_points))))
|
||||
],
|
||||
slices=0, convexity=4
|
||||
);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -781,4 +781,4 @@ module snap_pin_socket(size, r, radius, l,length, d,diameter,nub_depth, snap, fi
|
||||
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
174
knurling.scad
174
knurling.scad
@ -48,79 +48,79 @@
|
||||
// knurled_cylinder(l=30, r=20, count=30, profile=90, helix=30);
|
||||
// knurled_cylinder(l=30, r=20, count=20, profile=120, helix=30);
|
||||
module knurled_cylinder(
|
||||
l=20,
|
||||
r=undef, r1=undef, r2=undef,
|
||||
d=undef, d1=undef, d2=undef,
|
||||
count=30, profile=120, helix=30,
|
||||
chamfer=undef, chamfer1=undef, chamfer2=undef,
|
||||
chamfang=undef, chamfang1=undef, chamfang2=undef,
|
||||
from_end=false,
|
||||
rounding=undef, rounding1=undef, rounding2=undef,
|
||||
anchor=CENTER, spin=0, orient=UP
|
||||
l=20,
|
||||
r=undef, r1=undef, r2=undef,
|
||||
d=undef, d1=undef, d2=undef,
|
||||
count=30, profile=120, helix=30,
|
||||
chamfer=undef, chamfer1=undef, chamfer2=undef,
|
||||
chamfang=undef, chamfang1=undef, chamfang2=undef,
|
||||
from_end=false,
|
||||
rounding=undef, rounding1=undef, rounding2=undef,
|
||||
anchor=CENTER, spin=0, orient=UP
|
||||
) {
|
||||
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);
|
||||
twist = 360*l*tan(helix)/(r1*2*PI);
|
||||
c1 = circle(r=r1,$fn=count);
|
||||
c2 = rot(-180/count,p=circle(r=r1-inset,$fn=count));
|
||||
path = [for (i=idx(c1)) each [c1[i],c2[i]]];
|
||||
knob_w = 2*PI*r1/count;
|
||||
knob_h = knob_w / tan(helix);
|
||||
layers = ceil(l/knob_h);
|
||||
plen = len(path);
|
||||
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])
|
||||
], [
|
||||
[0,0,-layers*knob_h/2],
|
||||
[0,0, layers*knob_h/2]
|
||||
]
|
||||
);
|
||||
faces = concat(
|
||||
[
|
||||
for (layer = [0:1:layers-1], i=idx(path)) let(
|
||||
loff = (layer%2)? 2 : 0,
|
||||
i1 = layer*plen+((i+1)%plen),
|
||||
i2 = layer*plen+((i+2)%plen),
|
||||
i3 = (layer+1)*plen+posmod(i+1+loff,plen),
|
||||
i4 = (layer+1)*plen+posmod(i+2+loff,plen),
|
||||
i5 = (layer+1)*plen+posmod(i-0+loff,plen),
|
||||
i6 = (layer+1)*plen+posmod(i-1+loff,plen)
|
||||
) each [
|
||||
[i1, i2, ((i%2)? i5 : i3)],
|
||||
[i3, i5, ((i%2)? i2 : i1)]
|
||||
]
|
||||
], [
|
||||
for (i=[0:1:count-1]) let(
|
||||
i1 = posmod(i*2+1,plen),
|
||||
i2 = posmod(i*2+2,plen),
|
||||
i3 = posmod(i*2+3,plen),
|
||||
loff = layers*plen
|
||||
) each [
|
||||
[i1,i3,i2],
|
||||
[i1+loff,i2+loff,i3+loff],
|
||||
[i3,i1,len(vertices)-2],
|
||||
[i1+loff,i3+loff,len(vertices)-1]
|
||||
]
|
||||
]
|
||||
);
|
||||
attachable(anchor,spin,orient, r1=r1, r2=r2, l=l) {
|
||||
intersection() {
|
||||
polyhedron(points=vertices, faces=faces, convexity=2*layers);
|
||||
cyl(
|
||||
r1=r1, r2=r2, l=l,
|
||||
chamfer=chamfer, chamfer1=chamfer1, chamfer2=chamfer2,
|
||||
chamfang=chamfang, chamfang1=chamfang1, chamfang2=chamfang2,
|
||||
from_end=from_end,
|
||||
rounding=rounding, rounding1=rounding1, rounding2=rounding2,
|
||||
$fn=count*2
|
||||
);
|
||||
}
|
||||
children();
|
||||
}
|
||||
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);
|
||||
twist = 360*l*tan(helix)/(r1*2*PI);
|
||||
c1 = circle(r=r1,$fn=count);
|
||||
c2 = rot(-180/count,p=circle(r=r1-inset,$fn=count));
|
||||
path = [for (i=idx(c1)) each [c1[i],c2[i]]];
|
||||
knob_w = 2*PI*r1/count;
|
||||
knob_h = knob_w / tan(helix);
|
||||
layers = ceil(l/knob_h);
|
||||
plen = len(path);
|
||||
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])
|
||||
], [
|
||||
[0,0,-layers*knob_h/2],
|
||||
[0,0, layers*knob_h/2]
|
||||
]
|
||||
);
|
||||
faces = concat(
|
||||
[
|
||||
for (layer = [0:1:layers-1], i=idx(path)) let(
|
||||
loff = (layer%2)? 2 : 0,
|
||||
i1 = layer*plen+((i+1)%plen),
|
||||
i2 = layer*plen+((i+2)%plen),
|
||||
i3 = (layer+1)*plen+posmod(i+1+loff,plen),
|
||||
i4 = (layer+1)*plen+posmod(i+2+loff,plen),
|
||||
i5 = (layer+1)*plen+posmod(i-0+loff,plen),
|
||||
i6 = (layer+1)*plen+posmod(i-1+loff,plen)
|
||||
) each [
|
||||
[i1, i2, ((i%2)? i5 : i3)],
|
||||
[i3, i5, ((i%2)? i2 : i1)]
|
||||
]
|
||||
], [
|
||||
for (i=[0:1:count-1]) let(
|
||||
i1 = posmod(i*2+1,plen),
|
||||
i2 = posmod(i*2+2,plen),
|
||||
i3 = posmod(i*2+3,plen),
|
||||
loff = layers*plen
|
||||
) each [
|
||||
[i1,i3,i2],
|
||||
[i1+loff,i2+loff,i3+loff],
|
||||
[i3,i1,len(vertices)-2],
|
||||
[i1+loff,i3+loff,len(vertices)-1]
|
||||
]
|
||||
]
|
||||
);
|
||||
attachable(anchor,spin,orient, r1=r1, r2=r2, l=l) {
|
||||
intersection() {
|
||||
polyhedron(points=vertices, faces=faces, convexity=2*layers);
|
||||
cyl(
|
||||
r1=r1, r2=r2, l=l,
|
||||
chamfer=chamfer, chamfer1=chamfer1, chamfer2=chamfer2,
|
||||
chamfang=chamfang, chamfang1=chamfang1, chamfang2=chamfang2,
|
||||
from_end=from_end,
|
||||
rounding=rounding, rounding1=rounding1, rounding2=rounding2,
|
||||
$fn=count*2
|
||||
);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -149,22 +149,22 @@ 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,
|
||||
d=undef, d1=undef, d2=undef,
|
||||
count=30, profile=120, helix=30,
|
||||
anchor=CENTER, spin=0, orient=UP
|
||||
l=10, overage=5,
|
||||
r=undef, r1=undef, r2=undef,
|
||||
d=undef, d1=undef, d2=undef,
|
||||
count=30, profile=120, helix=30,
|
||||
anchor=CENTER, spin=0, orient=UP
|
||||
) {
|
||||
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);
|
||||
}
|
||||
children();
|
||||
}
|
||||
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);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -20,24 +20,24 @@ include <metric_screws.scad>
|
||||
// Arguments:
|
||||
// size = Inner size of lmXuu bearing, in mm.
|
||||
function get_lmXuu_bearing_diam(size) = lookup(size, [
|
||||
[ 4.0, 8.0],
|
||||
[ 5.0, 10.0],
|
||||
[ 6.0, 12.0],
|
||||
[ 8.0, 15.0],
|
||||
[ 10.0, 19.0],
|
||||
[ 12.0, 21.0],
|
||||
[ 13.0, 23.0],
|
||||
[ 16.0, 28.0],
|
||||
[ 20.0, 32.0],
|
||||
[ 25.0, 40.0],
|
||||
[ 30.0, 45.0],
|
||||
[ 35.0, 52.0],
|
||||
[ 40.0, 60.0],
|
||||
[ 50.0, 80.0],
|
||||
[ 60.0, 90.0],
|
||||
[ 80.0, 120.0],
|
||||
[100.0, 150.0]
|
||||
]);
|
||||
[ 4.0, 8.0],
|
||||
[ 5.0, 10.0],
|
||||
[ 6.0, 12.0],
|
||||
[ 8.0, 15.0],
|
||||
[ 10.0, 19.0],
|
||||
[ 12.0, 21.0],
|
||||
[ 13.0, 23.0],
|
||||
[ 16.0, 28.0],
|
||||
[ 20.0, 32.0],
|
||||
[ 25.0, 40.0],
|
||||
[ 30.0, 45.0],
|
||||
[ 35.0, 52.0],
|
||||
[ 40.0, 60.0],
|
||||
[ 50.0, 80.0],
|
||||
[ 60.0, 90.0],
|
||||
[ 80.0, 120.0],
|
||||
[100.0, 150.0]
|
||||
]);
|
||||
|
||||
|
||||
// Function: get_lmXuu_bearing_length()
|
||||
@ -45,24 +45,24 @@ function get_lmXuu_bearing_diam(size) = lookup(size, [
|
||||
// Arguments:
|
||||
// size = Inner size of lmXuu bearing, in mm.
|
||||
function get_lmXuu_bearing_length(size) = lookup(size, [
|
||||
[ 4.0, 12.0],
|
||||
[ 5.0, 15.0],
|
||||
[ 6.0, 19.0],
|
||||
[ 8.0, 24.0],
|
||||
[ 10.0, 29.0],
|
||||
[ 12.0, 30.0],
|
||||
[ 13.0, 32.0],
|
||||
[ 16.0, 37.0],
|
||||
[ 20.0, 42.0],
|
||||
[ 25.0, 59.0],
|
||||
[ 30.0, 64.0],
|
||||
[ 35.0, 70.0],
|
||||
[ 40.0, 80.0],
|
||||
[ 50.0, 100.0],
|
||||
[ 60.0, 110.0],
|
||||
[ 80.0, 140.0],
|
||||
[100.0, 175.0]
|
||||
]);
|
||||
[ 4.0, 12.0],
|
||||
[ 5.0, 15.0],
|
||||
[ 6.0, 19.0],
|
||||
[ 8.0, 24.0],
|
||||
[ 10.0, 29.0],
|
||||
[ 12.0, 30.0],
|
||||
[ 13.0, 32.0],
|
||||
[ 16.0, 37.0],
|
||||
[ 20.0, 42.0],
|
||||
[ 25.0, 59.0],
|
||||
[ 30.0, 64.0],
|
||||
[ 35.0, 70.0],
|
||||
[ 40.0, 80.0],
|
||||
[ 50.0, 100.0],
|
||||
[ 60.0, 110.0],
|
||||
[ 80.0, 140.0],
|
||||
[100.0, 175.0]
|
||||
]);
|
||||
|
||||
|
||||
// Module: linear_bearing_housing()
|
||||
@ -83,45 +83,45 @@ function get_lmXuu_bearing_length(size) = lookup(size, [
|
||||
// linear_bearing_housing(d=19, l=29, wall=2, tab=6, screwsize=2.5);
|
||||
module linear_bearing_housing(d=15, l=24, tab=7, gap=5, wall=3, tabwall=5, screwsize=3, anchor=BOTTOM, spin=0, orient=UP)
|
||||
{
|
||||
od = d+2*wall;
|
||||
ogap = gap+2*tabwall;
|
||||
tabh = tab/2+od/2*sqrt(2)-ogap/2;
|
||||
h = od+tab/2;
|
||||
anchors = [
|
||||
anchorpt("axis", [0,0,-tab/2/2]),
|
||||
anchorpt("screw", [0,2-ogap/2,tabh-tab/2/2],FWD),
|
||||
anchorpt("nut", [0,ogap/2-2,tabh-tab/2/2],FWD)
|
||||
];
|
||||
attachable(anchor,spin,orient, size=[l, od, h], anchors=anchors) {
|
||||
down(tab/2/2)
|
||||
difference() {
|
||||
union() {
|
||||
// Housing
|
||||
zrot(90) teardrop(r=od/2,h=l);
|
||||
od = d+2*wall;
|
||||
ogap = gap+2*tabwall;
|
||||
tabh = tab/2+od/2*sqrt(2)-ogap/2;
|
||||
h = od+tab/2;
|
||||
anchors = [
|
||||
anchorpt("axis", [0,0,-tab/2/2]),
|
||||
anchorpt("screw", [0,2-ogap/2,tabh-tab/2/2],FWD),
|
||||
anchorpt("nut", [0,ogap/2-2,tabh-tab/2/2],FWD)
|
||||
];
|
||||
attachable(anchor,spin,orient, size=[l, od, h], anchors=anchors) {
|
||||
down(tab/2/2)
|
||||
difference() {
|
||||
union() {
|
||||
// Housing
|
||||
zrot(90) teardrop(r=od/2,h=l);
|
||||
|
||||
// Base
|
||||
cube([l,od,od/2], anchor=TOP);
|
||||
// Base
|
||||
cube([l,od,od/2], anchor=TOP);
|
||||
|
||||
// Tabs
|
||||
cube([l,ogap,od/2+tab/2], anchor=BOTTOM);
|
||||
}
|
||||
// Tabs
|
||||
cube([l,ogap,od/2+tab/2], anchor=BOTTOM);
|
||||
}
|
||||
|
||||
// Clear bearing space
|
||||
zrot(90) teardrop(r=d/2,h=l+0.05);
|
||||
// Clear bearing space
|
||||
zrot(90) teardrop(r=d/2,h=l+0.05);
|
||||
|
||||
// Clear gap
|
||||
cube([l+0.05,gap,od], anchor=BOTTOM);
|
||||
// Clear gap
|
||||
cube([l+0.05,gap,od], anchor=BOTTOM);
|
||||
|
||||
up(tabh) {
|
||||
// Screwhole
|
||||
fwd(ogap/2-2+0.01) screw(screwsize=screwsize*1.06, screwlen=ogap, headsize=screwsize*2, headlen=10, orient=FWD);
|
||||
up(tabh) {
|
||||
// Screwhole
|
||||
fwd(ogap/2-2+0.01) screw(screwsize=screwsize*1.06, screwlen=ogap, headsize=screwsize*2, headlen=10, orient=FWD);
|
||||
|
||||
// Nut holder
|
||||
back(ogap/2-2+0.01) metric_nut(size=screwsize, hole=false, anchor=BOTTOM, orient=BACK);
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
// Nut holder
|
||||
back(ogap/2-2+0.01) metric_nut(size=screwsize, hole=false, anchor=BOTTOM, orient=BACK);
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -142,10 +142,10 @@ module linear_bearing_housing(d=15, l=24, tab=7, gap=5, wall=3, tabwall=5, screw
|
||||
// lmXuu_housing(size=10, wall=2, tab=6, screwsize=2.5);
|
||||
module lmXuu_housing(size=8, tab=7, gap=5, wall=3, tabwall=5, screwsize=3, anchor=BOTTOM, spin=0, orient=UP)
|
||||
{
|
||||
d = get_lmXuu_bearing_diam(size);
|
||||
l = get_lmXuu_bearing_length(size);
|
||||
linear_bearing_housing(d=d, l=l, tab=tab, gap=gap, wall=wall, tabwall=tabwall, screwsize=screwsize, orient=orient, spin=spin, anchor=anchor) children();
|
||||
d = get_lmXuu_bearing_diam(size);
|
||||
l = get_lmXuu_bearing_length(size);
|
||||
linear_bearing_housing(d=d, l=l, tab=tab, gap=gap, wall=wall, tabwall=tabwall, screwsize=screwsize, orient=orient, spin=spin, anchor=anchor) children();
|
||||
}
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
428
masks.scad
428
masks.scad
@ -31,19 +31,19 @@
|
||||
// Example(FR):
|
||||
// angle_pie_mask(ang=30, d=100, l=20);
|
||||
module angle_pie_mask(
|
||||
ang=45, l=undef,
|
||||
r=undef, r1=undef, r2=undef,
|
||||
d=undef, d1=undef, d2=undef,
|
||||
h=undef,
|
||||
anchor=CENTER, spin=0, orient=UP
|
||||
ang=45, l=undef,
|
||||
r=undef, r1=undef, r2=undef,
|
||||
d=undef, d1=undef, d2=undef,
|
||||
h=undef,
|
||||
anchor=CENTER, spin=0, orient=UP
|
||||
) {
|
||||
l = first_defined([l, h, 1]);
|
||||
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) {
|
||||
pie_slice(ang=ang, l=l+0.1, r1=r1, r2=r2, anchor=CENTER);
|
||||
children();
|
||||
}
|
||||
l = first_defined([l, h, 1]);
|
||||
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) {
|
||||
pie_slice(ang=ang, l=l+0.1, r1=r1, r2=r2, anchor=CENTER);
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -98,53 +98,53 @@ module angle_pie_mask(
|
||||
// cube([100,50,100], center=true);
|
||||
// }
|
||||
module cylinder_mask(
|
||||
l,
|
||||
r=undef, r1=undef, r2=undef,
|
||||
d=undef, d1=undef, d2=undef,
|
||||
chamfer=undef, chamfer1=undef, chamfer2=undef,
|
||||
chamfang=undef, chamfang1=undef, chamfang2=undef,
|
||||
rounding=undef, rounding1=undef, rounding2=undef,
|
||||
circum=false, from_end=false,
|
||||
overage=10, ends_only=false,
|
||||
anchor=CENTER, spin=0, orient=UP
|
||||
l,
|
||||
r=undef, r1=undef, r2=undef,
|
||||
d=undef, d1=undef, d2=undef,
|
||||
chamfer=undef, chamfer1=undef, chamfer2=undef,
|
||||
chamfang=undef, chamfang1=undef, chamfang2=undef,
|
||||
rounding=undef, rounding1=undef, rounding2=undef,
|
||||
circum=false, from_end=false,
|
||||
overage=10, ends_only=false,
|
||||
anchor=CENTER, spin=0, orient=UP
|
||||
) {
|
||||
r1 = get_radius(r=r, d=d, r1=r1, d1=d1, dflt=1);
|
||||
r2 = get_radius(r=r, d=d, r1=r2, d1=d2, dflt=1);
|
||||
sides = segs(max(r1,r2));
|
||||
sc = circum? 1/cos(180/sides) : 1;
|
||||
vang = atan2(l, r1-r2)/2;
|
||||
ang1 = first_defined([chamfang1, chamfang, vang]);
|
||||
ang2 = first_defined([chamfang2, chamfang, 90-vang]);
|
||||
cham1 = first_defined([chamfer1, chamfer, 0]);
|
||||
cham2 = first_defined([chamfer2, chamfer, 0]);
|
||||
fil1 = first_defined([rounding1, rounding, 0]);
|
||||
fil2 = first_defined([rounding2, rounding, 0]);
|
||||
maxd = max(r1,r2);
|
||||
if ($children > 0) {
|
||||
difference() {
|
||||
children();
|
||||
cylinder_mask(l=l, r1=sc*r1, r2=sc*r2, chamfer1=cham1, chamfer2=cham2, chamfang1=ang1, chamfang2=ang2, rounding1=fil1, rounding2=fil2, orient=orient, from_end=from_end);
|
||||
}
|
||||
} else {
|
||||
attachable(anchor,spin,orient, r=r1, l=l) {
|
||||
difference() {
|
||||
union() {
|
||||
chlen1 = cham1 / (from_end? 1 : tan(ang1));
|
||||
chlen2 = cham2 / (from_end? 1 : tan(ang2));
|
||||
if (!ends_only) {
|
||||
cylinder(r=maxd+overage, h=l+2*overage, center=true);
|
||||
} else {
|
||||
if (cham2>0) up(l/2-chlen2) cylinder(r=maxd+overage, h=chlen2+overage, center=false);
|
||||
if (cham1>0) down(l/2+overage) cylinder(r=maxd+overage, h=chlen1+overage, center=false);
|
||||
if (fil2>0) up(l/2-fil2) cylinder(r=maxd+overage, h=fil2+overage, center=false);
|
||||
if (fil1>0) down(l/2+overage) cylinder(r=maxd+overage, h=fil1+overage, center=false);
|
||||
}
|
||||
}
|
||||
cyl(r1=sc*r1, r2=sc*r2, l=l, chamfer1=cham1, chamfer2=cham2, chamfang1=ang1, chamfang2=ang2, from_end=from_end, rounding1=fil1, rounding2=fil2);
|
||||
}
|
||||
nil();
|
||||
}
|
||||
}
|
||||
r1 = get_radius(r=r, d=d, r1=r1, d1=d1, dflt=1);
|
||||
r2 = get_radius(r=r, d=d, r1=r2, d1=d2, dflt=1);
|
||||
sides = segs(max(r1,r2));
|
||||
sc = circum? 1/cos(180/sides) : 1;
|
||||
vang = atan2(l, r1-r2)/2;
|
||||
ang1 = first_defined([chamfang1, chamfang, vang]);
|
||||
ang2 = first_defined([chamfang2, chamfang, 90-vang]);
|
||||
cham1 = first_defined([chamfer1, chamfer, 0]);
|
||||
cham2 = first_defined([chamfer2, chamfer, 0]);
|
||||
fil1 = first_defined([rounding1, rounding, 0]);
|
||||
fil2 = first_defined([rounding2, rounding, 0]);
|
||||
maxd = max(r1,r2);
|
||||
if ($children > 0) {
|
||||
difference() {
|
||||
children();
|
||||
cylinder_mask(l=l, r1=sc*r1, r2=sc*r2, chamfer1=cham1, chamfer2=cham2, chamfang1=ang1, chamfang2=ang2, rounding1=fil1, rounding2=fil2, orient=orient, from_end=from_end);
|
||||
}
|
||||
} else {
|
||||
attachable(anchor,spin,orient, r=r1, l=l) {
|
||||
difference() {
|
||||
union() {
|
||||
chlen1 = cham1 / (from_end? 1 : tan(ang1));
|
||||
chlen2 = cham2 / (from_end? 1 : tan(ang2));
|
||||
if (!ends_only) {
|
||||
cylinder(r=maxd+overage, h=l+2*overage, center=true);
|
||||
} else {
|
||||
if (cham2>0) up(l/2-chlen2) cylinder(r=maxd+overage, h=chlen2+overage, center=false);
|
||||
if (cham1>0) down(l/2+overage) cylinder(r=maxd+overage, h=chlen1+overage, center=false);
|
||||
if (fil2>0) up(l/2-fil2) cylinder(r=maxd+overage, h=fil2+overage, center=false);
|
||||
if (fil1>0) down(l/2+overage) cylinder(r=maxd+overage, h=fil1+overage, center=false);
|
||||
}
|
||||
}
|
||||
cyl(r1=sc*r1, r2=sc*r2, l=l, chamfer1=cham1, chamfer2=cham2, chamfang1=ang1, chamfang2=ang2, from_end=from_end, rounding1=fil1, rounding2=fil2);
|
||||
}
|
||||
nil();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -171,10 +171,10 @@ module cylinder_mask(
|
||||
// #chamfer_mask(l=50, chamfer=10, orient=RIGHT);
|
||||
// }
|
||||
module chamfer_mask(l=1, chamfer=1, anchor=CENTER, spin=0, orient=UP) {
|
||||
attachable(anchor,spin,orient, size=[chamfer*2, chamfer*2, l]) {
|
||||
cylinder(r=chamfer, h=l+0.1, center=true, $fn=4);
|
||||
children();
|
||||
}
|
||||
attachable(anchor,spin,orient, size=[chamfer*2, chamfer*2, l]) {
|
||||
cylinder(r=chamfer, h=l+0.1, center=true, $fn=4);
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -196,7 +196,7 @@ module chamfer_mask(l=1, chamfer=1, anchor=CENTER, spin=0, orient=UP) {
|
||||
// #chamfer_mask_x(l=50, chamfer=10);
|
||||
// }
|
||||
module chamfer_mask_x(l=1.0, chamfer=1.0, anchor=CENTER, spin=0) {
|
||||
chamfer_mask(l=l, chamfer=chamfer, anchor=anchor, spin=spin, orient=RIGHT) children();
|
||||
chamfer_mask(l=l, chamfer=chamfer, anchor=anchor, spin=spin, orient=RIGHT) children();
|
||||
}
|
||||
|
||||
|
||||
@ -218,7 +218,7 @@ module chamfer_mask_x(l=1.0, chamfer=1.0, anchor=CENTER, spin=0) {
|
||||
// #chamfer_mask_y(l=50, chamfer=10);
|
||||
// }
|
||||
module chamfer_mask_y(l=1.0, chamfer=1.0, anchor=CENTER, spin=0) {
|
||||
chamfer_mask(l=l, chamfer=chamfer, anchor=anchor, spin=spin, orient=BACK) children();
|
||||
chamfer_mask(l=l, chamfer=chamfer, anchor=anchor, spin=spin, orient=BACK) children();
|
||||
}
|
||||
|
||||
|
||||
@ -240,7 +240,7 @@ module chamfer_mask_y(l=1.0, chamfer=1.0, anchor=CENTER, spin=0) {
|
||||
// #chamfer_mask_z(l=50, chamfer=10);
|
||||
// }
|
||||
module chamfer_mask_z(l=1.0, chamfer=1.0, anchor=CENTER, spin=0) {
|
||||
chamfer_mask(l=l, chamfer=chamfer, anchor=anchor, spin=spin, orient=UP) children();
|
||||
chamfer_mask(l=l, chamfer=chamfer, anchor=anchor, spin=spin, orient=UP) children();
|
||||
}
|
||||
|
||||
|
||||
@ -264,13 +264,13 @@ module chamfer_mask_z(l=1.0, chamfer=1.0, anchor=CENTER, spin=0) {
|
||||
// }
|
||||
module chamfer(chamfer=1, size=[1,1,1], edges=EDGES_ALL, except_edges=[])
|
||||
{
|
||||
difference() {
|
||||
children();
|
||||
difference() {
|
||||
cube(size, center=true);
|
||||
cuboid(size+[1,1,1]*0.02, chamfer=chamfer+0.01, edges=edges, except_edges=except_edges, trimcorners=true);
|
||||
}
|
||||
}
|
||||
difference() {
|
||||
children();
|
||||
difference() {
|
||||
cube(size, center=true);
|
||||
cuboid(size+[1,1,1]*0.02, chamfer=chamfer+0.01, edges=edges, except_edges=except_edges, trimcorners=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -303,11 +303,11 @@ module chamfer(chamfer=1, size=[1,1,1], edges=EDGES_ALL, except_edges=[])
|
||||
// }
|
||||
module chamfer_cylinder_mask(r=undef, d=undef, chamfer=0.25, ang=45, from_end=false, anchor=CENTER, spin=0, orient=UP)
|
||||
{
|
||||
r = get_radius(r=r, d=d, dflt=1);
|
||||
attachable(anchor,spin,orient, r=r, l=chamfer*2) {
|
||||
cylinder_mask(l=chamfer*3, r=r, chamfer2=chamfer, chamfang2=ang, from_end=from_end, ends_only=true, anchor=TOP);
|
||||
children();
|
||||
}
|
||||
r = get_radius(r=r, d=d, dflt=1);
|
||||
attachable(anchor,spin,orient, r=r, l=chamfer*2) {
|
||||
cylinder_mask(l=chamfer*3, r=r, chamfer2=chamfer, chamfang2=ang, from_end=from_end, ends_only=true, anchor=TOP);
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -344,17 +344,17 @@ module chamfer_cylinder_mask(r=undef, d=undef, chamfer=0.25, ang=45, from_end=fa
|
||||
// chamfer_hole_mask(d=100, chamfer=25, ang=30, overage=10);
|
||||
module chamfer_hole_mask(r=undef, d=undef, chamfer=0.25, ang=45, from_end=false, overage=0.1, anchor=CENTER, spin=0, orient=UP)
|
||||
{
|
||||
r = get_radius(r=r, d=d, dflt=1);
|
||||
h = chamfer * (from_end? 1 : tan(90-ang));
|
||||
r2 = r + chamfer * (from_end? tan(ang) : 1);
|
||||
$fn = segs(r);
|
||||
attachable(anchor,spin,orient, r1=r, r2=r2, l=h*2) {
|
||||
union() {
|
||||
cylinder(r=r2, h=overage, center=false);
|
||||
down(h) cylinder(r1=r, r2=r2, h=h, center=false);
|
||||
}
|
||||
children();
|
||||
}
|
||||
r = get_radius(r=r, d=d, dflt=1);
|
||||
h = chamfer * (from_end? 1 : tan(90-ang));
|
||||
r2 = r + chamfer * (from_end? tan(ang) : 1);
|
||||
$fn = segs(r);
|
||||
attachable(anchor,spin,orient, r1=r, r2=r2, l=h*2) {
|
||||
union() {
|
||||
cylinder(r=r2, h=overage, center=false);
|
||||
down(h) cylinder(r1=r, r2=r2, h=h, center=false);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -406,30 +406,30 @@ module chamfer_hole_mask(r=undef, d=undef, chamfer=0.25, ang=45, from_end=false,
|
||||
// }
|
||||
module rounding_mask(l=undef, r=undef, r1=undef, r2=undef, anchor=CENTER, spin=0, orient=UP, h=undef)
|
||||
{
|
||||
l = first_defined([l, h, 1]);
|
||||
r1 = get_radius(r1=r1, r=r, dflt=1);
|
||||
r2 = get_radius(r1=r2, r=r, dflt=1);
|
||||
sides = quantup(segs(max(r1,r2)),4);
|
||||
attachable(anchor,spin,orient, size=[2*r1,2*r1,l], size2=[2*r2,2*r2]) {
|
||||
if (r1<r2) {
|
||||
zflip() {
|
||||
linear_extrude(height=l, convexity=4, center=true, scale=r1/r2) {
|
||||
difference() {
|
||||
square(2*r2, center=true);
|
||||
xcopies(2*r2) ycopies(2*r2) circle(r=r2, $fn=sides);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
linear_extrude(height=l, convexity=4, center=true, scale=r2/r1) {
|
||||
difference() {
|
||||
square(2*r1, center=true);
|
||||
xcopies(2*r1) ycopies(2*r1) circle(r=r1, $fn=sides);
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
l = first_defined([l, h, 1]);
|
||||
r1 = get_radius(r1=r1, r=r, dflt=1);
|
||||
r2 = get_radius(r1=r2, r=r, dflt=1);
|
||||
sides = quantup(segs(max(r1,r2)),4);
|
||||
attachable(anchor,spin,orient, size=[2*r1,2*r1,l], size2=[2*r2,2*r2]) {
|
||||
if (r1<r2) {
|
||||
zflip() {
|
||||
linear_extrude(height=l, convexity=4, center=true, scale=r1/r2) {
|
||||
difference() {
|
||||
square(2*r2, center=true);
|
||||
xcopies(2*r2) ycopies(2*r2) circle(r=r2, $fn=sides);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
linear_extrude(height=l, convexity=4, center=true, scale=r2/r1) {
|
||||
difference() {
|
||||
square(2*r1, center=true);
|
||||
xcopies(2*r1) ycopies(2*r1) circle(r=r1, $fn=sides);
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -460,11 +460,11 @@ module rounding_mask(l=undef, r=undef, r1=undef, r2=undef, anchor=CENTER, spin=0
|
||||
// }
|
||||
module rounding_mask_x(l=1.0, r=undef, r1=undef, r2=undef, anchor=CENTER, spin=0)
|
||||
{
|
||||
anchor = rot(p=anchor, from=RIGHT, to=TOP);
|
||||
rounding_mask(l=l, r=r, r1=r1, r2=r2, anchor=anchor, spin=spin, orient=RIGHT) {
|
||||
for (i=[0:1:$children-2]) children(i);
|
||||
if ($children) children($children-1);
|
||||
}
|
||||
anchor = rot(p=anchor, from=RIGHT, to=TOP);
|
||||
rounding_mask(l=l, r=r, r1=r1, r2=r2, anchor=anchor, spin=spin, orient=RIGHT) {
|
||||
for (i=[0:1:$children-2]) children(i);
|
||||
if ($children) children($children-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -495,11 +495,11 @@ module rounding_mask_x(l=1.0, r=undef, r1=undef, r2=undef, anchor=CENTER, spin=0
|
||||
// }
|
||||
module rounding_mask_y(l=1.0, r=undef, r1=undef, r2=undef, anchor=CENTER, spin=0)
|
||||
{
|
||||
anchor = rot(p=anchor, from=BACK, to=TOP);
|
||||
rounding_mask(l=l, r=r, r1=r1, r2=r2, anchor=anchor, spin=spin, orient=BACK) {
|
||||
for (i=[0:1:$children-2]) children(i);
|
||||
if ($children) children($children-1);
|
||||
}
|
||||
anchor = rot(p=anchor, from=BACK, to=TOP);
|
||||
rounding_mask(l=l, r=r, r1=r1, r2=r2, anchor=anchor, spin=spin, orient=BACK) {
|
||||
for (i=[0:1:$children-2]) children(i);
|
||||
if ($children) children($children-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -530,10 +530,10 @@ module rounding_mask_y(l=1.0, r=undef, r1=undef, r2=undef, anchor=CENTER, spin=0
|
||||
// }
|
||||
module rounding_mask_z(l=1.0, r=undef, r1=undef, r2=undef, anchor=CENTER, spin=0)
|
||||
{
|
||||
rounding_mask(l=l, r=r, r1=r1, r2=r2, anchor=anchor, spin=spin, orient=UP) {
|
||||
for (i=[0:1:$children-2]) children(i);
|
||||
if ($children) children($children-1);
|
||||
}
|
||||
rounding_mask(l=l, r=r, r1=r1, r2=r2, anchor=anchor, spin=spin, orient=UP) {
|
||||
for (i=[0:1:$children-2]) children(i);
|
||||
if ($children) children($children-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -557,13 +557,13 @@ module rounding_mask_z(l=1.0, r=undef, r1=undef, r2=undef, anchor=CENTER, spin=0
|
||||
// }
|
||||
module rounding(r=1, size=[1,1,1], edges=EDGES_ALL, except_edges=[])
|
||||
{
|
||||
difference() {
|
||||
children();
|
||||
difference() {
|
||||
cube(size, center=true);
|
||||
cuboid(size+[1,1,1]*0.01, rounding=r, edges=edges, except_edges=except_edges, trimcorners=true);
|
||||
}
|
||||
}
|
||||
difference() {
|
||||
children();
|
||||
difference() {
|
||||
cube(size, center=true);
|
||||
cuboid(size+[1,1,1]*0.01, rounding=r, edges=edges, except_edges=except_edges, trimcorners=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -596,35 +596,35 @@ module rounding(r=1, size=[1,1,1], edges=EDGES_ALL, except_edges=[])
|
||||
// }
|
||||
module rounding_angled_edge_mask(h=1.0, r=undef, r1=undef, r2=undef, 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],
|
||||
for (i = [0:1:n]) let (a=90+i*sweep/n) [r*cos(a)+x, r*sin(a)-r],
|
||||
[min(-1, r*cos(270-ang)+x-1), r*sin(270-ang)-r],
|
||||
[min(-1, r*cos(90+ang)+x-1), r*sin(90+ang)+r],
|
||||
];
|
||||
function _mask_shape(r) = [
|
||||
for (i = [0:1:n]) let (a=90+ang+i*sweep/n) [r*cos(a)+x, r*sin(a)+r],
|
||||
for (i = [0:1:n]) let (a=90+i*sweep/n) [r*cos(a)+x, r*sin(a)-r],
|
||||
[min(-1, r*cos(270-ang)+x-1), r*sin(270-ang)-r],
|
||||
[min(-1, r*cos(90+ang)+x-1), r*sin(90+ang)+r],
|
||||
];
|
||||
|
||||
sweep = 180-ang;
|
||||
r1 = get_radius(r1=r1, r=r, dflt=1);
|
||||
r2 = get_radius(r1=r2, r=r, dflt=1);
|
||||
n = ceil(segs(max(r1,r2))*sweep/360);
|
||||
x = sin(90-(ang/2))/sin(ang/2) * (r1<r2? r2 : r1);
|
||||
if(r1<r2) {
|
||||
attachable(anchor,spin,orient, size=[2*x*r1/r2,2*r1,h], size2=[2*x,2*r2]) {
|
||||
zflip() {
|
||||
linear_extrude(height=h, convexity=4, center=true, scale=r1/r2) {
|
||||
polygon(_mask_shape(r2));
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
} else {
|
||||
attachable(anchor,spin,orient, size=[2*x,2*r1,h], size2=[2*x*r2/r1,2*r2]) {
|
||||
linear_extrude(height=h, convexity=4, center=true, scale=r2/r1) {
|
||||
polygon(_mask_shape(r1));
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
sweep = 180-ang;
|
||||
r1 = get_radius(r1=r1, r=r, dflt=1);
|
||||
r2 = get_radius(r1=r2, r=r, dflt=1);
|
||||
n = ceil(segs(max(r1,r2))*sweep/360);
|
||||
x = sin(90-(ang/2))/sin(ang/2) * (r1<r2? r2 : r1);
|
||||
if(r1<r2) {
|
||||
attachable(anchor,spin,orient, size=[2*x*r1/r2,2*r1,h], size2=[2*x,2*r2]) {
|
||||
zflip() {
|
||||
linear_extrude(height=h, convexity=4, center=true, scale=r1/r2) {
|
||||
polygon(_mask_shape(r2));
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
} else {
|
||||
attachable(anchor,spin,orient, size=[2*x,2*r1,h], size2=[2*x*r2/r1,2*r2]) {
|
||||
linear_extrude(height=h, convexity=4, center=true, scale=r2/r1) {
|
||||
polygon(_mask_shape(r1));
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -653,26 +653,26 @@ module rounding_angled_edge_mask(h=1.0, r=undef, r1=undef, r2=undef, ang=90, anc
|
||||
// }
|
||||
module rounding_angled_corner_mask(r=1.0, ang=90, anchor=CENTER, spin=0, orient=UP)
|
||||
{
|
||||
dx = r / tan(ang/2);
|
||||
dx2 = dx / cos(ang/2) + 1;
|
||||
fn = quantup(segs(r), 4);
|
||||
attachable(anchor,spin,orient, d=dx2, l=2*r) {
|
||||
difference() {
|
||||
down(r) cylinder(r=dx2, h=r+1, center=false);
|
||||
yflip_copy() {
|
||||
translate([dx, r, -r]) {
|
||||
hull() {
|
||||
sphere(r=r, $fn=fn);
|
||||
down(r*3) sphere(r=r, $fn=fn);
|
||||
zrot_copies([0,ang]) {
|
||||
right(r*3) sphere(r=r, $fn=fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
dx = r / tan(ang/2);
|
||||
dx2 = dx / cos(ang/2) + 1;
|
||||
fn = quantup(segs(r), 4);
|
||||
attachable(anchor,spin,orient, d=dx2, l=2*r) {
|
||||
difference() {
|
||||
down(r) cylinder(r=dx2, h=r+1, center=false);
|
||||
yflip_copy() {
|
||||
translate([dx, r, -r]) {
|
||||
hull() {
|
||||
sphere(r=r, $fn=fn);
|
||||
down(r*3) sphere(r=r, $fn=fn);
|
||||
zrot_copies([0,ang]) {
|
||||
right(r*3) sphere(r=r, $fn=fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -700,15 +700,15 @@ module rounding_angled_corner_mask(r=1.0, ang=90, anchor=CENTER, spin=0, orient=
|
||||
// }
|
||||
module rounding_corner_mask(r=1.0, anchor=CENTER, spin=0, orient=UP)
|
||||
{
|
||||
attachable(anchor,spin,orient, size=[2,2,2]*r) {
|
||||
difference() {
|
||||
cube(size=r*2, center=true);
|
||||
grid3d(n=[2,2,2], spacing=r*2-0.05) {
|
||||
sphere(r=r);
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
attachable(anchor,spin,orient, size=[2,2,2]*r) {
|
||||
difference() {
|
||||
cube(size=r*2, center=true);
|
||||
grid3d(n=[2,2,2], spacing=r*2-0.05) {
|
||||
sphere(r=r);
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -735,7 +735,7 @@ module rounding_corner_mask(r=1.0, anchor=CENTER, spin=0, orient=UP)
|
||||
// }
|
||||
module rounding_cylinder_mask(r=1.0, rounding=0.25)
|
||||
{
|
||||
cylinder_mask(l=rounding*3, r=r, rounding2=rounding, overage=rounding, ends_only=true, anchor=TOP);
|
||||
cylinder_mask(l=rounding*3, r=r, rounding2=rounding, overage=rounding, ends_only=true, anchor=TOP);
|
||||
}
|
||||
|
||||
|
||||
@ -772,16 +772,16 @@ module rounding_cylinder_mask(r=1.0, rounding=0.25)
|
||||
// rounding_hole_mask(r=40, rounding=20, $fa=2, $fs=2);
|
||||
module rounding_hole_mask(r=undef, d=undef, rounding=0.25, overage=0.1, 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) {
|
||||
rotate_extrude(convexity=4) {
|
||||
difference() {
|
||||
right(r-overage) fwd(rounding) square(rounding+overage, center=false);
|
||||
right(r+rounding) fwd(rounding) circle(r=rounding);
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
r = get_radius(r=r, d=d, dflt=1);
|
||||
attachable(anchor,spin,orient, r=r+rounding, l=2*rounding) {
|
||||
rotate_extrude(convexity=4) {
|
||||
difference() {
|
||||
right(r-overage) fwd(rounding) square(rounding+overage, center=false);
|
||||
right(r+rounding) fwd(rounding) circle(r=rounding);
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -803,21 +803,21 @@ module rounding_hole_mask(r=undef, d=undef, rounding=0.25, overage=0.1, anchor=C
|
||||
// Example:
|
||||
// diff("mask")
|
||||
// cuboid([50,60,70],rounding=10,edges="Z",anchor=CENTER) {
|
||||
// edge_profile(BOT)
|
||||
// mask2d_teardrop(r=10, angle=40);
|
||||
// corner_profile(BOT,r=10)
|
||||
// mask2d_teardrop(r=10, angle=40);
|
||||
// edge_profile(BOT)
|
||||
// mask2d_teardrop(r=10, angle=40);
|
||||
// corner_profile(BOT,r=10)
|
||||
// mask2d_teardrop(r=10, angle=40);
|
||||
// }
|
||||
module teardrop_corner_mask(r, d, angle, excess=0.1, anchor=CENTER, spin=0, orient=UP) {
|
||||
assert(is_num(angle));
|
||||
assert(is_num(excess));
|
||||
assert(angle>0 && angle<90);
|
||||
r = get_radius(r=r, d=d, dflt=1);
|
||||
difference() {
|
||||
translate(-[1,1,1]*excess) cube(r+excess, center=false);
|
||||
translate([1,1,1]*r) onion(r=r,maxang=angle,orient=DOWN);
|
||||
}
|
||||
assert(is_num(angle));
|
||||
assert(is_num(excess));
|
||||
assert(angle>0 && angle<90);
|
||||
r = get_radius(r=r, d=d, dflt=1);
|
||||
difference() {
|
||||
translate(-[1,1,1]*excess) cube(r+excess, center=false);
|
||||
translate([1,1,1]*r) onion(r=r,maxang=angle,orient=DOWN);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
514
math.scad
514
math.scad
@ -109,10 +109,10 @@ function factorial(n,d=1) = product([for (i=[n:-1:d]) i]);
|
||||
// // Points colored in ROYGBIV order.
|
||||
// rainbow(pts) translate($item) circle(d=3,$fn=8);
|
||||
function lerp(a,b,u) =
|
||||
assert(same_shape(a,b), "Bad or inconsistent inputs to lerp")
|
||||
is_num(u)? (1-u)*a + u*b :
|
||||
assert(!is_undef(u)&&!is_bool(u)&&!is_string(u), "Input u to lerp must be a number, vector, or range.")
|
||||
[for (v = u) lerp(a,b,v)];
|
||||
assert(same_shape(a,b), "Bad or inconsistent inputs to lerp")
|
||||
is_num(u)? (1-u)*a + u*b :
|
||||
assert(!is_undef(u)&&!is_bool(u)&&!is_string(u), "Input u to lerp must be a number, vector, or range.")
|
||||
[for (v = u) lerp(a,b,v)];
|
||||
|
||||
|
||||
|
||||
@ -121,37 +121,37 @@ function lerp(a,b,u) =
|
||||
// Function: sinh()
|
||||
// Description: Takes a value `x`, and returns the hyperbolic sine of it.
|
||||
function sinh(x) =
|
||||
(exp(x)-exp(-x))/2;
|
||||
(exp(x)-exp(-x))/2;
|
||||
|
||||
|
||||
// Function: cosh()
|
||||
// Description: Takes a value `x`, and returns the hyperbolic cosine of it.
|
||||
function cosh(x) =
|
||||
(exp(x)+exp(-x))/2;
|
||||
(exp(x)+exp(-x))/2;
|
||||
|
||||
|
||||
// Function: tanh()
|
||||
// Description: Takes a value `x`, and returns the hyperbolic tangent of it.
|
||||
function tanh(x) =
|
||||
sinh(x)/cosh(x);
|
||||
sinh(x)/cosh(x);
|
||||
|
||||
|
||||
// Function: asinh()
|
||||
// Description: Takes a value `x`, and returns the inverse hyperbolic sine of it.
|
||||
function asinh(x) =
|
||||
ln(x+sqrt(x*x+1));
|
||||
ln(x+sqrt(x*x+1));
|
||||
|
||||
|
||||
// Function: acosh()
|
||||
// Description: Takes a value `x`, and returns the inverse hyperbolic cosine of it.
|
||||
function acosh(x) =
|
||||
ln(x+sqrt(x*x-1));
|
||||
ln(x+sqrt(x*x-1));
|
||||
|
||||
|
||||
// Function: atanh()
|
||||
// Description: Takes a value `x`, and returns the inverse hyperbolic tangent of it.
|
||||
function atanh(x) =
|
||||
ln((1+x)/(1-x))/2;
|
||||
ln((1+x)/(1-x))/2;
|
||||
|
||||
|
||||
|
||||
@ -182,8 +182,8 @@ function atanh(x) =
|
||||
// quant([9,10,10.4,10.5,11,12],3); // Returns: [9,9,9,12,12,12]
|
||||
// quant([[9,10,10.4],[10.5,11,12]],3); // Returns: [[9,9,9],[12,12,12]]
|
||||
function quant(x,y) =
|
||||
is_list(x)? [for (v=x) quant(v,y)] :
|
||||
floor(x/y+0.5)*y;
|
||||
is_list(x)? [for (v=x) quant(v,y)] :
|
||||
floor(x/y+0.5)*y;
|
||||
|
||||
|
||||
// Function: quantdn()
|
||||
@ -211,8 +211,8 @@ function quant(x,y) =
|
||||
// quantdn([9,10,10.4,10.5,11,12],3); // Returns: [9,9,9,9,9,12]
|
||||
// quantdn([[9,10,10.4],[10.5,11,12]],3); // Returns: [[9,9,9],[9,9,12]]
|
||||
function quantdn(x,y) =
|
||||
is_list(x)? [for (v=x) quantdn(v,y)] :
|
||||
floor(x/y)*y;
|
||||
is_list(x)? [for (v=x) quantdn(v,y)] :
|
||||
floor(x/y)*y;
|
||||
|
||||
|
||||
// Function: quantup()
|
||||
@ -240,8 +240,8 @@ function quantdn(x,y) =
|
||||
// quantup([9,10,10.4,10.5,11,12],3); // Returns: [9,12,12,12,12,12]
|
||||
// quantup([[9,10,10.4],[10.5,11,12]],3); // Returns: [[9,12,12],[12,12,12]]
|
||||
function quantup(x,y) =
|
||||
is_list(x)? [for (v=x) quantup(v,y)] :
|
||||
ceil(x/y)*y;
|
||||
is_list(x)? [for (v=x) quantup(v,y)] :
|
||||
ceil(x/y)*y;
|
||||
|
||||
|
||||
// Section: Constraints and Modulos
|
||||
@ -296,7 +296,7 @@ function posmod(x,m) = (x%m+m)%m;
|
||||
// modang(270,360); // Returns: -90
|
||||
// modang(700,360); // Returns: -20
|
||||
function modang(x) =
|
||||
let(xx = posmod(x,360)) xx<180? xx : xx-360;
|
||||
let(xx = posmod(x,360)) xx<180? xx : xx-360;
|
||||
|
||||
|
||||
// Function: modrange()
|
||||
@ -315,11 +315,11 @@ function modang(x) =
|
||||
// modrange(90,270,360, step=-45); // Returns: [90,45,0,315,270]
|
||||
// modrange(270,90,360, step=-45); // Returns: [270,225,180,135,90]
|
||||
function modrange(x, y, m, step=1) =
|
||||
let(
|
||||
a = posmod(x, m),
|
||||
b = posmod(y, m),
|
||||
c = step>0? (a>b? b+m : b) : (a<b? b-m : b)
|
||||
) [for (i=[a:step:c]) (i%m+m)%m];
|
||||
let(
|
||||
a = posmod(x, m),
|
||||
b = posmod(y, m),
|
||||
c = step>0? (a>b? b+m : b) : (a<b? b-m : b)
|
||||
) [for (i=[a:step:c]) (i%m+m)%m];
|
||||
|
||||
|
||||
|
||||
@ -339,9 +339,9 @@ function modrange(x, y, m, step=1) =
|
||||
// ints = rand_int(0,100,3);
|
||||
// int = rand_int(-10,10,1)[0];
|
||||
function rand_int(min, max, N, seed=undef) =
|
||||
assert(max >= min, "Max value cannot be smaller than min")
|
||||
let (rvect = is_def(seed) ? rands(min,max+1,N,seed) : rands(min,max+1,N))
|
||||
[for(entry = rvect) floor(entry)];
|
||||
assert(max >= min, "Max value cannot be smaller than min")
|
||||
let (rvect = is_def(seed) ? rands(min,max+1,N,seed) : rands(min,max+1,N))
|
||||
[for(entry = rvect) floor(entry)];
|
||||
|
||||
|
||||
// Function: gaussian_rands()
|
||||
@ -355,8 +355,8 @@ function rand_int(min, max, N, seed=undef) =
|
||||
// N = Number of random numbers to return. Default: 1
|
||||
// seed = If given, sets the random number seed.
|
||||
function gaussian_rands(mean, stddev, N=1, seed=undef) =
|
||||
let(nums = is_undef(seed)? rands(0,1,N*2) : rands(0,1,N*2,seed))
|
||||
[for (i = list_range(N)) mean + stddev*sqrt(-2*ln(nums[i*2]))*cos(360*nums[i*2+1])];
|
||||
let(nums = is_undef(seed)? rands(0,1,N*2) : rands(0,1,N*2,seed))
|
||||
[for (i = list_range(N)) mean + stddev*sqrt(-2*ln(nums[i*2]))*cos(360*nums[i*2+1])];
|
||||
|
||||
|
||||
// Function: log_rands()
|
||||
@ -371,12 +371,12 @@ function gaussian_rands(mean, stddev, N=1, seed=undef) =
|
||||
// N = Number of random numbers to return. Default: 1
|
||||
// seed = If given, sets the random number seed.
|
||||
function log_rands(minval, maxval, factor, N=1, seed=undef) =
|
||||
assert(maxval >= minval, "maxval cannot be smaller than minval")
|
||||
let(
|
||||
minv = 1-1/pow(factor,minval),
|
||||
maxv = 1-1/pow(factor,maxval),
|
||||
nums = is_undef(seed)? rands(minv, maxv, N) : rands(minv, maxv, N, seed)
|
||||
) [for (num=nums) -ln(1-num)/ln(factor)];
|
||||
assert(maxval >= minval, "maxval cannot be smaller than minval")
|
||||
let(
|
||||
minv = 1-1/pow(factor,minval),
|
||||
maxv = 1-1/pow(factor,maxval),
|
||||
nums = is_undef(seed)? rands(minv, maxv, N) : rands(minv, maxv, N, seed)
|
||||
) [for (num=nums) -ln(1-num)/ln(factor)];
|
||||
|
||||
|
||||
|
||||
@ -388,22 +388,22 @@ function log_rands(minval, maxval, factor, N=1, seed=undef) =
|
||||
// Description:
|
||||
// Computes the Greatest Common Divisor/Factor of `a` and `b`.
|
||||
function gcd(a,b) =
|
||||
assert(is_int(a) && is_int(b),"Arguments to gcd must be integers")
|
||||
b==0 ? abs(a) : gcd(b,a % b);
|
||||
assert(is_int(a) && is_int(b),"Arguments to gcd must be integers")
|
||||
b==0 ? abs(a) : gcd(b,a % b);
|
||||
|
||||
|
||||
// Computes lcm for two scalars
|
||||
function _lcm(a,b) =
|
||||
assert(is_int(a), "Invalid non-integer parameters to lcm")
|
||||
assert(is_int(b), "Invalid non-integer parameters to lcm")
|
||||
assert(a!=0 && b!=0, "Arguments to lcm must be nonzero")
|
||||
abs(a*b) / gcd(a,b);
|
||||
assert(is_int(a), "Invalid non-integer parameters to lcm")
|
||||
assert(is_int(b), "Invalid non-integer parameters to lcm")
|
||||
assert(a!=0 && b!=0, "Arguments to lcm must be nonzero")
|
||||
abs(a*b) / gcd(a,b);
|
||||
|
||||
|
||||
// Computes lcm for a list of values
|
||||
function _lcmlist(a) =
|
||||
len(a)==1 ? a[0] :
|
||||
_lcmlist(concat(slice(a,0,len(a)-2),[lcm(a[len(a)-2],a[len(a)-1])]));
|
||||
len(a)==1 ? a[0] :
|
||||
_lcmlist(concat(slice(a,0,len(a)-2),[lcm(a[len(a)-2],a[len(a)-1])]));
|
||||
|
||||
|
||||
// Function: lcm()
|
||||
@ -415,12 +415,12 @@ function _lcmlist(a) =
|
||||
// be non-zero integers. The output is always a positive integer. It is an error to pass zero
|
||||
// as an argument.
|
||||
function lcm(a,b=[]) =
|
||||
!is_list(a) && !is_list(b) ? _lcm(a,b) :
|
||||
let(
|
||||
arglist = concat(force_list(a),force_list(b))
|
||||
)
|
||||
assert(len(arglist)>0,"invalid call to lcm with empty list(s)")
|
||||
_lcmlist(arglist);
|
||||
!is_list(a) && !is_list(b) ? _lcm(a,b) :
|
||||
let(
|
||||
arglist = concat(force_list(a),force_list(b))
|
||||
)
|
||||
assert(len(arglist)>0,"invalid call to lcm with empty list(s)")
|
||||
_lcmlist(arglist);
|
||||
|
||||
|
||||
|
||||
@ -438,8 +438,8 @@ function lcm(a,b=[]) =
|
||||
// sum([1,2,3]); // returns 6.
|
||||
// sum([[1,2,3], [3,4,5], [5,6,7]]); // returns [9, 12, 15]
|
||||
function sum(v, dflt=0) =
|
||||
assert(is_consistent(v), "Input to sum is non-numeric or inconsistent")
|
||||
len(v) == 0 ? dflt : _sum(v,v[0]*0);
|
||||
assert(is_consistent(v), "Input to sum is non-numeric or inconsistent")
|
||||
len(v) == 0 ? dflt : _sum(v,v[0]*0);
|
||||
|
||||
function _sum(v,_total,_i=0) = _i>=len(v) ? _total : _sum(v,_total+v[_i], _i+1);
|
||||
|
||||
@ -456,14 +456,14 @@ function _sum(v,_total,_i=0) = _i>=len(v) ? _total : _sum(v,_total+v[_i], _i+1);
|
||||
// cumsum([1,2,3]); // returns [1,3,6]
|
||||
// cumsum([[1,2,3], [3,4,5], [5,6,7]]); // returns [[1,2,3], [4,6,8], [9,12,15]]
|
||||
function cumsum(v,_i=0,_acc=[]) =
|
||||
_i==len(v) ? _acc :
|
||||
cumsum(
|
||||
v, _i+1,
|
||||
concat(
|
||||
_acc,
|
||||
[_i==0 ? v[_i] : select(_acc,-1)+v[_i]]
|
||||
)
|
||||
);
|
||||
_i==len(v) ? _acc :
|
||||
cumsum(
|
||||
v, _i+1,
|
||||
concat(
|
||||
_acc,
|
||||
[_i==0 ? v[_i] : select(_acc,-1)+v[_i]]
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
// Function: sum_of_squares()
|
||||
@ -489,12 +489,12 @@ function sum_of_squares(v, i=0, tot=0) = sum(vmul(v,v));
|
||||
// Examples:
|
||||
// v = sum_of_sines(30, [[10,3,0], [5,5.5,60]]);
|
||||
function sum_of_sines(a, sines) =
|
||||
sum([
|
||||
for (s = sines) let(
|
||||
ss=point3d(s),
|
||||
v=ss.x*sin(a*ss.y+ss.z)
|
||||
) v
|
||||
]);
|
||||
sum([
|
||||
for (s = sines) let(
|
||||
ss=point3d(s),
|
||||
v=ss.x*sin(a*ss.y+ss.z)
|
||||
) v
|
||||
]);
|
||||
|
||||
|
||||
// Function: deltas()
|
||||
@ -541,16 +541,16 @@ function mean(v) = sum(v)/len(v);
|
||||
// Given a list of numbers or vectors, finds the median value or midpoint.
|
||||
// If passed a list of vectors, returns the vector of the median of each part.
|
||||
function median(v) =
|
||||
assert(is_list(v))
|
||||
assert(len(v)>0)
|
||||
is_vector(v[0])? (
|
||||
assert(is_consistent(v))
|
||||
[
|
||||
for (i=idx(v[0]))
|
||||
let(vals = subindex(v,i))
|
||||
(min(vals)+max(vals))/2
|
||||
]
|
||||
) : (min(v)+max(v))/2;
|
||||
assert(is_list(v))
|
||||
assert(len(v)>0)
|
||||
is_vector(v[0])? (
|
||||
assert(is_consistent(v))
|
||||
[
|
||||
for (i=idx(v[0]))
|
||||
let(vals = subindex(v,i))
|
||||
(min(vals)+max(vals))/2
|
||||
]
|
||||
) : (min(v)+max(v))/2;
|
||||
|
||||
|
||||
// Section: Matrix math
|
||||
@ -565,23 +565,23 @@ function median(v) =
|
||||
// want to solve Ax=b1 and Ax=b2 that you need to form the matrix transpose([b1,b2]) for the right hand side and then
|
||||
// transpose the returned value.
|
||||
function linear_solve(A,b) =
|
||||
assert(is_matrix(A))
|
||||
let(
|
||||
m = len(A),
|
||||
n = len(A[0])
|
||||
)
|
||||
assert(is_vector(b,m) || is_matrix(b,m),"Incompatible matrix and right hand side")
|
||||
let (
|
||||
qr = m<n? qr_factor(transpose(A)) : qr_factor(A),
|
||||
maxdim = max(n,m),
|
||||
mindim = min(n,m),
|
||||
Q = submatrix(qr[0],[0:maxdim-1], [0:mindim-1]),
|
||||
R = submatrix(qr[1],[0:mindim-1], [0:mindim-1]),
|
||||
zeros = [for(i=[0:mindim-1]) if (approx(R[i][i],0)) i]
|
||||
)
|
||||
zeros != [] ? undef :
|
||||
m<n ? Q*back_substitute(R,b,transpose=true) :
|
||||
back_substitute(R, transpose(Q)*b);
|
||||
assert(is_matrix(A))
|
||||
let(
|
||||
m = len(A),
|
||||
n = len(A[0])
|
||||
)
|
||||
assert(is_vector(b,m) || is_matrix(b,m),"Incompatible matrix and right hand side")
|
||||
let (
|
||||
qr = m<n? qr_factor(transpose(A)) : qr_factor(A),
|
||||
maxdim = max(n,m),
|
||||
mindim = min(n,m),
|
||||
Q = submatrix(qr[0],[0:maxdim-1], [0:mindim-1]),
|
||||
R = submatrix(qr[1],[0:mindim-1], [0:mindim-1]),
|
||||
zeros = [for(i=[0:mindim-1]) if (approx(R[i][i],0)) i]
|
||||
)
|
||||
zeros != [] ? undef :
|
||||
m<n ? Q*back_substitute(R,b,transpose=true) :
|
||||
back_substitute(R, transpose(Q)*b);
|
||||
|
||||
|
||||
// Function: matrix_inverse()
|
||||
@ -593,8 +593,8 @@ function linear_solve(A,b) =
|
||||
// use this function. Instead use linear_solve, or use qr_factor. The computation
|
||||
// will be faster and more accurate.
|
||||
function matrix_inverse(A) =
|
||||
assert(is_matrix(A,square=true),"Input to matrix_inverse() must be a square matrix")
|
||||
linear_solve(A,ident(len(A)));
|
||||
assert(is_matrix(A,square=true),"Input to matrix_inverse() must be a square matrix")
|
||||
linear_solve(A,ident(len(A)));
|
||||
|
||||
|
||||
// Function: submatrix()
|
||||
@ -610,32 +610,32 @@ function submatrix(M,ind1,ind2) = [for(i=ind1) [for(j=ind2) M[i][j] ] ];
|
||||
// Calculates the QR factorization of the input matrix A and returns it as the list [Q,R]. This factorization can be
|
||||
// used to solve linear systems of equations.
|
||||
function qr_factor(A) =
|
||||
assert(is_matrix(A))
|
||||
let(
|
||||
m = len(A),
|
||||
n = len(A[0])
|
||||
)
|
||||
let(
|
||||
qr =_qr_factor(A, column=0, m = m, n=n, Q=ident(m)),
|
||||
Rzero = [
|
||||
for(i=[0:m-1]) [
|
||||
for(j=[0:n-1])
|
||||
i>j ? 0 : qr[1][i][j]
|
||||
]
|
||||
]
|
||||
) [qr[0],Rzero];
|
||||
assert(is_matrix(A))
|
||||
let(
|
||||
m = len(A),
|
||||
n = len(A[0])
|
||||
)
|
||||
let(
|
||||
qr =_qr_factor(A, column=0, m = m, n=n, Q=ident(m)),
|
||||
Rzero = [
|
||||
for(i=[0:m-1]) [
|
||||
for(j=[0:n-1])
|
||||
i>j ? 0 : qr[1][i][j]
|
||||
]
|
||||
]
|
||||
) [qr[0],Rzero];
|
||||
|
||||
function _qr_factor(A,Q, column, m, n) =
|
||||
column >= min(m-1,n) ? [Q,A] :
|
||||
let(
|
||||
x = [for(i=[column:1:m-1]) A[i][column]],
|
||||
alpha = (x[0]<=0 ? 1 : -1) * norm(x),
|
||||
u = x - concat([alpha],repeat(0,m-1)),
|
||||
v = u / norm(u),
|
||||
Qc = ident(len(x)) - 2*transpose([v])*[v],
|
||||
Qf = [for(i=[0:m-1]) [for(j=[0:m-1]) i<column || j<column ? (i==j ? 1 : 0) : Qc[i-column][j-column]]]
|
||||
)
|
||||
_qr_factor(Qf*A, Q*Qf, column+1, m, n);
|
||||
column >= min(m-1,n) ? [Q,A] :
|
||||
let(
|
||||
x = [for(i=[column:1:m-1]) A[i][column]],
|
||||
alpha = (x[0]<=0 ? 1 : -1) * norm(x),
|
||||
u = x - concat([alpha],repeat(0,m-1)),
|
||||
v = u / norm(u),
|
||||
Qc = ident(len(x)) - 2*transpose([v])*[v],
|
||||
Qf = [for(i=[0:m-1]) [for(j=[0:m-1]) i<column || j<column ? (i==j ? 1 : 0) : Qc[i-column][j-column]]]
|
||||
)
|
||||
_qr_factor(Qf*A, Q*Qf, column+1, m, n);
|
||||
|
||||
|
||||
// Function: back_substitute()
|
||||
@ -646,22 +646,22 @@ function _qr_factor(A,Q, column, m, n) =
|
||||
// You can supply a compatible matrix b and it will produce the solution for every column of b. Note that if you want to
|
||||
// solve Rx=b1 and Rx=b2 you must set b to transpose([b1,b2]) and then take the transpose of the result.
|
||||
function back_substitute(R, b, x=[],transpose = false) =
|
||||
assert(is_matrix(R, square=true))
|
||||
let(n=len(R))
|
||||
assert(is_vector(b,n) || is_matrix(b,n),"R and b are not compatible in back_substitute")
|
||||
!is_vector(b) ? transpose([for(i=[0:len(b[0])-1]) back_substitute(R,subindex(b,i),transpose=transpose)]) :
|
||||
transpose?
|
||||
reverse(back_substitute(
|
||||
[for(i=[0:n-1]) [for(j=[0:n-1]) R[n-1-j][n-1-i]]],
|
||||
reverse(b), x, false
|
||||
)) :
|
||||
len(x) == n ? x :
|
||||
let(
|
||||
ind = n - len(x) - 1,
|
||||
newvalue =
|
||||
len(x)==0? b[ind]/R[ind][ind] :
|
||||
(b[ind]-select(R[ind],ind+1,-1) * x)/R[ind][ind]
|
||||
) back_substitute(R, b, concat([newvalue],x));
|
||||
assert(is_matrix(R, square=true))
|
||||
let(n=len(R))
|
||||
assert(is_vector(b,n) || is_matrix(b,n),"R and b are not compatible in back_substitute")
|
||||
!is_vector(b) ? transpose([for(i=[0:len(b[0])-1]) back_substitute(R,subindex(b,i),transpose=transpose)]) :
|
||||
transpose?
|
||||
reverse(back_substitute(
|
||||
[for(i=[0:n-1]) [for(j=[0:n-1]) R[n-1-j][n-1-i]]],
|
||||
reverse(b), x, false
|
||||
)) :
|
||||
len(x) == n ? x :
|
||||
let(
|
||||
ind = n - len(x) - 1,
|
||||
newvalue =
|
||||
len(x)==0? b[ind]/R[ind][ind] :
|
||||
(b[ind]-select(R[ind],ind+1,-1) * x)/R[ind][ind]
|
||||
) back_substitute(R, b, concat([newvalue],x));
|
||||
|
||||
|
||||
// Function: det2()
|
||||
@ -684,9 +684,9 @@ function det2(M) = M[0][0] * M[1][1] - M[0][1]*M[1][0];
|
||||
// M = [ [6,4,-2], [1,-2,8], [1,5,7] ];
|
||||
// det = det3(M); // Returns: -334
|
||||
function det3(M) =
|
||||
M[0][0] * (M[1][1]*M[2][2]-M[2][1]*M[1][2]) -
|
||||
M[1][0] * (M[0][1]*M[2][2]-M[2][1]*M[0][2]) +
|
||||
M[2][0] * (M[0][1]*M[1][2]-M[1][1]*M[0][2]);
|
||||
M[0][0] * (M[1][1]*M[2][2]-M[2][1]*M[1][2]) -
|
||||
M[1][0] * (M[0][1]*M[2][2]-M[2][1]*M[0][2]) +
|
||||
M[2][0] * (M[0][1]*M[1][2]-M[1][1]*M[0][2]);
|
||||
|
||||
|
||||
// Function: determinant()
|
||||
@ -698,23 +698,23 @@ function det3(M) =
|
||||
// M = [ [6,4,-2,9], [1,-2,8,3], [1,5,7,6], [4,2,5,1] ];
|
||||
// det = determinant(M); // Returns: 2267
|
||||
function determinant(M) =
|
||||
assert(len(M)==len(M[0]))
|
||||
len(M)==1? M[0][0] :
|
||||
len(M)==2? det2(M) :
|
||||
len(M)==3? det3(M) :
|
||||
sum(
|
||||
[for (col=[0:1:len(M)-1])
|
||||
((col%2==0)? 1 : -1) *
|
||||
M[col][0] *
|
||||
determinant(
|
||||
[for (r=[1:1:len(M)-1])
|
||||
[for (c=[0:1:len(M)-1])
|
||||
if (c!=col) M[c][r]
|
||||
]
|
||||
]
|
||||
)
|
||||
]
|
||||
);
|
||||
assert(len(M)==len(M[0]))
|
||||
len(M)==1? M[0][0] :
|
||||
len(M)==2? det2(M) :
|
||||
len(M)==3? det3(M) :
|
||||
sum(
|
||||
[for (col=[0:1:len(M)-1])
|
||||
((col%2==0)? 1 : -1) *
|
||||
M[col][0] *
|
||||
determinant(
|
||||
[for (r=[1:1:len(M)-1])
|
||||
[for (c=[0:1:len(M)-1])
|
||||
if (c!=col) M[c][r]
|
||||
]
|
||||
]
|
||||
)
|
||||
]
|
||||
);
|
||||
|
||||
|
||||
// Function: is_matrix()
|
||||
@ -731,12 +731,12 @@ function determinant(M) =
|
||||
// n = optional width of matrix
|
||||
// square = set to true to require a square matrix. Default: false
|
||||
function is_matrix(A,m,n, square=false) =
|
||||
is_list(A) && len(A)>0 &&
|
||||
(is_undef(m) || len(A)==m) &&
|
||||
is_vector(A[0]) &&
|
||||
(is_undef(n) || len(A[0])==n) &&
|
||||
(!square || n==m) &&
|
||||
is_consistent(A);
|
||||
is_list(A) && len(A)>0 &&
|
||||
(is_undef(m) || len(A)==m) &&
|
||||
is_vector(A[0]) &&
|
||||
(is_undef(n) || len(A[0])==n) &&
|
||||
(!square || n==m) &&
|
||||
is_consistent(A);
|
||||
|
||||
|
||||
|
||||
@ -758,18 +758,18 @@ function is_matrix(A,m,n, square=false) =
|
||||
// approx(0.3333,1/3,eps=1e-3); // Returns: true
|
||||
// approx(PI,3.1415926536); // Returns: true
|
||||
function approx(a,b,eps=EPSILON) =
|
||||
a==b? true :
|
||||
a*0!=b*0? false :
|
||||
is_list(a)? ([for (i=idx(a)) if(!approx(a[i],b[i],eps=eps)) 1] == []) :
|
||||
(abs(a-b) <= eps);
|
||||
a==b? true :
|
||||
a*0!=b*0? false :
|
||||
is_list(a)? ([for (i=idx(a)) if(!approx(a[i],b[i],eps=eps)) 1] == []) :
|
||||
(abs(a-b) <= eps);
|
||||
|
||||
|
||||
function _type_num(x) =
|
||||
is_undef(x)? 0 :
|
||||
is_bool(x)? 1 :
|
||||
is_num(x)? 2 :
|
||||
is_string(x)? 3 :
|
||||
is_list(x)? 4 : 5;
|
||||
is_undef(x)? 0 :
|
||||
is_bool(x)? 1 :
|
||||
is_num(x)? 2 :
|
||||
is_string(x)? 3 :
|
||||
is_list(x)? 4 : 5;
|
||||
|
||||
|
||||
// Function: compare_vals()
|
||||
@ -782,10 +782,10 @@ function _type_num(x) =
|
||||
// a = First value to compare.
|
||||
// b = Second value to compare.
|
||||
function compare_vals(a, b) =
|
||||
(a==b)? 0 :
|
||||
let(t1=_type_num(a), t2=_type_num(b)) (t1!=t2)? (t1-t2) :
|
||||
is_list(a)? compare_lists(a,b) :
|
||||
(a<b)? -1 : (a>b)? 1 : 0;
|
||||
(a==b)? 0 :
|
||||
let(t1=_type_num(a), t2=_type_num(b)) (t1!=t2)? (t1-t2) :
|
||||
is_list(a)? compare_lists(a,b) :
|
||||
(a<b)? -1 : (a>b)? 1 : 0;
|
||||
|
||||
|
||||
// Function: compare_lists()
|
||||
@ -800,13 +800,13 @@ function compare_vals(a, b) =
|
||||
// a = First list to compare.
|
||||
// b = Second list to compare.
|
||||
function compare_lists(a, b) =
|
||||
a==b? 0 : let(
|
||||
cmps = [
|
||||
for(i=[0:1:min(len(a),len(b))-1]) let(
|
||||
cmp = compare_vals(a[i],b[i])
|
||||
) if(cmp!=0) cmp
|
||||
]
|
||||
) cmps==[]? (len(a)-len(b)) : cmps[0];
|
||||
a==b? 0 : let(
|
||||
cmps = [
|
||||
for(i=[0:1:min(len(a),len(b))-1]) let(
|
||||
cmp = compare_vals(a[i],b[i])
|
||||
) if(cmp!=0) cmp
|
||||
]
|
||||
) cmps==[]? (len(a)-len(b)) : cmps[0];
|
||||
|
||||
|
||||
// Function: any()
|
||||
@ -822,13 +822,13 @@ function compare_lists(a, b) =
|
||||
// any([[0,0], [0,0]]); // Returns false.
|
||||
// any([[0,0], [1,0]]); // Returns true.
|
||||
function any(l, i=0, succ=false) =
|
||||
(i>=len(l) || succ)? succ :
|
||||
any(
|
||||
l, i=i+1, succ=(
|
||||
is_list(l[i])? any(l[i]) :
|
||||
!(!l[i])
|
||||
)
|
||||
);
|
||||
(i>=len(l) || succ)? succ :
|
||||
any(
|
||||
l, i=i+1, succ=(
|
||||
is_list(l[i])? any(l[i]) :
|
||||
!(!l[i])
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
// Function: all()
|
||||
@ -845,13 +845,13 @@ function any(l, i=0, succ=false) =
|
||||
// all([[0,0], [1,0]]); // Returns false.
|
||||
// all([[1,1], [1,1]]); // Returns true.
|
||||
function all(l, i=0, fail=false) =
|
||||
(i>=len(l) || fail)? (!fail) :
|
||||
all(
|
||||
l, i=i+1, fail=(
|
||||
is_list(l[i])? !all(l[i]) :
|
||||
!l[i]
|
||||
)
|
||||
);
|
||||
(i>=len(l) || fail)? (!fail) :
|
||||
all(
|
||||
l, i=i+1, fail=(
|
||||
is_list(l[i])? !all(l[i]) :
|
||||
!l[i]
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
// Function: count_true()
|
||||
@ -875,13 +875,13 @@ function all(l, i=0, fail=false) =
|
||||
// count_true([[1,1], [1,1]]); // Returns 4.
|
||||
// count_true([[1,1], [1,1]], nmax=3); // Returns 3.
|
||||
function count_true(l, nmax=undef, i=0, cnt=0) =
|
||||
(i>=len(l) || (nmax!=undef && cnt>=nmax))? cnt :
|
||||
count_true(
|
||||
l=l, nmax=nmax, i=i+1, cnt=cnt+(
|
||||
is_list(l[i])? count_true(l[i], nmax=nmax-cnt) :
|
||||
(l[i]? 1 : 0)
|
||||
)
|
||||
);
|
||||
(i>=len(l) || (nmax!=undef && cnt>=nmax))? cnt :
|
||||
count_true(
|
||||
l=l, nmax=nmax, i=i+1, cnt=cnt+(
|
||||
is_list(l[i])? count_true(l[i], nmax=nmax-cnt) :
|
||||
(l[i]? 1 : 0)
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
|
||||
@ -897,23 +897,23 @@ function count_true(l, nmax=undef, i=0, cnt=0) =
|
||||
// for internal points, f'(t) = (f(t+h)-f(t-h))/2h. For the endpoints (when closed=false) the algorithm
|
||||
// uses a two point method if sufficient points are available: f'(t) = (3*(f(t+h)-f(t)) - (f(t+2*h)-f(t+h)))/2h.
|
||||
function deriv(data, h=1, closed=false) =
|
||||
let( L = len(data) )
|
||||
closed? [
|
||||
for(i=[0:1:L-1])
|
||||
(data[(i+1)%L]-data[(L+i-1)%L])/2/h
|
||||
] :
|
||||
let(
|
||||
first =
|
||||
L<3? data[1]-data[0] :
|
||||
3*(data[1]-data[0]) - (data[2]-data[1]),
|
||||
last =
|
||||
L<3? data[L-1]-data[L-2]:
|
||||
(data[L-3]-data[L-2])-3*(data[L-2]-data[L-1])
|
||||
) [
|
||||
first/2/h,
|
||||
for(i=[1:1:L-2]) (data[i+1]-data[i-1])/2/h,
|
||||
last/2/h
|
||||
];
|
||||
let( L = len(data) )
|
||||
closed? [
|
||||
for(i=[0:1:L-1])
|
||||
(data[(i+1)%L]-data[(L+i-1)%L])/2/h
|
||||
] :
|
||||
let(
|
||||
first =
|
||||
L<3? data[1]-data[0] :
|
||||
3*(data[1]-data[0]) - (data[2]-data[1]),
|
||||
last =
|
||||
L<3? data[L-1]-data[L-2]:
|
||||
(data[L-3]-data[L-2])-3*(data[L-2]-data[L-1])
|
||||
) [
|
||||
first/2/h,
|
||||
for(i=[1:1:L-2]) (data[i+1]-data[i-1])/2/h,
|
||||
last/2/h
|
||||
];
|
||||
|
||||
|
||||
// Function: deriv2()
|
||||
@ -928,25 +928,25 @@ function deriv(data, h=1, closed=false) =
|
||||
// f''(t) = (2*f(t) - 5*f(t+h) + 4*f(t+2*h) - f(t+3*h))/h^2 or if five points are available
|
||||
// f''(t) = (35*f(t) - 104*f(t+h) + 114*f(t+2*h) - 56*f(t+3*h) + 11*f(t+4*h)) / 12h^2
|
||||
function deriv2(data, h=1, closed=false) =
|
||||
let( L = len(data) )
|
||||
closed? [
|
||||
for(i=[0:1:L-1])
|
||||
(data[(i+1)%L]-2*data[i]+data[(L+i-1)%L])/h/h
|
||||
] :
|
||||
let(
|
||||
first = L<3? undef :
|
||||
L==3? data[0] - 2*data[1] + data[2] :
|
||||
L==4? 2*data[0] - 5*data[1] + 4*data[2] - data[3] :
|
||||
(35*data[0] - 104*data[1] + 114*data[2] - 56*data[3] + 11*data[4])/12,
|
||||
last = L<3? undef :
|
||||
L==3? data[L-1] - 2*data[L-2] + data[L-3] :
|
||||
L==4? -2*data[L-1] + 5*data[L-2] - 4*data[L-3] + data[L-4] :
|
||||
(35*data[L-1] - 104*data[L-2] + 114*data[L-3] - 56*data[L-4] + 11*data[L-5])/12
|
||||
) [
|
||||
first/h/h,
|
||||
for(i=[1:1:L-2]) (data[i+1]-2*data[i]+data[i-1])/h/h,
|
||||
last/h/h
|
||||
];
|
||||
let( L = len(data) )
|
||||
closed? [
|
||||
for(i=[0:1:L-1])
|
||||
(data[(i+1)%L]-2*data[i]+data[(L+i-1)%L])/h/h
|
||||
] :
|
||||
let(
|
||||
first = L<3? undef :
|
||||
L==3? data[0] - 2*data[1] + data[2] :
|
||||
L==4? 2*data[0] - 5*data[1] + 4*data[2] - data[3] :
|
||||
(35*data[0] - 104*data[1] + 114*data[2] - 56*data[3] + 11*data[4])/12,
|
||||
last = L<3? undef :
|
||||
L==3? data[L-1] - 2*data[L-2] + data[L-3] :
|
||||
L==4? -2*data[L-1] + 5*data[L-2] - 4*data[L-3] + data[L-4] :
|
||||
(35*data[L-1] - 104*data[L-2] + 114*data[L-3] - 56*data[L-4] + 11*data[L-5])/12
|
||||
) [
|
||||
first/h/h,
|
||||
for(i=[1:1:L-2]) (data[i+1]-2*data[i]+data[i-1])/h/h,
|
||||
last/h/h
|
||||
];
|
||||
|
||||
|
||||
// Function: deriv3()
|
||||
@ -960,28 +960,28 @@ function deriv2(data, h=1, closed=false) =
|
||||
// the estimates are f'''(t) = (-5*f(t)+18*f(t+h)-24*f(t+2*h)+14*f(t+3*h)-3*f(t+4*h)) / 2h^3 and
|
||||
// f'''(t) = (-3*f(t-h)+10*f(t)-12*f(t+h)+6*f(t+2*h)-f(t+3*h)) / 2h^3.
|
||||
function deriv3(data, h=1, closed=false) =
|
||||
let(
|
||||
L = len(data),
|
||||
h3 = h*h*h
|
||||
)
|
||||
assert(L>=5, "Need five points for 3rd derivative estimate")
|
||||
closed? [
|
||||
for(i=[0:1:L-1])
|
||||
(-data[(L+i-2)%L]+2*data[(L+i-1)%L]-2*data[(i+1)%L]+data[(i+2)%L])/2/h3
|
||||
] :
|
||||
let(
|
||||
first=(-5*data[0]+18*data[1]-24*data[2]+14*data[3]-3*data[4])/2,
|
||||
second=(-3*data[0]+10*data[1]-12*data[2]+6*data[3]-data[4])/2,
|
||||
last=(5*data[L-1]-18*data[L-2]+24*data[L-3]-14*data[L-4]+3*data[L-5])/2,
|
||||
prelast=(3*data[L-1]-10*data[L-2]+12*data[L-3]-6*data[L-4]+data[L-5])/2
|
||||
) [
|
||||
first/h3,
|
||||
second/h3,
|
||||
for(i=[2:1:L-3]) (-data[i-2]+2*data[i-1]-2*data[i+1]+data[i+2])/2/h3,
|
||||
prelast/h3,
|
||||
last/h3
|
||||
];
|
||||
let(
|
||||
L = len(data),
|
||||
h3 = h*h*h
|
||||
)
|
||||
assert(L>=5, "Need five points for 3rd derivative estimate")
|
||||
closed? [
|
||||
for(i=[0:1:L-1])
|
||||
(-data[(L+i-2)%L]+2*data[(L+i-1)%L]-2*data[(i+1)%L]+data[(i+2)%L])/2/h3
|
||||
] :
|
||||
let(
|
||||
first=(-5*data[0]+18*data[1]-24*data[2]+14*data[3]-3*data[4])/2,
|
||||
second=(-3*data[0]+10*data[1]-12*data[2]+6*data[3]-data[4])/2,
|
||||
last=(5*data[L-1]-18*data[L-2]+24*data[L-3]-14*data[L-4]+3*data[L-5])/2,
|
||||
prelast=(3*data[L-1]-10*data[L-2]+12*data[L-3]-6*data[L-4]+data[L-5])/2
|
||||
) [
|
||||
first/h3,
|
||||
second/h3,
|
||||
for(i=[2:1:L-3]) (-data[i-2]+2*data[i-1]-2*data[i+1]+data[i+2])/2/h3,
|
||||
prelast/h3,
|
||||
last/h3
|
||||
];
|
||||
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
File diff suppressed because it is too large
Load Diff
384
mutators.scad
384
mutators.scad
@ -33,30 +33,30 @@
|
||||
// half_of([1,1], planar=true) circle(d=50);
|
||||
module half_of(v=UP, cp, s=1000, planar=false)
|
||||
{
|
||||
cp = is_vector(v,4)? assert(cp==undef, "Don't use cp with plane definition.") plane_normal(v) * v[3] :
|
||||
is_vector(cp)? cp :
|
||||
is_num(cp)? cp*unit(v) :
|
||||
[0,0,0];
|
||||
v = is_vector(v,4)? plane_normal(v) : v;
|
||||
if (cp != [0,0,0]) {
|
||||
translate(cp) half_of(v=v, s=s, planar=planar) translate(-cp) children();
|
||||
} else if (planar) {
|
||||
v = (v==UP)? BACK : (v==DOWN)? FWD : v;
|
||||
ang = atan2(v.y, v.x);
|
||||
difference() {
|
||||
children();
|
||||
rotate(ang+90) {
|
||||
back(s/2) square(s, center=true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
difference() {
|
||||
children();
|
||||
rot(from=UP, to=-v) {
|
||||
up(s/2) cube(s, center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
cp = is_vector(v,4)? assert(cp==undef, "Don't use cp with plane definition.") plane_normal(v) * v[3] :
|
||||
is_vector(cp)? cp :
|
||||
is_num(cp)? cp*unit(v) :
|
||||
[0,0,0];
|
||||
v = is_vector(v,4)? plane_normal(v) : v;
|
||||
if (cp != [0,0,0]) {
|
||||
translate(cp) half_of(v=v, s=s, planar=planar) translate(-cp) children();
|
||||
} else if (planar) {
|
||||
v = (v==UP)? BACK : (v==DOWN)? FWD : v;
|
||||
ang = atan2(v.y, v.x);
|
||||
difference() {
|
||||
children();
|
||||
rotate(ang+90) {
|
||||
back(s/2) square(s, center=true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
difference() {
|
||||
children();
|
||||
rot(from=UP, to=-v) {
|
||||
up(s/2) cube(s, center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -81,17 +81,17 @@ module half_of(v=UP, cp, s=1000, planar=false)
|
||||
// left_half(planar=true) circle(r=20);
|
||||
module left_half(s=1000, x=0, planar=false)
|
||||
{
|
||||
dir = LEFT;
|
||||
difference() {
|
||||
children();
|
||||
translate([x,0,0]-dir*s/2) {
|
||||
if (planar) {
|
||||
square(s, center=true);
|
||||
} else {
|
||||
cube(s, center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
dir = LEFT;
|
||||
difference() {
|
||||
children();
|
||||
translate([x,0,0]-dir*s/2) {
|
||||
if (planar) {
|
||||
square(s, center=true);
|
||||
} else {
|
||||
cube(s, center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -117,17 +117,17 @@ module left_half(s=1000, x=0, planar=false)
|
||||
// right_half(planar=true) circle(r=20);
|
||||
module right_half(s=1000, x=0, planar=false)
|
||||
{
|
||||
dir = RIGHT;
|
||||
difference() {
|
||||
children();
|
||||
translate([x,0,0]-dir*s/2) {
|
||||
if (planar) {
|
||||
square(s, center=true);
|
||||
} else {
|
||||
cube(s, center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
dir = RIGHT;
|
||||
difference() {
|
||||
children();
|
||||
translate([x,0,0]-dir*s/2) {
|
||||
if (planar) {
|
||||
square(s, center=true);
|
||||
} else {
|
||||
cube(s, center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -153,17 +153,17 @@ module right_half(s=1000, x=0, planar=false)
|
||||
// front_half(planar=true) circle(r=20);
|
||||
module front_half(s=1000, y=0, planar=false)
|
||||
{
|
||||
dir = FWD;
|
||||
difference() {
|
||||
children();
|
||||
translate([0,y,0]-dir*s/2) {
|
||||
if (planar) {
|
||||
square(s, center=true);
|
||||
} else {
|
||||
cube(s, center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
dir = FWD;
|
||||
difference() {
|
||||
children();
|
||||
translate([0,y,0]-dir*s/2) {
|
||||
if (planar) {
|
||||
square(s, center=true);
|
||||
} else {
|
||||
cube(s, center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -189,17 +189,17 @@ module front_half(s=1000, y=0, planar=false)
|
||||
// back_half(planar=true) circle(r=20);
|
||||
module back_half(s=1000, y=0, planar=false)
|
||||
{
|
||||
dir = BACK;
|
||||
difference() {
|
||||
children();
|
||||
translate([0,y,0]-dir*s/2) {
|
||||
if (planar) {
|
||||
square(s, center=true);
|
||||
} else {
|
||||
cube(s, center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
dir = BACK;
|
||||
difference() {
|
||||
children();
|
||||
translate([0,y,0]-dir*s/2) {
|
||||
if (planar) {
|
||||
square(s, center=true);
|
||||
} else {
|
||||
cube(s, center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -221,13 +221,13 @@ module back_half(s=1000, y=0, planar=false)
|
||||
// bottom_half(z=-10) sphere(r=20);
|
||||
module bottom_half(s=1000, z=0)
|
||||
{
|
||||
dir = DOWN;
|
||||
difference() {
|
||||
children();
|
||||
translate([0,0,z]-dir*s/2) {
|
||||
cube(s, center=true);
|
||||
}
|
||||
}
|
||||
dir = DOWN;
|
||||
difference() {
|
||||
children();
|
||||
translate([0,0,z]-dir*s/2) {
|
||||
cube(s, center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -249,13 +249,13 @@ module bottom_half(s=1000, z=0)
|
||||
// top_half(z=5) sphere(r=20);
|
||||
module top_half(s=1000, z=0)
|
||||
{
|
||||
dir = UP;
|
||||
difference() {
|
||||
children();
|
||||
translate([0,0,z]-dir*s/2) {
|
||||
cube(s, center=true);
|
||||
}
|
||||
}
|
||||
dir = UP;
|
||||
difference() {
|
||||
children();
|
||||
translate([0,0,z]-dir*s/2) {
|
||||
cube(s, center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -296,19 +296,19 @@ module top_half(s=1000, z=0)
|
||||
// }
|
||||
module chain_hull()
|
||||
{
|
||||
union() {
|
||||
if ($children == 1) {
|
||||
children();
|
||||
} else if ($children > 1) {
|
||||
for (i =[1:1:$children-1]) {
|
||||
$idx = i;
|
||||
hull() {
|
||||
let($primary=true) children(i-1);
|
||||
let($primary=false) children(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
union() {
|
||||
if ($children == 1) {
|
||||
children();
|
||||
} else if ($children > 1) {
|
||||
for (i =[1:1:$children-1]) {
|
||||
$idx = i;
|
||||
hull() {
|
||||
let($primary=true) children(i-1);
|
||||
let($primary=false) children(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -341,35 +341,35 @@ module chain_hull()
|
||||
// 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) {
|
||||
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);
|
||||
index_r = or;
|
||||
circumf = 2 * PI * index_r;
|
||||
width = min(size.x, circumf);
|
||||
assert(width <= circumf, "Shape would more than completely wrap around.");
|
||||
sides = segs(or);
|
||||
step = circumf / sides;
|
||||
steps = ceil(width / step);
|
||||
rot(from=UP, to=orient) rot(spin) {
|
||||
for (i=[0:1:steps-2]) {
|
||||
x = (i+0.5-steps/2) * step;
|
||||
zrot(360 * x / circumf) {
|
||||
fwd(or*cos(180/sides)) {
|
||||
xrot(-90) {
|
||||
linear_extrude(height=or-ir, scale=[ir/or,1], center=false, convexity=convexity) {
|
||||
yflip()
|
||||
intersection() {
|
||||
left(x) children();
|
||||
rect([quantup(step,pow(2,-15)),size.y],center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
index_r = or;
|
||||
circumf = 2 * PI * index_r;
|
||||
width = min(size.x, circumf);
|
||||
assert(width <= circumf, "Shape would more than completely wrap around.");
|
||||
sides = segs(or);
|
||||
step = circumf / sides;
|
||||
steps = ceil(width / step);
|
||||
rot(from=UP, to=orient) rot(spin) {
|
||||
for (i=[0:1:steps-2]) {
|
||||
x = (i+0.5-steps/2) * step;
|
||||
zrot(360 * x / circumf) {
|
||||
fwd(or*cos(180/sides)) {
|
||||
xrot(-90) {
|
||||
linear_extrude(height=or-ir, scale=[ir/or,1], center=false, convexity=convexity) {
|
||||
yflip()
|
||||
intersection() {
|
||||
left(x) children();
|
||||
rect([quantup(step,pow(2,-15)),size.y],center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -397,12 +397,12 @@ module cylindrical_extrude(or, ir, od, id, size=1000, convexity=10, spin=0, orie
|
||||
// ir = Radius to round only inside (concave) corners to. Use instead of `r`.
|
||||
module round3d(r, or, ir, size=100)
|
||||
{
|
||||
or = get_radius(r1=or, r=r, dflt=0);
|
||||
ir = get_radius(r1=ir, r=r, dflt=0);
|
||||
offset3d(or, size=size)
|
||||
offset3d(-ir-or, size=size)
|
||||
offset3d(ir, size=size)
|
||||
children();
|
||||
or = get_radius(r1=or, r=r, dflt=0);
|
||||
ir = get_radius(r1=ir, r=r, dflt=0);
|
||||
offset3d(or, size=size)
|
||||
offset3d(-ir-or, size=size)
|
||||
offset3d(ir, size=size)
|
||||
children();
|
||||
}
|
||||
|
||||
|
||||
@ -418,30 +418,30 @@ module round3d(r, or, ir, size=100)
|
||||
// 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) {
|
||||
n = quant(max(8,segs(abs(r))),4);
|
||||
if (r==0) {
|
||||
children();
|
||||
} else if (r>0) {
|
||||
render(convexity=convexity)
|
||||
minkowski() {
|
||||
children();
|
||||
sphere(r, $fn=n);
|
||||
}
|
||||
} else {
|
||||
size2 = size * [1,1,1];
|
||||
size1 = size2 * 1.02;
|
||||
render(convexity=convexity)
|
||||
difference() {
|
||||
cube(size2, center=true);
|
||||
minkowski() {
|
||||
difference() {
|
||||
cube(size1, center=true);
|
||||
children();
|
||||
}
|
||||
sphere(-r, $fn=n);
|
||||
}
|
||||
}
|
||||
}
|
||||
n = quant(max(8,segs(abs(r))),4);
|
||||
if (r==0) {
|
||||
children();
|
||||
} else if (r>0) {
|
||||
render(convexity=convexity)
|
||||
minkowski() {
|
||||
children();
|
||||
sphere(r, $fn=n);
|
||||
}
|
||||
} else {
|
||||
size2 = size * [1,1,1];
|
||||
size1 = size2 * 1.02;
|
||||
render(convexity=convexity)
|
||||
difference() {
|
||||
cube(size2, center=true);
|
||||
minkowski() {
|
||||
difference() {
|
||||
cube(size1, center=true);
|
||||
children();
|
||||
}
|
||||
sphere(-r, $fn=n);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -468,9 +468,9 @@ module offset3d(r=1, size=100, convexity=10) {
|
||||
// round2d(or=16,ir=8) {square([40,100], center=true); square([100,40], center=true);}
|
||||
module round2d(r, or, ir)
|
||||
{
|
||||
or = get_radius(r1=or, r=r, dflt=0);
|
||||
ir = get_radius(r1=ir, r=r, dflt=0);
|
||||
offset(or) offset(-ir-or) offset(delta=ir,chamfer=true) children();
|
||||
or = get_radius(r1=or, r=r, dflt=0);
|
||||
ir = get_radius(r1=ir, r=r, dflt=0);
|
||||
offset(or) offset(-ir-or) offset(delta=ir,chamfer=true) children();
|
||||
}
|
||||
|
||||
|
||||
@ -496,19 +496,19 @@ module round2d(r, or, ir)
|
||||
// shell2d(8,or=16,ir=8,round=16,fill=8) {square([40,100], center=true); square([100,40], center=true);}
|
||||
module shell2d(thickness, or=0, ir=0, fill=0, round=0)
|
||||
{
|
||||
thickness = is_num(thickness)? (
|
||||
thickness<0? [thickness,0] : [0,thickness]
|
||||
) : (thickness[0]>thickness[1])? (
|
||||
[thickness[1],thickness[0]]
|
||||
) : thickness;
|
||||
difference() {
|
||||
round2d(or=or,ir=ir)
|
||||
offset(delta=thickness[1])
|
||||
children();
|
||||
round2d(or=fill,ir=round)
|
||||
offset(delta=thickness[0])
|
||||
children();
|
||||
}
|
||||
thickness = is_num(thickness)? (
|
||||
thickness<0? [thickness,0] : [0,thickness]
|
||||
) : (thickness[0]>thickness[1])? (
|
||||
[thickness[1],thickness[0]]
|
||||
) : thickness;
|
||||
difference() {
|
||||
round2d(or=or,ir=ir)
|
||||
offset(delta=thickness[1])
|
||||
children();
|
||||
round2d(or=fill,ir=round)
|
||||
offset(delta=thickness[0])
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -534,13 +534,13 @@ module shell2d(thickness, or=0, ir=0, fill=0, round=0)
|
||||
// rgb = HSL(h=270,s=0.75,l=0.6);
|
||||
// color(rgb) cube(60, center=true);
|
||||
function HSL(h,s=1,l=0.5) =
|
||||
let(
|
||||
h=posmod(h,360)
|
||||
) [
|
||||
for (n=[0,8,4]) let(
|
||||
k=(n+h/30)%12
|
||||
) l - s*min(l,1-l)*max(min(k-3,9-k,1),-1)
|
||||
];
|
||||
let(
|
||||
h=posmod(h,360)
|
||||
) [
|
||||
for (n=[0,8,4]) let(
|
||||
k=(n+h/30)%12
|
||||
) l - s*min(l,1-l)*max(min(k-3,9-k,1),-1)
|
||||
];
|
||||
|
||||
module HSL(h,s=1,l=0.5,a=1) color(HSL(h,s,l),a) children();
|
||||
|
||||
@ -563,13 +563,13 @@ module HSL(h,s=1,l=0.5,a=1) color(HSL(h,s,l),a) children();
|
||||
// rgb = HSV(h=270,s=0.75,v=0.9);
|
||||
// color(rgb) cube(60, center=true);
|
||||
function HSV(h,s=1,v=1) =
|
||||
let(
|
||||
h=posmod(h,360),
|
||||
v2=v*(1-s),
|
||||
r=lookup(h,[[0,v], [60,v], [120,v2], [240,v2], [300,v], [360,v]]),
|
||||
g=lookup(h,[[0,v2], [60,v], [180,v], [240,v2], [360,v2]]),
|
||||
b=lookup(h,[[0,v2], [120,v2], [180,v], [300,v], [360,v2]])
|
||||
) [r,g,b];
|
||||
let(
|
||||
h=posmod(h,360),
|
||||
v2=v*(1-s),
|
||||
r=lookup(h,[[0,v], [60,v], [120,v2], [240,v2], [300,v], [360,v]]),
|
||||
g=lookup(h,[[0,v2], [60,v], [180,v], [240,v2], [360,v2]]),
|
||||
b=lookup(h,[[0,v2], [120,v2], [180,v], [300,v], [360,v2]])
|
||||
) [r,g,b];
|
||||
|
||||
module HSV(h,s=1,v=1,a=1) color(HSV(h,s,v),a) children();
|
||||
|
||||
@ -594,14 +594,14 @@ module HSV(h,s=1,v=1,a=1) color(HSV(h,s,v),a) children();
|
||||
// rainbow(rgn) stroke($item, closed=true);
|
||||
module rainbow(list, stride=1)
|
||||
{
|
||||
ll = len(list);
|
||||
huestep = 360 / ll;
|
||||
hues = [for (i=[0:1:ll-1]) posmod(i*huestep+i*360/stride,360)];
|
||||
for($idx=idx(list)) {
|
||||
$item = list[$idx];
|
||||
HSV(h=hues[$idx]) children();
|
||||
}
|
||||
ll = len(list);
|
||||
huestep = 360 / ll;
|
||||
hues = [for (i=[0:1:ll-1]) posmod(i*huestep+i*360/stride,360)];
|
||||
for($idx=idx(list)) {
|
||||
$item = list[$idx];
|
||||
HSV(h=hues[$idx]) children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -17,12 +17,12 @@
|
||||
// Arguments:
|
||||
// size = The standard NEMA motor size.
|
||||
function nema_motor_width(size) = lookup(size, [
|
||||
[11.0, 28.2],
|
||||
[14.0, 35.2],
|
||||
[17.0, 42.3],
|
||||
[23.0, 57.0],
|
||||
[34.0, 86.0],
|
||||
]);
|
||||
[11.0, 28.2],
|
||||
[14.0, 35.2],
|
||||
[17.0, 42.3],
|
||||
[23.0, 57.0],
|
||||
[34.0, 86.0],
|
||||
]);
|
||||
|
||||
|
||||
// Function: nema_motor_plinth_height()
|
||||
@ -30,12 +30,12 @@ function nema_motor_width(size) = lookup(size, [
|
||||
// Arguments:
|
||||
// size = The standard NEMA motor size.
|
||||
function nema_motor_plinth_height(size) = lookup(size, [
|
||||
[11.0, 1.5],
|
||||
[14.0, 2.0],
|
||||
[17.0, 2.0],
|
||||
[23.0, 1.6],
|
||||
[34.0, 2.03],
|
||||
]);
|
||||
[11.0, 1.5],
|
||||
[14.0, 2.0],
|
||||
[17.0, 2.0],
|
||||
[23.0, 1.6],
|
||||
[34.0, 2.03],
|
||||
]);
|
||||
|
||||
|
||||
// Function: nema_motor_plinth_diam()
|
||||
@ -43,12 +43,12 @@ function nema_motor_plinth_height(size) = lookup(size, [
|
||||
// Arguments:
|
||||
// size = The standard NEMA motor size.
|
||||
function nema_motor_plinth_diam(size) = lookup(size, [
|
||||
[11.0, 22.0],
|
||||
[14.0, 22.0],
|
||||
[17.0, 22.0],
|
||||
[23.0, 38.1],
|
||||
[34.0, 73.0],
|
||||
]);
|
||||
[11.0, 22.0],
|
||||
[14.0, 22.0],
|
||||
[17.0, 22.0],
|
||||
[23.0, 38.1],
|
||||
[34.0, 73.0],
|
||||
]);
|
||||
|
||||
|
||||
// Function: nema_motor_screw_spacing()
|
||||
@ -56,12 +56,12 @@ function nema_motor_plinth_diam(size) = lookup(size, [
|
||||
// Arguments:
|
||||
// size = The standard NEMA motor size.
|
||||
function nema_motor_screw_spacing(size) = lookup(size, [
|
||||
[11.0, 23.11],
|
||||
[14.0, 26.0],
|
||||
[17.0, 30.99],
|
||||
[23.0, 47.14],
|
||||
[34.0, 69.6],
|
||||
]);
|
||||
[11.0, 23.11],
|
||||
[14.0, 26.0],
|
||||
[17.0, 30.99],
|
||||
[23.0, 47.14],
|
||||
[34.0, 69.6],
|
||||
]);
|
||||
|
||||
|
||||
// Function: nema_motor_screw_size()
|
||||
@ -69,12 +69,12 @@ function nema_motor_screw_spacing(size) = lookup(size, [
|
||||
// Arguments:
|
||||
// size = The standard NEMA motor size.
|
||||
function nema_motor_screw_size(size) = lookup(size, [
|
||||
[11.0, 2.6],
|
||||
[14.0, 3.0],
|
||||
[17.0, 3.0],
|
||||
[23.0, 5.1],
|
||||
[34.0, 5.5],
|
||||
]);
|
||||
[11.0, 2.6],
|
||||
[14.0, 3.0],
|
||||
[17.0, 3.0],
|
||||
[23.0, 5.1],
|
||||
[34.0, 5.5],
|
||||
]);
|
||||
|
||||
|
||||
// Function: nema_motor_screw_depth()
|
||||
@ -82,12 +82,12 @@ function nema_motor_screw_size(size) = lookup(size, [
|
||||
// Arguments:
|
||||
// size = The standard NEMA motor size.
|
||||
function nema_motor_screw_depth(size) = lookup(size, [
|
||||
[11.0, 3.0],
|
||||
[14.0, 4.5],
|
||||
[17.0, 4.5],
|
||||
[23.0, 4.8],
|
||||
[34.0, 9.0],
|
||||
]);
|
||||
[11.0, 3.0],
|
||||
[14.0, 4.5],
|
||||
[17.0, 4.5],
|
||||
[23.0, 4.8],
|
||||
[34.0, 9.0],
|
||||
]);
|
||||
|
||||
|
||||
// Section: Motor Models
|
||||
@ -115,45 +115,45 @@ function nema_motor_screw_depth(size) = lookup(size, [
|
||||
// nema11_stepper();
|
||||
module nema11_stepper(h=24, shaft=5, shaft_len=20, anchor=TOP, spin=0, orient=UP)
|
||||
{
|
||||
size = 11;
|
||||
motor_width = nema_motor_width(size);
|
||||
plinth_height = nema_motor_plinth_height(size);
|
||||
plinth_diam = nema_motor_plinth_diam(size);
|
||||
screw_spacing = nema_motor_screw_spacing(size);
|
||||
screw_size = nema_motor_screw_size(size);
|
||||
screw_depth = nema_motor_screw_depth(size);
|
||||
size = 11;
|
||||
motor_width = nema_motor_width(size);
|
||||
plinth_height = nema_motor_plinth_height(size);
|
||||
plinth_diam = nema_motor_plinth_diam(size);
|
||||
screw_spacing = nema_motor_screw_spacing(size);
|
||||
screw_size = nema_motor_screw_size(size);
|
||||
screw_depth = nema_motor_screw_depth(size);
|
||||
|
||||
anchors = [
|
||||
anchorpt("shaft-top", [0,0,h/2+shaft_len]),
|
||||
anchorpt("shaft-middle", [0,0,h/2+plinth_height+(shaft_len-plinth_height)/2]),
|
||||
anchorpt("shaft-bottom", [0,0,h/2+plinth_height+0.1]),
|
||||
anchorpt("plinth-top", [0,0,h/2+plinth_height]),
|
||||
anchorpt("screw1", [+screw_spacing/2, +screw_spacing/2, h/2]),
|
||||
anchorpt("screw2", [-screw_spacing/2, +screw_spacing/2, h/2]),
|
||||
anchorpt("screw3", [-screw_spacing/2, -screw_spacing/2, h/2]),
|
||||
anchorpt("screw4", [+screw_spacing/2, -screw_spacing/2, h/2]),
|
||||
];
|
||||
attachable(anchor,spin,orient, size=[motor_width, motor_width, h], anchors=anchors) {
|
||||
up(h/2)
|
||||
union() {
|
||||
difference() {
|
||||
color([0.4, 0.4, 0.4])
|
||||
cuboid(size=[motor_width, motor_width, h], chamfer=2, edges=edges("Z"), anchor=TOP);
|
||||
color("silver")
|
||||
xcopies(screw_spacing)
|
||||
ycopies(screw_spacing)
|
||||
cyl(r=screw_size/2, h=screw_depth*2, $fn=max(12,segs(screw_size/2)));
|
||||
}
|
||||
color([0.6, 0.6, 0.6]) {
|
||||
difference() {
|
||||
cylinder(h=plinth_height, d=plinth_diam);
|
||||
cyl(h=plinth_height*3, d=shaft+0.75);
|
||||
}
|
||||
}
|
||||
color("silver") cylinder(h=shaft_len, d=shaft, $fn=max(12,segs(shaft/2)));
|
||||
}
|
||||
children();
|
||||
}
|
||||
anchors = [
|
||||
anchorpt("shaft-top", [0,0,h/2+shaft_len]),
|
||||
anchorpt("shaft-middle", [0,0,h/2+plinth_height+(shaft_len-plinth_height)/2]),
|
||||
anchorpt("shaft-bottom", [0,0,h/2+plinth_height+0.1]),
|
||||
anchorpt("plinth-top", [0,0,h/2+plinth_height]),
|
||||
anchorpt("screw1", [+screw_spacing/2, +screw_spacing/2, h/2]),
|
||||
anchorpt("screw2", [-screw_spacing/2, +screw_spacing/2, h/2]),
|
||||
anchorpt("screw3", [-screw_spacing/2, -screw_spacing/2, h/2]),
|
||||
anchorpt("screw4", [+screw_spacing/2, -screw_spacing/2, h/2]),
|
||||
];
|
||||
attachable(anchor,spin,orient, size=[motor_width, motor_width, h], anchors=anchors) {
|
||||
up(h/2)
|
||||
union() {
|
||||
difference() {
|
||||
color([0.4, 0.4, 0.4])
|
||||
cuboid(size=[motor_width, motor_width, h], chamfer=2, edges=edges("Z"), anchor=TOP);
|
||||
color("silver")
|
||||
xcopies(screw_spacing)
|
||||
ycopies(screw_spacing)
|
||||
cyl(r=screw_size/2, h=screw_depth*2, $fn=max(12,segs(screw_size/2)));
|
||||
}
|
||||
color([0.6, 0.6, 0.6]) {
|
||||
difference() {
|
||||
cylinder(h=plinth_height, d=plinth_diam);
|
||||
cyl(h=plinth_height*3, d=shaft+0.75);
|
||||
}
|
||||
}
|
||||
color("silver") cylinder(h=shaft_len, d=shaft, $fn=max(12,segs(shaft/2)));
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -180,45 +180,45 @@ module nema11_stepper(h=24, shaft=5, shaft_len=20, anchor=TOP, spin=0, orient=UP
|
||||
// nema14_stepper();
|
||||
module nema14_stepper(h=24, shaft=5, shaft_len=24, anchor=TOP, spin=0, orient=UP)
|
||||
{
|
||||
size = 14;
|
||||
motor_width = nema_motor_width(size);
|
||||
plinth_height = nema_motor_plinth_height(size);
|
||||
plinth_diam = nema_motor_plinth_diam(size);
|
||||
screw_spacing = nema_motor_screw_spacing(size);
|
||||
screw_size = nema_motor_screw_size(size);
|
||||
screw_depth = nema_motor_screw_depth(size);
|
||||
size = 14;
|
||||
motor_width = nema_motor_width(size);
|
||||
plinth_height = nema_motor_plinth_height(size);
|
||||
plinth_diam = nema_motor_plinth_diam(size);
|
||||
screw_spacing = nema_motor_screw_spacing(size);
|
||||
screw_size = nema_motor_screw_size(size);
|
||||
screw_depth = nema_motor_screw_depth(size);
|
||||
|
||||
anchors = [
|
||||
anchorpt("shaft-top", [0,0,h/2+shaft_len]),
|
||||
anchorpt("shaft-middle", [0,0,h/2+plinth_height+(shaft_len-plinth_height)/2]),
|
||||
anchorpt("shaft-bottom", [0,0,h/2+plinth_height+0.1]),
|
||||
anchorpt("plinth-top", [0,0,h/2+plinth_height]),
|
||||
anchorpt("screw1", [+screw_spacing/2, +screw_spacing/2, h/2]),
|
||||
anchorpt("screw2", [-screw_spacing/2, +screw_spacing/2, h/2]),
|
||||
anchorpt("screw3", [-screw_spacing/2, -screw_spacing/2, h/2]),
|
||||
anchorpt("screw4", [+screw_spacing/2, -screw_spacing/2, h/2]),
|
||||
];
|
||||
attachable(anchor,spin,orient, size=[motor_width, motor_width, h], anchors=anchors) {
|
||||
up(h/2)
|
||||
union() {
|
||||
difference() {
|
||||
color([0.4, 0.4, 0.4])
|
||||
cuboid(size=[motor_width, motor_width, h], chamfer=2, edges=edges("Z"), anchor=TOP);
|
||||
color("silver")
|
||||
xcopies(screw_spacing)
|
||||
ycopies(screw_spacing)
|
||||
cyl(d=screw_size, h=screw_depth*2, $fn=max(12,segs(screw_size/2)));
|
||||
}
|
||||
color([0.6, 0.6, 0.6]) {
|
||||
difference() {
|
||||
cylinder(h=plinth_height, d=plinth_diam);
|
||||
cyl(h=plinth_height*3, d=shaft+0.75);
|
||||
}
|
||||
}
|
||||
color("silver") cylinder(h=shaft_len, d=shaft, $fn=max(12,segs(shaft/2)));
|
||||
}
|
||||
children();
|
||||
}
|
||||
anchors = [
|
||||
anchorpt("shaft-top", [0,0,h/2+shaft_len]),
|
||||
anchorpt("shaft-middle", [0,0,h/2+plinth_height+(shaft_len-plinth_height)/2]),
|
||||
anchorpt("shaft-bottom", [0,0,h/2+plinth_height+0.1]),
|
||||
anchorpt("plinth-top", [0,0,h/2+plinth_height]),
|
||||
anchorpt("screw1", [+screw_spacing/2, +screw_spacing/2, h/2]),
|
||||
anchorpt("screw2", [-screw_spacing/2, +screw_spacing/2, h/2]),
|
||||
anchorpt("screw3", [-screw_spacing/2, -screw_spacing/2, h/2]),
|
||||
anchorpt("screw4", [+screw_spacing/2, -screw_spacing/2, h/2]),
|
||||
];
|
||||
attachable(anchor,spin,orient, size=[motor_width, motor_width, h], anchors=anchors) {
|
||||
up(h/2)
|
||||
union() {
|
||||
difference() {
|
||||
color([0.4, 0.4, 0.4])
|
||||
cuboid(size=[motor_width, motor_width, h], chamfer=2, edges=edges("Z"), anchor=TOP);
|
||||
color("silver")
|
||||
xcopies(screw_spacing)
|
||||
ycopies(screw_spacing)
|
||||
cyl(d=screw_size, h=screw_depth*2, $fn=max(12,segs(screw_size/2)));
|
||||
}
|
||||
color([0.6, 0.6, 0.6]) {
|
||||
difference() {
|
||||
cylinder(h=plinth_height, d=plinth_diam);
|
||||
cyl(h=plinth_height*3, d=shaft+0.75);
|
||||
}
|
||||
}
|
||||
color("silver") cylinder(h=shaft_len, d=shaft, $fn=max(12,segs(shaft/2)));
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -245,64 +245,64 @@ module nema14_stepper(h=24, shaft=5, shaft_len=24, anchor=TOP, spin=0, orient=UP
|
||||
// nema17_stepper();
|
||||
module nema17_stepper(h=34, shaft=5, shaft_len=20, anchor=TOP, spin=0, orient=UP)
|
||||
{
|
||||
size = 17;
|
||||
motor_width = nema_motor_width(size);
|
||||
plinth_height = nema_motor_plinth_height(size);
|
||||
plinth_diam = nema_motor_plinth_diam(size);
|
||||
screw_spacing = nema_motor_screw_spacing(size);
|
||||
screw_size = nema_motor_screw_size(size);
|
||||
screw_depth = nema_motor_screw_depth(size);
|
||||
size = 17;
|
||||
motor_width = nema_motor_width(size);
|
||||
plinth_height = nema_motor_plinth_height(size);
|
||||
plinth_diam = nema_motor_plinth_diam(size);
|
||||
screw_spacing = nema_motor_screw_spacing(size);
|
||||
screw_size = nema_motor_screw_size(size);
|
||||
screw_depth = nema_motor_screw_depth(size);
|
||||
|
||||
anchors = [
|
||||
anchorpt("shaft-top", [0,0,h/2+shaft_len]),
|
||||
anchorpt("shaft-middle", [0,0,h/2+plinth_height+(shaft_len-plinth_height)/2]),
|
||||
anchorpt("shaft-bottom", [0,0,h/2+plinth_height+0.1]),
|
||||
anchorpt("plinth-top", [0,0,h/2+plinth_height]),
|
||||
anchorpt("screw1", [+screw_spacing/2, +screw_spacing/2, h/2]),
|
||||
anchorpt("screw2", [-screw_spacing/2, +screw_spacing/2, h/2]),
|
||||
anchorpt("screw3", [-screw_spacing/2, -screw_spacing/2, h/2]),
|
||||
anchorpt("screw4", [+screw_spacing/2, -screw_spacing/2, h/2]),
|
||||
];
|
||||
attachable(anchor,spin,orient, size=[motor_width, motor_width, h], anchors=anchors) {
|
||||
up(h/2)
|
||||
union() {
|
||||
difference() {
|
||||
color([0.4, 0.4, 0.4])
|
||||
cuboid([motor_width, motor_width, h], chamfer=2, edges=edges("Z"), anchor=TOP);
|
||||
color("silver")
|
||||
xcopies(screw_spacing)
|
||||
ycopies(screw_spacing)
|
||||
cyl(d=screw_size, h=screw_depth*2, $fn=max(12,segs(screw_size/2)));
|
||||
}
|
||||
color([0.6, 0.6, 0.6]) {
|
||||
difference() {
|
||||
cylinder(h=plinth_height, d=plinth_diam);
|
||||
cyl(h=plinth_height*3, d=shaft+0.75);
|
||||
}
|
||||
}
|
||||
color([0.9, 0.9, 0.9]) {
|
||||
down(h-motor_width/12) {
|
||||
fwd(motor_width/2+motor_width/24/2-0.1) {
|
||||
difference() {
|
||||
cube(size=[motor_width/8, motor_width/24, motor_width/8], center=true);
|
||||
cyl(d=motor_width/8-2, h=motor_width/6, orient=BACK, $fn=12);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
color("silver") {
|
||||
difference() {
|
||||
cylinder(h=shaft_len, d=shaft, $fn=max(12,segs(shaft/2)));
|
||||
up(shaft_len/2+1) {
|
||||
right(shaft-0.75) {
|
||||
cube([shaft, shaft, shaft_len], center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
anchors = [
|
||||
anchorpt("shaft-top", [0,0,h/2+shaft_len]),
|
||||
anchorpt("shaft-middle", [0,0,h/2+plinth_height+(shaft_len-plinth_height)/2]),
|
||||
anchorpt("shaft-bottom", [0,0,h/2+plinth_height+0.1]),
|
||||
anchorpt("plinth-top", [0,0,h/2+plinth_height]),
|
||||
anchorpt("screw1", [+screw_spacing/2, +screw_spacing/2, h/2]),
|
||||
anchorpt("screw2", [-screw_spacing/2, +screw_spacing/2, h/2]),
|
||||
anchorpt("screw3", [-screw_spacing/2, -screw_spacing/2, h/2]),
|
||||
anchorpt("screw4", [+screw_spacing/2, -screw_spacing/2, h/2]),
|
||||
];
|
||||
attachable(anchor,spin,orient, size=[motor_width, motor_width, h], anchors=anchors) {
|
||||
up(h/2)
|
||||
union() {
|
||||
difference() {
|
||||
color([0.4, 0.4, 0.4])
|
||||
cuboid([motor_width, motor_width, h], chamfer=2, edges=edges("Z"), anchor=TOP);
|
||||
color("silver")
|
||||
xcopies(screw_spacing)
|
||||
ycopies(screw_spacing)
|
||||
cyl(d=screw_size, h=screw_depth*2, $fn=max(12,segs(screw_size/2)));
|
||||
}
|
||||
color([0.6, 0.6, 0.6]) {
|
||||
difference() {
|
||||
cylinder(h=plinth_height, d=plinth_diam);
|
||||
cyl(h=plinth_height*3, d=shaft+0.75);
|
||||
}
|
||||
}
|
||||
color([0.9, 0.9, 0.9]) {
|
||||
down(h-motor_width/12) {
|
||||
fwd(motor_width/2+motor_width/24/2-0.1) {
|
||||
difference() {
|
||||
cube(size=[motor_width/8, motor_width/24, motor_width/8], center=true);
|
||||
cyl(d=motor_width/8-2, h=motor_width/6, orient=BACK, $fn=12);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
color("silver") {
|
||||
difference() {
|
||||
cylinder(h=shaft_len, d=shaft, $fn=max(12,segs(shaft/2)));
|
||||
up(shaft_len/2+1) {
|
||||
right(shaft-0.75) {
|
||||
cube([shaft, shaft, shaft_len], center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -329,47 +329,47 @@ module nema17_stepper(h=34, shaft=5, shaft_len=20, anchor=TOP, spin=0, orient=UP
|
||||
// nema23_stepper();
|
||||
module nema23_stepper(h=50, shaft=6.35, shaft_len=25, anchor=TOP, spin=0, orient=UP)
|
||||
{
|
||||
size = 23;
|
||||
motor_width = nema_motor_width(size);
|
||||
plinth_height = nema_motor_plinth_height(size);
|
||||
plinth_diam = nema_motor_plinth_diam(size);
|
||||
screw_spacing = nema_motor_screw_spacing(size);
|
||||
screw_size = nema_motor_screw_size(size);
|
||||
screw_depth = nema_motor_screw_depth(size);
|
||||
size = 23;
|
||||
motor_width = nema_motor_width(size);
|
||||
plinth_height = nema_motor_plinth_height(size);
|
||||
plinth_diam = nema_motor_plinth_diam(size);
|
||||
screw_spacing = nema_motor_screw_spacing(size);
|
||||
screw_size = nema_motor_screw_size(size);
|
||||
screw_depth = nema_motor_screw_depth(size);
|
||||
|
||||
screw_inset = motor_width - screw_spacing + 1;
|
||||
anchors = [
|
||||
anchorpt("shaft-top", [0,0,h/2+shaft_len]),
|
||||
anchorpt("shaft-middle", [0,0,h/2+plinth_height+(shaft_len-plinth_height)/2]),
|
||||
anchorpt("shaft-bottom", [0,0,h/2+plinth_height+0.1]),
|
||||
anchorpt("plinth-top", [0,0,h/2+plinth_height]),
|
||||
anchorpt("screw1", [+screw_spacing/2, +screw_spacing/2, h/2]),
|
||||
anchorpt("screw2", [-screw_spacing/2, +screw_spacing/2, h/2]),
|
||||
anchorpt("screw3", [-screw_spacing/2, -screw_spacing/2, h/2]),
|
||||
anchorpt("screw4", [+screw_spacing/2, -screw_spacing/2, h/2]),
|
||||
];
|
||||
attachable(anchor,spin,orient, size=[motor_width, motor_width, h], anchors=anchors) {
|
||||
up(h/2)
|
||||
difference() {
|
||||
union() {
|
||||
color([0.4, 0.4, 0.4])
|
||||
cuboid([motor_width, motor_width, h], chamfer=2, edges=edges("Z"), anchor=TOP);
|
||||
color([0.4, 0.4, 0.4])
|
||||
cylinder(h=plinth_height, d=plinth_diam);
|
||||
color("silver")
|
||||
cylinder(h=shaft_len, d=shaft, $fn=max(12,segs(shaft/2)));
|
||||
}
|
||||
color([0.4, 0.4, 0.4]) {
|
||||
xcopies(screw_spacing) {
|
||||
ycopies(screw_spacing) {
|
||||
cyl(d=screw_size, h=screw_depth*3, $fn=max(12,segs(screw_size/2)));
|
||||
down(screw_depth) cuboid([screw_inset, screw_inset, h], anchor=TOP);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
screw_inset = motor_width - screw_spacing + 1;
|
||||
anchors = [
|
||||
anchorpt("shaft-top", [0,0,h/2+shaft_len]),
|
||||
anchorpt("shaft-middle", [0,0,h/2+plinth_height+(shaft_len-plinth_height)/2]),
|
||||
anchorpt("shaft-bottom", [0,0,h/2+plinth_height+0.1]),
|
||||
anchorpt("plinth-top", [0,0,h/2+plinth_height]),
|
||||
anchorpt("screw1", [+screw_spacing/2, +screw_spacing/2, h/2]),
|
||||
anchorpt("screw2", [-screw_spacing/2, +screw_spacing/2, h/2]),
|
||||
anchorpt("screw3", [-screw_spacing/2, -screw_spacing/2, h/2]),
|
||||
anchorpt("screw4", [+screw_spacing/2, -screw_spacing/2, h/2]),
|
||||
];
|
||||
attachable(anchor,spin,orient, size=[motor_width, motor_width, h], anchors=anchors) {
|
||||
up(h/2)
|
||||
difference() {
|
||||
union() {
|
||||
color([0.4, 0.4, 0.4])
|
||||
cuboid([motor_width, motor_width, h], chamfer=2, edges=edges("Z"), anchor=TOP);
|
||||
color([0.4, 0.4, 0.4])
|
||||
cylinder(h=plinth_height, d=plinth_diam);
|
||||
color("silver")
|
||||
cylinder(h=shaft_len, d=shaft, $fn=max(12,segs(shaft/2)));
|
||||
}
|
||||
color([0.4, 0.4, 0.4]) {
|
||||
xcopies(screw_spacing) {
|
||||
ycopies(screw_spacing) {
|
||||
cyl(d=screw_size, h=screw_depth*3, $fn=max(12,segs(screw_size/2)));
|
||||
down(screw_depth) cuboid([screw_inset, screw_inset, h], anchor=TOP);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -396,47 +396,47 @@ module nema23_stepper(h=50, shaft=6.35, shaft_len=25, anchor=TOP, spin=0, orient
|
||||
// nema34_stepper();
|
||||
module nema34_stepper(h=75, shaft=12.7, shaft_len=32, anchor=TOP, spin=0, orient=UP)
|
||||
{
|
||||
size = 34;
|
||||
motor_width = nema_motor_width(size);
|
||||
plinth_height = nema_motor_plinth_height(size);
|
||||
plinth_diam = nema_motor_plinth_diam(size);
|
||||
screw_spacing = nema_motor_screw_spacing(size);
|
||||
screw_size = nema_motor_screw_size(size);
|
||||
screw_depth = nema_motor_screw_depth(size);
|
||||
size = 34;
|
||||
motor_width = nema_motor_width(size);
|
||||
plinth_height = nema_motor_plinth_height(size);
|
||||
plinth_diam = nema_motor_plinth_diam(size);
|
||||
screw_spacing = nema_motor_screw_spacing(size);
|
||||
screw_size = nema_motor_screw_size(size);
|
||||
screw_depth = nema_motor_screw_depth(size);
|
||||
|
||||
screw_inset = motor_width - screw_spacing + 1;
|
||||
anchors = [
|
||||
anchorpt("shaft-top", [0,0,h/2+shaft_len]),
|
||||
anchorpt("shaft-middle", [0,0,h/2+plinth_height+(shaft_len-plinth_height)/2]),
|
||||
anchorpt("shaft-bottom", [0,0,h/2+plinth_height+0.1]),
|
||||
anchorpt("plinth-top", [0,0,h/2+plinth_height]),
|
||||
anchorpt("screw1", [+screw_spacing/2, +screw_spacing/2, h/2]),
|
||||
anchorpt("screw2", [-screw_spacing/2, +screw_spacing/2, h/2]),
|
||||
anchorpt("screw3", [-screw_spacing/2, -screw_spacing/2, h/2]),
|
||||
anchorpt("screw4", [+screw_spacing/2, -screw_spacing/2, h/2]),
|
||||
];
|
||||
attachable(anchor,spin,orient, size=[motor_width, motor_width, h], anchors=anchors) {
|
||||
up(h/2)
|
||||
difference() {
|
||||
union() {
|
||||
color([0.4, 0.4, 0.4])
|
||||
cuboid(size=[motor_width, motor_width, h], chamfer=2, edges=edges("Z"), anchor=TOP);
|
||||
color([0.4, 0.4, 0.4])
|
||||
cylinder(h=plinth_height, d=plinth_diam);
|
||||
color("silver")
|
||||
cylinder(h=shaft_len, d=shaft, $fn=max(24,segs(shaft/2)));
|
||||
}
|
||||
color([0.4, 0.4, 0.4]) {
|
||||
xcopies(screw_spacing) {
|
||||
ycopies(screw_spacing) {
|
||||
cylinder(d=screw_size, h=screw_depth*3, center=true, $fn=max(12,segs(screw_size/2)));
|
||||
down(screw_depth) cube([screw_inset, screw_inset, h], anchor=TOP);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
screw_inset = motor_width - screw_spacing + 1;
|
||||
anchors = [
|
||||
anchorpt("shaft-top", [0,0,h/2+shaft_len]),
|
||||
anchorpt("shaft-middle", [0,0,h/2+plinth_height+(shaft_len-plinth_height)/2]),
|
||||
anchorpt("shaft-bottom", [0,0,h/2+plinth_height+0.1]),
|
||||
anchorpt("plinth-top", [0,0,h/2+plinth_height]),
|
||||
anchorpt("screw1", [+screw_spacing/2, +screw_spacing/2, h/2]),
|
||||
anchorpt("screw2", [-screw_spacing/2, +screw_spacing/2, h/2]),
|
||||
anchorpt("screw3", [-screw_spacing/2, -screw_spacing/2, h/2]),
|
||||
anchorpt("screw4", [+screw_spacing/2, -screw_spacing/2, h/2]),
|
||||
];
|
||||
attachable(anchor,spin,orient, size=[motor_width, motor_width, h], anchors=anchors) {
|
||||
up(h/2)
|
||||
difference() {
|
||||
union() {
|
||||
color([0.4, 0.4, 0.4])
|
||||
cuboid(size=[motor_width, motor_width, h], chamfer=2, edges=edges("Z"), anchor=TOP);
|
||||
color([0.4, 0.4, 0.4])
|
||||
cylinder(h=plinth_height, d=plinth_diam);
|
||||
color("silver")
|
||||
cylinder(h=shaft_len, d=shaft, $fn=max(24,segs(shaft/2)));
|
||||
}
|
||||
color([0.4, 0.4, 0.4]) {
|
||||
xcopies(screw_spacing) {
|
||||
ycopies(screw_spacing) {
|
||||
cylinder(d=screw_size, h=screw_depth*3, center=true, $fn=max(12,segs(screw_size/2)));
|
||||
down(screw_depth) cube([screw_inset, screw_inset, h], anchor=TOP);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -468,45 +468,45 @@ module nema34_stepper(h=75, shaft=12.7, shaft_len=32, anchor=TOP, spin=0, orient
|
||||
// nema_mount_holes(size=17, depth=5, l=0);
|
||||
module nema_mount_holes(size=17, depth=5, l=5, anchor=CENTER, spin=0, orient=UP)
|
||||
{
|
||||
motor_width = nema_motor_width(size);
|
||||
plinth_diam = nema_motor_plinth_diam(size)+$slop;
|
||||
screw_spacing = nema_motor_screw_spacing(size);
|
||||
screw_size = nema_motor_screw_size(size)+$slop;
|
||||
motor_width = nema_motor_width(size);
|
||||
plinth_diam = nema_motor_plinth_diam(size)+$slop;
|
||||
screw_spacing = nema_motor_screw_spacing(size);
|
||||
screw_size = nema_motor_screw_size(size)+$slop;
|
||||
|
||||
anchors = [
|
||||
anchorpt("screw1", [+screw_spacing/2, +screw_spacing/2, depth/2]),
|
||||
anchorpt("screw2", [-screw_spacing/2, +screw_spacing/2, depth/2]),
|
||||
anchorpt("screw3", [-screw_spacing/2, -screw_spacing/2, depth/2]),
|
||||
anchorpt("screw4", [+screw_spacing/2, -screw_spacing/2, depth/2]),
|
||||
];
|
||||
screwfn = quantup(max(8,segs(screw_size/2)),4);
|
||||
plinthfn = quantup(max(8,segs(plinth_diam/2)),4);
|
||||
s = [screw_spacing+screw_size, screw_spacing+screw_size+l, depth];
|
||||
attachable(anchor,spin,orient, size=s, anchors=anchors) {
|
||||
union() {
|
||||
xcopies(screw_spacing) {
|
||||
ycopies(screw_spacing) {
|
||||
if (l>0) {
|
||||
union() {
|
||||
ycopies(l) cyl(h=depth, d=screw_size, $fn=screwfn);
|
||||
cube([screw_size, l, depth], center=true);
|
||||
}
|
||||
} else {
|
||||
cyl(h=depth, d=screw_size, $fn=screwfn);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (l>0) {
|
||||
union () {
|
||||
ycopies(l) cyl(h=depth, d=plinth_diam, $fn=plinthfn);
|
||||
cube([plinth_diam, l, depth], center=true);
|
||||
}
|
||||
} else {
|
||||
cyl(h=depth, d=plinth_diam, $fn=plinthfn);
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
anchors = [
|
||||
anchorpt("screw1", [+screw_spacing/2, +screw_spacing/2, depth/2]),
|
||||
anchorpt("screw2", [-screw_spacing/2, +screw_spacing/2, depth/2]),
|
||||
anchorpt("screw3", [-screw_spacing/2, -screw_spacing/2, depth/2]),
|
||||
anchorpt("screw4", [+screw_spacing/2, -screw_spacing/2, depth/2]),
|
||||
];
|
||||
screwfn = quantup(max(8,segs(screw_size/2)),4);
|
||||
plinthfn = quantup(max(8,segs(plinth_diam/2)),4);
|
||||
s = [screw_spacing+screw_size, screw_spacing+screw_size+l, depth];
|
||||
attachable(anchor,spin,orient, size=s, anchors=anchors) {
|
||||
union() {
|
||||
xcopies(screw_spacing) {
|
||||
ycopies(screw_spacing) {
|
||||
if (l>0) {
|
||||
union() {
|
||||
ycopies(l) cyl(h=depth, d=screw_size, $fn=screwfn);
|
||||
cube([screw_size, l, depth], center=true);
|
||||
}
|
||||
} else {
|
||||
cyl(h=depth, d=screw_size, $fn=screwfn);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (l>0) {
|
||||
union () {
|
||||
ycopies(l) cyl(h=depth, d=plinth_diam, $fn=plinthfn);
|
||||
cube([plinth_diam, l, depth], center=true);
|
||||
}
|
||||
} else {
|
||||
cyl(h=depth, d=plinth_diam, $fn=plinthfn);
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -531,7 +531,7 @@ module nema_mount_holes(size=17, depth=5, l=5, anchor=CENTER, spin=0, orient=UP)
|
||||
// nema11_mount_holes(depth=5, l=0);
|
||||
module nema11_mount_holes(depth=5, l=5, anchor=CENTER, spin=0, orient=UP)
|
||||
{
|
||||
nema_mount_holes(size=11, depth=depth, l=l, anchor=anchor, spin=spin, orient=orient) children();
|
||||
nema_mount_holes(size=11, depth=depth, l=l, anchor=anchor, spin=spin, orient=orient) children();
|
||||
}
|
||||
|
||||
|
||||
@ -556,7 +556,7 @@ module nema11_mount_holes(depth=5, l=5, anchor=CENTER, spin=0, orient=UP)
|
||||
// nema14_mount_holes(depth=5, l=0);
|
||||
module nema14_mount_holes(depth=5, l=5, anchor=CENTER, spin=0, orient=UP)
|
||||
{
|
||||
nema_mount_holes(size=14, depth=depth, l=l, anchor=anchor, spin=spin, orient=orient) children();
|
||||
nema_mount_holes(size=14, depth=depth, l=l, anchor=anchor, spin=spin, orient=orient) children();
|
||||
}
|
||||
|
||||
|
||||
@ -581,7 +581,7 @@ module nema14_mount_holes(depth=5, l=5, anchor=CENTER, spin=0, orient=UP)
|
||||
// nema17_mount_holes(depth=5, l=0);
|
||||
module nema17_mount_holes(depth=5, l=5, anchor=CENTER, spin=0, orient=UP)
|
||||
{
|
||||
nema_mount_holes(size=17, depth=depth, l=l, anchor=anchor, spin=spin, orient=orient) children();
|
||||
nema_mount_holes(size=17, depth=depth, l=l, anchor=anchor, spin=spin, orient=orient) children();
|
||||
}
|
||||
|
||||
|
||||
@ -606,7 +606,7 @@ module nema17_mount_holes(depth=5, l=5, anchor=CENTER, spin=0, orient=UP)
|
||||
// nema23_mount_holes(depth=5, l=0);
|
||||
module nema23_mount_holes(depth=5, l=5, anchor=CENTER, spin=0, orient=UP)
|
||||
{
|
||||
nema_mount_holes(size=23, depth=depth, l=l, anchor=anchor, spin=spin, orient=orient) children();
|
||||
nema_mount_holes(size=23, depth=depth, l=l, anchor=anchor, spin=spin, orient=orient) children();
|
||||
}
|
||||
|
||||
|
||||
@ -631,9 +631,9 @@ module nema23_mount_holes(depth=5, l=5, anchor=CENTER, spin=0, orient=UP)
|
||||
// nema34_mount_holes(depth=5, l=0);
|
||||
module nema34_mount_holes(depth=5, l=5, anchor=CENTER, spin=0, orient=UP)
|
||||
{
|
||||
nema_mount_holes(size=34, depth=depth, l=l, anchor=anchor, spin=spin, orient=orient) children();
|
||||
nema_mount_holes(size=34, depth=depth, l=l, anchor=anchor, spin=spin, orient=orient) children();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
130
partitions.scad
130
partitions.scad
@ -13,39 +13,39 @@
|
||||
|
||||
|
||||
_partition_cutpaths = [
|
||||
["flat", [[0,0],[1,0]]],
|
||||
["sawtooth", [[0,-0.5], [0.5,0.5], [1,-0.5]]],
|
||||
["sinewave", [for (a=[0:5:360]) [a/360,sin(a)/2]]],
|
||||
["comb", let(dx=0.5*sin(2)) [[0,0],[0+dx,0.5],[0.5-dx,0.5],[0.5+dx,-0.5],[1-dx,-0.5],[1,0]]],
|
||||
["finger", let(dx=0.5*sin(20)) [[0,0],[0+dx,0.5],[0.5-dx,0.5],[0.5+dx,-0.5],[1-dx,-0.5],[1,0]]],
|
||||
["dovetail", [[0,-0.5], [0.3,-0.5], [0.2,0.5], [0.8,0.5], [0.7,-0.5], [1,-0.5]]],
|
||||
["hammerhead", [[0,-0.5], [0.35,-0.5], [0.35,0], [0.15,0], [0.15,0.5], [0.85,0.5], [0.85,0], [0.65,0], [0.65,-0.5],[1,-0.5]]],
|
||||
["jigsaw", concat(
|
||||
arc(N=6, r=5/16, cp=[0,-3/16], start=270, angle=125),
|
||||
arc(N=12, r=5/16, cp=[1/2,3/16], start=215, angle=-250),
|
||||
arc(N=6, r=5/16, cp=[1,-3/16], start=145, angle=125)
|
||||
)
|
||||
],
|
||||
["flat", [[0,0],[1,0]]],
|
||||
["sawtooth", [[0,-0.5], [0.5,0.5], [1,-0.5]]],
|
||||
["sinewave", [for (a=[0:5:360]) [a/360,sin(a)/2]]],
|
||||
["comb", let(dx=0.5*sin(2)) [[0,0],[0+dx,0.5],[0.5-dx,0.5],[0.5+dx,-0.5],[1-dx,-0.5],[1,0]]],
|
||||
["finger", let(dx=0.5*sin(20)) [[0,0],[0+dx,0.5],[0.5-dx,0.5],[0.5+dx,-0.5],[1-dx,-0.5],[1,0]]],
|
||||
["dovetail", [[0,-0.5], [0.3,-0.5], [0.2,0.5], [0.8,0.5], [0.7,-0.5], [1,-0.5]]],
|
||||
["hammerhead", [[0,-0.5], [0.35,-0.5], [0.35,0], [0.15,0], [0.15,0.5], [0.85,0.5], [0.85,0], [0.65,0], [0.65,-0.5],[1,-0.5]]],
|
||||
["jigsaw", concat(
|
||||
arc(N=6, r=5/16, cp=[0,-3/16], start=270, angle=125),
|
||||
arc(N=12, r=5/16, cp=[1/2,3/16], start=215, angle=-250),
|
||||
arc(N=6, r=5/16, cp=[1,-3/16], start=145, angle=125)
|
||||
)
|
||||
],
|
||||
];
|
||||
|
||||
|
||||
function _partition_cutpath(l, h, cutsize, cutpath, gap) =
|
||||
let(
|
||||
cutsize = is_vector(cutsize)? cutsize : [cutsize*2, cutsize],
|
||||
cutpath = is_path(cutpath)? cutpath : (
|
||||
assert(is_string(cutpath), "cutpath must be a 2D path or a string.")
|
||||
let(idx = search([cutpath], _partition_cutpaths))
|
||||
idx==[[]]? assert(in_list(cutpath,_partition_cutpaths,idx=0)) :
|
||||
_partition_cutpaths[idx.x][1]
|
||||
),
|
||||
reps = ceil(l/(cutsize.x+gap)),
|
||||
cplen = (cutsize.x+gap) * reps,
|
||||
path = deduplicate(concat(
|
||||
[[-l/2, cutpath[0].y*cutsize.y]],
|
||||
[for (i=[0:1:reps-1], pt=cutpath) vmul(pt,cutsize)+[i*(cutsize.x+gap)+gap/2-cplen/2,0]],
|
||||
[[ l/2, cutpath[len(cutpath)-1].y*cutsize.y]]
|
||||
))
|
||||
) path;
|
||||
let(
|
||||
cutsize = is_vector(cutsize)? cutsize : [cutsize*2, cutsize],
|
||||
cutpath = is_path(cutpath)? cutpath : (
|
||||
assert(is_string(cutpath), "cutpath must be a 2D path or a string.")
|
||||
let(idx = search([cutpath], _partition_cutpaths))
|
||||
idx==[[]]? assert(in_list(cutpath,_partition_cutpaths,idx=0)) :
|
||||
_partition_cutpaths[idx.x][1]
|
||||
),
|
||||
reps = ceil(l/(cutsize.x+gap)),
|
||||
cplen = (cutsize.x+gap) * reps,
|
||||
path = deduplicate(concat(
|
||||
[[-l/2, cutpath[0].y*cutsize.y]],
|
||||
[for (i=[0:1:reps-1], pt=cutpath) vmul(pt,cutsize)+[i*(cutsize.x+gap)+gap/2-cplen/2,0]],
|
||||
[[ l/2, cutpath[len(cutpath)-1].y*cutsize.y]]
|
||||
))
|
||||
) path;
|
||||
|
||||
|
||||
// Module: partition_mask()
|
||||
@ -79,16 +79,16 @@ function _partition_cutpath(l, h, cutsize, cutpath, gap) =
|
||||
// partition_mask(w=20, cutpath="jigsaw");
|
||||
module partition_mask(l=100, w=100, h=100, cutsize=10, cutpath=undef, gap=0, inverse=false, spin=0, orient=UP)
|
||||
{
|
||||
cutsize = is_vector(cutsize)? cutsize : [cutsize*2, cutsize];
|
||||
path = _partition_cutpath(l, h, cutsize, cutpath, gap);
|
||||
fullpath = concat(path, [[l/2,w*(inverse?-1:1)], [-l/2,w*(inverse?-1:1)]]);
|
||||
rot(from=UP,to=orient) {
|
||||
rotate(spin) {
|
||||
linear_extrude(height=h, convexity=10) {
|
||||
offset(delta=-$slop) polygon(fullpath);
|
||||
}
|
||||
}
|
||||
}
|
||||
cutsize = is_vector(cutsize)? cutsize : [cutsize*2, cutsize];
|
||||
path = _partition_cutpath(l, h, cutsize, cutpath, gap);
|
||||
fullpath = concat(path, [[l/2,w*(inverse?-1:1)], [-l/2,w*(inverse?-1:1)]]);
|
||||
rot(from=UP,to=orient) {
|
||||
rotate(spin) {
|
||||
linear_extrude(height=h, convexity=10) {
|
||||
offset(delta=-$slop) polygon(fullpath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -121,15 +121,15 @@ module partition_mask(l=100, w=100, h=100, cutsize=10, cutpath=undef, gap=0, inv
|
||||
// partition_cut_mask(cutpath="jigsaw");
|
||||
module partition_cut_mask(l=100, h=100, cutsize=10, cutpath=undef, gap=0, spin=0, orient=UP)
|
||||
{
|
||||
cutsize = is_vector(cutsize)? cutsize : [cutsize*2, cutsize];
|
||||
path = _partition_cutpath(l, h, cutsize, cutpath, gap);
|
||||
rot(from=UP,to=orient) {
|
||||
rotate(spin) {
|
||||
linear_extrude(height=h, convexity=10) {
|
||||
stroke(path, width=$slop*2);
|
||||
}
|
||||
}
|
||||
}
|
||||
cutsize = is_vector(cutsize)? cutsize : [cutsize*2, cutsize];
|
||||
path = _partition_cutpath(l, h, cutsize, cutpath, gap);
|
||||
rot(from=UP,to=orient) {
|
||||
rotate(spin) {
|
||||
linear_extrude(height=h, convexity=10) {
|
||||
stroke(path, width=$slop*2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -160,24 +160,24 @@ module partition_cut_mask(l=100, h=100, cutsize=10, cutpath=undef, gap=0, spin=0
|
||||
// partition(cutpath="jigsaw") cylinder(h=50, d=80, center=false);
|
||||
module partition(size=100, spread=10, cutsize=10, cutpath=undef, gap=0, spin=0)
|
||||
{
|
||||
size = is_vector(size)? size : [size,size,size];
|
||||
cutsize = is_vector(cutsize)? cutsize : [cutsize*2, cutsize];
|
||||
rsize = vabs(rot(spin,p=size));
|
||||
vec = rot(spin,p=BACK)*spread/2;
|
||||
move(vec) {
|
||||
intersection() {
|
||||
children();
|
||||
partition_mask(l=rsize.x, w=rsize.y, h=rsize.z, cutsize=cutsize, cutpath=cutpath, gap=gap, spin=spin);
|
||||
}
|
||||
}
|
||||
move(-vec) {
|
||||
intersection() {
|
||||
children();
|
||||
partition_mask(l=rsize.x, w=rsize.y, h=rsize.z, cutsize=cutsize, cutpath=cutpath, gap=gap, inverse=true, spin=spin);
|
||||
}
|
||||
}
|
||||
size = is_vector(size)? size : [size,size,size];
|
||||
cutsize = is_vector(cutsize)? cutsize : [cutsize*2, cutsize];
|
||||
rsize = vabs(rot(spin,p=size));
|
||||
vec = rot(spin,p=BACK)*spread/2;
|
||||
move(vec) {
|
||||
intersection() {
|
||||
children();
|
||||
partition_mask(l=rsize.x, w=rsize.y, h=rsize.z, cutsize=cutsize, cutpath=cutpath, gap=gap, spin=spin);
|
||||
}
|
||||
}
|
||||
move(-vec) {
|
||||
intersection() {
|
||||
children();
|
||||
partition_mask(l=rsize.x, w=rsize.y, h=rsize.z, cutsize=cutsize, cutpath=cutpath, gap=gap, inverse=true, spin=spin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
1136
paths.scad
1136
paths.scad
File diff suppressed because it is too large
Load Diff
@ -28,52 +28,52 @@
|
||||
// phillips_drive(size="#3", shaft=6, l=20);
|
||||
// }
|
||||
module phillips_drive(size="#2", shaft=6, l=20, $fn=36, anchor=BOTTOM, spin=0, orient=UP) {
|
||||
assert(is_string(size));
|
||||
assert(in_list(size,["#0","#1","#2","#3","#4"]));
|
||||
assert(is_string(size));
|
||||
assert(in_list(size,["#0","#1","#2","#3","#4"]));
|
||||
|
||||
num = ord(size[1]) - ord("0");
|
||||
b = [0.61, 0.97, 1.47, 2.41, 3.48][num];
|
||||
e = [0.31, 0.43, 0.81, 2.00, 2.41][num];
|
||||
g = [0.81, 1.27, 2.29, 3.81, 5.08][num];
|
||||
//f = [0.33, 0.53, 0.70, 0.82, 1.23][num];
|
||||
//r = [0.30, 0.50, 0.60, 0.80, 1.00][num];
|
||||
alpha = [ 136, 138, 140, 146, 153][num];
|
||||
beta = [7.00, 7.00, 5.75, 5.75, 7.00][num];
|
||||
gamma = 92.0;
|
||||
ang1 = 28.0;
|
||||
ang2 = 26.5;
|
||||
h1 = adj_ang_to_opp(g/2, ang1);
|
||||
h2 = adj_ang_to_opp((shaft-g)/2, 90-ang2);
|
||||
h3 = adj_ang_to_opp(b/2, ang1);
|
||||
p0 = [0,0];
|
||||
p1 = [e/2, adj_ang_to_opp(e/2, 90-alpha/2)];
|
||||
p2 = p1 + [(shaft-e)/2, adj_ang_to_hyp((shaft-e)/2, 90-gamma/2)];
|
||||
attachable(anchor,spin,orient, d=shaft, l=l) {
|
||||
down(l/2) {
|
||||
difference() {
|
||||
union() {
|
||||
cyl(d1=0, d2=g, h=h1, anchor=BOT);
|
||||
up(h1) {
|
||||
cyl(d1=g, d2=shaft, h=h2, anchor=BOT);
|
||||
up(h2) cyl(d=shaft, h=l-h1-h2, anchor=BOT);
|
||||
}
|
||||
}
|
||||
zrot(45)
|
||||
zrot_copies(n=4, r=b/2/cos(90-alpha/2), sa=90) {
|
||||
up(h3) {
|
||||
xrot(-beta) {
|
||||
linear_extrude(height=(h1+h2)*20, convexity=4, center=true) {
|
||||
path = [p0, p1, p2, [-p2.x,p2.y], [-p1.x,p1.y]];
|
||||
polygon(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
num = ord(size[1]) - ord("0");
|
||||
b = [0.61, 0.97, 1.47, 2.41, 3.48][num];
|
||||
e = [0.31, 0.43, 0.81, 2.00, 2.41][num];
|
||||
g = [0.81, 1.27, 2.29, 3.81, 5.08][num];
|
||||
//f = [0.33, 0.53, 0.70, 0.82, 1.23][num];
|
||||
//r = [0.30, 0.50, 0.60, 0.80, 1.00][num];
|
||||
alpha = [ 136, 138, 140, 146, 153][num];
|
||||
beta = [7.00, 7.00, 5.75, 5.75, 7.00][num];
|
||||
gamma = 92.0;
|
||||
ang1 = 28.0;
|
||||
ang2 = 26.5;
|
||||
h1 = adj_ang_to_opp(g/2, ang1);
|
||||
h2 = adj_ang_to_opp((shaft-g)/2, 90-ang2);
|
||||
h3 = adj_ang_to_opp(b/2, ang1);
|
||||
p0 = [0,0];
|
||||
p1 = [e/2, adj_ang_to_opp(e/2, 90-alpha/2)];
|
||||
p2 = p1 + [(shaft-e)/2, adj_ang_to_hyp((shaft-e)/2, 90-gamma/2)];
|
||||
attachable(anchor,spin,orient, d=shaft, l=l) {
|
||||
down(l/2) {
|
||||
difference() {
|
||||
union() {
|
||||
cyl(d1=0, d2=g, h=h1, anchor=BOT);
|
||||
up(h1) {
|
||||
cyl(d1=g, d2=shaft, h=h2, anchor=BOT);
|
||||
up(h2) cyl(d=shaft, h=l-h1-h2, anchor=BOT);
|
||||
}
|
||||
}
|
||||
zrot(45)
|
||||
zrot_copies(n=4, r=b/2/cos(90-alpha/2), sa=90) {
|
||||
up(h3) {
|
||||
xrot(-beta) {
|
||||
linear_extrude(height=(h1+h2)*20, convexity=4, center=true) {
|
||||
path = [p0, p1, p2, [-p2.x,p2.y], [-p1.x,p1.y]];
|
||||
polygon(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
810
polyhedra.scad
810
polyhedra.scad
@ -22,9 +22,9 @@ include <hull.scad>
|
||||
// Groups entries in "arr" into groups of equal values and returns index lists of those groups
|
||||
|
||||
function _unique_groups(m) = [
|
||||
for (i=[0:1:len(m)-1]) let(
|
||||
s = search([m[i]], m, 0)[0]
|
||||
) if (s[0]==i) s
|
||||
for (i=[0:1:len(m)-1]) let(
|
||||
s = search([m[i]], m, 0)[0]
|
||||
) if (s[0]==i) s
|
||||
];
|
||||
|
||||
|
||||
@ -277,82 +277,82 @@ function _unique_groups(m) = [
|
||||
// regular_polyhedron("pentagonal hexecontahedron", or=1,facedown=false);
|
||||
// }
|
||||
module regular_polyhedron(
|
||||
name=undef,
|
||||
index=undef,
|
||||
type=undef,
|
||||
faces=undef,
|
||||
facetype=undef,
|
||||
hasfaces=undef,
|
||||
side=1,
|
||||
ir=undef,
|
||||
mr=undef,
|
||||
or=undef,
|
||||
r=undef,
|
||||
d=undef,
|
||||
anchor=[0,0,0],
|
||||
center=undef,
|
||||
rounding=0,
|
||||
repeat=true,
|
||||
facedown=true,
|
||||
draw=true,
|
||||
rotate_children=true,
|
||||
stellate = false,
|
||||
longside=undef, // special parameter for trapezohedron
|
||||
h=undef // special parameter for trapezohedron
|
||||
name=undef,
|
||||
index=undef,
|
||||
type=undef,
|
||||
faces=undef,
|
||||
facetype=undef,
|
||||
hasfaces=undef,
|
||||
side=1,
|
||||
ir=undef,
|
||||
mr=undef,
|
||||
or=undef,
|
||||
r=undef,
|
||||
d=undef,
|
||||
anchor=[0,0,0],
|
||||
center=undef,
|
||||
rounding=0,
|
||||
repeat=true,
|
||||
facedown=true,
|
||||
draw=true,
|
||||
rotate_children=true,
|
||||
stellate = false,
|
||||
longside=undef, // special parameter for trapezohedron
|
||||
h=undef // special parameter for trapezohedron
|
||||
) {
|
||||
assert(rounding>=0, "'rounding' must be nonnegative");
|
||||
entry = regular_polyhedron_info(
|
||||
"fullentry", name=name, index=index,
|
||||
type=type, faces=faces, facetype=facetype,
|
||||
hasfaces=hasfaces, side=side,
|
||||
ir=ir, mr=mr, or=or,
|
||||
r=r, d=d,
|
||||
anchor=anchor, center=center,
|
||||
facedown=facedown,
|
||||
stellate=stellate,
|
||||
longside=longside, h=h
|
||||
);
|
||||
scaled_points = entry[0];
|
||||
translation = entry[1];
|
||||
face_triangles = entry[2];
|
||||
faces = entry[3];
|
||||
face_normals = entry[4];
|
||||
in_radius = entry[5];
|
||||
if (draw){
|
||||
if (rounding==0)
|
||||
polyhedron(move(translation, p=scaled_points), faces = face_triangles);
|
||||
else {
|
||||
fn = segs(rounding);
|
||||
rounding = rounding/cos(180/fn);
|
||||
adjusted_scale = 1 - rounding / in_radius;
|
||||
minkowski(){
|
||||
sphere(r=rounding, $fn=fn);
|
||||
polyhedron(move(translation,p=adjusted_scale*scaled_points), faces = face_triangles);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($children>0) {
|
||||
maxrange = repeat ? len(faces)-1 : $children-1;
|
||||
for(i=[0:1:maxrange]) {
|
||||
// Would like to orient so an edge (longest edge?) is parallel to x axis
|
||||
facepts = move(translation, p=select(scaled_points, faces[i]));
|
||||
center = mean(facepts);
|
||||
rotatedface = rot(from=face_normals[i], to=[0,0,1], p=move(-center, p=facepts));
|
||||
clockwise = sortidx([for(pt=rotatedface) -atan2(pt.y,pt.x)]);
|
||||
$face = rotate_children?
|
||||
path2d(select(rotatedface,clockwise)) :
|
||||
select(move(-center,p=facepts), clockwise);
|
||||
$faceindex = i;
|
||||
$center = -translation-center;
|
||||
translate(center)
|
||||
if (rotate_children) {
|
||||
rot(from=[0,0,1], to=face_normals[i])
|
||||
children(i % $children);
|
||||
} else {
|
||||
children(i % $children);
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(rounding>=0, "'rounding' must be nonnegative");
|
||||
entry = regular_polyhedron_info(
|
||||
"fullentry", name=name, index=index,
|
||||
type=type, faces=faces, facetype=facetype,
|
||||
hasfaces=hasfaces, side=side,
|
||||
ir=ir, mr=mr, or=or,
|
||||
r=r, d=d,
|
||||
anchor=anchor, center=center,
|
||||
facedown=facedown,
|
||||
stellate=stellate,
|
||||
longside=longside, h=h
|
||||
);
|
||||
scaled_points = entry[0];
|
||||
translation = entry[1];
|
||||
face_triangles = entry[2];
|
||||
faces = entry[3];
|
||||
face_normals = entry[4];
|
||||
in_radius = entry[5];
|
||||
if (draw){
|
||||
if (rounding==0)
|
||||
polyhedron(move(translation, p=scaled_points), faces = face_triangles);
|
||||
else {
|
||||
fn = segs(rounding);
|
||||
rounding = rounding/cos(180/fn);
|
||||
adjusted_scale = 1 - rounding / in_radius;
|
||||
minkowski(){
|
||||
sphere(r=rounding, $fn=fn);
|
||||
polyhedron(move(translation,p=adjusted_scale*scaled_points), faces = face_triangles);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($children>0) {
|
||||
maxrange = repeat ? len(faces)-1 : $children-1;
|
||||
for(i=[0:1:maxrange]) {
|
||||
// Would like to orient so an edge (longest edge?) is parallel to x axis
|
||||
facepts = move(translation, p=select(scaled_points, faces[i]));
|
||||
center = mean(facepts);
|
||||
rotatedface = rot(from=face_normals[i], to=[0,0,1], p=move(-center, p=facepts));
|
||||
clockwise = sortidx([for(pt=rotatedface) -atan2(pt.y,pt.x)]);
|
||||
$face = rotate_children?
|
||||
path2d(select(rotatedface,clockwise)) :
|
||||
select(move(-center,p=facepts), clockwise);
|
||||
$faceindex = i;
|
||||
$center = -translation-center;
|
||||
translate(center)
|
||||
if (rotate_children) {
|
||||
rot(from=[0,0,1], to=face_normals[i])
|
||||
children(i % $children);
|
||||
} else {
|
||||
children(i % $children);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@ -364,17 +364,17 @@ module regular_polyhedron(
|
||||
function _even_perms(v) = [v, [v[2], v[0], v[1]], [v[1],v[2],v[0]]];
|
||||
function _all_perms(v) = [v, [v[2], v[0], v[1]], [v[1],v[2],v[0]], [v[1],v[0],v[2]],[v[2],v[1],v[0]],[v[0],v[2],v[1]]];
|
||||
//
|
||||
// Point reflections across all planes. In the unconstrained case, this means one point becomes 8 points.
|
||||
// Point reflections across all planes. In the unconstrained case, this means one point becomes 8 points.
|
||||
//
|
||||
// sign=="even" means an even number of minus signs (odd number of plus signs)
|
||||
// sign=="odd" means an odd number of minus signs (even number of plus signs)
|
||||
//
|
||||
function _point_ref(points, sign="both") =
|
||||
unique([
|
||||
for(i=[-1,1],j=[-1,1],k=[-1,1])
|
||||
if (sign=="both" || sign=="even" && i*j*k>0 || sign=="odd" && i*j*k<0)
|
||||
each [for(point=points) vmul(point,[i,j,k])]
|
||||
]);
|
||||
unique([
|
||||
for(i=[-1,1],j=[-1,1],k=[-1,1])
|
||||
if (sign=="both" || sign=="even" && i*j*k>0 || sign=="odd" && i*j*k<0)
|
||||
each [for(point=points) vmul(point,[i,j,k])]
|
||||
]);
|
||||
//
|
||||
_tribonacci=(1+4*cosh(acosh(2+3/8)/3))/3;
|
||||
//
|
||||
@ -384,160 +384,160 @@ _tribonacci=(1+4*cosh(acosh(2+3/8)/3))/3;
|
||||
// The polyhedra information is from Wikipedia and http://dmccooey.com/polyhedra/
|
||||
//
|
||||
_polyhedra_ = [
|
||||
// Platonic Solids
|
||||
// Platonic Solids
|
||||
|
||||
["tetrahedron", "platonic", 4,[3], 2*sqrt(2), sqrt(6)/12, sqrt(2)/4, sqrt(6)/4, 1/6/sqrt(2),
|
||||
_point_ref([[1,1,1]], sign="even")],
|
||||
["cube", "platonic", 6, [4], 2, 1/2, 1/sqrt(2), sqrt(3)/2, 1,
|
||||
_point_ref([[1,1,1]])],
|
||||
["octahedron", "platonic", 8, [3], sqrt(2), sqrt(6)/6, 1/2, sqrt(2)/2, sqrt(2)/3,
|
||||
_point_ref(_even_perms([1,0,0]))],
|
||||
["dodecahedron", "platonic", 12, [5], 2/PHI, sqrt(5/2+11*sqrt(5)/10)/2, (3+sqrt(5))/4, sqrt(3)*PHI/2, (15+7*sqrt(5))/4,
|
||||
_point_ref(concat([[1,1,1]],_even_perms([0,PHI,1/PHI])))],
|
||||
["icosahedron", "platonic", 20, [3], 2, PHI*PHI/2/sqrt(3), cos(36), sin(72), 5*(3+sqrt(5))/12,
|
||||
_point_ref(_even_perms([0,1,PHI]))],
|
||||
["tetrahedron", "platonic", 4,[3], 2*sqrt(2), sqrt(6)/12, sqrt(2)/4, sqrt(6)/4, 1/6/sqrt(2),
|
||||
_point_ref([[1,1,1]], sign="even")],
|
||||
["cube", "platonic", 6, [4], 2, 1/2, 1/sqrt(2), sqrt(3)/2, 1,
|
||||
_point_ref([[1,1,1]])],
|
||||
["octahedron", "platonic", 8, [3], sqrt(2), sqrt(6)/6, 1/2, sqrt(2)/2, sqrt(2)/3,
|
||||
_point_ref(_even_perms([1,0,0]))],
|
||||
["dodecahedron", "platonic", 12, [5], 2/PHI, sqrt(5/2+11*sqrt(5)/10)/2, (3+sqrt(5))/4, sqrt(3)*PHI/2, (15+7*sqrt(5))/4,
|
||||
_point_ref(concat([[1,1,1]],_even_perms([0,PHI,1/PHI])))],
|
||||
["icosahedron", "platonic", 20, [3], 2, PHI*PHI/2/sqrt(3), cos(36), sin(72), 5*(3+sqrt(5))/12,
|
||||
_point_ref(_even_perms([0,1,PHI]))],
|
||||
|
||||
// Archimedian Solids, listed in order by Wenniger number, W6-W18
|
||||
// Archimedian Solids, listed in order by Wenniger number, W6-W18
|
||||
|
||||
["truncated tetrahedron", "archimedean", 8,[6,3], sqrt(8), sqrt(6)/4, 3*sqrt(2)/4, sqrt(11/8), 23*sqrt(2)/12,
|
||||
_point_ref(_all_perms([1,1,3]),sign="even")],
|
||||
["truncated octahedron", "archimedean", 14, [6,4], sqrt(2), sqrt(6)/2, 1.5, sqrt(10)/2, 8*sqrt(2),
|
||||
_point_ref(_all_perms([0,1,2]))],
|
||||
["truncated cube", "archimedean", 14, [8,3], 2*(sqrt(2)-1), (1+sqrt(2))/2, 1+sqrt(2)/2, sqrt(7+4*sqrt(2))/2, 7+14*sqrt(2)/3,
|
||||
_point_ref(_all_perms([1,1,sqrt(2)-1]))],
|
||||
["truncated icosahedron", "archimedean", 32, [6, 5], 2, (3*sqrt(3)+sqrt(15))/4, 3*PHI/2, sqrt(58+18*sqrt(5))/4, (125+43*sqrt(5))/4,
|
||||
_point_ref(concat(
|
||||
_even_perms([0,1,3*PHI]),
|
||||
_even_perms([1,2+PHI,2*PHI]),
|
||||
_even_perms([PHI,2,PHI*PHI*PHI])
|
||||
))],
|
||||
["truncated dodecahedron", "archimedean", 32, [10, 3], 2*PHI-2, sqrt(7+11*PHI)/2, (3*PHI+1)/2,sqrt(11+PHI*15)/2, 5*(99+47*sqrt(5))/12,
|
||||
_point_ref(concat(
|
||||
_even_perms([0,1/PHI, 2+PHI]),
|
||||
_even_perms([1/PHI,PHI,2*PHI]),
|
||||
_even_perms([PHI,2,PHI+1])
|
||||
))],
|
||||
["cuboctahedron", "archimedean", 14, [4,3], sqrt(2), sqrt(2)/2, sqrt(3)/2, 1, 5*sqrt(2)/3,
|
||||
_point_ref(_all_perms([1,1,0]))],
|
||||
["icosidodecahedron", "archimedean", 32, [5,3], 1, sqrt(5*(5+2*sqrt(5)))/5,sqrt(5+2*sqrt(5))/2, PHI, (14+17*PHI)/3,
|
||||
_point_ref(concat(_even_perms([0,0,PHI]),_even_perms([1/2,PHI/2,PHI*PHI/2])))],
|
||||
["rhombicuboctahedron", "archimedean", 26, [4, 3], 2, (1+sqrt(2))/2, sqrt(2*(2+sqrt(2)))/2, sqrt(5+2*sqrt(2))/2, 4+10*sqrt(2)/3,
|
||||
_point_ref(_even_perms([1,1,1+sqrt(2)]))],
|
||||
["rhombicosidodecahedron", "archimedean", 62, [5,4,3], 2, 3/10*sqrt(15+20*PHI), sqrt(3/2+2*PHI), sqrt(8*PHI+7)/2, (31+58*PHI)/3,
|
||||
_point_ref(concat(
|
||||
_even_perms([1,1,PHI*PHI*PHI]),
|
||||
_even_perms([PHI*PHI,PHI,2*PHI]),
|
||||
_even_perms([2+PHI,0,PHI*PHI])
|
||||
))],
|
||||
["truncated cuboctahedron", "archimedean", 26, [8, 6, 4], 2, (1+2*sqrt(2))/2, sqrt(6*(2+sqrt(2)))/2, sqrt(13+6*sqrt(2))/2, (22+14*sqrt(2)),
|
||||
_point_ref(_all_perms([1,1+sqrt(2), 1+2*sqrt(2)]))],
|
||||
["truncated icosidodecahedron", "archimedean", 62, [10,6,4], 2*PHI - 2, sqrt(15/4+5*PHI),sqrt(9/2+6*PHI),sqrt(19/4+6*PHI), 95+50*sqrt(5),
|
||||
_point_ref(concat(
|
||||
_even_perms([1/PHI,1/PHI,3+PHI]),
|
||||
_even_perms([2/PHI,PHI,1+2*PHI]),
|
||||
_even_perms([1/PHI,PHI*PHI,3*PHI-1]),
|
||||
_even_perms([2*PHI-1,2,2+PHI]),
|
||||
_even_perms([PHI,3,2*PHI])
|
||||
))],
|
||||
["snub cube", "archimedean", 38, [4,3], 1.60972,1.14261350892596209,1.24722316799364325, 1.34371337374460170,
|
||||
sqrt((613*_tribonacci+203)/(9*(35*_tribonacci-62))),
|
||||
concat(
|
||||
_point_ref(_even_perms([1,1/_tribonacci,_tribonacci]), sign="odd"),
|
||||
_point_ref(_even_perms([1,_tribonacci,1/_tribonacci]), sign="even")
|
||||
)],
|
||||
["snub dodecahedron", "archimedean", 92, [5, 3], 1, 1.98091594728184,2.097053835252087,2.155837375115, 37.61664996273336,
|
||||
concat(
|
||||
_point_ref(_even_perms([0.374821658114562,0.330921024729844,2.097053835252088]), sign="odd"),
|
||||
_point_ref(_even_perms([0.192893711352359,1.249503788463027,1.746186440985827]), sign="odd"),
|
||||
_point_ref(_even_perms([1.103156835071754,0.847550046789061,1.646917940690374]), sign="odd"),
|
||||
_point_ref(_even_perms([0.567715369466922,0.643029605914072,1.977838965420219]), sign="even"),
|
||||
_point_ref(_even_perms([1.415265416255982,0.728335176957192,1.454024229338015]), sign="even")
|
||||
)],
|
||||
["truncated tetrahedron", "archimedean", 8,[6,3], sqrt(8), sqrt(6)/4, 3*sqrt(2)/4, sqrt(11/8), 23*sqrt(2)/12,
|
||||
_point_ref(_all_perms([1,1,3]),sign="even")],
|
||||
["truncated octahedron", "archimedean", 14, [6,4], sqrt(2), sqrt(6)/2, 1.5, sqrt(10)/2, 8*sqrt(2),
|
||||
_point_ref(_all_perms([0,1,2]))],
|
||||
["truncated cube", "archimedean", 14, [8,3], 2*(sqrt(2)-1), (1+sqrt(2))/2, 1+sqrt(2)/2, sqrt(7+4*sqrt(2))/2, 7+14*sqrt(2)/3,
|
||||
_point_ref(_all_perms([1,1,sqrt(2)-1]))],
|
||||
["truncated icosahedron", "archimedean", 32, [6, 5], 2, (3*sqrt(3)+sqrt(15))/4, 3*PHI/2, sqrt(58+18*sqrt(5))/4, (125+43*sqrt(5))/4,
|
||||
_point_ref(concat(
|
||||
_even_perms([0,1,3*PHI]),
|
||||
_even_perms([1,2+PHI,2*PHI]),
|
||||
_even_perms([PHI,2,PHI*PHI*PHI])
|
||||
))],
|
||||
["truncated dodecahedron", "archimedean", 32, [10, 3], 2*PHI-2, sqrt(7+11*PHI)/2, (3*PHI+1)/2,sqrt(11+PHI*15)/2, 5*(99+47*sqrt(5))/12,
|
||||
_point_ref(concat(
|
||||
_even_perms([0,1/PHI, 2+PHI]),
|
||||
_even_perms([1/PHI,PHI,2*PHI]),
|
||||
_even_perms([PHI,2,PHI+1])
|
||||
))],
|
||||
["cuboctahedron", "archimedean", 14, [4,3], sqrt(2), sqrt(2)/2, sqrt(3)/2, 1, 5*sqrt(2)/3,
|
||||
_point_ref(_all_perms([1,1,0]))],
|
||||
["icosidodecahedron", "archimedean", 32, [5,3], 1, sqrt(5*(5+2*sqrt(5)))/5,sqrt(5+2*sqrt(5))/2, PHI, (14+17*PHI)/3,
|
||||
_point_ref(concat(_even_perms([0,0,PHI]),_even_perms([1/2,PHI/2,PHI*PHI/2])))],
|
||||
["rhombicuboctahedron", "archimedean", 26, [4, 3], 2, (1+sqrt(2))/2, sqrt(2*(2+sqrt(2)))/2, sqrt(5+2*sqrt(2))/2, 4+10*sqrt(2)/3,
|
||||
_point_ref(_even_perms([1,1,1+sqrt(2)]))],
|
||||
["rhombicosidodecahedron", "archimedean", 62, [5,4,3], 2, 3/10*sqrt(15+20*PHI), sqrt(3/2+2*PHI), sqrt(8*PHI+7)/2, (31+58*PHI)/3,
|
||||
_point_ref(concat(
|
||||
_even_perms([1,1,PHI*PHI*PHI]),
|
||||
_even_perms([PHI*PHI,PHI,2*PHI]),
|
||||
_even_perms([2+PHI,0,PHI*PHI])
|
||||
))],
|
||||
["truncated cuboctahedron", "archimedean", 26, [8, 6, 4], 2, (1+2*sqrt(2))/2, sqrt(6*(2+sqrt(2)))/2, sqrt(13+6*sqrt(2))/2, (22+14*sqrt(2)),
|
||||
_point_ref(_all_perms([1,1+sqrt(2), 1+2*sqrt(2)]))],
|
||||
["truncated icosidodecahedron", "archimedean", 62, [10,6,4], 2*PHI - 2, sqrt(15/4+5*PHI),sqrt(9/2+6*PHI),sqrt(19/4+6*PHI), 95+50*sqrt(5),
|
||||
_point_ref(concat(
|
||||
_even_perms([1/PHI,1/PHI,3+PHI]),
|
||||
_even_perms([2/PHI,PHI,1+2*PHI]),
|
||||
_even_perms([1/PHI,PHI*PHI,3*PHI-1]),
|
||||
_even_perms([2*PHI-1,2,2+PHI]),
|
||||
_even_perms([PHI,3,2*PHI])
|
||||
))],
|
||||
["snub cube", "archimedean", 38, [4,3], 1.60972,1.14261350892596209,1.24722316799364325, 1.34371337374460170,
|
||||
sqrt((613*_tribonacci+203)/(9*(35*_tribonacci-62))),
|
||||
concat(
|
||||
_point_ref(_even_perms([1,1/_tribonacci,_tribonacci]), sign="odd"),
|
||||
_point_ref(_even_perms([1,_tribonacci,1/_tribonacci]), sign="even")
|
||||
)],
|
||||
["snub dodecahedron", "archimedean", 92, [5, 3], 1, 1.98091594728184,2.097053835252087,2.155837375115, 37.61664996273336,
|
||||
concat(
|
||||
_point_ref(_even_perms([0.374821658114562,0.330921024729844,2.097053835252088]), sign="odd"),
|
||||
_point_ref(_even_perms([0.192893711352359,1.249503788463027,1.746186440985827]), sign="odd"),
|
||||
_point_ref(_even_perms([1.103156835071754,0.847550046789061,1.646917940690374]), sign="odd"),
|
||||
_point_ref(_even_perms([0.567715369466922,0.643029605914072,1.977838965420219]), sign="even"),
|
||||
_point_ref(_even_perms([1.415265416255982,0.728335176957192,1.454024229338015]), sign="even")
|
||||
)],
|
||||
|
||||
// Catalan Solids, the duals to the Archimedean solids, listed in the corresponding order
|
||||
// Catalan Solids, the duals to the Archimedean solids, listed in the corresponding order
|
||||
|
||||
["triakis tetrahedron","catalan", 12, [3], 9/5, 5*sqrt(22)/44, 5*sqrt(2)/12, 5*sqrt(6)/12, 25*sqrt(2)/36,
|
||||
concat(
|
||||
_point_ref([9*sqrt(2)/20*[1,1,1]],sign="even"),
|
||||
_point_ref([3*sqrt(2)/4*[1,1,1]],sign="odd")
|
||||
)],
|
||||
["tetrakis hexahedron", "catalan", 24, [3], 1, 2/sqrt(5), 2*sqrt(2)/3, 2/sqrt(3), 32/9,
|
||||
_point_ref(concat([[2/3,2/3,2/3]],_even_perms([1,0,0])))],
|
||||
["triakis octahedron", "catalan", 24, [3], 2, sqrt(17*(23+16*sqrt(2)))/34, 1/2+sqrt(2)/4,(1+sqrt(2))/2,3/2+sqrt(2),
|
||||
_point_ref(concat([[1,1,1]],_even_perms([1+sqrt(2),0,0])))],
|
||||
["pentakis dodecahedron", "catalan", 60, [3], 1,sqrt(477/436+97*sqrt(5)/218), sqrt(5)/4+11/12, sqrt(7/4+sqrt(5)/3), 125*sqrt(5)/36+205/36,
|
||||
_point_ref(concat(
|
||||
_even_perms([0,(5-PHI)/6, PHI/2+2/3]),
|
||||
_even_perms([0,(PHI+1)/2,PHI/2]),[(4*PHI-1)/6 * [1,1,1]]
|
||||
))],
|
||||
["triakis icosahedron", "catalan", 60, [3], 1, sqrt((139+199*PHI)/244), (8*PHI+1)/10, sqrt(13/8+19/8/sqrt(5)), (13*PHI+3)/2,
|
||||
_point_ref(concat(
|
||||
_even_perms([(PHI+7)/10, 0, (8*PHI+1)/10]),
|
||||
_even_perms([0, 1/2, (PHI+1)/2]),[PHI/2*[1,1,1]]
|
||||
))],
|
||||
["rhombic dodecahedron", "catalan", 12, [4], sqrt(3), sqrt(2/3), 2*sqrt(2)/3, 2/sqrt(3), 16*sqrt(3)/9,
|
||||
_point_ref(concat([[1,1,1]], _even_perms([2,0,0])))],
|
||||
["rhombic triacontahedron", "catalan", 30,[4], 1, sqrt(1+2/sqrt(5)), 1+1/sqrt(5), (1+sqrt(5))/2, 4*sqrt(5+2*sqrt(5)),
|
||||
concat(
|
||||
_point_ref(_even_perms([0,sqrt(1+2/sqrt(5)), sqrt((5+sqrt(5))/10)])),
|
||||
_point_ref(_even_perms([0,sqrt(2/(5+sqrt(5))), sqrt(1+2/sqrt(5))])),
|
||||
_point_ref([sqrt((5+sqrt(5))/10)*[1,1,1]])
|
||||
)],
|
||||
["deltoidal icositetrahedron", "catalan", 24, [4], 2*sqrt(10-sqrt(2))/7, 7*sqrt((7+4*sqrt(2))/(34 * (10-sqrt(2)))),
|
||||
7*sqrt(2*(2+sqrt(2)))/sqrt(10-sqrt(2))/4, 7*sqrt(2)/sqrt(10-sqrt(2))/2,
|
||||
(14+21*sqrt(2))/sqrt(10-sqrt(2)),
|
||||
_point_ref(concat(
|
||||
_even_perms([0,1,1]), _even_perms([sqrt(2),0,0]),
|
||||
_even_perms((4+sqrt(2))/7*[1,1,1])
|
||||
))],
|
||||
["deltoidal hexecontahedron", "catalan", 60, [4], sqrt(5*(85-31*sqrt(5)))/11, sqrt(571/164+1269/164/sqrt(5)), 5/4+13/4/sqrt(5),
|
||||
sqrt(147+65*sqrt(5))/6, sqrt(29530+13204*sqrt(5))/3,
|
||||
_point_ref(concat(
|
||||
_even_perms([0,0,sqrt(5)]),
|
||||
_even_perms([0,(15+sqrt(5))/22, (25+9*sqrt(5))/22]),
|
||||
_even_perms([0,(5+3*sqrt(5))/6, (5+sqrt(5))/6]),
|
||||
_even_perms([(5-sqrt(5))/4, sqrt(5)/2, (5+sqrt(5))/4]),
|
||||
[(5+4*sqrt(5))/11*[1,1,1]]
|
||||
))],
|
||||
["disdyakis dodecahedron", "catalan", 48, [3], 1,sqrt(249/194+285/194/sqrt(2)) ,(2+3*sqrt(2))/4, sqrt(183/98+213/98/sqrt(2)),
|
||||
sqrt(6582+4539*sqrt(2))/7,
|
||||
_point_ref(concat(
|
||||
_even_perms([sqrt(183/98+213/98/sqrt(2)),0,0]),
|
||||
_even_perms(sqrt(3+3/sqrt(2))/2 * [1,1,0]),[7/sqrt(6*(10-sqrt(2)))*[1,1,1]]
|
||||
))],
|
||||
["disdyakis triacontahedron","catalan", 120, [3], sqrt(15*(85-31*sqrt(5)))/11, sqrt(3477/964+7707/964/sqrt(5)), 5/4+13/4/sqrt(5),
|
||||
sqrt(441+195*sqrt(5))/10,sqrt(17718/5+39612/5/sqrt(5)),
|
||||
_point_ref(concat(
|
||||
_even_perms([0,0,3*(5+4*sqrt(5))/11]),
|
||||
_even_perms([0,(5-sqrt(5))/2,(5+sqrt(5))/2]),
|
||||
_even_perms([0,(15+9*sqrt(5))/10,3*(5+sqrt(5))/10]),
|
||||
_even_perms([3*(15+sqrt(5))/44,3*(5+4*sqrt(5))/22, (75+27*sqrt(5))/44]), [sqrt(5)*[1,1,1]]
|
||||
))],
|
||||
["pentagonal icositetrahedron","catalan",24, [5], 0.593465355971, 1.950681331784, 2.1015938932963, 2.29400105368695, 35.6302020120713,
|
||||
concat(
|
||||
_point_ref(_even_perms([0.21879664300048044,0.740183741369857,1.0236561781126901]),sign="even"),
|
||||
_point_ref(_even_perms([0.21879664300048044,1.0236561781126901,0.740183741369857]),sign="odd"),
|
||||
_point_ref(_even_perms([1.3614101519264425,0,0])),
|
||||
_point_ref([0.7401837413698572*[1,1,1]])
|
||||
)],
|
||||
["pentagonal hexecontahedron", "catalan", 60,[5], 0.58289953474498, 3.499527848905764,3.597624822551189,3.80854772878239, 189.789852066885,
|
||||
concat(
|
||||
_point_ref(_even_perms([0.192893711352359,0.218483370127321,2.097053835252087]), sign="even"),
|
||||
_point_ref(_even_perms([0,0.7554672605165955,1.9778389654202186])),
|
||||
_point_ref(_even_perms([0,1.888445389283669154,1.1671234364753339])),
|
||||
_point_ref(_even_perms([0.56771536946692131,0.824957552676275846,1.8654013108176956657]),sign="odd"),
|
||||
_point_ref(_even_perms([0.37482165811456229,1.13706613386050418,1.746186440985826345]), sign="even"),
|
||||
_point_ref(_even_perms([0.921228888309550,0.95998770139158,1.6469179406903744]),sign="even"),
|
||||
_point_ref(_even_perms([0.7283351769571914773,1.2720962825758121,1.5277030708585051]),sign="odd"),
|
||||
_point_ref([1.222371704903623092*[1,1,1]])
|
||||
)],
|
||||
["triakis tetrahedron","catalan", 12, [3], 9/5, 5*sqrt(22)/44, 5*sqrt(2)/12, 5*sqrt(6)/12, 25*sqrt(2)/36,
|
||||
concat(
|
||||
_point_ref([9*sqrt(2)/20*[1,1,1]],sign="even"),
|
||||
_point_ref([3*sqrt(2)/4*[1,1,1]],sign="odd")
|
||||
)],
|
||||
["tetrakis hexahedron", "catalan", 24, [3], 1, 2/sqrt(5), 2*sqrt(2)/3, 2/sqrt(3), 32/9,
|
||||
_point_ref(concat([[2/3,2/3,2/3]],_even_perms([1,0,0])))],
|
||||
["triakis octahedron", "catalan", 24, [3], 2, sqrt(17*(23+16*sqrt(2)))/34, 1/2+sqrt(2)/4,(1+sqrt(2))/2,3/2+sqrt(2),
|
||||
_point_ref(concat([[1,1,1]],_even_perms([1+sqrt(2),0,0])))],
|
||||
["pentakis dodecahedron", "catalan", 60, [3], 1,sqrt(477/436+97*sqrt(5)/218), sqrt(5)/4+11/12, sqrt(7/4+sqrt(5)/3), 125*sqrt(5)/36+205/36,
|
||||
_point_ref(concat(
|
||||
_even_perms([0,(5-PHI)/6, PHI/2+2/3]),
|
||||
_even_perms([0,(PHI+1)/2,PHI/2]),[(4*PHI-1)/6 * [1,1,1]]
|
||||
))],
|
||||
["triakis icosahedron", "catalan", 60, [3], 1, sqrt((139+199*PHI)/244), (8*PHI+1)/10, sqrt(13/8+19/8/sqrt(5)), (13*PHI+3)/2,
|
||||
_point_ref(concat(
|
||||
_even_perms([(PHI+7)/10, 0, (8*PHI+1)/10]),
|
||||
_even_perms([0, 1/2, (PHI+1)/2]),[PHI/2*[1,1,1]]
|
||||
))],
|
||||
["rhombic dodecahedron", "catalan", 12, [4], sqrt(3), sqrt(2/3), 2*sqrt(2)/3, 2/sqrt(3), 16*sqrt(3)/9,
|
||||
_point_ref(concat([[1,1,1]], _even_perms([2,0,0])))],
|
||||
["rhombic triacontahedron", "catalan", 30,[4], 1, sqrt(1+2/sqrt(5)), 1+1/sqrt(5), (1+sqrt(5))/2, 4*sqrt(5+2*sqrt(5)),
|
||||
concat(
|
||||
_point_ref(_even_perms([0,sqrt(1+2/sqrt(5)), sqrt((5+sqrt(5))/10)])),
|
||||
_point_ref(_even_perms([0,sqrt(2/(5+sqrt(5))), sqrt(1+2/sqrt(5))])),
|
||||
_point_ref([sqrt((5+sqrt(5))/10)*[1,1,1]])
|
||||
)],
|
||||
["deltoidal icositetrahedron", "catalan", 24, [4], 2*sqrt(10-sqrt(2))/7, 7*sqrt((7+4*sqrt(2))/(34 * (10-sqrt(2)))),
|
||||
7*sqrt(2*(2+sqrt(2)))/sqrt(10-sqrt(2))/4, 7*sqrt(2)/sqrt(10-sqrt(2))/2,
|
||||
(14+21*sqrt(2))/sqrt(10-sqrt(2)),
|
||||
_point_ref(concat(
|
||||
_even_perms([0,1,1]), _even_perms([sqrt(2),0,0]),
|
||||
_even_perms((4+sqrt(2))/7*[1,1,1])
|
||||
))],
|
||||
["deltoidal hexecontahedron", "catalan", 60, [4], sqrt(5*(85-31*sqrt(5)))/11, sqrt(571/164+1269/164/sqrt(5)), 5/4+13/4/sqrt(5),
|
||||
sqrt(147+65*sqrt(5))/6, sqrt(29530+13204*sqrt(5))/3,
|
||||
_point_ref(concat(
|
||||
_even_perms([0,0,sqrt(5)]),
|
||||
_even_perms([0,(15+sqrt(5))/22, (25+9*sqrt(5))/22]),
|
||||
_even_perms([0,(5+3*sqrt(5))/6, (5+sqrt(5))/6]),
|
||||
_even_perms([(5-sqrt(5))/4, sqrt(5)/2, (5+sqrt(5))/4]),
|
||||
[(5+4*sqrt(5))/11*[1,1,1]]
|
||||
))],
|
||||
["disdyakis dodecahedron", "catalan", 48, [3], 1,sqrt(249/194+285/194/sqrt(2)) ,(2+3*sqrt(2))/4, sqrt(183/98+213/98/sqrt(2)),
|
||||
sqrt(6582+4539*sqrt(2))/7,
|
||||
_point_ref(concat(
|
||||
_even_perms([sqrt(183/98+213/98/sqrt(2)),0,0]),
|
||||
_even_perms(sqrt(3+3/sqrt(2))/2 * [1,1,0]),[7/sqrt(6*(10-sqrt(2)))*[1,1,1]]
|
||||
))],
|
||||
["disdyakis triacontahedron","catalan", 120, [3], sqrt(15*(85-31*sqrt(5)))/11, sqrt(3477/964+7707/964/sqrt(5)), 5/4+13/4/sqrt(5),
|
||||
sqrt(441+195*sqrt(5))/10,sqrt(17718/5+39612/5/sqrt(5)),
|
||||
_point_ref(concat(
|
||||
_even_perms([0,0,3*(5+4*sqrt(5))/11]),
|
||||
_even_perms([0,(5-sqrt(5))/2,(5+sqrt(5))/2]),
|
||||
_even_perms([0,(15+9*sqrt(5))/10,3*(5+sqrt(5))/10]),
|
||||
_even_perms([3*(15+sqrt(5))/44,3*(5+4*sqrt(5))/22, (75+27*sqrt(5))/44]), [sqrt(5)*[1,1,1]]
|
||||
))],
|
||||
["pentagonal icositetrahedron","catalan",24, [5], 0.593465355971, 1.950681331784, 2.1015938932963, 2.29400105368695, 35.6302020120713,
|
||||
concat(
|
||||
_point_ref(_even_perms([0.21879664300048044,0.740183741369857,1.0236561781126901]),sign="even"),
|
||||
_point_ref(_even_perms([0.21879664300048044,1.0236561781126901,0.740183741369857]),sign="odd"),
|
||||
_point_ref(_even_perms([1.3614101519264425,0,0])),
|
||||
_point_ref([0.7401837413698572*[1,1,1]])
|
||||
)],
|
||||
["pentagonal hexecontahedron", "catalan", 60,[5], 0.58289953474498, 3.499527848905764,3.597624822551189,3.80854772878239, 189.789852066885,
|
||||
concat(
|
||||
_point_ref(_even_perms([0.192893711352359,0.218483370127321,2.097053835252087]), sign="even"),
|
||||
_point_ref(_even_perms([0,0.7554672605165955,1.9778389654202186])),
|
||||
_point_ref(_even_perms([0,1.888445389283669154,1.1671234364753339])),
|
||||
_point_ref(_even_perms([0.56771536946692131,0.824957552676275846,1.8654013108176956657]),sign="odd"),
|
||||
_point_ref(_even_perms([0.37482165811456229,1.13706613386050418,1.746186440985826345]), sign="even"),
|
||||
_point_ref(_even_perms([0.921228888309550,0.95998770139158,1.6469179406903744]),sign="even"),
|
||||
_point_ref(_even_perms([0.7283351769571914773,1.2720962825758121,1.5277030708585051]),sign="odd"),
|
||||
_point_ref([1.222371704903623092*[1,1,1]])
|
||||
)],
|
||||
];
|
||||
|
||||
|
||||
_stellated_polyhedra_ = [
|
||||
["great dodecahedron", "icosahedron", -sqrt(5/3-PHI)],
|
||||
["small stellated dodecahedron", "dodecahedron", sqrt((5+2*sqrt(5))/5)],
|
||||
["great stellated dodecahedron", "icosahedron", sqrt(2/3+PHI)],
|
||||
["great dodecahedron", "icosahedron", -sqrt(5/3-PHI)],
|
||||
["small stellated dodecahedron", "dodecahedron", sqrt((5+2*sqrt(5))/5)],
|
||||
["great stellated dodecahedron", "icosahedron", sqrt(2/3+PHI)],
|
||||
];
|
||||
|
||||
|
||||
@ -587,130 +587,130 @@ _stellated_polyhedra_ = [
|
||||
// longside = Specify the long side length for a trapezohedron. Ignored for other shapes.
|
||||
// h = Specify the height of the apex for a trapezohedron. Ignored for other shapes.
|
||||
function regular_polyhedron_info(
|
||||
info=undef, name=undef,
|
||||
index=undef, type=undef,
|
||||
faces=undef, facetype=undef,
|
||||
hasfaces=undef, side=1,
|
||||
ir=undef, mr=undef, or=undef,
|
||||
r=undef, d=undef,
|
||||
anchor=[0,0,0], center=undef,
|
||||
facedown=true, stellate=false,
|
||||
longside=undef, h=undef // special parameters for trapezohedron
|
||||
info=undef, name=undef,
|
||||
index=undef, type=undef,
|
||||
faces=undef, facetype=undef,
|
||||
hasfaces=undef, side=1,
|
||||
ir=undef, mr=undef, or=undef,
|
||||
r=undef, d=undef,
|
||||
anchor=[0,0,0], center=undef,
|
||||
facedown=true, stellate=false,
|
||||
longside=undef, h=undef // special parameters for trapezohedron
|
||||
) = let(
|
||||
anchor = !is_undef(center) ? [0,0,0] : anchor,
|
||||
argcount = num_defined([ir,mr,or,r,d])
|
||||
)
|
||||
assert(argcount<=1, "You must specify only one of 'ir', 'mr', 'or', 'r', and 'd'")
|
||||
let(
|
||||
//////////////////////
|
||||
//Index values into the _polyhedra_ array
|
||||
//
|
||||
pname = 0, // name of polyhedron
|
||||
class = 1, // class name (e.g. platonic, archimedean)
|
||||
facecount = 2, // number of faces
|
||||
facevertices = 3, // vertices on the faces, e.g. [3] for all triangles, [3,4] for triangles and squares
|
||||
edgelen = 4, // length of the edge for the vertex list in the database
|
||||
in_radius = 5, // in radius for unit polyhedron (shortest side 1)
|
||||
mid_radius = 6, // mid radius for unit polyhedron
|
||||
out_radius = 7, // out radius for unit polyhedron
|
||||
volume = 8, // volume of unit polyhedron (data not validated, not used right now)
|
||||
vertices = 9, // vertex list (in arbitrary order)
|
||||
//////////////////////
|
||||
r = !is_undef(d) ? d/2 : r,
|
||||
or = !is_undef(r) ? r : or,
|
||||
stellate_index = search([name], _stellated_polyhedra_, 1, 0)[0],
|
||||
name = stellate_index==[] ? name : _stellated_polyhedra_[stellate_index][1],
|
||||
stellate = stellate_index==[] ? stellate : _stellated_polyhedra_[stellate_index][2],
|
||||
indexlist = (
|
||||
name=="trapezohedron" ? [0] : [ // dumy list of one item
|
||||
for(i=[0:1:len(_polyhedra_)-1]) (
|
||||
if (
|
||||
(is_undef(name) || _polyhedra_[i][pname]==name) &&
|
||||
(is_undef(type) || _polyhedra_[i][class]==type) &&
|
||||
(is_undef(faces) || _polyhedra_[i][facecount]==faces) &&
|
||||
(
|
||||
is_undef(facetype) || 0==compare_lists(
|
||||
is_list(facetype)? reverse(sort(facetype)) : [facetype],
|
||||
_polyhedra_[i][facevertices]
|
||||
)
|
||||
) &&
|
||||
(is_undef(hasfaces) || any([for (ft=hasfaces) in_list(ft,_polyhedra_[i][facevertices])]))
|
||||
) i
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
assert(len(indexlist)>0, "No polyhedra meet your specification")
|
||||
let(validindex = is_undef(index) || (index>=0 && index<len(indexlist)))
|
||||
assert(validindex, str(
|
||||
len(indexlist),
|
||||
" polyhedra meet specifications, so 'index' must be in [0,",
|
||||
len(indexlist)-1,
|
||||
"], but 'index' is ",
|
||||
index
|
||||
))
|
||||
let(
|
||||
entry = (
|
||||
name == "trapezohedron"? (
|
||||
trapezohedron(faces=faces, side=side, longside=longside, h=h, r=r)
|
||||
) : (
|
||||
_polyhedra_[!is_undef(index)?
|
||||
indexlist[index] :
|
||||
indexlist[0]]
|
||||
)
|
||||
),
|
||||
valid_facedown = is_bool(facedown) || in_list(facedown, entry[facevertices])
|
||||
)
|
||||
assert(valid_facedown,str("'facedown' set to ",facedown," but selected polygon only has faces with size(s) ",entry[facevertices]))
|
||||
let(
|
||||
scalefactor = (
|
||||
name=="trapezohedron" ? 1 : (
|
||||
argcount == 0? side :
|
||||
!is_undef(ir)? ir/entry[in_radius] :
|
||||
!is_undef(mr)? mr/entry[mid_radius] : or/entry[out_radius]
|
||||
) / entry[edgelen]
|
||||
),
|
||||
face_triangles = hull(entry[vertices]),
|
||||
faces_normals_vertices = stellate_faces(
|
||||
entry[edgelen], stellate, entry[vertices],
|
||||
entry[facevertices]==[3]?
|
||||
[face_triangles, [for(face=face_triangles) _facenormal(entry[vertices],face)]] :
|
||||
_full_faces(entry[vertices], face_triangles)
|
||||
),
|
||||
faces = faces_normals_vertices[0],
|
||||
faces_vertex_count = [for(face=faces) len(face)],
|
||||
facedown = facedown == true ? (stellate==false? entry[facevertices][0] : 3) : facedown,
|
||||
down_direction = facedown == false? [0,0,-1] :
|
||||
faces_normals_vertices[1][search(facedown, faces_vertex_count)[0]],
|
||||
scaled_points = scalefactor * rot(p=faces_normals_vertices[2], from=down_direction, to=[0,0,-1]),
|
||||
bounds = pointlist_bounds(scaled_points),
|
||||
boundtable = [bounds[0], [0,0,0], bounds[1]],
|
||||
translation = [for(i=[0:2]) -boundtable[1+anchor[i]][i]],
|
||||
face_normals = rot(p=faces_normals_vertices[1], from=down_direction, to=[0,0,-1]),
|
||||
side_length = scalefactor * entry[edgelen]
|
||||
)
|
||||
info == "fullentry" ? [
|
||||
scaled_points,
|
||||
translation,
|
||||
stellate ? faces : face_triangles,
|
||||
faces,
|
||||
face_normals,
|
||||
side_length*entry[in_radius]
|
||||
] :
|
||||
info == "vnf" ? [move(translation,p=scaled_points), stellate ? faces : face_triangles] :
|
||||
info == "vertices" ? move(translation,p=scaled_points) :
|
||||
info == "faces" ? faces :
|
||||
info == "face normals" ? face_normals :
|
||||
info == "in_radius" ? side_length * entry[in_radius] :
|
||||
info == "mid_radius" ? side_length * entry[mid_radius] :
|
||||
info == "out_radius" ? side_length * entry[out_radius] :
|
||||
info == "index set" ? indexlist :
|
||||
info == "face vertices" ? (stellate==false? entry[facevertices] : [3]) :
|
||||
info == "edge length" ? scalefactor * entry[edgelen] :
|
||||
info == "center" ? translation :
|
||||
info == "type" ? entry[class] :
|
||||
info == "name" ? entry[pname] :
|
||||
echo_warning(str("Unknown info type '",info,"' requested"));
|
||||
anchor = !is_undef(center) ? [0,0,0] : anchor,
|
||||
argcount = num_defined([ir,mr,or,r,d])
|
||||
)
|
||||
assert(argcount<=1, "You must specify only one of 'ir', 'mr', 'or', 'r', and 'd'")
|
||||
let(
|
||||
//////////////////////
|
||||
//Index values into the _polyhedra_ array
|
||||
//
|
||||
pname = 0, // name of polyhedron
|
||||
class = 1, // class name (e.g. platonic, archimedean)
|
||||
facecount = 2, // number of faces
|
||||
facevertices = 3, // vertices on the faces, e.g. [3] for all triangles, [3,4] for triangles and squares
|
||||
edgelen = 4, // length of the edge for the vertex list in the database
|
||||
in_radius = 5, // in radius for unit polyhedron (shortest side 1)
|
||||
mid_radius = 6, // mid radius for unit polyhedron
|
||||
out_radius = 7, // out radius for unit polyhedron
|
||||
volume = 8, // volume of unit polyhedron (data not validated, not used right now)
|
||||
vertices = 9, // vertex list (in arbitrary order)
|
||||
//////////////////////
|
||||
r = !is_undef(d) ? d/2 : r,
|
||||
or = !is_undef(r) ? r : or,
|
||||
stellate_index = search([name], _stellated_polyhedra_, 1, 0)[0],
|
||||
name = stellate_index==[] ? name : _stellated_polyhedra_[stellate_index][1],
|
||||
stellate = stellate_index==[] ? stellate : _stellated_polyhedra_[stellate_index][2],
|
||||
indexlist = (
|
||||
name=="trapezohedron" ? [0] : [ // dumy list of one item
|
||||
for(i=[0:1:len(_polyhedra_)-1]) (
|
||||
if (
|
||||
(is_undef(name) || _polyhedra_[i][pname]==name) &&
|
||||
(is_undef(type) || _polyhedra_[i][class]==type) &&
|
||||
(is_undef(faces) || _polyhedra_[i][facecount]==faces) &&
|
||||
(
|
||||
is_undef(facetype) || 0==compare_lists(
|
||||
is_list(facetype)? reverse(sort(facetype)) : [facetype],
|
||||
_polyhedra_[i][facevertices]
|
||||
)
|
||||
) &&
|
||||
(is_undef(hasfaces) || any([for (ft=hasfaces) in_list(ft,_polyhedra_[i][facevertices])]))
|
||||
) i
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
assert(len(indexlist)>0, "No polyhedra meet your specification")
|
||||
let(validindex = is_undef(index) || (index>=0 && index<len(indexlist)))
|
||||
assert(validindex, str(
|
||||
len(indexlist),
|
||||
" polyhedra meet specifications, so 'index' must be in [0,",
|
||||
len(indexlist)-1,
|
||||
"], but 'index' is ",
|
||||
index
|
||||
))
|
||||
let(
|
||||
entry = (
|
||||
name == "trapezohedron"? (
|
||||
trapezohedron(faces=faces, side=side, longside=longside, h=h, r=r)
|
||||
) : (
|
||||
_polyhedra_[!is_undef(index)?
|
||||
indexlist[index] :
|
||||
indexlist[0]]
|
||||
)
|
||||
),
|
||||
valid_facedown = is_bool(facedown) || in_list(facedown, entry[facevertices])
|
||||
)
|
||||
assert(valid_facedown,str("'facedown' set to ",facedown," but selected polygon only has faces with size(s) ",entry[facevertices]))
|
||||
let(
|
||||
scalefactor = (
|
||||
name=="trapezohedron" ? 1 : (
|
||||
argcount == 0? side :
|
||||
!is_undef(ir)? ir/entry[in_radius] :
|
||||
!is_undef(mr)? mr/entry[mid_radius] : or/entry[out_radius]
|
||||
) / entry[edgelen]
|
||||
),
|
||||
face_triangles = hull(entry[vertices]),
|
||||
faces_normals_vertices = stellate_faces(
|
||||
entry[edgelen], stellate, entry[vertices],
|
||||
entry[facevertices]==[3]?
|
||||
[face_triangles, [for(face=face_triangles) _facenormal(entry[vertices],face)]] :
|
||||
_full_faces(entry[vertices], face_triangles)
|
||||
),
|
||||
faces = faces_normals_vertices[0],
|
||||
faces_vertex_count = [for(face=faces) len(face)],
|
||||
facedown = facedown == true ? (stellate==false? entry[facevertices][0] : 3) : facedown,
|
||||
down_direction = facedown == false? [0,0,-1] :
|
||||
faces_normals_vertices[1][search(facedown, faces_vertex_count)[0]],
|
||||
scaled_points = scalefactor * rot(p=faces_normals_vertices[2], from=down_direction, to=[0,0,-1]),
|
||||
bounds = pointlist_bounds(scaled_points),
|
||||
boundtable = [bounds[0], [0,0,0], bounds[1]],
|
||||
translation = [for(i=[0:2]) -boundtable[1+anchor[i]][i]],
|
||||
face_normals = rot(p=faces_normals_vertices[1], from=down_direction, to=[0,0,-1]),
|
||||
side_length = scalefactor * entry[edgelen]
|
||||
)
|
||||
info == "fullentry" ? [
|
||||
scaled_points,
|
||||
translation,
|
||||
stellate ? faces : face_triangles,
|
||||
faces,
|
||||
face_normals,
|
||||
side_length*entry[in_radius]
|
||||
] :
|
||||
info == "vnf" ? [move(translation,p=scaled_points), stellate ? faces : face_triangles] :
|
||||
info == "vertices" ? move(translation,p=scaled_points) :
|
||||
info == "faces" ? faces :
|
||||
info == "face normals" ? face_normals :
|
||||
info == "in_radius" ? side_length * entry[in_radius] :
|
||||
info == "mid_radius" ? side_length * entry[mid_radius] :
|
||||
info == "out_radius" ? side_length * entry[out_radius] :
|
||||
info == "index set" ? indexlist :
|
||||
info == "face vertices" ? (stellate==false? entry[facevertices] : [3]) :
|
||||
info == "edge length" ? scalefactor * entry[edgelen] :
|
||||
info == "center" ? translation :
|
||||
info == "type" ? entry[class] :
|
||||
info == "name" ? entry[pname] :
|
||||
echo_warning(str("Unknown info type '",info,"' requested"));
|
||||
|
||||
|
||||
|
||||
@ -718,68 +718,68 @@ function regular_polyhedron_info(
|
||||
/// either cross product or just rotate to
|
||||
///
|
||||
function stellate_faces(scalefactor,stellate,vertices,faces_normals) =
|
||||
(stellate == false || stellate == 0)? concat(faces_normals,[vertices]) :
|
||||
let(
|
||||
faces = [for(face=faces_normals[0]) select(face,hull(select(vertices,face)))],
|
||||
direction = [for(i=[0:1:len(faces)-1]) _facenormal(vertices, faces[i])*faces_normals[1][i]>0 ? 1 : -1],
|
||||
maxvertex = len(vertices),
|
||||
newpts = [for(i=[0:1:len(faces)-1]) mean(select(vertices,faces[i]))+stellate*scalefactor*faces_normals[1][i]],
|
||||
newfaces = [for(i=[0:1:len(faces)-1], j=[0:len(faces[i])-1]) concat([i+maxvertex],select(faces[i], [j, j+direction[i]]))],
|
||||
allpts = concat(vertices, newpts),
|
||||
normals = [for(face=newfaces) _facenormal(allpts,face)]
|
||||
) [newfaces, normals, allpts];
|
||||
(stellate == false || stellate == 0)? concat(faces_normals,[vertices]) :
|
||||
let(
|
||||
faces = [for(face=faces_normals[0]) select(face,hull(select(vertices,face)))],
|
||||
direction = [for(i=[0:1:len(faces)-1]) _facenormal(vertices, faces[i])*faces_normals[1][i]>0 ? 1 : -1],
|
||||
maxvertex = len(vertices),
|
||||
newpts = [for(i=[0:1:len(faces)-1]) mean(select(vertices,faces[i]))+stellate*scalefactor*faces_normals[1][i]],
|
||||
newfaces = [for(i=[0:1:len(faces)-1], j=[0:len(faces[i])-1]) concat([i+maxvertex],select(faces[i], [j, j+direction[i]]))],
|
||||
allpts = concat(vertices, newpts),
|
||||
normals = [for(face=newfaces) _facenormal(allpts,face)]
|
||||
) [newfaces, normals, allpts];
|
||||
|
||||
|
||||
function trapezohedron(faces, r, side, longside, h) =
|
||||
assert(faces%2==0, "Number of faces must be even")
|
||||
let(
|
||||
N = faces/2,
|
||||
parmcount = num_defined([r,side,longside,h])
|
||||
)
|
||||
assert(parmcount==2,"Must define exactly two of 'r', 'side', 'longside', and 'height'")
|
||||
let(
|
||||
separation = (
|
||||
!is_undef(h) ? 2*h*sqr(tan(90/N)) :
|
||||
(!is_undef(r) && !is_undef(side))? sqrt(side*side+2*r*r*(cos(180/N)-1)) :
|
||||
(!is_undef(r) && !is_undef(longside))? 2 * sqrt(sqr(longside)-sqr(r)) / (1-sqr(tan(90/N))) * sqr(tan(90/N)) :
|
||||
2*sqr(sin(90/N))*sqrt((sqr(side) + 2*sqr(longside)*(cos(180/N)-1)) / (cos(180/N)-1) / (cos(180/N)+cos(360/N)))
|
||||
)
|
||||
)
|
||||
assert(separation==separation, "Impossible trapezohedron specification")
|
||||
let(
|
||||
h = !is_undef(h) ? h : 0.5*separation / sqr(tan(90/N)),
|
||||
r = (
|
||||
!is_undef(r) ? r :
|
||||
!is_undef(side) ? sqrt((sqr(separation) - sqr(side))/2/(cos(180/N)-1)) :
|
||||
sqrt(sqr(longside) - sqr(h-separation/2))
|
||||
),
|
||||
top = [for(i=[0:1:N-1]) [r*cos(360/N*i), r*sin(360/N*i),separation/2]],
|
||||
bot = [for(i=[0:1:N-1]) [r*cos(180/N+360/N*i), r*sin(180/N+360/N*i),-separation/2]],
|
||||
vertices = concat([[0,0,h],[0,0,-h]],top,bot)
|
||||
) [
|
||||
"trapezohedron", "trapezohedron", faces, [4],
|
||||
!is_undef(side)? side : sqrt(sqr(separation)-2*r*(cos(180/N)-1)), // actual side length
|
||||
h*r/sqrt(r*r+sqr(h+separation/2)), // in_radius
|
||||
h*r/sqrt(r*r+sqr(h-separation/2)), // mid_radius
|
||||
max(h,sqrt(r*r+sqr(separation/2))), // out_radius
|
||||
undef, // volume
|
||||
vertices
|
||||
];
|
||||
assert(faces%2==0, "Number of faces must be even")
|
||||
let(
|
||||
N = faces/2,
|
||||
parmcount = num_defined([r,side,longside,h])
|
||||
)
|
||||
assert(parmcount==2,"Must define exactly two of 'r', 'side', 'longside', and 'height'")
|
||||
let(
|
||||
separation = (
|
||||
!is_undef(h) ? 2*h*sqr(tan(90/N)) :
|
||||
(!is_undef(r) && !is_undef(side))? sqrt(side*side+2*r*r*(cos(180/N)-1)) :
|
||||
(!is_undef(r) && !is_undef(longside))? 2 * sqrt(sqr(longside)-sqr(r)) / (1-sqr(tan(90/N))) * sqr(tan(90/N)) :
|
||||
2*sqr(sin(90/N))*sqrt((sqr(side) + 2*sqr(longside)*(cos(180/N)-1)) / (cos(180/N)-1) / (cos(180/N)+cos(360/N)))
|
||||
)
|
||||
)
|
||||
assert(separation==separation, "Impossible trapezohedron specification")
|
||||
let(
|
||||
h = !is_undef(h) ? h : 0.5*separation / sqr(tan(90/N)),
|
||||
r = (
|
||||
!is_undef(r) ? r :
|
||||
!is_undef(side) ? sqrt((sqr(separation) - sqr(side))/2/(cos(180/N)-1)) :
|
||||
sqrt(sqr(longside) - sqr(h-separation/2))
|
||||
),
|
||||
top = [for(i=[0:1:N-1]) [r*cos(360/N*i), r*sin(360/N*i),separation/2]],
|
||||
bot = [for(i=[0:1:N-1]) [r*cos(180/N+360/N*i), r*sin(180/N+360/N*i),-separation/2]],
|
||||
vertices = concat([[0,0,h],[0,0,-h]],top,bot)
|
||||
) [
|
||||
"trapezohedron", "trapezohedron", faces, [4],
|
||||
!is_undef(side)? side : sqrt(sqr(separation)-2*r*(cos(180/N)-1)), // actual side length
|
||||
h*r/sqrt(r*r+sqr(h+separation/2)), // in_radius
|
||||
h*r/sqrt(r*r+sqr(h-separation/2)), // mid_radius
|
||||
max(h,sqrt(r*r+sqr(separation/2))), // out_radius
|
||||
undef, // volume
|
||||
vertices
|
||||
];
|
||||
|
||||
|
||||
function _facenormal(pts, face) = unit(cross(pts[face[2]]-pts[face[0]], pts[face[1]]-pts[face[0]]));
|
||||
|
||||
// hull() function returns triangulated faces. This function identifies the vertices that belong to each face
|
||||
// by grouping together the face triangles that share normal vectors. The output gives the face polygon
|
||||
// hull() function returns triangulated faces. This function identifies the vertices that belong to each face
|
||||
// by grouping together the face triangles that share normal vectors. The output gives the face polygon
|
||||
// point indices in arbitrary order (not usable as input to a polygon call) and a normal vector.
|
||||
|
||||
function _full_faces(pts,faces) =
|
||||
let(
|
||||
normals = [for(face=faces) quant(_facenormal(pts,face),1e-12)],
|
||||
groups = _unique_groups(normals),
|
||||
faces = [for(entry=groups) unique(flatten(select(faces, entry)))],
|
||||
facenormals = [for(entry=groups) normals[entry[0]]]
|
||||
) [faces, facenormals];
|
||||
let(
|
||||
normals = [for(face=faces) quant(_facenormal(pts,face),1e-12)],
|
||||
groups = _unique_groups(normals),
|
||||
faces = [for(entry=groups) unique(flatten(select(faces, entry)))],
|
||||
facenormals = [for(entry=groups) normals[entry[0]]]
|
||||
) [faces, facenormals];
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
162
primitives.scad
162
primitives.scad
@ -32,16 +32,16 @@
|
||||
// stroke(path, closed=true);
|
||||
// move_copies(path) color("blue") circle(d=2,$fn=8);
|
||||
function square(size=1, center, anchor, spin=0) =
|
||||
let(
|
||||
anchor = get_anchor(anchor, center, [-1,-1], [-1,-1]),
|
||||
size = is_num(size)? [size,size] : point2d(size),
|
||||
path = [
|
||||
[ size.x,-size.y],
|
||||
[-size.x,-size.y],
|
||||
[-size.x, size.y],
|
||||
[ size.x, size.y]
|
||||
] / 2
|
||||
) reorient(anchor,spin, two_d=true, size=size, p=path);
|
||||
let(
|
||||
anchor = get_anchor(anchor, center, [-1,-1], [-1,-1]),
|
||||
size = is_num(size)? [size,size] : point2d(size),
|
||||
path = [
|
||||
[ size.x,-size.y],
|
||||
[-size.x,-size.y],
|
||||
[-size.x, size.y],
|
||||
[ size.x, size.y]
|
||||
] / 2
|
||||
) reorient(anchor,spin, two_d=true, size=size, p=path);
|
||||
|
||||
|
||||
// Function&Module: circle()
|
||||
@ -62,11 +62,11 @@ function square(size=1, center, anchor, spin=0) =
|
||||
// Example(NORENDER): Called as Function
|
||||
// path = circle(d=50, anchor=FRONT, spin=45);
|
||||
function circle(r, d, anchor=CENTER, spin=0) =
|
||||
let(
|
||||
r = get_radius(r=r, d=d, dflt=1),
|
||||
sides = segs(r),
|
||||
path = [for (i=[0:1:sides-1]) let(a=360-i*360/sides) r*[cos(a),sin(a)]]
|
||||
) reorient(anchor,spin, two_d=true, r=r, p=path);
|
||||
let(
|
||||
r = get_radius(r=r, d=d, dflt=1),
|
||||
sides = segs(r),
|
||||
path = [for (i=[0:1:sides-1]) let(a=360-i*360/sides) r*[cos(a),sin(a)]]
|
||||
) reorient(anchor,spin, two_d=true, r=r, p=path);
|
||||
|
||||
|
||||
|
||||
@ -105,36 +105,36 @@ function circle(r, d, anchor=CENTER, spin=0) =
|
||||
// vnf_polyhedron(vnf);
|
||||
module cube(size=1, center, anchor, spin=0, orient=UP)
|
||||
{
|
||||
anchor = get_anchor(anchor, center, ALLNEG, ALLNEG);
|
||||
size = scalar_vec3(size);
|
||||
attachable(anchor,spin,orient, size=size) {
|
||||
linear_extrude(height=size.z, center=true, convexity=2) {
|
||||
square([size.x,size.y], center=true);
|
||||
}
|
||||
children();
|
||||
}
|
||||
anchor = get_anchor(anchor, center, ALLNEG, ALLNEG);
|
||||
size = scalar_vec3(size);
|
||||
attachable(anchor,spin,orient, size=size) {
|
||||
linear_extrude(height=size.z, center=true, convexity=2) {
|
||||
square([size.x,size.y], center=true);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
function cube(size=1, center, anchor, spin=0, orient=UP) =
|
||||
let(
|
||||
siz = scalar_vec3(size),
|
||||
anchor = get_anchor(anchor, center, ALLNEG, ALLNEG),
|
||||
unscaled = [
|
||||
[-1,-1,-1],[1,-1,-1],[1,1,-1],[-1,1,-1],
|
||||
[-1,-1, 1],[1,-1, 1],[1,1, 1],[-1,1, 1],
|
||||
]/2,
|
||||
verts = is_num(size)? unscaled * size :
|
||||
is_vector(size,3)? [for (p=unscaled) vmul(p,size)] :
|
||||
assert(is_num(size) || is_vector(size,3)),
|
||||
faces = [
|
||||
[0,1,2], [0,2,3], //BOTTOM
|
||||
[0,4,5], [0,5,1], //FRONT
|
||||
[1,5,6], [1,6,2], //RIGHT
|
||||
[2,6,7], [2,7,3], //BACK
|
||||
[3,7,4], [3,4,0], //LEFT
|
||||
[6,4,7], [6,5,4] //TOP
|
||||
]
|
||||
) [reorient(anchor,spin,orient, size=siz, p=verts), faces];
|
||||
let(
|
||||
siz = scalar_vec3(size),
|
||||
anchor = get_anchor(anchor, center, ALLNEG, ALLNEG),
|
||||
unscaled = [
|
||||
[-1,-1,-1],[1,-1,-1],[1,1,-1],[-1,1,-1],
|
||||
[-1,-1, 1],[1,-1, 1],[1,1, 1],[-1,1, 1],
|
||||
]/2,
|
||||
verts = is_num(size)? unscaled * size :
|
||||
is_vector(size,3)? [for (p=unscaled) vmul(p,size)] :
|
||||
assert(is_num(size) || is_vector(size,3)),
|
||||
faces = [
|
||||
[0,1,2], [0,2,3], //BOTTOM
|
||||
[0,4,5], [0,5,1], //FRONT
|
||||
[1,5,6], [1,6,2], //RIGHT
|
||||
[2,6,7], [2,7,3], //BACK
|
||||
[3,7,4], [3,4,0], //LEFT
|
||||
[6,4,7], [6,5,4] //TOP
|
||||
]
|
||||
) [reorient(anchor,spin,orient, size=siz, p=verts), faces];
|
||||
|
||||
|
||||
// Function&Module: cylinder()
|
||||
@ -183,45 +183,45 @@ function cube(size=1, center, anchor, spin=0, orient=UP) =
|
||||
// }
|
||||
module cylinder(h, r1, r2, center, l, r, d, d1, d2, anchor, spin=0, orient=UP)
|
||||
{
|
||||
anchor = get_anchor(anchor, center, BOTTOM, BOTTOM);
|
||||
r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=1);
|
||||
r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=1);
|
||||
l = first_defined([h, l, 1]);
|
||||
sides = segs(max(r1,r2));
|
||||
attachable(anchor,spin,orient, r1=r1, r2=r2, l=l) {
|
||||
if(r1>r2) {
|
||||
linear_extrude(height=l, center=true, convexity=2, scale=r2/r1) {
|
||||
circle(r=r1);
|
||||
}
|
||||
} else {
|
||||
zflip() {
|
||||
linear_extrude(height=l, center=true, convexity=2, scale=r1/r2) {
|
||||
circle(r=r2);
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
anchor = get_anchor(anchor, center, BOTTOM, BOTTOM);
|
||||
r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=1);
|
||||
r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=1);
|
||||
l = first_defined([h, l, 1]);
|
||||
sides = segs(max(r1,r2));
|
||||
attachable(anchor,spin,orient, r1=r1, r2=r2, l=l) {
|
||||
if(r1>r2) {
|
||||
linear_extrude(height=l, center=true, convexity=2, scale=r2/r1) {
|
||||
circle(r=r1);
|
||||
}
|
||||
} else {
|
||||
zflip() {
|
||||
linear_extrude(height=l, center=true, convexity=2, scale=r1/r2) {
|
||||
circle(r=r2);
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
function cylinder(h, r1, r2, center, l, r, d, d1, d2, anchor, spin=0, orient=UP) =
|
||||
let(
|
||||
anchor = get_anchor(anchor, center, BOTTOM, BOTTOM),
|
||||
r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=1),
|
||||
r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=1),
|
||||
l = first_defined([h, l, 1]),
|
||||
sides = segs(max(r1,r2)),
|
||||
verts = [
|
||||
for (i=[0:1:sides-1]) let(a=360*(1-i/sides)) [r1*cos(a),r1*sin(a),-l/2],
|
||||
for (i=[0:1:sides-1]) let(a=360*(1-i/sides)) [r2*cos(a),r2*sin(a), l/2],
|
||||
],
|
||||
faces = [
|
||||
[for (i=[0:1:sides-1]) sides-1-i],
|
||||
for (i=[0:1:sides-1]) [i, ((i+1)%sides)+sides, i+sides],
|
||||
for (i=[0:1:sides-1]) [i, (i+1)%sides, ((i+1)%sides)+sides],
|
||||
[for (i=[0:1:sides-1]) sides+i]
|
||||
]
|
||||
) [reorient(anchor,spin,orient, l=l, r1=r1, r2=r2, p=verts), faces];
|
||||
let(
|
||||
anchor = get_anchor(anchor, center, BOTTOM, BOTTOM),
|
||||
r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=1),
|
||||
r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=1),
|
||||
l = first_defined([h, l, 1]),
|
||||
sides = segs(max(r1,r2)),
|
||||
verts = [
|
||||
for (i=[0:1:sides-1]) let(a=360*(1-i/sides)) [r1*cos(a),r1*sin(a),-l/2],
|
||||
for (i=[0:1:sides-1]) let(a=360*(1-i/sides)) [r2*cos(a),r2*sin(a), l/2],
|
||||
],
|
||||
faces = [
|
||||
[for (i=[0:1:sides-1]) sides-1-i],
|
||||
for (i=[0:1:sides-1]) [i, ((i+1)%sides)+sides, i+sides],
|
||||
for (i=[0:1:sides-1]) [i, (i+1)%sides, ((i+1)%sides)+sides],
|
||||
[for (i=[0:1:sides-1]) sides+i]
|
||||
]
|
||||
) [reorient(anchor,spin,orient, l=l, r1=r1, r2=r2, p=verts), faces];
|
||||
|
||||
|
||||
|
||||
@ -268,11 +268,11 @@ function cylinder(h, r1, r2, center, l, r, d, d1, d2, anchor, spin=0, orient=UP)
|
||||
// vnf = sphere(d=100, style="icosa");
|
||||
// vnf_polyhedron(vnf);
|
||||
module sphere(r, d, circum=false, style="aligned", anchor=CENTER, spin=0, orient=UP)
|
||||
spheroid(r=r, d=d, circum=circum, style=style, anchor=anchor, spin=spin, orient=orient) children();
|
||||
spheroid(r=r, d=d, circum=circum, style=style, anchor=anchor, spin=spin, orient=orient) children();
|
||||
|
||||
|
||||
function sphere(r, d, circum=false, style="aligned", anchor=CENTER, spin=0, orient=UP) =
|
||||
spheroid(r=r, d=d, circum=circum, style=style, anchor=anchor, spin=spin, orient=orient);
|
||||
spheroid(r=r, d=d, circum=circum, style=style, anchor=anchor, spin=spin, orient=orient);
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -65,12 +65,12 @@ function QuatZ(a=0) = Quat([0,0,1],a);
|
||||
// Arguments:
|
||||
// a = The triplet of rotation angles, [X,Y,Z]
|
||||
function QuatXYZ(a=[0,0,0]) =
|
||||
let(
|
||||
qx = QuatX(a[0]),
|
||||
qy = QuatY(a[1]),
|
||||
qz = QuatZ(a[2])
|
||||
)
|
||||
Q_Mul(qz, Q_Mul(qy, qx));
|
||||
let(
|
||||
qx = QuatX(a[0]),
|
||||
qy = QuatY(a[1]),
|
||||
qz = QuatZ(a[2])
|
||||
)
|
||||
Q_Mul(qz, Q_Mul(qy, qx));
|
||||
|
||||
|
||||
// Function: Q_Ident()
|
||||
@ -125,10 +125,10 @@ function Q_Sub(a, b) = a-b;
|
||||
// Q_Mul(a, b)
|
||||
// Description: Multiplies quaternion `a` by quaternion `b`.
|
||||
function Q_Mul(a, b) = [
|
||||
a[3]*b.x + a.x*b[3] + a.y*b.z - a.z*b.y,
|
||||
a[3]*b.y - a.x*b.z + a.y*b[3] + a.z*b.x,
|
||||
a[3]*b.z + a.x*b.y - a.y*b.x + a.z*b[3],
|
||||
a[3]*b[3] - a.x*b.x - a.y*b.y - a.z*b.z,
|
||||
a[3]*b.x + a.x*b[3] + a.y*b.z - a.z*b.y,
|
||||
a[3]*b.y - a.x*b.z + a.y*b[3] + a.z*b.x,
|
||||
a[3]*b.z + a.x*b.y - a.y*b.x + a.z*b[3],
|
||||
a[3]*b[3] - a.x*b.x - a.y*b.y - a.z*b.z,
|
||||
];
|
||||
|
||||
|
||||
@ -140,14 +140,14 @@ function Q_Mul(a, b) = [
|
||||
// of each cumulative Quaternion product. It starts with the first quaternion
|
||||
// given in the list, and applies successive quaternion rotations in list order.
|
||||
function Q_Cumulative(v, _i=0, _acc=[]) =
|
||||
_i==len(v) ? _acc :
|
||||
Q_Cumulative(
|
||||
v, _i+1,
|
||||
concat(
|
||||
_acc,
|
||||
[_i==0 ? v[_i] : Q_Mul(v[_i], select(_acc,-1))]
|
||||
)
|
||||
);
|
||||
_i==len(v) ? _acc :
|
||||
Q_Cumulative(
|
||||
v, _i+1,
|
||||
concat(
|
||||
_acc,
|
||||
[_i==0 ? v[_i] : Q_Mul(v[_i], select(_acc,-1))]
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
// Function: Q_Dot()
|
||||
@ -215,23 +215,23 @@ function Q_Dist(q1, q2) = norm(q2-q1);
|
||||
// Qrot(q) right(80) cube([10,10,1]);
|
||||
// #sphere(r=80);
|
||||
function Q_Slerp(q1, q2, u) =
|
||||
assert(is_num(u) || is_num(u[0]))
|
||||
!is_num(u)? [for (uu=u) Q_Slerp(q1,q2,uu)] :
|
||||
assert(is_num(u) || is_num(u[0]))
|
||||
!is_num(u)? [for (uu=u) Q_Slerp(q1,q2,uu)] :
|
||||
let(
|
||||
q1 = Q_Normalize(q1),
|
||||
q2 = Q_Normalize(q2),
|
||||
dot = Q_Dot(q1, q2)
|
||||
) let(
|
||||
q2 = dot<0? Q_Neg(q2) : q2,
|
||||
dot = dot<0? -dot : dot
|
||||
) (dot>0.9995)? Q_Normalize(q1 + (u * (q2-q1))) :
|
||||
let(
|
||||
dot = constrain(dot,-1,1),
|
||||
theta_0 = acos(dot),
|
||||
theta = theta_0 * u,
|
||||
q3 = Q_Normalize(q2 - q1*dot),
|
||||
out = q1*cos(theta) + q3*sin(theta)
|
||||
) out;
|
||||
q1 = Q_Normalize(q1),
|
||||
q2 = Q_Normalize(q2),
|
||||
dot = Q_Dot(q1, q2)
|
||||
) let(
|
||||
q2 = dot<0? Q_Neg(q2) : q2,
|
||||
dot = dot<0? -dot : dot
|
||||
) (dot>0.9995)? Q_Normalize(q1 + (u * (q2-q1))) :
|
||||
let(
|
||||
dot = constrain(dot,-1,1),
|
||||
theta_0 = acos(dot),
|
||||
theta = theta_0 * u,
|
||||
q3 = Q_Normalize(q2 - q1*dot),
|
||||
out = q1*cos(theta) + q3*sin(theta)
|
||||
) out;
|
||||
|
||||
|
||||
// Function: Q_Matrix3()
|
||||
@ -240,9 +240,9 @@ function Q_Slerp(q1, q2, u) =
|
||||
// Description:
|
||||
// Returns the 3x3 rotation matrix for the given normalized quaternion q.
|
||||
function Q_Matrix3(q) = [
|
||||
[1-2*q[1]*q[1]-2*q[2]*q[2], 2*q[0]*q[1]-2*q[2]*q[3], 2*q[0]*q[2]+2*q[1]*q[3]],
|
||||
[ 2*q[0]*q[1]+2*q[2]*q[3], 1-2*q[0]*q[0]-2*q[2]*q[2], 2*q[1]*q[2]-2*q[0]*q[3]],
|
||||
[ 2*q[0]*q[2]-2*q[1]*q[3], 2*q[1]*q[2]+2*q[0]*q[3], 1-2*q[0]*q[0]-2*q[1]*q[1]]
|
||||
[1-2*q[1]*q[1]-2*q[2]*q[2], 2*q[0]*q[1]-2*q[2]*q[3], 2*q[0]*q[2]+2*q[1]*q[3]],
|
||||
[ 2*q[0]*q[1]+2*q[2]*q[3], 1-2*q[0]*q[0]-2*q[2]*q[2], 2*q[1]*q[2]-2*q[0]*q[3]],
|
||||
[ 2*q[0]*q[2]-2*q[1]*q[3], 2*q[1]*q[2]+2*q[0]*q[3], 1-2*q[0]*q[0]-2*q[1]*q[1]]
|
||||
];
|
||||
|
||||
|
||||
@ -252,10 +252,10 @@ function Q_Matrix3(q) = [
|
||||
// Description:
|
||||
// Returns the 4x4 rotation matrix for the given normalized quaternion q.
|
||||
function Q_Matrix4(q) = [
|
||||
[1-2*q[1]*q[1]-2*q[2]*q[2], 2*q[0]*q[1]-2*q[2]*q[3], 2*q[0]*q[2]+2*q[1]*q[3], 0],
|
||||
[ 2*q[0]*q[1]+2*q[2]*q[3], 1-2*q[0]*q[0]-2*q[2]*q[2], 2*q[1]*q[2]-2*q[0]*q[3], 0],
|
||||
[ 2*q[0]*q[2]-2*q[1]*q[3], 2*q[1]*q[2]+2*q[0]*q[3], 1-2*q[0]*q[0]-2*q[1]*q[1], 0],
|
||||
[ 0, 0, 0, 1]
|
||||
[1-2*q[1]*q[1]-2*q[2]*q[2], 2*q[0]*q[1]-2*q[2]*q[3], 2*q[0]*q[2]+2*q[1]*q[3], 0],
|
||||
[ 2*q[0]*q[1]+2*q[2]*q[3], 1-2*q[0]*q[0]-2*q[2]*q[2], 2*q[1]*q[2]-2*q[0]*q[3], 0],
|
||||
[ 2*q[0]*q[2]-2*q[1]*q[3], 2*q[1]*q[2]+2*q[0]*q[3], 1-2*q[0]*q[0]-2*q[1]*q[1], 0],
|
||||
[ 0, 0, 0, 1]
|
||||
];
|
||||
|
||||
|
||||
@ -299,15 +299,15 @@ function Q_Angle(q) = 2 * acos(q[3]);
|
||||
// q = QuatXYZ([45,35,10]);
|
||||
// pts = Qrot(q, p=[[2,3,4], [4,5,6], [9,2,3]]);
|
||||
module Qrot(q) {
|
||||
multmatrix(Q_Matrix4(q)) {
|
||||
children();
|
||||
}
|
||||
multmatrix(Q_Matrix4(q)) {
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
function Qrot(q,p) =
|
||||
is_undef(p)? Q_Matrix4(q) :
|
||||
is_vector(p)? Qrot(q,[p])[0] :
|
||||
apply(Q_Matrix4(q), p);
|
||||
is_undef(p)? Q_Matrix4(q) :
|
||||
is_vector(p)? Qrot(q,[p])[0] :
|
||||
apply(Q_Matrix4(q), p);
|
||||
|
||||
|
||||
// Module: Qrot_copies()
|
||||
@ -327,4 +327,4 @@ function Qrot(q,p) =
|
||||
module Qrot_copies(quats) for (q=quats) Qrot(q) children();
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
92
queues.scad
92
queues.scad
@ -39,8 +39,8 @@ function queue_init() = [];
|
||||
// queue2 = queue_add(queue, "foo");
|
||||
// is_empty2 = queue_empty(queue2); // Returns: false
|
||||
function queue_empty(queue) =
|
||||
assert(is_list(queue))
|
||||
len(queue)==0;
|
||||
assert(is_list(queue))
|
||||
len(queue)==0;
|
||||
|
||||
|
||||
// Function: queue_size()
|
||||
@ -58,8 +58,8 @@ function queue_empty(queue) =
|
||||
// queue3 = queue_add(queue2, ["bar","baz","qux"]);
|
||||
// depth3 = queue_size(queue3); // Returns: 4
|
||||
function queue_size(queue) =
|
||||
assert(is_list(queue))
|
||||
len(queue);
|
||||
assert(is_list(queue))
|
||||
len(queue);
|
||||
|
||||
|
||||
// Function: queue_head()
|
||||
@ -76,16 +76,16 @@ function queue_size(queue) =
|
||||
// item = queue_head(queue); // Returns: 4
|
||||
// list = queue_head(queue,n=3); // Returns: [4,5,6]
|
||||
function queue_head(queue,n=undef) =
|
||||
assert(is_list(queue))
|
||||
is_undef(n)? (
|
||||
queue[0]
|
||||
) : (
|
||||
let(queuesize = len(queue))
|
||||
assert(is_num(n))
|
||||
assert(n>=0)
|
||||
assert(queuesize>=n, "queue underflow")
|
||||
[for (i=[0:1:n-1]) queue[i]]
|
||||
);
|
||||
assert(is_list(queue))
|
||||
is_undef(n)? (
|
||||
queue[0]
|
||||
) : (
|
||||
let(queuesize = len(queue))
|
||||
assert(is_num(n))
|
||||
assert(n>=0)
|
||||
assert(queuesize>=n, "queue underflow")
|
||||
[for (i=[0:1:n-1]) queue[i]]
|
||||
);
|
||||
|
||||
|
||||
// Function: queue_tail()
|
||||
@ -102,16 +102,16 @@ function queue_head(queue,n=undef) =
|
||||
// item = queue_tail(queue); // Returns: 9
|
||||
// list = queue_tail(queue,n=3); // Returns: [7,8,9]
|
||||
function queue_tail(queue,n=undef) =
|
||||
assert(is_list(queue))
|
||||
let(queuesize = len(queue))
|
||||
is_undef(n)? (
|
||||
queue[queuesize-1]
|
||||
) : (
|
||||
assert(is_num(n))
|
||||
assert(n>=0)
|
||||
assert(queuesize>=n, "queue underflow")
|
||||
[for (i=[0:1:n-1]) queue[queuesize-n+i]]
|
||||
);
|
||||
assert(is_list(queue))
|
||||
let(queuesize = len(queue))
|
||||
is_undef(n)? (
|
||||
queue[queuesize-1]
|
||||
) : (
|
||||
assert(is_num(n))
|
||||
assert(n>=0)
|
||||
assert(queuesize>=n, "queue underflow")
|
||||
[for (i=[0:1:n-1]) queue[queuesize-n+i]]
|
||||
);
|
||||
|
||||
|
||||
// Function: queue_peek()
|
||||
@ -131,19 +131,19 @@ function queue_tail(queue,n=undef) =
|
||||
// item2 = queue_peek(queue, 3); // Returns: 5
|
||||
// list = queue_peek(queue, 4, 3); // Returns: [6,7,8]
|
||||
function queue_peek(queue,pos=0,n=undef) =
|
||||
assert(is_list(queue))
|
||||
assert(is_num(pos))
|
||||
assert(pos>=0)
|
||||
let(queuesize = len(queue))
|
||||
assert(queuesize>=pos, "queue underflow")
|
||||
is_undef(n)? (
|
||||
queue[pos]
|
||||
) : (
|
||||
assert(is_num(n))
|
||||
assert(n>=0)
|
||||
assert(n<queuesize-pos)
|
||||
[for (i=[0:1:n-1]) queue[pos+i]]
|
||||
);
|
||||
assert(is_list(queue))
|
||||
assert(is_num(pos))
|
||||
assert(pos>=0)
|
||||
let(queuesize = len(queue))
|
||||
assert(queuesize>=pos, "queue underflow")
|
||||
is_undef(n)? (
|
||||
queue[pos]
|
||||
) : (
|
||||
assert(is_num(n))
|
||||
assert(n>=0)
|
||||
assert(n<queuesize-pos)
|
||||
[for (i=[0:1:n-1]) queue[pos+i]]
|
||||
);
|
||||
|
||||
|
||||
// Function: queue_add()
|
||||
@ -166,8 +166,8 @@ function queue_peek(queue,pos=0,n=undef) =
|
||||
// val = queue_head(q2);
|
||||
// q3 = queue_pop(q2);
|
||||
function queue_add(queue,items) =
|
||||
assert(is_list(queue))
|
||||
is_list(items)? concat(queue, items) : concat(queue, [items]);
|
||||
assert(is_list(queue))
|
||||
is_list(items)? concat(queue, items) : concat(queue, [items]);
|
||||
|
||||
|
||||
// Function: queue_pop()
|
||||
@ -188,13 +188,13 @@ function queue_add(queue,items) =
|
||||
// val = queue_head(q2);
|
||||
// q3 = queue_pop(q2);
|
||||
function queue_pop(queue,n=1) =
|
||||
assert(is_list(queue))
|
||||
assert(is_num(n))
|
||||
assert(n>=0)
|
||||
let(queuesize = len(queue))
|
||||
assert(queuesize>=n, "queue underflow")
|
||||
[for (i = [n:1:queuesize-1]) queue[i]];
|
||||
assert(is_list(queue))
|
||||
assert(is_num(n))
|
||||
assert(n>=0)
|
||||
let(queuesize = len(queue))
|
||||
assert(queuesize>=n, "queue underflow")
|
||||
[for (i = [n:1:queuesize-1]) queue[i]];
|
||||
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
1172
regions.scad
1172
regions.scad
File diff suppressed because it is too large
Load Diff
@ -1548,10 +1548,10 @@ function rounded_prism(bottom, top, joint_bot, joint_top, joint_sides, k_bot, k_
|
||||
if (norm(top[i]-top_patch[i][4][2]) + norm(bottom[i]-bot_patch[i][4][2]) > norm(bottom[i]-top[i])) i],
|
||||
topbad = [for(i=[0:N-1])
|
||||
if (norm(top_patch[i][2][4]-top_patch[i][2][2]) + norm(select(top_patch,i+1)[2][0]-select(top_patch,i+1)[2][2])
|
||||
> norm(top_patch[i][2][2] - select(top_patch,i+1)[2][2])) [i,(i+1)%N]],
|
||||
> norm(top_patch[i][2][2] - select(top_patch,i+1)[2][2])) [i,(i+1)%N]],
|
||||
botbad = [for(i=[0:N-1])
|
||||
if (norm(bot_patch[i][2][4]-bot_patch[i][2][2]) + norm(select(bot_patch,i+1)[2][0]-select(bot_patch,i+1)[2][2])
|
||||
> norm(bot_patch[i][2][2] - select(bot_patch,i+1)[2][2])) [i,(i+1)%N]],
|
||||
> norm(bot_patch[i][2][2] - select(bot_patch,i+1)[2][2])) [i,(i+1)%N]],
|
||||
topinbad = [for(i=[0:N-1])
|
||||
if (norm(top_patch[i][0][2]-top_patch[i][0][4]) + norm(select(top_patch,i+1)[0][0]-select(top_patch,i+1)[0][2])
|
||||
> norm(top_patch[i][0][2]-select(top_patch,i+1)[0][2])) [i,(i+1)%N]],
|
||||
@ -1619,7 +1619,7 @@ function rounded_prism(bottom, top, joint_bot, joint_top, joint_sides, k_bot, k_
|
||||
each subindex(bot_samples,1),
|
||||
for(pts=edge_points) vnf_vertex_array(pts),
|
||||
vnf_triangulate(vnf_add_faces(EMPTY_VNF,faces))
|
||||
])
|
||||
])
|
||||
)
|
||||
debug ? [concat(top_patch, bot_patch), vnf] : vnf;
|
||||
|
||||
@ -1942,4 +1942,4 @@ module bent_cutout_mask(r, thickness, path, convexity=10)
|
||||
}
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
318
screws.scad
318
screws.scad
@ -493,55 +493,55 @@ function _screw_info_metric(diam, pitch, head, thread, drive) =
|
||||
tind=struct_val([["coarse",0],
|
||||
["fine",1],
|
||||
["extra fine",2],["extrafine",2],
|
||||
["super fine",3],["superfine",3]],
|
||||
["super fine",3],["superfine",3]],
|
||||
downcase(thread)),
|
||||
// coarse fine xfine superfine
|
||||
ISO_thread = [
|
||||
[1 , [0.25, 0.2 , undef, undef,]],
|
||||
[1.2, [0.25, 0.2 , undef, undef,]],
|
||||
[1.4, [0.3 , 0.2 , undef, undef,]],
|
||||
[1.6, [0.35, 0.2 , undef, undef,]],
|
||||
[1.7, [0.35, undef, undef, undef,]],
|
||||
[1.8, [0.35, 0.2 , undef, undef,]],
|
||||
[2 , [0.4 , 0.25, undef, undef,]],
|
||||
[2.2, [0.45, 0.25, undef, undef,]],
|
||||
[2.3, [0.4 , undef, undef, undef,]],
|
||||
[2.5, [0.45, 0.35, undef, undef,]],
|
||||
[2.6, [0.45, undef, undef, undef,]],
|
||||
[3 , [0.5 , 0.35, undef, undef,]],
|
||||
[3.5, [0.6 , 0.35, undef, undef,]],
|
||||
[4 , [0.7 , 0.5 , undef, undef,]],
|
||||
[5 , [0.8 , 0.5 , undef, undef,]],
|
||||
[6 , [1 , 0.75, undef, undef,]],
|
||||
[7 , [1 , 0.75, undef, undef,]],
|
||||
[8 , [1.25, 1 , 0.75, undef,]],
|
||||
[9 , [1.25, 1 , 0.75, undef,]],
|
||||
[10 , [1.5 , 1.25, 1 , 0.75,]],
|
||||
[11 , [1.5 , 1 , 0.75, undef,]],
|
||||
[12 , [1.75, 1.5 , 1.25, 1, ]],
|
||||
[14 , [2 , 1.5 , 1.25, 1, ]],
|
||||
[16 , [2 , 1.5 , 1 , undef,]],
|
||||
[18 , [2.5 , 2 , 1.5 , 1, ]],
|
||||
[20 , [2.5 , 2 , 1.5 , 1, ]],
|
||||
[22 , [2.5 , 2 , 1.5 , 1,]],
|
||||
[24 , [3 , 2 , 1.5 , 1,]],
|
||||
[27 , [3 , 2 , 1.5 , 1,]],
|
||||
[30 , [3.5 , 3 , 2 , 1.5,]],
|
||||
[33 , [3.5 , 3 , 2 , 1.5,]],
|
||||
[36 , [4 , 3 , 2 , 1.5,]],
|
||||
[39 , [4 , 3 , 2 , 1.5,]],
|
||||
[42 , [4.5 , 4 , 3 , 2,]],
|
||||
[45 , [4.5 , 4 , 3 , 2,]],
|
||||
[48 , [5 , 4 , 3 , 2,]],
|
||||
[52 , [5 , 4 , 3 , 2,]],
|
||||
[56 , [5.5 , 4 , 3 , 2,]],
|
||||
[60 , [5.5 , 4 , 3 , 2,]],
|
||||
[64 , [6 , 4 , 3 , 2,]],
|
||||
[68 , [6 , 4 , 3 , 2,]],
|
||||
[72 , [6 , 4 , 3 , 2,]],
|
||||
[80 , [6 , 4 , 3 , 2,]],
|
||||
[90 , [6 , 4 , 3 , 2,]],
|
||||
[100, [6 , 4 , 3 , 2,]],
|
||||
[1 , [0.25, 0.2 , undef, undef,]],
|
||||
[1.2, [0.25, 0.2 , undef, undef,]],
|
||||
[1.4, [0.3 , 0.2 , undef, undef,]],
|
||||
[1.6, [0.35, 0.2 , undef, undef,]],
|
||||
[1.7, [0.35, undef, undef, undef,]],
|
||||
[1.8, [0.35, 0.2 , undef, undef,]],
|
||||
[2 , [0.4 , 0.25, undef, undef,]],
|
||||
[2.2, [0.45, 0.25, undef, undef,]],
|
||||
[2.3, [0.4 , undef, undef, undef,]],
|
||||
[2.5, [0.45, 0.35, undef, undef,]],
|
||||
[2.6, [0.45, undef, undef, undef,]],
|
||||
[3 , [0.5 , 0.35, undef, undef,]],
|
||||
[3.5, [0.6 , 0.35, undef, undef,]],
|
||||
[4 , [0.7 , 0.5 , undef, undef,]],
|
||||
[5 , [0.8 , 0.5 , undef, undef,]],
|
||||
[6 , [1 , 0.75, undef, undef,]],
|
||||
[7 , [1 , 0.75, undef, undef,]],
|
||||
[8 , [1.25, 1 , 0.75, undef,]],
|
||||
[9 , [1.25, 1 , 0.75, undef,]],
|
||||
[10 , [1.5 , 1.25, 1 , 0.75,]],
|
||||
[11 , [1.5 , 1 , 0.75, undef,]],
|
||||
[12 , [1.75, 1.5 , 1.25, 1, ]],
|
||||
[14 , [2 , 1.5 , 1.25, 1, ]],
|
||||
[16 , [2 , 1.5 , 1 , undef,]],
|
||||
[18 , [2.5 , 2 , 1.5 , 1, ]],
|
||||
[20 , [2.5 , 2 , 1.5 , 1, ]],
|
||||
[22 , [2.5 , 2 , 1.5 , 1,]],
|
||||
[24 , [3 , 2 , 1.5 , 1,]],
|
||||
[27 , [3 , 2 , 1.5 , 1,]],
|
||||
[30 , [3.5 , 3 , 2 , 1.5,]],
|
||||
[33 , [3.5 , 3 , 2 , 1.5,]],
|
||||
[36 , [4 , 3 , 2 , 1.5,]],
|
||||
[39 , [4 , 3 , 2 , 1.5,]],
|
||||
[42 , [4.5 , 4 , 3 , 2,]],
|
||||
[45 , [4.5 , 4 , 3 , 2,]],
|
||||
[48 , [5 , 4 , 3 , 2,]],
|
||||
[52 , [5 , 4 , 3 , 2,]],
|
||||
[56 , [5.5 , 4 , 3 , 2,]],
|
||||
[60 , [5.5 , 4 , 3 , 2,]],
|
||||
[64 , [6 , 4 , 3 , 2,]],
|
||||
[68 , [6 , 4 , 3 , 2,]],
|
||||
[72 , [6 , 4 , 3 , 2,]],
|
||||
[80 , [6 , 4 , 3 , 2,]],
|
||||
[90 , [6 , 4 , 3 , 2,]],
|
||||
[100, [6 , 4 , 3 , 2,]],
|
||||
]
|
||||
)
|
||||
struct_val(ISO_thread, diam)[tind],
|
||||
@ -550,19 +550,19 @@ function _screw_info_metric(diam, pitch, head, thread, drive) =
|
||||
metric_setscrew =
|
||||
[
|
||||
[1.4, [0.7]],
|
||||
[1.6, [0.7]],
|
||||
[1.8, [0.7]],
|
||||
[2, [0.9]],
|
||||
[2.5, [1.3]],
|
||||
[3, [1.5, 6, 0.77]],
|
||||
[4, [2, 8, 1.05]],
|
||||
[5, [2.5, 10, 1.24]],
|
||||
[6, [3, 15, 1.74]],
|
||||
[8, [4, 25, 2.24]],
|
||||
[10, [5, 40, 2.97]],
|
||||
[12, [6, 45, 3.48]],
|
||||
[16, [8, 55, 5.15]],
|
||||
[20, [10, undef, undef]],
|
||||
[1.6, [0.7]],
|
||||
[1.8, [0.7]],
|
||||
[2, [0.9]],
|
||||
[2.5, [1.3]],
|
||||
[3, [1.5, 6, 0.77]],
|
||||
[4, [2, 8, 1.05]],
|
||||
[5, [2.5, 10, 1.24]],
|
||||
[6, [3, 15, 1.74]],
|
||||
[8, [4, 25, 2.24]],
|
||||
[10, [5, 40, 2.97]],
|
||||
[12, [6, 45, 3.48]],
|
||||
[16, [8, 55, 5.15]],
|
||||
[20, [10, undef, undef]],
|
||||
],
|
||||
entry = struct_val(metric_setscrew, diam),
|
||||
drive_dim = drive=="hex" ? [["drive_size", entry[0]], ["drive_depth", diam/2]] :
|
||||
@ -572,17 +572,17 @@ function _screw_info_metric(diam, pitch, head, thread, drive) =
|
||||
head=="hex" ? let(
|
||||
metric_hex = [
|
||||
// flat to flat width, height
|
||||
[5, [8, 3.5]],
|
||||
[6, [10,4]],
|
||||
[8, [13, 5.3]],
|
||||
[10, [17, 6.4]],
|
||||
[12, [19, 7.5]],
|
||||
[14, [22, 8.8]],
|
||||
[16, [24, 10]],
|
||||
[18, [27,11.5]],
|
||||
[20, [30, 12.5]],
|
||||
[24, [36, 15]],
|
||||
[30, [46, 18.7]],
|
||||
[5, [8, 3.5]],
|
||||
[6, [10,4]],
|
||||
[8, [13, 5.3]],
|
||||
[10, [17, 6.4]],
|
||||
[12, [19, 7.5]],
|
||||
[14, [22, 8.8]],
|
||||
[16, [24, 10]],
|
||||
[18, [27,11.5]],
|
||||
[20, [30, 12.5]],
|
||||
[24, [36, 15]],
|
||||
[30, [46, 18.7]],
|
||||
],
|
||||
entry = struct_val(metric_hex, diam)
|
||||
)
|
||||
@ -591,31 +591,31 @@ function _screw_info_metric(diam, pitch, head, thread, drive) =
|
||||
metric_socket = [ // height = screw diameter
|
||||
//diam, hex
|
||||
[1.4, [2.5, 1.3]],
|
||||
[1.6, [3, 1.5]],
|
||||
[2, [3.8, 1.5, 6, 0.77]],
|
||||
[2.5, [4.5, 2, 8, 1.05]],
|
||||
[2.6, [5, 2, 8, 1.05]],
|
||||
[3, [5.5, 2.5, 10, 1.24]],
|
||||
[3.5, [6.2, 2.5]],
|
||||
[4, [7, 3, 25, 1.76]],
|
||||
[5, [8.5, 4, 27, 2.24]],
|
||||
[6, [10, 5, 30, 2.47]],
|
||||
[7, [12, 6]],
|
||||
[8, [13, 6, 45, 3.48]],
|
||||
[10, [16, 8, 50, 3.93]],
|
||||
[12, [18, 10, 55, 5.15]],
|
||||
[14, [21, 12]],
|
||||
[16, [24, 14, 70, 7.39]],
|
||||
[18, [27, 14]],
|
||||
[20, [30, 17, 90, 9.67]],
|
||||
[22, [33, 17]],
|
||||
[24, [36, 19, 100, 10.79]],
|
||||
[27, [40, 19]],
|
||||
[30, [45, 22]],
|
||||
[33, [50, 24]],
|
||||
[36, [54, 27]],
|
||||
[42, [63, 32]],
|
||||
[48, [72, 36]],
|
||||
[1.6, [3, 1.5]],
|
||||
[2, [3.8, 1.5, 6, 0.77]],
|
||||
[2.5, [4.5, 2, 8, 1.05]],
|
||||
[2.6, [5, 2, 8, 1.05]],
|
||||
[3, [5.5, 2.5, 10, 1.24]],
|
||||
[3.5, [6.2, 2.5]],
|
||||
[4, [7, 3, 25, 1.76]],
|
||||
[5, [8.5, 4, 27, 2.24]],
|
||||
[6, [10, 5, 30, 2.47]],
|
||||
[7, [12, 6]],
|
||||
[8, [13, 6, 45, 3.48]],
|
||||
[10, [16, 8, 50, 3.93]],
|
||||
[12, [18, 10, 55, 5.15]],
|
||||
[14, [21, 12]],
|
||||
[16, [24, 14, 70, 7.39]],
|
||||
[18, [27, 14]],
|
||||
[20, [30, 17, 90, 9.67]],
|
||||
[22, [33, 17]],
|
||||
[24, [36, 19, 100, 10.79]],
|
||||
[27, [40, 19]],
|
||||
[30, [45, 22]],
|
||||
[33, [50, 24]],
|
||||
[36, [54, 27]],
|
||||
[42, [63, 32]],
|
||||
[48, [72, 36]],
|
||||
],
|
||||
entry = struct_val(metric_socket, diam),
|
||||
drive_size = drive=="hex" ? [["drive_size",entry[1]],["drive_depth",diam/2]] :
|
||||
@ -626,16 +626,16 @@ function _screw_info_metric(diam, pitch, head, thread, drive) =
|
||||
starts_with(head,"pan") ? let (
|
||||
metric_pan = [ // pan head for phillips or slotted
|
||||
// diam, slotted diam, phillips diam, phillips depth, ph width, slot width,slot depth
|
||||
[1.6,[3.2, 1 , 1.3, 0, undef,undef,undef, 0.4, 0.35]],
|
||||
[2, [4, 1.3, 1.6, 1, 1.82, 1.19, 0.48, 0.5, 0.5]],
|
||||
[2.5,[5, 1.5, 2, 1, 2.68, 1.53, 0.70, 0.6, 0.6]],
|
||||
[3, [5.6, 1.8, 2.4, 1, 2.90, 1.76, 0.74, 0.8, 0.7]],
|
||||
[3.5,[7, 2.1, 3.1, 2, 3.92, 1.95, 0.87, 1.0, 0.8]],
|
||||
[1.6,[3.2, 1 , 1.3, 0, undef,undef,undef, 0.4, 0.35]],
|
||||
[2, [4, 1.3, 1.6, 1, 1.82, 1.19, 0.48, 0.5, 0.5]],
|
||||
[2.5,[5, 1.5, 2, 1, 2.68, 1.53, 0.70, 0.6, 0.6]],
|
||||
[3, [5.6, 1.8, 2.4, 1, 2.90, 1.76, 0.74, 0.8, 0.7]],
|
||||
[3.5,[7, 2.1, 3.1, 2, 3.92, 1.95, 0.87, 1.0, 0.8]],
|
||||
[4, [8, 2.4 , 3.1, 2, 4.40, 2.45, 0.93, 1.2, 1.0]],
|
||||
[5, [9.5, 3, 3.8, 2, 4.90, 2.95, 1.00, 1.2, 1.2]],
|
||||
[6, [12, 3.6, 4.6, 3, 6.92, 3.81, 1.14, 1.6, 1.4]],
|
||||
[8, [16, 4.8, 6, 4, 9.02, 4.88, 1.69, 2.0, 1.9]],
|
||||
[10, [20, 6.0, 7.5, 4, 10.18, 5.09, 1.84,2.5, 2.4]],
|
||||
[5, [9.5, 3, 3.8, 2, 4.90, 2.95, 1.00, 1.2, 1.2]],
|
||||
[6, [12, 3.6, 4.6, 3, 6.92, 3.81, 1.14, 1.6, 1.4]],
|
||||
[8, [16, 4.8, 6, 4, 9.02, 4.88, 1.69, 2.0, 1.9]],
|
||||
[10, [20, 6.0, 7.5, 4, 10.18, 5.09, 1.84,2.5, 2.4]],
|
||||
],
|
||||
type = head=="pan" ? (drive=="slot" ? "pan flat" : "pan round") : head,
|
||||
htind = drive=="slot" ? 1 : 2,
|
||||
@ -648,34 +648,34 @@ function _screw_info_metric(diam, pitch, head, thread, drive) =
|
||||
metric_button = [ // button, hex drive
|
||||
// head diam, height, hex, phillips, hex drive depth
|
||||
[1.6, [2.9, 0.8, 0.9, undef, 0.55]], // These four cases,
|
||||
[2, [3.5, 1.3, 1.3, undef, 0.69]], // extrapolated hex depth
|
||||
[2.2, [3.8, 0.9, 1.3, undef, 0.76]], //
|
||||
[2.5, [4.6, 1.5, 1.5, undef, 0.87]], //
|
||||
[3, [5.7, 1.65, 2, undef, 1.04, 8, 0.81]],
|
||||
[3.5, [5.7, 1.65, 2, undef, 1.21]], // interpolated hex depth
|
||||
[4, [7.6, 2.2, 2.5, undef, 1.30, 15, 1.3]],
|
||||
[5, [9.5, 2.75, 3, undef, 1.56, 25, 1.56]],
|
||||
[6, [10.5,3.3, 4, undef, 2.08, 27, 2.08]],
|
||||
[8, [14, 4.4, 5, undef, 2.60, 40, 2.3]],
|
||||
[10, [17.5,5.5, 6, undef, 3.21, 45, 2.69]],
|
||||
[12, [21, 6.6, 8, undef, 4.16, 55, 4.02]],
|
||||
[16, [28, 8.8, 10, undef, 5.55]], // interpolated hex depth
|
||||
[2, [3.5, 1.3, 1.3, undef, 0.69]], // extrapolated hex depth
|
||||
[2.2, [3.8, 0.9, 1.3, undef, 0.76]], //
|
||||
[2.5, [4.6, 1.5, 1.5, undef, 0.87]], //
|
||||
[3, [5.7, 1.65, 2, undef, 1.04, 8, 0.81]],
|
||||
[3.5, [5.7, 1.65, 2, undef, 1.21]], // interpolated hex depth
|
||||
[4, [7.6, 2.2, 2.5, undef, 1.30, 15, 1.3]],
|
||||
[5, [9.5, 2.75, 3, undef, 1.56, 25, 1.56]],
|
||||
[6, [10.5,3.3, 4, undef, 2.08, 27, 2.08]],
|
||||
[8, [14, 4.4, 5, undef, 2.60, 40, 2.3]],
|
||||
[10, [17.5,5.5, 6, undef, 3.21, 45, 2.69]],
|
||||
[12, [21, 6.6, 8, undef, 4.16, 55, 4.02]],
|
||||
[16, [28, 8.8, 10, undef, 5.55]], // interpolated hex depth
|
||||
],
|
||||
metric_cheese = [ // slotted, phillips ISO 1207, ISO 7048
|
||||
// head diam, head height, hex drive, phillips drive, slot width, slight depth, ph diam
|
||||
[1, [2, 0.7, undef, undef]],
|
||||
[1.2, [2.3,0.8, undef, undef]],
|
||||
[1.4, [2.6,0.9, undef, undef]],
|
||||
[1.6, [3, 1, undef, undef, 0.4, 0.45]],
|
||||
[2, [3.8,1.3, undef, 1 , 0.5, 0.6]],
|
||||
[2.5, [4.5,1.6, undef, 1 , 0.6, 0.7, 2.7,1.2]],
|
||||
[3, [5.5,2, undef, 2 , 0.8, 0.85, 3.5,0.86]],
|
||||
[3.5, [6, 2.4, undef, 2 , 1.0, 1.0, 3.8, 1.15]],
|
||||
[4, [7, 2.6, undef, 2 , 1.2, 1.1, 4.1, 1.45]],
|
||||
[5, [8.5,3.3, undef, 2 , 1.2, 1.3, 4.8, 2.14]],
|
||||
[6, [10, 3.9, undef, 3 , 1.6, 1.6, 6.2, 2.25]],
|
||||
[8, [13, 5, undef, 3 , 2.0, 2.0, 7.7, 3.73]],
|
||||
[10, [16, 6, undef, undef, 2.5, 2.4]]
|
||||
[1, [2, 0.7, undef, undef]],
|
||||
[1.2, [2.3,0.8, undef, undef]],
|
||||
[1.4, [2.6,0.9, undef, undef]],
|
||||
[1.6, [3, 1, undef, undef, 0.4, 0.45]],
|
||||
[2, [3.8,1.3, undef, 1 , 0.5, 0.6]],
|
||||
[2.5, [4.5,1.6, undef, 1 , 0.6, 0.7, 2.7,1.2]],
|
||||
[3, [5.5,2, undef, 2 , 0.8, 0.85, 3.5,0.86]],
|
||||
[3.5, [6, 2.4, undef, 2 , 1.0, 1.0, 3.8, 1.15]],
|
||||
[4, [7, 2.6, undef, 2 , 1.2, 1.1, 4.1, 1.45]],
|
||||
[5, [8.5,3.3, undef, 2 , 1.2, 1.3, 4.8, 2.14]],
|
||||
[6, [10, 3.9, undef, 3 , 1.6, 1.6, 6.2, 2.25]],
|
||||
[8, [13, 5, undef, 3 , 2.0, 2.0, 7.7, 3.73]],
|
||||
[10, [16, 6, undef, undef, 2.5, 2.4]]
|
||||
],
|
||||
entry = struct_val(head=="button" ? metric_button : metric_cheese, diam),
|
||||
drive_index = drive=="phillips" ? 3 :
|
||||
@ -693,18 +693,18 @@ function _screw_info_metric(diam, pitch, head, thread, drive) =
|
||||
small = head == "flat small" || (head=="flat" && (drive!="hex" && drive!="torx")),
|
||||
metric_flat_large = [ // for hex drive
|
||||
[2, [4, 1.3,undef]],
|
||||
[2.5,[5, 1.5, undef]],
|
||||
[3, [6, 2 , 1.1, 10, 0.96]],
|
||||
[4, [8, 2.5, 1.5, 20, 1.34]],
|
||||
[5, [10, 3 , 1.9, 25, 1.54]],
|
||||
[6, [12, 4 , 2.2, 30, 1.91]],
|
||||
[8, [16, 5 , 3.0, 40, 2.3]],
|
||||
[10, [20, 6 , 3.6, 50, 3.04]],
|
||||
[12, [24, 8 ,undef]],
|
||||
[14, [27, 10 ,undef]],
|
||||
[16, [30, 10 ,undef]],
|
||||
[18, [33, 12 ,undef]],
|
||||
[20, [36, 12 ,undef]],
|
||||
[2.5,[5, 1.5, undef]],
|
||||
[3, [6, 2 , 1.1, 10, 0.96]],
|
||||
[4, [8, 2.5, 1.5, 20, 1.34]],
|
||||
[5, [10, 3 , 1.9, 25, 1.54]],
|
||||
[6, [12, 4 , 2.2, 30, 1.91]],
|
||||
[8, [16, 5 , 3.0, 40, 2.3]],
|
||||
[10, [20, 6 , 3.6, 50, 3.04]],
|
||||
[12, [24, 8 ,undef]],
|
||||
[14, [27, 10 ,undef]],
|
||||
[16, [30, 10 ,undef]],
|
||||
[18, [33, 12 ,undef]],
|
||||
[20, [36, 12 ,undef]],
|
||||
],
|
||||
metric_flat_small = [ // for phillips, slotted
|
||||
// Phillips from ASME B18.6.7M (ISO 7046 gives different values),
|
||||
@ -715,20 +715,20 @@ function _screw_info_metric(diam, pitch, head, thread, drive) =
|
||||
[1.6, [2.6, 0,undef,undef,undef, 0.3, 0.28]],
|
||||
[1.6, [3, 0,undef,undef,undef, 0.4, 0.32]],
|
||||
[2, [3.8, 0, 2.14, 1.54, 0.53, 0.5, 0.4]],
|
||||
[2.5, [4.7, 1, 2.80, 1.78, 0.74, 0.6, 0.5]],
|
||||
[2.6, [4.7, 1, 2.80, 1.78, 0.74, 0.6, 0.5]],
|
||||
[3, [5.6, 1, 3.10, 2.08, 0.79, 0.8, 0.6]],
|
||||
[3.5, [6.5, 1, 4.06, 2.25, 0.91, 0.8, 0.7]],
|
||||
[4, [7.5, 2, 4.46, 2.65, 0.96, 1.0, 0.8]],
|
||||
[5, [9.2, 2, 5.06, 3.25, 1.04, 1.2, 1.0]],
|
||||
[6, [11, 3, 6.62, 3.61, 1.12, 1.6, 1.2]],
|
||||
[8, [14.5,4, 8.78, 4.88, 1.80, 2.0, 1.6]],
|
||||
[10, [18,undef,undef,undef,undef,2.5,2 ]],
|
||||
[12, [22,undef,undef,undef,undef,3,2.4 ]],
|
||||
[14, [25,undef,undef,undef,undef,3,2.8 ]],
|
||||
[16, [29,undef,undef,undef,undef,4,3.2 ]],
|
||||
[18, [33,undef,undef,undef,undef,4,3.6 ]],
|
||||
[20, [36,undef,undef,undef,undef,5,4 ]],
|
||||
[2.5, [4.7, 1, 2.80, 1.78, 0.74, 0.6, 0.5]],
|
||||
[2.6, [4.7, 1, 2.80, 1.78, 0.74, 0.6, 0.5]],
|
||||
[3, [5.6, 1, 3.10, 2.08, 0.79, 0.8, 0.6]],
|
||||
[3.5, [6.5, 1, 4.06, 2.25, 0.91, 0.8, 0.7]],
|
||||
[4, [7.5, 2, 4.46, 2.65, 0.96, 1.0, 0.8]],
|
||||
[5, [9.2, 2, 5.06, 3.25, 1.04, 1.2, 1.0]],
|
||||
[6, [11, 3, 6.62, 3.61, 1.12, 1.6, 1.2]],
|
||||
[8, [14.5,4, 8.78, 4.88, 1.80, 2.0, 1.6]],
|
||||
[10, [18,undef,undef,undef,undef,2.5,2 ]],
|
||||
[12, [22,undef,undef,undef,undef,3,2.4 ]],
|
||||
[14, [25,undef,undef,undef,undef,3,2.8 ]],
|
||||
[16, [29,undef,undef,undef,undef,4,3.2 ]],
|
||||
[18, [33,undef,undef,undef,undef,4,3.6 ]],
|
||||
[20, [36,undef,undef,undef,undef,5,4 ]],
|
||||
],
|
||||
entry = struct_val(small ? metric_flat_small : metric_flat_large, diam),
|
||||
driveind = small && drive=="phillips" || !small && drive=="hex" ? 1 : !small && drive=="torx" ? 3 : undef,
|
||||
@ -1330,10 +1330,10 @@ module nut(name, thread="coarse", oversize=0, spec, diameter, thickness, toleran
|
||||
echo(threadspec=threadspec,"for nut threads");
|
||||
echo(nut_minor_diam = mean(struct_val(threadspec,"d_minor")));
|
||||
trapezoidal_threaded_nut(
|
||||
od=diameter, id=mean(struct_val(threadspec, "d_major")), h=thickness,
|
||||
pitch=struct_val(threadspec, "pitch"),
|
||||
profile=_thread_profile(threadspec),
|
||||
bevel=false,anchor=anchor,spin=spin,orient=orient);
|
||||
od=diameter, id=mean(struct_val(threadspec, "d_major")), h=thickness,
|
||||
pitch=struct_val(threadspec, "pitch"),
|
||||
profile=_thread_profile(threadspec),
|
||||
bevel=false,anchor=anchor,spin=spin,orient=orient);
|
||||
}
|
||||
|
||||
|
||||
|
1632
shapes.scad
1632
shapes.scad
File diff suppressed because it is too large
Load Diff
1776
shapes2d.scad
1776
shapes2d.scad
File diff suppressed because it is too large
Load Diff
122
skin.scad
122
skin.scad
@ -163,26 +163,26 @@ include <vnf.scad>
|
||||
// Example: Vaccum nozzle example from list-comprehension-demos, using "length" sampling (the default)
|
||||
// xrot(90)down(1.5)
|
||||
// difference() {
|
||||
// skin(
|
||||
// [square([2,.2],center=true),
|
||||
// circle($fn=64,r=0.5)], z=[0,3],
|
||||
// slices=40,sampling="length",method="reindex");
|
||||
// skin(
|
||||
// [square([1.9,.1],center=true),
|
||||
// circle($fn=64,r=0.45)], z=[-.01,3.01],
|
||||
// slices=40,sampling="length",method="reindex");
|
||||
// skin(
|
||||
// [square([2,.2],center=true),
|
||||
// circle($fn=64,r=0.5)], z=[0,3],
|
||||
// slices=40,sampling="length",method="reindex");
|
||||
// skin(
|
||||
// [square([1.9,.1],center=true),
|
||||
// circle($fn=64,r=0.45)], z=[-.01,3.01],
|
||||
// slices=40,sampling="length",method="reindex");
|
||||
// }
|
||||
// Example: Same thing with "segment" sampling
|
||||
// xrot(90)down(1.5)
|
||||
// difference() {
|
||||
// skin(
|
||||
// [square([2,.2],center=true),
|
||||
// circle($fn=64,r=0.5)], z=[0,3],
|
||||
// slices=40,sampling="segment",method="reindex");
|
||||
// skin(
|
||||
// [square([1.9,.1],center=true),
|
||||
// circle($fn=64,r=0.45)], z=[-.01,3.01],
|
||||
// slices=40,sampling="segment",method="reindex");
|
||||
// skin(
|
||||
// [square([2,.2],center=true),
|
||||
// circle($fn=64,r=0.5)], z=[0,3],
|
||||
// slices=40,sampling="segment",method="reindex");
|
||||
// skin(
|
||||
// [square([1.9,.1],center=true),
|
||||
// circle($fn=64,r=0.45)], z=[-.01,3.01],
|
||||
// slices=40,sampling="segment",method="reindex");
|
||||
// }
|
||||
// Example: Forma Candle Holder (from list-comprehension-demos)
|
||||
// r = 50;
|
||||
@ -319,7 +319,7 @@ include <vnf.scad>
|
||||
|
||||
module skin(profiles, slices, refine=1, method="direct", sampling, caps, closed=false, z, convexity=10)
|
||||
{
|
||||
vnf_polyhedron(skin(profiles, slices, refine, method, sampling, caps, closed, z), convexity=convexity);
|
||||
vnf_polyhedron(skin(profiles, slices, refine, method, sampling, caps, closed, z), convexity=convexity);
|
||||
}
|
||||
|
||||
|
||||
@ -421,56 +421,56 @@ function skin(profiles, slices, refine=1, method="direct", sampling, caps, close
|
||||
|
||||
|
||||
function _skin_core(profiles, caps) =
|
||||
let(
|
||||
let(
|
||||
vertices = [for (prof=profiles) each prof],
|
||||
plens = [for (prof=profiles) len(prof)],
|
||||
sidefaces = [
|
||||
for(pidx=idx(profiles,end=-2))
|
||||
let(
|
||||
prof1 = profiles[pidx%len(profiles)],
|
||||
prof2 = profiles[(pidx+1)%len(profiles)],
|
||||
voff = default(sum([for (i=[0:1:pidx-1]) plens[i]]),0),
|
||||
faces = [
|
||||
for(
|
||||
first = true,
|
||||
finishing = false,
|
||||
finished = false,
|
||||
plen1 = len(prof1),
|
||||
plen2 = len(prof2),
|
||||
i=0, j=0, side=0;
|
||||
plens = [for (prof=profiles) len(prof)],
|
||||
sidefaces = [
|
||||
for(pidx=idx(profiles,end=-2))
|
||||
let(
|
||||
prof1 = profiles[pidx%len(profiles)],
|
||||
prof2 = profiles[(pidx+1)%len(profiles)],
|
||||
voff = default(sum([for (i=[0:1:pidx-1]) plens[i]]),0),
|
||||
faces = [
|
||||
for(
|
||||
first = true,
|
||||
finishing = false,
|
||||
finished = false,
|
||||
plen1 = len(prof1),
|
||||
plen2 = len(prof2),
|
||||
i=0, j=0, side=0;
|
||||
|
||||
!finished;
|
||||
!finished;
|
||||
|
||||
side =
|
||||
let(
|
||||
p1a = prof1[(i+0)%plen1],
|
||||
p1b = prof1[(i+1)%plen1],
|
||||
p2a = prof2[(j+0)%plen2],
|
||||
p2b = prof2[(j+1)%plen2],
|
||||
dist1 = norm(p1a-p2b),
|
||||
dist2 = norm(p1b-p2a)
|
||||
) (i==j) ? (dist1>dist2? 1 : 0) : (i<j ? 1 : 0) ,
|
||||
p1 = voff + (i%plen1),
|
||||
p2 = voff + (j%plen2) + plen1,
|
||||
p3 = voff + (side? ((i+1)%plen1) : (((j+1)%plen2) + plen1)),
|
||||
face = [p1, p3, p2],
|
||||
i = i + (side? 1 : 0),
|
||||
j = j + (side? 0 : 1),
|
||||
first = false,
|
||||
finished = finishing,
|
||||
finishing = i>=plen1 && j>=plen2
|
||||
) if (!first) face
|
||||
]
|
||||
) each faces
|
||||
],
|
||||
side =
|
||||
let(
|
||||
p1a = prof1[(i+0)%plen1],
|
||||
p1b = prof1[(i+1)%plen1],
|
||||
p2a = prof2[(j+0)%plen2],
|
||||
p2b = prof2[(j+1)%plen2],
|
||||
dist1 = norm(p1a-p2b),
|
||||
dist2 = norm(p1b-p2a)
|
||||
) (i==j) ? (dist1>dist2? 1 : 0) : (i<j ? 1 : 0) ,
|
||||
p1 = voff + (i%plen1),
|
||||
p2 = voff + (j%plen2) + plen1,
|
||||
p3 = voff + (side? ((i+1)%plen1) : (((j+1)%plen2) + plen1)),
|
||||
face = [p1, p3, p2],
|
||||
i = i + (side? 1 : 0),
|
||||
j = j + (side? 0 : 1),
|
||||
first = false,
|
||||
finished = finishing,
|
||||
finishing = i>=plen1 && j>=plen2
|
||||
) if (!first) face
|
||||
]
|
||||
) each faces
|
||||
],
|
||||
firstcap = !caps[0] ? [] : let(
|
||||
prof1 = profiles[0]
|
||||
) [[for (i=idx(prof1)) plens[0]-1-i]],
|
||||
secondcap = !caps[1] ? [] : let(
|
||||
prof2 = select(profiles,-1),
|
||||
eoff = sum(select(plens,0,-2))
|
||||
) [[for (i=idx(prof2)) eoff+i]]
|
||||
) [vertices, concat(sidefaces,firstcap,secondcap)];
|
||||
prof2 = select(profiles,-1),
|
||||
eoff = sum(select(plens,0,-2))
|
||||
) [[for (i=idx(prof2)) eoff+i]]
|
||||
) [vertices, concat(sidefaces,firstcap,secondcap)];
|
||||
|
||||
|
||||
|
||||
@ -1223,4 +1223,4 @@ function path_sweep(shape, path, method="incremental", normal, closed=false, twi
|
||||
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
262
sliders.scad
262
sliders.scad
@ -32,30 +32,30 @@
|
||||
// slider(l=30, base=10, wall=4, $slop=0.2, spin=90);
|
||||
module slider(l=30, w=10, h=10, base=10, wall=5, ang=30, anchor=BOTTOM, spin=0, orient=UP)
|
||||
{
|
||||
full_width = w + 2*wall;
|
||||
full_height = h + base;
|
||||
full_width = w + 2*wall;
|
||||
full_height = h + base;
|
||||
|
||||
attachable(anchor,spin,orient, size=[full_width, l, h+2*base]) {
|
||||
zrot(90)
|
||||
down(base+h/2) {
|
||||
// Base
|
||||
cuboid([full_width, l, base-$slop], chamfer=2, edges=edges([FRONT,BACK], except=BOT), anchor=BOTTOM);
|
||||
attachable(anchor,spin,orient, size=[full_width, l, h+2*base]) {
|
||||
zrot(90)
|
||||
down(base+h/2) {
|
||||
// Base
|
||||
cuboid([full_width, l, base-$slop], chamfer=2, edges=edges([FRONT,BACK], except=BOT), anchor=BOTTOM);
|
||||
|
||||
// Wall
|
||||
xflip_copy(offset=w/2+$slop) {
|
||||
cuboid([wall, l, full_height], chamfer=2, edges=edges(RIGHT, except=BOT), anchor=BOTTOM+LEFT);
|
||||
}
|
||||
// Wall
|
||||
xflip_copy(offset=w/2+$slop) {
|
||||
cuboid([wall, l, full_height], chamfer=2, edges=edges(RIGHT, except=BOT), anchor=BOTTOM+LEFT);
|
||||
}
|
||||
|
||||
// Sliders
|
||||
up(base+h/2) {
|
||||
xflip_copy(offset=w/2+$slop+0.02) {
|
||||
bev_h = h/2*tan(ang);
|
||||
prismoid([h, l], [0, l-w], h=bev_h+0.01, orient=LEFT, anchor=BOT);
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
// Sliders
|
||||
up(base+h/2) {
|
||||
xflip_copy(offset=w/2+$slop+0.02) {
|
||||
bev_h = h/2*tan(ang);
|
||||
prismoid([h, l], [0, l-w], h=bev_h+0.01, orient=LEFT, anchor=BOT);
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -78,129 +78,129 @@ module slider(l=30, w=10, h=10, base=10, wall=5, ang=30, anchor=BOTTOM, spin=0,
|
||||
// rail(l=100, w=10, h=10);
|
||||
module rail(l=30, w=10, h=10, chamfer=1.0, ang=30, anchor=BOTTOM, spin=0, orient=UP)
|
||||
{
|
||||
attack_ang = 30;
|
||||
attack_len = 2;
|
||||
attack_ang = 30;
|
||||
attack_len = 2;
|
||||
|
||||
fudge = 1.177;
|
||||
chamf = sqrt(2) * chamfer;
|
||||
cosa = cos(ang*fudge);
|
||||
sina = sin(ang*fudge);
|
||||
fudge = 1.177;
|
||||
chamf = sqrt(2) * chamfer;
|
||||
cosa = cos(ang*fudge);
|
||||
sina = sin(ang*fudge);
|
||||
|
||||
z1 = h/2;
|
||||
z2 = z1 - chamf * cosa;
|
||||
z3 = z1 - attack_len * sin(attack_ang);
|
||||
z4 = 0;
|
||||
z1 = h/2;
|
||||
z2 = z1 - chamf * cosa;
|
||||
z3 = z1 - attack_len * sin(attack_ang);
|
||||
z4 = 0;
|
||||
|
||||
x1 = w/2;
|
||||
x2 = x1 - chamf * sina;
|
||||
x3 = x1 - chamf;
|
||||
x4 = x1 - attack_len * sin(attack_ang);
|
||||
x5 = x2 - attack_len * sin(attack_ang);
|
||||
x6 = x1 - z1 * sina;
|
||||
x7 = x4 - z1 * sina;
|
||||
x1 = w/2;
|
||||
x2 = x1 - chamf * sina;
|
||||
x3 = x1 - chamf;
|
||||
x4 = x1 - attack_len * sin(attack_ang);
|
||||
x5 = x2 - attack_len * sin(attack_ang);
|
||||
x6 = x1 - z1 * sina;
|
||||
x7 = x4 - z1 * sina;
|
||||
|
||||
y1 = l/2;
|
||||
y2 = y1 - attack_len * cos(attack_ang);
|
||||
y1 = l/2;
|
||||
y2 = y1 - attack_len * cos(attack_ang);
|
||||
|
||||
attachable(anchor,spin,orient, size=[w, l, h]) {
|
||||
polyhedron(
|
||||
convexity=4,
|
||||
points=[
|
||||
[-x5, -y1, z3],
|
||||
[ x5, -y1, z3],
|
||||
[ x7, -y1, z4],
|
||||
[ x4, -y1, -z1-0.05],
|
||||
[-x4, -y1, -z1-0.05],
|
||||
[-x7, -y1, z4],
|
||||
attachable(anchor,spin,orient, size=[w, l, h]) {
|
||||
polyhedron(
|
||||
convexity=4,
|
||||
points=[
|
||||
[-x5, -y1, z3],
|
||||
[ x5, -y1, z3],
|
||||
[ x7, -y1, z4],
|
||||
[ x4, -y1, -z1-0.05],
|
||||
[-x4, -y1, -z1-0.05],
|
||||
[-x7, -y1, z4],
|
||||
|
||||
[-x3, -y2, z1],
|
||||
[ x3, -y2, z1],
|
||||
[ x2, -y2, z2],
|
||||
[ x6, -y2, z4],
|
||||
[ x1, -y2, -z1-0.05],
|
||||
[-x1, -y2, -z1-0.05],
|
||||
[-x6, -y2, z4],
|
||||
[-x2, -y2, z2],
|
||||
[-x3, -y2, z1],
|
||||
[ x3, -y2, z1],
|
||||
[ x2, -y2, z2],
|
||||
[ x6, -y2, z4],
|
||||
[ x1, -y2, -z1-0.05],
|
||||
[-x1, -y2, -z1-0.05],
|
||||
[-x6, -y2, z4],
|
||||
[-x2, -y2, z2],
|
||||
|
||||
[ x5, y1, z3],
|
||||
[-x5, y1, z3],
|
||||
[-x7, y1, z4],
|
||||
[-x4, y1, -z1-0.05],
|
||||
[ x4, y1, -z1-0.05],
|
||||
[ x7, y1, z4],
|
||||
[ x5, y1, z3],
|
||||
[-x5, y1, z3],
|
||||
[-x7, y1, z4],
|
||||
[-x4, y1, -z1-0.05],
|
||||
[ x4, y1, -z1-0.05],
|
||||
[ x7, y1, z4],
|
||||
|
||||
[ x3, y2, z1],
|
||||
[-x3, y2, z1],
|
||||
[-x2, y2, z2],
|
||||
[-x6, y2, z4],
|
||||
[-x1, y2, -z1-0.05],
|
||||
[ x1, y2, -z1-0.05],
|
||||
[ x6, y2, z4],
|
||||
[ x2, y2, z2],
|
||||
],
|
||||
faces=[
|
||||
[0, 1, 2],
|
||||
[0, 2, 5],
|
||||
[2, 3, 4],
|
||||
[2, 4, 5],
|
||||
[ x3, y2, z1],
|
||||
[-x3, y2, z1],
|
||||
[-x2, y2, z2],
|
||||
[-x6, y2, z4],
|
||||
[-x1, y2, -z1-0.05],
|
||||
[ x1, y2, -z1-0.05],
|
||||
[ x6, y2, z4],
|
||||
[ x2, y2, z2],
|
||||
],
|
||||
faces=[
|
||||
[0, 1, 2],
|
||||
[0, 2, 5],
|
||||
[2, 3, 4],
|
||||
[2, 4, 5],
|
||||
|
||||
[0, 13, 6],
|
||||
[0, 6, 7],
|
||||
[0, 7, 1],
|
||||
[1, 7, 8],
|
||||
[1, 8, 9],
|
||||
[1, 9, 2],
|
||||
[2, 9, 10],
|
||||
[2, 10, 3],
|
||||
[3, 10, 11],
|
||||
[3, 11, 4],
|
||||
[4, 11, 12],
|
||||
[4, 12, 5],
|
||||
[5, 12, 13],
|
||||
[5, 13, 0],
|
||||
[0, 13, 6],
|
||||
[0, 6, 7],
|
||||
[0, 7, 1],
|
||||
[1, 7, 8],
|
||||
[1, 8, 9],
|
||||
[1, 9, 2],
|
||||
[2, 9, 10],
|
||||
[2, 10, 3],
|
||||
[3, 10, 11],
|
||||
[3, 11, 4],
|
||||
[4, 11, 12],
|
||||
[4, 12, 5],
|
||||
[5, 12, 13],
|
||||
[5, 13, 0],
|
||||
|
||||
[14, 15, 16],
|
||||
[14, 16, 19],
|
||||
[16, 17, 18],
|
||||
[16, 18, 19],
|
||||
[14, 15, 16],
|
||||
[14, 16, 19],
|
||||
[16, 17, 18],
|
||||
[16, 18, 19],
|
||||
|
||||
[14, 27, 20],
|
||||
[14, 20, 21],
|
||||
[14, 21, 15],
|
||||
[15, 21, 22],
|
||||
[15, 22, 23],
|
||||
[15, 23, 16],
|
||||
[16, 23, 24],
|
||||
[16, 24, 17],
|
||||
[17, 24, 25],
|
||||
[17, 25, 18],
|
||||
[18, 25, 26],
|
||||
[18, 26, 19],
|
||||
[19, 26, 27],
|
||||
[19, 27, 14],
|
||||
[14, 27, 20],
|
||||
[14, 20, 21],
|
||||
[14, 21, 15],
|
||||
[15, 21, 22],
|
||||
[15, 22, 23],
|
||||
[15, 23, 16],
|
||||
[16, 23, 24],
|
||||
[16, 24, 17],
|
||||
[17, 24, 25],
|
||||
[17, 25, 18],
|
||||
[18, 25, 26],
|
||||
[18, 26, 19],
|
||||
[19, 26, 27],
|
||||
[19, 27, 14],
|
||||
|
||||
[6, 21, 20],
|
||||
[6, 20, 7],
|
||||
[7, 20, 27],
|
||||
[7, 27, 8],
|
||||
[8, 27, 26],
|
||||
[8, 26, 9],
|
||||
[9, 26, 25],
|
||||
[9, 25, 10],
|
||||
[10, 25, 24],
|
||||
[10, 24, 11],
|
||||
[11, 24, 23],
|
||||
[11, 23, 12],
|
||||
[12, 23, 22],
|
||||
[12, 22, 13],
|
||||
[13, 22, 21],
|
||||
[13, 21, 6],
|
||||
]
|
||||
);
|
||||
children();
|
||||
}
|
||||
[6, 21, 20],
|
||||
[6, 20, 7],
|
||||
[7, 20, 27],
|
||||
[7, 27, 8],
|
||||
[8, 27, 26],
|
||||
[8, 26, 9],
|
||||
[9, 26, 25],
|
||||
[9, 25, 10],
|
||||
[10, 25, 24],
|
||||
[10, 24, 11],
|
||||
[11, 24, 23],
|
||||
[11, 23, 12],
|
||||
[12, 23, 22],
|
||||
[12, 22, 13],
|
||||
[13, 22, 21],
|
||||
[13, 21, 6],
|
||||
]
|
||||
);
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
94
stacks.scad
94
stacks.scad
@ -41,8 +41,8 @@ function stack_init() = [];
|
||||
// stack2 = stack_push(stack, "foo");
|
||||
// is_empty2 = stack_empty(stack2); // Returns: false
|
||||
function stack_empty(stack) =
|
||||
assert(is_list(stack))
|
||||
len(stack)==0;
|
||||
assert(is_list(stack))
|
||||
len(stack)==0;
|
||||
|
||||
|
||||
// Function: stack_depth()
|
||||
@ -60,8 +60,8 @@ function stack_empty(stack) =
|
||||
// stack3 = stack_push(stack2, ["bar","baz","qux"]);
|
||||
// depth3 = stack_depth(stack3); // Returns: 4
|
||||
function stack_depth(stack) =
|
||||
assert(is_list(stack))
|
||||
len(stack);
|
||||
assert(is_list(stack))
|
||||
len(stack);
|
||||
|
||||
|
||||
// Function: stack_top()
|
||||
@ -78,16 +78,16 @@ function stack_depth(stack) =
|
||||
// item = stack_top(stack); // Returns: 7
|
||||
// list = stack_top(stack,n=3); // Returns: [5,6,7]
|
||||
function stack_top(stack,n=undef) =
|
||||
assert(is_list(stack))
|
||||
is_undef(n)? (
|
||||
stack[len(stack)-1]
|
||||
) : (
|
||||
let(stacksize = len(stack))
|
||||
assert(is_num(n))
|
||||
assert(n>=0)
|
||||
assert(stacksize>=n, "stack underflow")
|
||||
[for (i=[0:1:n-1]) stack[stacksize-n+i]]
|
||||
);
|
||||
assert(is_list(stack))
|
||||
is_undef(n)? (
|
||||
stack[len(stack)-1]
|
||||
) : (
|
||||
let(stacksize = len(stack))
|
||||
assert(is_num(n))
|
||||
assert(n>=0)
|
||||
assert(stacksize>=n, "stack underflow")
|
||||
[for (i=[0:1:n-1]) stack[stacksize-n+i]]
|
||||
);
|
||||
|
||||
|
||||
// Function: stack_peek()
|
||||
@ -107,19 +107,19 @@ function stack_top(stack,n=undef) =
|
||||
// item2 = stack_peek(stack, 3); // Returns: 7
|
||||
// list = stack_peek(stack, 6, 4); // Returns: [4,5,6,7]
|
||||
function stack_peek(stack,depth=0,n=undef) =
|
||||
assert(is_list(stack))
|
||||
assert(is_num(depth))
|
||||
assert(depth>=0)
|
||||
let(stacksize = len(stack))
|
||||
assert(stacksize>=depth, "stack underflow")
|
||||
is_undef(n)? (
|
||||
stack[stacksize-depth-1]
|
||||
) : (
|
||||
assert(is_num(n))
|
||||
assert(n>=0)
|
||||
assert(n<=depth+1)
|
||||
[for (i=[0:1:n-1]) stack[stacksize-1-depth+i]]
|
||||
);
|
||||
assert(is_list(stack))
|
||||
assert(is_num(depth))
|
||||
assert(depth>=0)
|
||||
let(stacksize = len(stack))
|
||||
assert(stacksize>=depth, "stack underflow")
|
||||
is_undef(n)? (
|
||||
stack[stacksize-depth-1]
|
||||
) : (
|
||||
assert(is_num(n))
|
||||
assert(n>=0)
|
||||
assert(n<=depth+1)
|
||||
[for (i=[0:1:n-1]) stack[stacksize-1-depth+i]]
|
||||
);
|
||||
|
||||
|
||||
// Function: stack_push()
|
||||
@ -137,8 +137,8 @@ function stack_peek(stack,depth=0,n=undef) =
|
||||
// stack4 = stack_push(stack,[[5,8]]); // Returns: [4,9,2,3,[5,8]]
|
||||
// stack5 = stack_push(stack,[[5,8],6,7]); // Returns: [4,9,2,3,[5,8],6,7]
|
||||
function stack_push(stack,items) =
|
||||
assert(is_list(stack))
|
||||
is_list(items)? concat(stack, items) : concat(stack, [items]);
|
||||
assert(is_list(stack))
|
||||
is_list(items)? concat(stack, items) : concat(stack, [items]);
|
||||
|
||||
|
||||
// Function: stack_pop()
|
||||
@ -154,11 +154,11 @@ function stack_push(stack,items) =
|
||||
// stack2 = stack_pop(stack); // Returns: [4,5,6,7,8]
|
||||
// stack3 = stack_pop(stack2,n=3); // Returns: [4,5]
|
||||
function stack_pop(stack,n=1) =
|
||||
assert(is_list(stack))
|
||||
assert(is_num(n))
|
||||
assert(n>=0)
|
||||
assert(len(stack)>=n, "stack underflow")
|
||||
[for (i = [0:1:len(stack)-1-n]) stack[i]];
|
||||
assert(is_list(stack))
|
||||
assert(is_num(n))
|
||||
assert(n>=0)
|
||||
assert(len(stack)>=n, "stack underflow")
|
||||
[for (i = [0:1:len(stack)-1-n]) stack[i]];
|
||||
|
||||
|
||||
// Function: stack_rotate()
|
||||
@ -176,18 +176,18 @@ function stack_pop(stack,n=1) =
|
||||
// stack2 = stack_rotate(stack,3); // Returns: [4,5,7,8,6]
|
||||
// stack3 = stack_rotate(stack2,-4); // Returns: [4,6,5,7,8]
|
||||
function stack_rotate(stack,n=3) =
|
||||
assert(is_list(stack))
|
||||
let(stacksize = len(stack))
|
||||
assert(stacksize>=n, "stack underflow")
|
||||
n>=0? concat(
|
||||
[for (i=[0:1:stacksize-1-n]) stack[i]],
|
||||
[for (i=[0:1:n-2]) stack[stacksize-n+i+1]],
|
||||
[stack[stacksize-n]]
|
||||
) : concat(
|
||||
[for (i=[0:1:stacksize-1+n]) stack[i]],
|
||||
[stack[stacksize-1]],
|
||||
[for (i=[0:1:-n-2]) stack[stacksize+n+i]]
|
||||
);
|
||||
assert(is_list(stack))
|
||||
let(stacksize = len(stack))
|
||||
assert(stacksize>=n, "stack underflow")
|
||||
n>=0? concat(
|
||||
[for (i=[0:1:stacksize-1-n]) stack[i]],
|
||||
[for (i=[0:1:n-2]) stack[stacksize-n+i+1]],
|
||||
[stack[stacksize-n]]
|
||||
) : concat(
|
||||
[for (i=[0:1:stacksize-1+n]) stack[i]],
|
||||
[stack[stacksize-1]],
|
||||
[for (i=[0:1:-n-2]) stack[stacksize+n+i]]
|
||||
);
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
2
std.scad
2
std.scad
@ -39,5 +39,5 @@ include <masks.scad>
|
||||
include <paths.scad>
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
||||
|
430
strings.scad
430
strings.scad
@ -27,13 +27,13 @@
|
||||
// substr("abcdefg",[2,4]); // Returns "cde"
|
||||
// substr("abcdefg",len=-2); // Returns ""
|
||||
function substr(str, pos=0, len=undef) =
|
||||
is_list(pos) ? _substr(str, pos[0], pos[1]-pos[0]+1) :
|
||||
len == undef ? _substr(str, pos, len(str)-pos) :
|
||||
_substr(str,pos,len);
|
||||
is_list(pos) ? _substr(str, pos[0], pos[1]-pos[0]+1) :
|
||||
len == undef ? _substr(str, pos, len(str)-pos) :
|
||||
_substr(str,pos,len);
|
||||
|
||||
function _substr(str,pos,len,substr="") =
|
||||
len <= 0 || pos>=len(str) ? substr :
|
||||
_substr(str, pos+1, len-1, str(substr, str[pos]));
|
||||
len <= 0 || pos>=len(str) ? substr :
|
||||
_substr(str, pos+1, len-1, str(substr, str[pos]));
|
||||
|
||||
|
||||
// Function suffix()
|
||||
@ -57,8 +57,8 @@ function suffix(str,len) = substr(str, len(str)-len,len);
|
||||
// str_join(["abc","def","ghi"]); // Returns "abcdefghi"
|
||||
// str_join(["abc","def","ghi"], " + "); // Returns "abc + def + ghi"
|
||||
function str_join(list,sep="",_i=0, _result="") =
|
||||
_i >= len(list)-1 ? (_i==len(list) ? _result : str(_result,list[_i])) :
|
||||
str_join(list,sep,_i+1,str(_result,list[_i],sep));
|
||||
_i >= len(list)-1 ? (_i==len(list) ? _result : str(_result,list[_i])) :
|
||||
str_join(list,sep,_i+1,str(_result,list[_i],sep));
|
||||
|
||||
|
||||
// Function: downcase()
|
||||
@ -72,7 +72,7 @@ function str_join(list,sep="",_i=0, _result="") =
|
||||
// Example:
|
||||
// downcase("ABCdef"); // Returns "abcdef"
|
||||
function downcase(str) =
|
||||
str_join([for(char=str) let(code=ord(char)) code>=65 && code<=90 ? chr(code+32) : char]);
|
||||
str_join([for(char=str) let(code=ord(char)) code>=65 && code<=90 ? chr(code+32) : char]);
|
||||
|
||||
|
||||
// Function: upcase()
|
||||
@ -86,7 +86,7 @@ function downcase(str) =
|
||||
// Example:
|
||||
// upcase("ABCdef"); // Returns "ABCDEF"
|
||||
function upcase(str) =
|
||||
str_join([for(char=str) let(code=ord(char)) code>=97 && code<=122 ? chr(code-32) : char]);
|
||||
str_join([for(char=str) let(code=ord(char)) code>=97 && code<=122 ? chr(code-32) : char]);
|
||||
|
||||
|
||||
// Function: str_int()
|
||||
@ -110,19 +110,19 @@ function upcase(str) =
|
||||
// str_int("CEDE", 16); // Returns 52958
|
||||
// str_int(""); // Returns 0
|
||||
function str_int(str,base=10) =
|
||||
str==undef ? undef :
|
||||
len(str)==0 ? 0 :
|
||||
let(str=downcase(str))
|
||||
str[0] == "-" ? -_str_int_recurse(substr(str,1),base,len(str)-2) :
|
||||
str[0] == "+" ? _str_int_recurse(substr(str,1),base,len(str)-2) :
|
||||
_str_int_recurse(str,base,len(str)-1);
|
||||
str==undef ? undef :
|
||||
len(str)==0 ? 0 :
|
||||
let(str=downcase(str))
|
||||
str[0] == "-" ? -_str_int_recurse(substr(str,1),base,len(str)-2) :
|
||||
str[0] == "+" ? _str_int_recurse(substr(str,1),base,len(str)-2) :
|
||||
_str_int_recurse(str,base,len(str)-1);
|
||||
|
||||
function _str_int_recurse(str,base,i) =
|
||||
let(
|
||||
digit = search(str[i],"0123456789abcdef"),
|
||||
last_digit = digit == [] || digit[0] >= base ? (0/0) : digit[0]
|
||||
) i==0 ? last_digit :
|
||||
_str_int_recurse(str,base,i-1)*base + last_digit;
|
||||
let(
|
||||
digit = search(str[i],"0123456789abcdef"),
|
||||
last_digit = digit == [] || digit[0] >= base ? (0/0) : digit[0]
|
||||
) i==0 ? last_digit :
|
||||
_str_int_recurse(str,base,i-1)*base + last_digit;
|
||||
|
||||
|
||||
// Function: str_float()
|
||||
@ -142,15 +142,15 @@ function _str_int_recurse(str,base,i) =
|
||||
// str_float("7.342e-4"); // Returns 0.0007342
|
||||
// str_float(""); // Returns 0
|
||||
function str_float(str) =
|
||||
str==undef ? undef :
|
||||
len(str) == 0 ? 0 :
|
||||
in_list(str[1], ["+","-"]) ? (0/0) : // Don't allow --3, or +-3
|
||||
str[0]=="-" ? -str_float(substr(str,1)) :
|
||||
str[0]=="+" ? str_float(substr(str,1)) :
|
||||
let(esplit = str_split(str,"eE") )
|
||||
len(esplit)==2 ? str_float(esplit[0]) * pow(10,str_int(esplit[1])) :
|
||||
let( dsplit = str_split(str,["."]))
|
||||
str_int(dsplit[0])+str_int(dsplit[1])/pow(10,len(dsplit[1]));
|
||||
str==undef ? undef :
|
||||
len(str) == 0 ? 0 :
|
||||
in_list(str[1], ["+","-"]) ? (0/0) : // Don't allow --3, or +-3
|
||||
str[0]=="-" ? -str_float(substr(str,1)) :
|
||||
str[0]=="+" ? str_float(substr(str,1)) :
|
||||
let(esplit = str_split(str,"eE") )
|
||||
len(esplit)==2 ? str_float(esplit[0]) * pow(10,str_int(esplit[1])) :
|
||||
let( dsplit = str_split(str,["."]))
|
||||
str_int(dsplit[0])+str_int(dsplit[1])/pow(10,len(dsplit[1]));
|
||||
|
||||
|
||||
// Function: str_frac()
|
||||
@ -186,24 +186,24 @@ function str_float(str) =
|
||||
// str_frac("-2 12/4",mixed=false); // Returns nan
|
||||
// str_frac("2 1/4",mixed=false); // Returns nan
|
||||
function str_frac(str,mixed=true,improper=true,signed=true) =
|
||||
str == undef ? undef :
|
||||
len(str)==0 ? 0 :
|
||||
signed && str[0]=="-" ? -str_frac(substr(str,1),mixed=mixed,improper=improper,signed=false) :
|
||||
signed && str[0]=="+" ? str_frac(substr(str,1),mixed=mixed,improper=improper,signed=false) :
|
||||
mixed ? (
|
||||
str_find(str," ")>0 || is_undef(str_find(str,"/"))? (
|
||||
let(whole = str_split(str,[" "]))
|
||||
_str_int_recurse(whole[0],10,len(whole[0])-1) + str_frac(whole[1], mixed=false, improper=improper, signed=false)
|
||||
) : str_frac(str,mixed=false, improper=improper)
|
||||
) : (
|
||||
let(split = str_split(str,"/"))
|
||||
len(split)!=2 ? (0/0) :
|
||||
let(
|
||||
numerator = _str_int_recurse(split[0],10,len(split[0])-1),
|
||||
denominator = _str_int_recurse(split[1],10,len(split[1])-1)
|
||||
) !improper && numerator>=denominator? (0/0) :
|
||||
denominator<0 ? (0/0) : numerator/denominator
|
||||
);
|
||||
str == undef ? undef :
|
||||
len(str)==0 ? 0 :
|
||||
signed && str[0]=="-" ? -str_frac(substr(str,1),mixed=mixed,improper=improper,signed=false) :
|
||||
signed && str[0]=="+" ? str_frac(substr(str,1),mixed=mixed,improper=improper,signed=false) :
|
||||
mixed ? (
|
||||
str_find(str," ")>0 || is_undef(str_find(str,"/"))? (
|
||||
let(whole = str_split(str,[" "]))
|
||||
_str_int_recurse(whole[0],10,len(whole[0])-1) + str_frac(whole[1], mixed=false, improper=improper, signed=false)
|
||||
) : str_frac(str,mixed=false, improper=improper)
|
||||
) : (
|
||||
let(split = str_split(str,"/"))
|
||||
len(split)!=2 ? (0/0) :
|
||||
let(
|
||||
numerator = _str_int_recurse(split[0],10,len(split[0])-1),
|
||||
denominator = _str_int_recurse(split[1],10,len(split[1])-1)
|
||||
) !improper && numerator>=denominator? (0/0) :
|
||||
denominator<0 ? (0/0) : numerator/denominator
|
||||
);
|
||||
|
||||
|
||||
// Function: str_num()
|
||||
@ -216,10 +216,10 @@ function str_frac(str,mixed=true,improper=true,signed=true) =
|
||||
// str_num("3/4"); // Returns 0.75
|
||||
// str_num("3.4e-2"); // Returns 0.034
|
||||
function str_num(str) =
|
||||
str == undef ? undef :
|
||||
let( val = str_frac(str) )
|
||||
val == val ? val :
|
||||
str_float(str);
|
||||
str == undef ? undef :
|
||||
let( val = str_frac(str) )
|
||||
val == val ? val :
|
||||
str_float(str);
|
||||
|
||||
|
||||
// Function: str_split()
|
||||
@ -247,25 +247,25 @@ function str_num(str) =
|
||||
// str_split("abc+def-qrs*iop",["+","-","*"]); // Returns ["abc", "def", "qrs", "iop"]
|
||||
// str_split("abc+def-qrs*iop",["-","+","*"]); // Returns ["abc+def", "qrs*iop", "", ""]
|
||||
function str_split(str,sep,keep_nulls=true) =
|
||||
!keep_nulls ? _remove_empty_strs(str_split(str,sep,keep_nulls=true)) :
|
||||
is_list(sep) ? _str_split_recurse(str,sep,i=0,result=[]) :
|
||||
let( cutpts = concat([-1],sort(flatten(search(sep, str,0))),[len(str)]))
|
||||
[for(i=[0:len(cutpts)-2]) substr(str,cutpts[i]+1,cutpts[i+1]-cutpts[i]-1)];
|
||||
!keep_nulls ? _remove_empty_strs(str_split(str,sep,keep_nulls=true)) :
|
||||
is_list(sep) ? _str_split_recurse(str,sep,i=0,result=[]) :
|
||||
let( cutpts = concat([-1],sort(flatten(search(sep, str,0))),[len(str)]))
|
||||
[for(i=[0:len(cutpts)-2]) substr(str,cutpts[i]+1,cutpts[i+1]-cutpts[i]-1)];
|
||||
|
||||
function _str_split_recurse(str,sep,i,result) =
|
||||
i == len(sep) ? concat(result,[str]) :
|
||||
let(
|
||||
pos = search(sep[i], str),
|
||||
end = pos==[] ? len(str) : pos[0]
|
||||
)
|
||||
_str_split_recurse(
|
||||
substr(str,end+1),
|
||||
sep, i+1,
|
||||
concat(result, [substr(str,0,end)])
|
||||
);
|
||||
i == len(sep) ? concat(result,[str]) :
|
||||
let(
|
||||
pos = search(sep[i], str),
|
||||
end = pos==[] ? len(str) : pos[0]
|
||||
)
|
||||
_str_split_recurse(
|
||||
substr(str,end+1),
|
||||
sep, i+1,
|
||||
concat(result, [substr(str,0,end)])
|
||||
);
|
||||
|
||||
function _remove_empty_strs(list) =
|
||||
list_remove(list, search([""], list,0)[0]);
|
||||
list_remove(list, search([""], list,0)[0]);
|
||||
|
||||
|
||||
// _str_cmp(str,sindex,pattern)
|
||||
@ -276,11 +276,11 @@ function _remove_empty_strs(list) =
|
||||
// cuts run time in half when the string is long. Two other string
|
||||
// comparison methods were slower.
|
||||
function _str_cmp(str,sindex,pattern) =
|
||||
len(str)-sindex <len(pattern)? false :
|
||||
_str_cmp_recurse(str,sindex,pattern,len(pattern));
|
||||
len(str)-sindex <len(pattern)? false :
|
||||
_str_cmp_recurse(str,sindex,pattern,len(pattern));
|
||||
|
||||
function _str_cmp_recurse(str,sindex,pattern,plen,pindex=0,) =
|
||||
pindex < plen && pattern[pindex]==str[sindex] ? _str_cmp_recurse(str,sindex+1,pattern,plen,pindex+1): (pindex==plen);
|
||||
pindex < plen && pattern[pindex]==str[sindex] ? _str_cmp_recurse(str,sindex+1,pattern,plen,pindex+1): (pindex==plen);
|
||||
|
||||
|
||||
// Function: str_find()
|
||||
@ -315,25 +315,25 @@ function _str_cmp_recurse(str,sindex,pattern,plen,pindex=0,) =
|
||||
// str_find("abc123def123abc","1234",all=true); // Returns []
|
||||
// str_find("abc","",all=true); // Returns [0,1,2]
|
||||
function str_find(str,pattern,start=undef,last=false,all=false) =
|
||||
all? _str_find_all(str,pattern) :
|
||||
let( start = first_defined([start,last?len(str)-len(pattern):0]) )
|
||||
pattern==""? start :
|
||||
last? _str_find_last(str,pattern,start) :
|
||||
_str_find_first(str,pattern,len(str)-len(pattern),start);
|
||||
all? _str_find_all(str,pattern) :
|
||||
let( start = first_defined([start,last?len(str)-len(pattern):0]) )
|
||||
pattern==""? start :
|
||||
last? _str_find_last(str,pattern,start) :
|
||||
_str_find_first(str,pattern,len(str)-len(pattern),start);
|
||||
|
||||
function _str_find_first(str,pattern,max_sindex,sindex) =
|
||||
sindex<=max_sindex && !_str_cmp(str,sindex, pattern)?
|
||||
_str_find_first(str,pattern,max_sindex,sindex+1) :
|
||||
(sindex <= max_sindex ? sindex : undef);
|
||||
sindex<=max_sindex && !_str_cmp(str,sindex, pattern)?
|
||||
_str_find_first(str,pattern,max_sindex,sindex+1) :
|
||||
(sindex <= max_sindex ? sindex : undef);
|
||||
|
||||
function _str_find_last(str,pattern,sindex) =
|
||||
sindex>=0 && !_str_cmp(str,sindex, pattern)?
|
||||
_str_find_last(str,pattern,sindex-1) :
|
||||
(sindex >=0 ? sindex : undef);
|
||||
sindex>=0 && !_str_cmp(str,sindex, pattern)?
|
||||
_str_find_last(str,pattern,sindex-1) :
|
||||
(sindex >=0 ? sindex : undef);
|
||||
|
||||
function _str_find_all(str,pattern) =
|
||||
pattern == "" ? list_range(len(str)) :
|
||||
[for(i=[0:1:len(str)-len(pattern)]) if (_str_cmp(str,i,pattern)) i];
|
||||
pattern == "" ? list_range(len(str)) :
|
||||
[for(i=[0:1:len(str)-len(pattern)]) if (_str_cmp(str,i,pattern)) i];
|
||||
|
||||
|
||||
// Function: starts_with()
|
||||
@ -369,12 +369,12 @@ function ends_with(str,pattern) = _str_cmp(str,len(str)-len(pattern),pattern);
|
||||
|
||||
|
||||
function _str_count_leading(s,c,_i=0) =
|
||||
(_i>=len(s)||!in_list(s[_i],[each c]))? _i :
|
||||
_str_count_leading(s,c,_i=_i+1);
|
||||
(_i>=len(s)||!in_list(s[_i],[each c]))? _i :
|
||||
_str_count_leading(s,c,_i=_i+1);
|
||||
|
||||
function _str_count_trailing(s,c,_i=0) =
|
||||
(_i>=len(s)||!in_list(s[len(s)-1-_i],[each c]))? _i :
|
||||
_str_count_trailing(s,c,_i=_i+1);
|
||||
(_i>=len(s)||!in_list(s[len(s)-1-_i],[each c]))? _i :
|
||||
_str_count_trailing(s,c,_i=_i+1);
|
||||
|
||||
|
||||
// Function: str_strip_leading()
|
||||
@ -435,15 +435,15 @@ function str_strip(s,c) = str_strip_trailing(str_strip_leading(s,c),c);
|
||||
// fmt_int(123456789012345); // Returns "123456789012345"
|
||||
// fmt_int(-123456789012345); // Returns "-123456789012345"
|
||||
function fmt_int(i,mindigits=1) =
|
||||
i<0? str("-", fmt_int(-i)) :
|
||||
let(i=floor(i), e=floor(log(i)))
|
||||
i==0? "0" :
|
||||
str_join(
|
||||
concat(
|
||||
[for (j=[0:1:mindigits-e-2]) "0"],
|
||||
[for (j=[e:-1:0]) str(floor(i/pow(10,j)%10))]
|
||||
)
|
||||
);
|
||||
i<0? str("-", fmt_int(-i)) :
|
||||
let(i=floor(i), e=floor(log(i)))
|
||||
i==0? "0" :
|
||||
str_join(
|
||||
concat(
|
||||
[for (j=[0:1:mindigits-e-2]) "0"],
|
||||
[for (j=[e:-1:0]) str(floor(i/pow(10,j)%10))]
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
// Function: fmt_fixed()
|
||||
@ -455,19 +455,19 @@ function fmt_int(i,mindigits=1) =
|
||||
// f = The floating point number to format.
|
||||
// digits = The number of digits after the decimal to show. Default: 6
|
||||
function fmt_fixed(f,digits=6) =
|
||||
assert(is_int(digits))
|
||||
assert(digits>0)
|
||||
is_list(f)? str("[",str_join(sep=", ", [for (g=f) fmt_fixed(g,digits=digits)]),"]") :
|
||||
str(f)=="nan"? "nan" :
|
||||
str(f)=="inf"? "inf" :
|
||||
f<0? str("-",fmt_fixed(-f,digits=digits)) :
|
||||
assert(is_num(f))
|
||||
let(
|
||||
sc = pow(10,digits),
|
||||
scaled = floor(f * sc + 0.5),
|
||||
whole = floor(scaled/sc),
|
||||
part = floor(scaled-(whole*sc))
|
||||
) str(fmt_int(whole),".",fmt_int(part,digits));
|
||||
assert(is_int(digits))
|
||||
assert(digits>0)
|
||||
is_list(f)? str("[",str_join(sep=", ", [for (g=f) fmt_fixed(g,digits=digits)]),"]") :
|
||||
str(f)=="nan"? "nan" :
|
||||
str(f)=="inf"? "inf" :
|
||||
f<0? str("-",fmt_fixed(-f,digits=digits)) :
|
||||
assert(is_num(f))
|
||||
let(
|
||||
sc = pow(10,digits),
|
||||
scaled = floor(f * sc + 0.5),
|
||||
whole = floor(scaled/sc),
|
||||
part = floor(scaled-(whole*sc))
|
||||
) str(fmt_int(whole),".",fmt_int(part,digits));
|
||||
|
||||
|
||||
// Function: fmt_float()
|
||||
@ -485,34 +485,34 @@ function fmt_fixed(f,digits=6) =
|
||||
// fmt_float(PI,12); // Returns: "3.14159265359"
|
||||
// fmt_float([PI,-16.75],12); // Returns: "[3.14159265359, -16.75]"
|
||||
function fmt_float(f,sig=12) =
|
||||
assert(is_int(sig))
|
||||
assert(sig>0)
|
||||
is_list(f)? str("[",str_join(sep=", ", [for (g=f) fmt_float(g,sig=sig)]),"]") :
|
||||
f==0? "0" :
|
||||
str(f)=="nan"? "nan" :
|
||||
str(f)=="inf"? "inf" :
|
||||
f<0? str("-",fmt_float(-f,sig=sig)) :
|
||||
assert(is_num(f))
|
||||
let(
|
||||
e = floor(log(f)),
|
||||
mv = sig - e - 1
|
||||
) mv == 0? fmt_int(floor(f + 0.5)) :
|
||||
(e<-sig/2||mv<0)? str(fmt_float(f*pow(10,-e),sig=sig),"e",e) :
|
||||
let(
|
||||
ff = f + pow(10,-mv)*0.5,
|
||||
whole = floor(ff),
|
||||
part = floor((ff-whole) * pow(10,mv))
|
||||
)
|
||||
str_join([
|
||||
str(whole),
|
||||
str_strip_trailing(
|
||||
str_join([
|
||||
".",
|
||||
fmt_int(part, mindigits=mv)
|
||||
]),
|
||||
"0."
|
||||
)
|
||||
]);
|
||||
assert(is_int(sig))
|
||||
assert(sig>0)
|
||||
is_list(f)? str("[",str_join(sep=", ", [for (g=f) fmt_float(g,sig=sig)]),"]") :
|
||||
f==0? "0" :
|
||||
str(f)=="nan"? "nan" :
|
||||
str(f)=="inf"? "inf" :
|
||||
f<0? str("-",fmt_float(-f,sig=sig)) :
|
||||
assert(is_num(f))
|
||||
let(
|
||||
e = floor(log(f)),
|
||||
mv = sig - e - 1
|
||||
) mv == 0? fmt_int(floor(f + 0.5)) :
|
||||
(e<-sig/2||mv<0)? str(fmt_float(f*pow(10,-e),sig=sig),"e",e) :
|
||||
let(
|
||||
ff = f + pow(10,-mv)*0.5,
|
||||
whole = floor(ff),
|
||||
part = floor((ff-whole) * pow(10,mv))
|
||||
)
|
||||
str_join([
|
||||
str(whole),
|
||||
str_strip_trailing(
|
||||
str_join([
|
||||
".",
|
||||
fmt_int(part, mindigits=mv)
|
||||
]),
|
||||
"0."
|
||||
)
|
||||
]);
|
||||
|
||||
|
||||
// Function: escape_html()
|
||||
@ -521,14 +521,14 @@ function fmt_float(f,sig=12) =
|
||||
// Description:
|
||||
// Converts "<", ">", "&", and double-quote chars to their entity encoding so that echoing the strong will show it verbatim.
|
||||
function escape_html(s) =
|
||||
str_join([
|
||||
for (c=s)
|
||||
c=="<"? "<" :
|
||||
c==">"? ">" :
|
||||
c=="&"? "&" :
|
||||
c=="\""? """ :
|
||||
c
|
||||
]);
|
||||
str_join([
|
||||
for (c=s)
|
||||
c=="<"? "<" :
|
||||
c==">"? ">" :
|
||||
c=="&"? "&" :
|
||||
c=="\""? """ :
|
||||
c
|
||||
]);
|
||||
|
||||
|
||||
// Function: is_lower()
|
||||
@ -537,10 +537,10 @@ function escape_html(s) =
|
||||
// Description:
|
||||
// Returns true if all the characters in the given string are lowercase letters. (a-z)
|
||||
function is_lower(s) =
|
||||
assert(is_string(s))
|
||||
s==""? false :
|
||||
len(s)>1? all([for (v=s) is_lower(v)]) :
|
||||
let(v = ord(s[0])) (v>=ord("a") && v<=ord("z"));
|
||||
assert(is_string(s))
|
||||
s==""? false :
|
||||
len(s)>1? all([for (v=s) is_lower(v)]) :
|
||||
let(v = ord(s[0])) (v>=ord("a") && v<=ord("z"));
|
||||
|
||||
|
||||
// Function: is_upper()
|
||||
@ -549,10 +549,10 @@ function is_lower(s) =
|
||||
// Description:
|
||||
// Returns true if all the characters in the given string are uppercase letters. (A-Z)
|
||||
function is_upper(s) =
|
||||
assert(is_string(s))
|
||||
s==""? false :
|
||||
len(s)>1? all([for (v=s) is_upper(v)]) :
|
||||
let(v = ord(s[0])) (v>=ord("A") && v<=ord("Z"));
|
||||
assert(is_string(s))
|
||||
s==""? false :
|
||||
len(s)>1? all([for (v=s) is_upper(v)]) :
|
||||
let(v = ord(s[0])) (v>=ord("A") && v<=ord("Z"));
|
||||
|
||||
|
||||
// Function: is_digit()
|
||||
@ -561,10 +561,10 @@ function is_upper(s) =
|
||||
// Description:
|
||||
// Returns true if all the characters in the given string are digits. (0-9)
|
||||
function is_digit(s) =
|
||||
assert(is_string(s))
|
||||
s==""? false :
|
||||
len(s)>1? all([for (v=s) is_digit(v)]) :
|
||||
let(v = ord(s[0])) (v>=ord("0") && v<=ord("9"));
|
||||
assert(is_string(s))
|
||||
s==""? false :
|
||||
len(s)>1? all([for (v=s) is_digit(v)]) :
|
||||
let(v = ord(s[0])) (v>=ord("0") && v<=ord("9"));
|
||||
|
||||
|
||||
// Function: is_hexdigit()
|
||||
@ -573,13 +573,13 @@ function is_digit(s) =
|
||||
// Description:
|
||||
// Returns true if all the characters in the given string are valid hexadecimal digits. (0-9 or a-f or A-F))
|
||||
function is_hexdigit(s) =
|
||||
assert(is_string(s))
|
||||
s==""? false :
|
||||
len(s)>1? all([for (v=s) is_hexdigit(v)]) :
|
||||
let(v = ord(s[0]))
|
||||
(v>=ord("0") && v<=ord("9")) ||
|
||||
(v>=ord("A") && v<=ord("F")) ||
|
||||
(v>=ord("a") && v<=ord("f"));
|
||||
assert(is_string(s))
|
||||
s==""? false :
|
||||
len(s)>1? all([for (v=s) is_hexdigit(v)]) :
|
||||
let(v = ord(s[0]))
|
||||
(v>=ord("0") && v<=ord("9")) ||
|
||||
(v>=ord("A") && v<=ord("F")) ||
|
||||
(v>=ord("a") && v<=ord("f"));
|
||||
|
||||
|
||||
// Function: is_letter()
|
||||
@ -588,9 +588,9 @@ function is_hexdigit(s) =
|
||||
// Description:
|
||||
// Returns true if all the characters in the given string are standard ASCII letters. (A-Z or a-z)
|
||||
function is_letter(s) =
|
||||
assert(is_string(s))
|
||||
s==""? false :
|
||||
all([for (v=s) is_lower(v) || is_upper(v)]);
|
||||
assert(is_string(s))
|
||||
s==""? false :
|
||||
all([for (v=s) is_lower(v) || is_upper(v)]);
|
||||
|
||||
|
||||
// Function: str_format()
|
||||
@ -630,54 +630,54 @@ function is_letter(s) =
|
||||
// str_format("{:-10s}{:.3f}", ["plecostamus",27.43982]); // Returns: "plecostamus27.440"
|
||||
// str_format("{:-10.9s}{:.3f}", ["plecostamus",27.43982]); // Returns: "plecostam 27.440"
|
||||
function str_format(fmt, vals, use_nbsp=false) =
|
||||
let(
|
||||
parts = str_split(fmt,"{")
|
||||
) str_join([
|
||||
for(i = idx(parts))
|
||||
let(
|
||||
found_brace = i==0 || [for (c=parts[i]) if(c=="}") c] != [],
|
||||
err = assert(found_brace, "Unbalanced { in format string."),
|
||||
p = i==0? [undef,parts[i]] : str_split(parts[i],"}"),
|
||||
fmta = p[0],
|
||||
raw = p[1]
|
||||
) each [
|
||||
assert(i<99)
|
||||
is_undef(fmta)? "" : let(
|
||||
fmtb = str_split(fmta,":"),
|
||||
num = is_digit(fmtb[0])? str_int(fmtb[0]) : (i-1),
|
||||
left = fmtb[1][0] == "-",
|
||||
fmtb1 = default(fmtb[1],""),
|
||||
fmtc = left? substr(fmtb1,1) : fmtb1,
|
||||
zero = fmtc[0] == "0",
|
||||
lch = fmtc==""? "" : fmtc[len(fmtc)-1],
|
||||
hastyp = is_letter(lch),
|
||||
typ = hastyp? lch : "s",
|
||||
fmtd = hastyp? substr(fmtc,0,len(fmtc)-1) : fmtc,
|
||||
fmte = str_split((zero? substr(fmtd,1) : fmtd), "."),
|
||||
wid = str_int(fmte[0]),
|
||||
prec = str_int(fmte[1]),
|
||||
val = assert(num>=0&&num<len(vals)) vals[num],
|
||||
unpad = typ=="s"? (
|
||||
let( sval = str(val) )
|
||||
is_undef(prec)? sval :
|
||||
substr(sval, 0, min(len(sval)-1, prec))
|
||||
) :
|
||||
(typ=="d" || typ=="i")? fmt_int(val) :
|
||||
typ=="b"? (val? "true" : "false") :
|
||||
typ=="B"? (val? "TRUE" : "FALSE") :
|
||||
typ=="f"? downcase(fmt_fixed(val,default(prec,6))) :
|
||||
typ=="F"? upcase(fmt_fixed(val,default(prec,6))) :
|
||||
typ=="g"? downcase(fmt_float(val,default(prec,6))) :
|
||||
typ=="G"? upcase(fmt_float(val,default(prec,6))) :
|
||||
assert(false,str("Unknown format type: ",typ)),
|
||||
padlen = max(0,wid-len(unpad)),
|
||||
padfill = str_join([for (i=[0:1:padlen-1]) zero? "0" : use_nbsp? " " : " "]),
|
||||
out = left? str(unpad, padfill) : str(padfill, unpad)
|
||||
)
|
||||
out, raw
|
||||
]
|
||||
]);
|
||||
|
||||
let(
|
||||
parts = str_split(fmt,"{")
|
||||
) str_join([
|
||||
for(i = idx(parts))
|
||||
let(
|
||||
found_brace = i==0 || [for (c=parts[i]) if(c=="}") c] != [],
|
||||
err = assert(found_brace, "Unbalanced { in format string."),
|
||||
p = i==0? [undef,parts[i]] : str_split(parts[i],"}"),
|
||||
fmta = p[0],
|
||||
raw = p[1]
|
||||
) each [
|
||||
assert(i<99)
|
||||
is_undef(fmta)? "" : let(
|
||||
fmtb = str_split(fmta,":"),
|
||||
num = is_digit(fmtb[0])? str_int(fmtb[0]) : (i-1),
|
||||
left = fmtb[1][0] == "-",
|
||||
fmtb1 = default(fmtb[1],""),
|
||||
fmtc = left? substr(fmtb1,1) : fmtb1,
|
||||
zero = fmtc[0] == "0",
|
||||
lch = fmtc==""? "" : fmtc[len(fmtc)-1],
|
||||
hastyp = is_letter(lch),
|
||||
typ = hastyp? lch : "s",
|
||||
fmtd = hastyp? substr(fmtc,0,len(fmtc)-1) : fmtc,
|
||||
fmte = str_split((zero? substr(fmtd,1) : fmtd), "."),
|
||||
wid = str_int(fmte[0]),
|
||||
prec = str_int(fmte[1]),
|
||||
val = assert(num>=0&&num<len(vals)) vals[num],
|
||||
unpad = typ=="s"? (
|
||||
let( sval = str(val) )
|
||||
is_undef(prec)? sval :
|
||||
substr(sval, 0, min(len(sval)-1, prec))
|
||||
) :
|
||||
(typ=="d" || typ=="i")? fmt_int(val) :
|
||||
typ=="b"? (val? "true" : "false") :
|
||||
typ=="B"? (val? "TRUE" : "FALSE") :
|
||||
typ=="f"? downcase(fmt_fixed(val,default(prec,6))) :
|
||||
typ=="F"? upcase(fmt_fixed(val,default(prec,6))) :
|
||||
typ=="g"? downcase(fmt_float(val,default(prec,6))) :
|
||||
typ=="G"? upcase(fmt_float(val,default(prec,6))) :
|
||||
assert(false,str("Unknown format type: ",typ)),
|
||||
padlen = max(0,wid-len(unpad)),
|
||||
padfill = str_join([for (i=[0:1:padlen-1]) zero? "0" : use_nbsp? " " : " "]),
|
||||
out = left? str(unpad, padfill) : str(padfill, unpad)
|
||||
)
|
||||
out, raw
|
||||
]
|
||||
]);
|
||||
|
||||
|
||||
// Function&Module: echofmt()
|
||||
// Usage:
|
||||
@ -699,4 +699,4 @@ function echofmt(fmt, vals, use_nbsp=false) = echo(str_format(fmt,vals,use_nbsp)
|
||||
module echofmt(fmt, vals, use_nbsp=false) echo(str_format(fmt,vals,use_nbsp));
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
60
structs.scad
60
structs.scad
@ -32,20 +32,20 @@
|
||||
// value = Value to set the keyword to.
|
||||
// grow = Set to true to allow structure to grow, or false for new keywords to generate an error. Default: true
|
||||
function struct_set(struct, keyword, value=undef, grow=true) =
|
||||
!is_list(keyword)? (
|
||||
let( ind=search([keyword],struct,1,0)[0] )
|
||||
ind==[]? (
|
||||
assert(grow,str("Unknown keyword \"",keyword))
|
||||
concat(struct, [[keyword,value]])
|
||||
) : list_set(struct, [ind], [[keyword,value]])
|
||||
) : _parse_pairs(struct,keyword,grow);
|
||||
!is_list(keyword)? (
|
||||
let( ind=search([keyword],struct,1,0)[0] )
|
||||
ind==[]? (
|
||||
assert(grow,str("Unknown keyword \"",keyword))
|
||||
concat(struct, [[keyword,value]])
|
||||
) : list_set(struct, [ind], [[keyword,value]])
|
||||
) : _parse_pairs(struct,keyword,grow);
|
||||
|
||||
|
||||
function _parse_pairs(spec, input, grow=true, index=0, result=undef) =
|
||||
assert(len(input)%2==0,"Odd number of entries in [keyword,value] pair list")
|
||||
let( result = result==undef ? spec : result)
|
||||
index == len(input) ? result :
|
||||
_parse_pairs(spec,input,grow,index+2,struct_set(result, input[index], input[index+1],grow));
|
||||
assert(len(input)%2==0,"Odd number of entries in [keyword,value] pair list")
|
||||
let( result = result==undef ? spec : result)
|
||||
index == len(input) ? result :
|
||||
_parse_pairs(spec,input,grow,index+2,struct_set(result, input[index], input[index+1],grow));
|
||||
|
||||
|
||||
// Function: struct_remove()
|
||||
@ -57,9 +57,9 @@ function _parse_pairs(spec, input, grow=true, index=0, result=undef) =
|
||||
// struct = input structure
|
||||
// keyword = a single string (keyword) or list of strings (keywords) to remove
|
||||
function struct_remove(struct, keyword) =
|
||||
is_string(keyword)? struct_remove(struct, [keyword]) :
|
||||
let(ind = search(keyword, struct))
|
||||
list_remove(struct, ind);
|
||||
is_string(keyword)? struct_remove(struct, [keyword]) :
|
||||
let(ind = search(keyword, struct))
|
||||
list_remove(struct, ind);
|
||||
|
||||
|
||||
// Function: struct_val()
|
||||
@ -71,9 +71,9 @@ function struct_remove(struct, keyword) =
|
||||
// struct = input structure
|
||||
// keyword = keyword whose value to return
|
||||
function struct_val(struct,keyword) =
|
||||
assert(is_def(keyword),"keyword is missing")
|
||||
let(ind = search([keyword],struct)[0])
|
||||
ind == [] ? undef : struct[ind][1];
|
||||
assert(is_def(keyword),"keyword is missing")
|
||||
let(ind = search([keyword],struct)[0])
|
||||
ind == [] ? undef : struct[ind][1];
|
||||
|
||||
|
||||
// Function: struct_keys()
|
||||
@ -84,7 +84,7 @@ function struct_val(struct,keyword) =
|
||||
// Arguments:
|
||||
// struct = input structure
|
||||
function struct_keys(struct) =
|
||||
[for(entry=struct) entry[0]];
|
||||
[for(entry=struct) entry[0]];
|
||||
|
||||
|
||||
// Function&Module: struct_echo()
|
||||
@ -96,12 +96,12 @@ function struct_keys(struct) =
|
||||
// struct = input structure
|
||||
// name = optional structure name to list at the top of the output. Default: ""
|
||||
function struct_echo(struct,name="") =
|
||||
let( keylist = [for(entry=struct) str(" ",entry[0],": ",entry[1],"\n")])
|
||||
echo(str("\nStructure ",name,"\n",str_join(keylist)))
|
||||
undef;
|
||||
let( keylist = [for(entry=struct) str(" ",entry[0],": ",entry[1],"\n")])
|
||||
echo(str("\nStructure ",name,"\n",str_join(keylist)))
|
||||
undef;
|
||||
|
||||
module struct_echo(struct,name="") {
|
||||
dummy = struct_echo(struct,name);
|
||||
dummy = struct_echo(struct,name);
|
||||
}
|
||||
|
||||
|
||||
@ -111,14 +111,14 @@ module struct_echo(struct,name="") {
|
||||
// Description:
|
||||
// Returns true if the input has the form of a structure, false otherwise.
|
||||
function is_struct(x) =
|
||||
is_list(x) && [
|
||||
for (xx=x) if(
|
||||
!is_list(xx) ||
|
||||
len(xx) != 2 ||
|
||||
!is_string(xx[0])
|
||||
) 1
|
||||
] == [];
|
||||
is_list(x) && [
|
||||
for (xx=x) if(
|
||||
!is_list(xx) ||
|
||||
len(xx) != 2 ||
|
||||
!is_string(xx[0])
|
||||
) 1
|
||||
] == [];
|
||||
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -3,12 +3,12 @@ include <BOSL2/hull.scad>
|
||||
|
||||
|
||||
testpoints_on_sphere = [ for(p =
|
||||
[
|
||||
[1,PHI,0], [-1,PHI,0], [1,-PHI,0], [-1,-PHI,0],
|
||||
[0,1,PHI], [0,-1,PHI], [0,1,-PHI], [0,-1,-PHI],
|
||||
[PHI,0,1], [-PHI,0,1], [PHI,0,-1], [-PHI,0,-1]
|
||||
])
|
||||
unit(p)
|
||||
[
|
||||
[1,PHI,0], [-1,PHI,0], [1,-PHI,0], [-1,-PHI,0],
|
||||
[0,1,PHI], [0,-1,PHI], [0,1,-PHI], [0,-1,-PHI],
|
||||
[PHI,0,1], [-PHI,0,1], [PHI,0,-1], [-PHI,0,-1]
|
||||
])
|
||||
unit(p)
|
||||
];
|
||||
|
||||
testpoints_circular = [ for(a = [0:15:360-EPSILON]) [cos(a),sin(a)] ];
|
||||
@ -44,30 +44,30 @@ visualize_hull(testpoints3d);
|
||||
|
||||
|
||||
module visualize_hull(points) {
|
||||
hull = hull(points);
|
||||
|
||||
%if (len(hull) > 0 && is_list(hull[0]) && len(hull[0]) > 0)
|
||||
polyhedron(points=points, faces = hull);
|
||||
else
|
||||
polyhedron(points=points, faces = [hull]);
|
||||
|
||||
for (i = [0:len(points)-1]) {
|
||||
p = points[i];
|
||||
$fn = 16;
|
||||
translate(p) {
|
||||
if (hull_contains_index(hull,i)) {
|
||||
color("blue") sphere(1);
|
||||
} else {
|
||||
color("red") sphere(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function hull_contains_index(hull, index) =
|
||||
search(index,hull,1,0) ||
|
||||
search(index,hull,1,1) ||
|
||||
search(index,hull,1,2);
|
||||
hull = hull(points);
|
||||
|
||||
%if (len(hull) > 0 && is_list(hull[0]) && len(hull[0]) > 0)
|
||||
polyhedron(points=points, faces = hull);
|
||||
else
|
||||
polyhedron(points=points, faces = [hull]);
|
||||
|
||||
for (i = [0:len(points)-1]) {
|
||||
p = points[i];
|
||||
$fn = 16;
|
||||
translate(p) {
|
||||
if (hull_contains_index(hull,i)) {
|
||||
color("blue") sphere(1);
|
||||
} else {
|
||||
color("red") sphere(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function hull_contains_index(hull, index) =
|
||||
search(index,hull,1,0) ||
|
||||
search(index,hull,1,1) ||
|
||||
search(index,hull,1,2);
|
||||
}
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -4,259 +4,259 @@ include <BOSL2/std.scad>
|
||||
// List/Array Ops
|
||||
|
||||
module test_repeat() {
|
||||
assert(repeat(1, 4) == [1,1,1,1]);
|
||||
assert(repeat(8, [2,3]) == [[8,8,8], [8,8,8]]);
|
||||
assert(repeat(0, [2,2,3]) == [[[0,0,0],[0,0,0]], [[0,0,0],[0,0,0]]]);
|
||||
assert(repeat([1,2,3],3) == [[1,2,3], [1,2,3], [1,2,3]]);
|
||||
assert(repeat(1, 4) == [1,1,1,1]);
|
||||
assert(repeat(8, [2,3]) == [[8,8,8], [8,8,8]]);
|
||||
assert(repeat(0, [2,2,3]) == [[[0,0,0],[0,0,0]], [[0,0,0],[0,0,0]]]);
|
||||
assert(repeat([1,2,3],3) == [[1,2,3], [1,2,3], [1,2,3]]);
|
||||
}
|
||||
test_repeat();
|
||||
|
||||
|
||||
module test_in_list() {
|
||||
assert(in_list("bar", ["foo", "bar", "baz"]));
|
||||
assert(!in_list("bee", ["foo", "bar", "baz"]));
|
||||
assert(in_list("bar", [[2,"foo"], [4,"bar"], [3,"baz"]], idx=1));
|
||||
assert(in_list("bar", ["foo", "bar", "baz"]));
|
||||
assert(!in_list("bee", ["foo", "bar", "baz"]));
|
||||
assert(in_list("bar", [[2,"foo"], [4,"bar"], [3,"baz"]], idx=1));
|
||||
}
|
||||
test_in_list();
|
||||
|
||||
|
||||
module test_slice() {
|
||||
assert(slice([3,4,5,6,7,8,9], 3, 5) == [6,7]);
|
||||
assert(slice([3,4,5,6,7,8,9], 2, -1) == [5,6,7,8,9]);
|
||||
assert(slice([3,4,5,6,7,8,9], 1, 1) == []);
|
||||
assert(slice([3,4,5,6,7,8,9], 6, -1) == [9]);
|
||||
assert(slice([3,4,5,6,7,8,9], 2, -2) == [5,6,7,8]);
|
||||
assert(slice([3,4,5,6,7,8,9], 3, 5) == [6,7]);
|
||||
assert(slice([3,4,5,6,7,8,9], 2, -1) == [5,6,7,8,9]);
|
||||
assert(slice([3,4,5,6,7,8,9], 1, 1) == []);
|
||||
assert(slice([3,4,5,6,7,8,9], 6, -1) == [9]);
|
||||
assert(slice([3,4,5,6,7,8,9], 2, -2) == [5,6,7,8]);
|
||||
}
|
||||
test_slice();
|
||||
|
||||
|
||||
module test_select() {
|
||||
l = [3,4,5,6,7,8,9];
|
||||
assert(select(l, 5, 6) == [8,9]);
|
||||
assert(select(l, 5, 8) == [8,9,3,4]);
|
||||
assert(select(l, 5, 2) == [8,9,3,4,5]);
|
||||
assert(select(l, -3, -1) == [7,8,9]);
|
||||
assert(select(l, 3, 3) == [6]);
|
||||
assert(select(l, 4) == 7);
|
||||
assert(select(l, -2) == 8);
|
||||
assert(select(l, [1:3]) == [4,5,6]);
|
||||
assert(select(l, [1,3]) == [4,6]);
|
||||
l = [3,4,5,6,7,8,9];
|
||||
assert(select(l, 5, 6) == [8,9]);
|
||||
assert(select(l, 5, 8) == [8,9,3,4]);
|
||||
assert(select(l, 5, 2) == [8,9,3,4,5]);
|
||||
assert(select(l, -3, -1) == [7,8,9]);
|
||||
assert(select(l, 3, 3) == [6]);
|
||||
assert(select(l, 4) == 7);
|
||||
assert(select(l, -2) == 8);
|
||||
assert(select(l, [1:3]) == [4,5,6]);
|
||||
assert(select(l, [1,3]) == [4,6]);
|
||||
}
|
||||
test_select();
|
||||
|
||||
|
||||
module test_list_range() {
|
||||
assert(list_range(4) == [0,1,2,3]);
|
||||
assert(list_range(n=4, step=2) == [0,2,4,6]);
|
||||
assert(list_range(n=4, s=3, step=3) == [3,6,9,12]);
|
||||
assert(list_range(e=3) == [0,1,2,3]);
|
||||
assert(list_range(e=6, step=2) == [0,2,4,6]);
|
||||
assert(list_range(s=3, e=5) == [3,4,5]);
|
||||
assert(list_range(s=3, e=8, step=2) == [3,5,7]);
|
||||
assert(list_range(s=4, e=8, step=2) == [4,6,8]);
|
||||
assert(list_range(e=4, n=3) == [0,2,4]);
|
||||
assert(list_range(n=4, s=[3,4], step=[2,3]) == [[3,4], [5,7], [7,10], [9,13]]);
|
||||
assert(list_range(4) == [0,1,2,3]);
|
||||
assert(list_range(n=4, step=2) == [0,2,4,6]);
|
||||
assert(list_range(n=4, s=3, step=3) == [3,6,9,12]);
|
||||
assert(list_range(e=3) == [0,1,2,3]);
|
||||
assert(list_range(e=6, step=2) == [0,2,4,6]);
|
||||
assert(list_range(s=3, e=5) == [3,4,5]);
|
||||
assert(list_range(s=3, e=8, step=2) == [3,5,7]);
|
||||
assert(list_range(s=4, e=8, step=2) == [4,6,8]);
|
||||
assert(list_range(e=4, n=3) == [0,2,4]);
|
||||
assert(list_range(n=4, s=[3,4], step=[2,3]) == [[3,4], [5,7], [7,10], [9,13]]);
|
||||
}
|
||||
test_list_range();
|
||||
|
||||
|
||||
module test_reverse() {
|
||||
assert(reverse([3,4,5,6]) == [6,5,4,3]);
|
||||
assert(reverse([3,4,5,6]) == [6,5,4,3]);
|
||||
}
|
||||
test_reverse();
|
||||
|
||||
|
||||
module test_list_rotate() {
|
||||
assert(list_rotate([1,2,3,4,5],-2) == [4,5,1,2,3]);
|
||||
assert(list_rotate([1,2,3,4,5],-1) == [5,1,2,3,4]);
|
||||
assert(list_rotate([1,2,3,4,5],0) == [1,2,3,4,5]);
|
||||
assert(list_rotate([1,2,3,4,5],1) == [2,3,4,5,1]);
|
||||
assert(list_rotate([1,2,3,4,5],2) == [3,4,5,1,2]);
|
||||
assert(list_rotate([1,2,3,4,5],3) == [4,5,1,2,3]);
|
||||
assert(list_rotate([1,2,3,4,5],4) == [5,1,2,3,4]);
|
||||
assert(list_rotate([1,2,3,4,5],5) == [1,2,3,4,5]);
|
||||
assert(list_rotate([1,2,3,4,5],6) == [2,3,4,5,1]);
|
||||
assert(list_rotate([],3) == []);
|
||||
assert(list_rotate([1,2,3,4,5],-2) == [4,5,1,2,3]);
|
||||
assert(list_rotate([1,2,3,4,5],-1) == [5,1,2,3,4]);
|
||||
assert(list_rotate([1,2,3,4,5],0) == [1,2,3,4,5]);
|
||||
assert(list_rotate([1,2,3,4,5],1) == [2,3,4,5,1]);
|
||||
assert(list_rotate([1,2,3,4,5],2) == [3,4,5,1,2]);
|
||||
assert(list_rotate([1,2,3,4,5],3) == [4,5,1,2,3]);
|
||||
assert(list_rotate([1,2,3,4,5],4) == [5,1,2,3,4]);
|
||||
assert(list_rotate([1,2,3,4,5],5) == [1,2,3,4,5]);
|
||||
assert(list_rotate([1,2,3,4,5],6) == [2,3,4,5,1]);
|
||||
assert(list_rotate([],3) == []);
|
||||
}
|
||||
test_list_rotate();
|
||||
|
||||
|
||||
module test_deduplicate() {
|
||||
assert(deduplicate([8,3,4,4,4,8,2,3,3,8,8]) == [8,3,4,8,2,3,8]);
|
||||
assert(deduplicate(closed=true, [8,3,4,4,4,8,2,3,3,8,8]) == [8,3,4,8,2,3]);
|
||||
assert(deduplicate("Hello") == ["H","e","l","o"]);
|
||||
assert(deduplicate([[3,4],[7,1.99],[7,2],[1,4]],eps=0.1) == [[3,4],[7,2],[1,4]]);
|
||||
assert(deduplicate([8,3,4,4,4,8,2,3,3,8,8]) == [8,3,4,8,2,3,8]);
|
||||
assert(deduplicate(closed=true, [8,3,4,4,4,8,2,3,3,8,8]) == [8,3,4,8,2,3]);
|
||||
assert(deduplicate("Hello") == ["H","e","l","o"]);
|
||||
assert(deduplicate([[3,4],[7,1.99],[7,2],[1,4]],eps=0.1) == [[3,4],[7,2],[1,4]]);
|
||||
}
|
||||
test_deduplicate();
|
||||
|
||||
|
||||
module test_deduplicate_indexed() {
|
||||
assert(deduplicate_indexed([8,6,4,6,3], [1,4,3,1,2,2,0,1]) == [1,4,1,2,0,1]);
|
||||
assert(deduplicate_indexed([8,6,4,6,3], [1,4,3,1,2,2,0,1], closed=true) == [1,4,1,2,0]);
|
||||
assert(deduplicate_indexed([8,6,4,6,3], [1,4,3,1,2,2,0,1]) == [1,4,1,2,0,1]);
|
||||
assert(deduplicate_indexed([8,6,4,6,3], [1,4,3,1,2,2,0,1], closed=true) == [1,4,1,2,0]);
|
||||
}
|
||||
test_deduplicate_indexed();
|
||||
|
||||
|
||||
module test_list_set() {
|
||||
assert(list_set([2,3,4,5], 2, 21) == [2,3,21,5]);
|
||||
assert(list_set([2,3,4,5], [1,3], [81,47]) == [2,81,4,47]);
|
||||
assert(list_set([2,3,4,5], 2, 21) == [2,3,21,5]);
|
||||
assert(list_set([2,3,4,5], [1,3], [81,47]) == [2,81,4,47]);
|
||||
}
|
||||
test_list_set();
|
||||
|
||||
|
||||
module test_list_remove() {
|
||||
assert(list_remove([3,6,9,12],1) == [3,9,12]);
|
||||
assert(list_remove([3,6,9,12],[1,3]) == [3,9]);
|
||||
assert(list_remove([3,6,9,12],1) == [3,9,12]);
|
||||
assert(list_remove([3,6,9,12],[1,3]) == [3,9]);
|
||||
}
|
||||
test_list_remove();
|
||||
|
||||
|
||||
module test_list_remove_values() {
|
||||
animals = ["bat", "cat", "rat", "dog", "bat", "rat"];
|
||||
assert(list_remove_values(animals, "rat") == ["bat","cat","dog","bat","rat"]);
|
||||
assert(list_remove_values(animals, "bat", all=true) == ["cat","rat","dog","rat"]);
|
||||
assert(list_remove_values(animals, ["bat","rat"]) == ["cat","dog","bat","rat"]);
|
||||
assert(list_remove_values(animals, ["bat","rat"], all=true) == ["cat","dog"]);
|
||||
assert(list_remove_values(animals, ["tucan","rat"], all=true) == ["bat","cat","dog","bat"]);
|
||||
animals = ["bat", "cat", "rat", "dog", "bat", "rat"];
|
||||
assert(list_remove_values(animals, "rat") == ["bat","cat","dog","bat","rat"]);
|
||||
assert(list_remove_values(animals, "bat", all=true) == ["cat","rat","dog","rat"]);
|
||||
assert(list_remove_values(animals, ["bat","rat"]) == ["cat","dog","bat","rat"]);
|
||||
assert(list_remove_values(animals, ["bat","rat"], all=true) == ["cat","dog"]);
|
||||
assert(list_remove_values(animals, ["tucan","rat"], all=true) == ["bat","cat","dog","bat"]);
|
||||
}
|
||||
test_list_remove_values();
|
||||
|
||||
|
||||
module test_list_insert() {
|
||||
assert(list_insert([3,6,9,12],1,5) == [3,5,6,9,12]);
|
||||
assert(list_insert([3,6,9,12],[1,3],[5,11]) == [3,5,6,9,11,12]);
|
||||
assert(list_insert([3,6,9,12],1,5) == [3,5,6,9,12]);
|
||||
assert(list_insert([3,6,9,12],[1,3],[5,11]) == [3,5,6,9,11,12]);
|
||||
}
|
||||
test_list_insert();
|
||||
|
||||
|
||||
module test_bselect() {
|
||||
assert(bselect([3,4,5,6,7], [false,false,false,false,false]) == []);
|
||||
assert(bselect([3,4,5,6,7], [false,true,true,false,true]) == [4,5,7]);
|
||||
assert(bselect([3,4,5,6,7], [true,true,true,true,true]) == [3,4,5,6,7]);
|
||||
assert(bselect([3,4,5,6,7], [false,false,false,false,false]) == []);
|
||||
assert(bselect([3,4,5,6,7], [false,true,true,false,true]) == [4,5,7]);
|
||||
assert(bselect([3,4,5,6,7], [true,true,true,true,true]) == [3,4,5,6,7]);
|
||||
}
|
||||
test_bselect();
|
||||
|
||||
|
||||
module test_list_bset() {
|
||||
assert(list_bset([false,true,false,true,false], [3,4]) == [0,3,0,4,0]);
|
||||
assert(list_bset([false,true,false,true,false], [3,4], dflt=1) == [1,3,1,4,1]);
|
||||
assert(list_bset([false,true,false,true,false], [3,4]) == [0,3,0,4,0]);
|
||||
assert(list_bset([false,true,false,true,false], [3,4], dflt=1) == [1,3,1,4,1]);
|
||||
}
|
||||
test_list_bset();
|
||||
|
||||
|
||||
module test_list_increasing() {
|
||||
assert(list_increasing([1,2,3,4]) == true);
|
||||
assert(list_increasing([1,3,2,4]) == false);
|
||||
assert(list_increasing([4,3,2,1]) == false);
|
||||
assert(list_increasing([1,2,3,4]) == true);
|
||||
assert(list_increasing([1,3,2,4]) == false);
|
||||
assert(list_increasing([4,3,2,1]) == false);
|
||||
}
|
||||
test_list_increasing();
|
||||
|
||||
|
||||
module test_list_decreasing() {
|
||||
assert(list_decreasing([1,2,3,4]) == false);
|
||||
assert(list_decreasing([4,2,3,1]) == false);
|
||||
assert(list_decreasing([4,3,2,1]) == true);
|
||||
assert(list_decreasing([1,2,3,4]) == false);
|
||||
assert(list_decreasing([4,2,3,1]) == false);
|
||||
assert(list_decreasing([4,3,2,1]) == true);
|
||||
}
|
||||
test_list_decreasing();
|
||||
|
||||
|
||||
module test_list_shortest() {
|
||||
assert(list_shortest(["foobar", "bazquxx", "abcd"]) == 4);
|
||||
assert(list_shortest(["foobar", "bazquxx", "abcd"]) == 4);
|
||||
}
|
||||
test_list_shortest();
|
||||
|
||||
|
||||
module test_list_longest() {
|
||||
assert(list_longest(["foobar", "bazquxx", "abcd"]) == 7);
|
||||
assert(list_longest(["foobar", "bazquxx", "abcd"]) == 7);
|
||||
}
|
||||
test_list_longest();
|
||||
|
||||
|
||||
module test_list_pad() {
|
||||
assert(list_pad([4,5,6], 5, 8) == [4,5,6,8,8]);
|
||||
assert(list_pad([4,5,6,7,8], 5, 8) == [4,5,6,7,8]);
|
||||
assert(list_pad([4,5,6,7,8,9], 5, 8) == [4,5,6,7,8,9]);
|
||||
assert(list_pad([4,5,6], 5, 8) == [4,5,6,8,8]);
|
||||
assert(list_pad([4,5,6,7,8], 5, 8) == [4,5,6,7,8]);
|
||||
assert(list_pad([4,5,6,7,8,9], 5, 8) == [4,5,6,7,8,9]);
|
||||
}
|
||||
test_list_pad();
|
||||
|
||||
|
||||
module test_list_trim() {
|
||||
assert(list_trim([4,5,6], 5) == [4,5,6]);
|
||||
assert(list_trim([4,5,6,7,8], 5) == [4,5,6,7,8]);
|
||||
assert(list_trim([3,4,5,6,7,8,9], 5) == [3,4,5,6,7]);
|
||||
assert(list_trim([4,5,6], 5) == [4,5,6]);
|
||||
assert(list_trim([4,5,6,7,8], 5) == [4,5,6,7,8]);
|
||||
assert(list_trim([3,4,5,6,7,8,9], 5) == [3,4,5,6,7]);
|
||||
}
|
||||
test_list_trim();
|
||||
|
||||
|
||||
module test_list_fit() {
|
||||
assert(list_fit([4,5,6], 5, 8) == [4,5,6,8,8]);
|
||||
assert(list_fit([4,5,6,7,8], 5, 8) == [4,5,6,7,8]);
|
||||
assert(list_fit([3,4,5,6,7,8,9], 5, 8) == [3,4,5,6,7]);
|
||||
assert(list_fit([4,5,6], 5, 8) == [4,5,6,8,8]);
|
||||
assert(list_fit([4,5,6,7,8], 5, 8) == [4,5,6,7,8]);
|
||||
assert(list_fit([3,4,5,6,7,8,9], 5, 8) == [3,4,5,6,7]);
|
||||
}
|
||||
test_list_fit();
|
||||
|
||||
|
||||
module test_idx() {
|
||||
colors = ["red", "green", "blue", "cyan"];
|
||||
assert([for (i=idx(colors)) i] == [0,1,2,3]);
|
||||
assert([for (i=idx(colors,end=-2)) i] == [0,1,2]);
|
||||
assert([for (i=idx(colors,start=1)) i] == [1,2,3]);
|
||||
assert([for (i=idx(colors,start=1,end=-2)) i] == [1,2]);
|
||||
colors = ["red", "green", "blue", "cyan"];
|
||||
assert([for (i=idx(colors)) i] == [0,1,2,3]);
|
||||
assert([for (i=idx(colors,end=-2)) i] == [0,1,2]);
|
||||
assert([for (i=idx(colors,start=1)) i] == [1,2,3]);
|
||||
assert([for (i=idx(colors,start=1,end=-2)) i] == [1,2]);
|
||||
}
|
||||
test_idx();
|
||||
|
||||
|
||||
module test_enumerate() {
|
||||
assert(enumerate(["a","b","c"]) == [[0,"a"], [1,"b"], [2,"c"]]);
|
||||
assert(enumerate([[88,"a"],[76,"b"],[21,"c"]], idx=1) == [[0,"a"], [1,"b"], [2,"c"]]);
|
||||
assert(enumerate([["cat","a",12],["dog","b",10],["log","c",14]], idx=[1:2]) == [[0,"a",12], [1,"b",10], [2,"c",14]]);
|
||||
assert(enumerate(["a","b","c"]) == [[0,"a"], [1,"b"], [2,"c"]]);
|
||||
assert(enumerate([[88,"a"],[76,"b"],[21,"c"]], idx=1) == [[0,"a"], [1,"b"], [2,"c"]]);
|
||||
assert(enumerate([["cat","a",12],["dog","b",10],["log","c",14]], idx=[1:2]) == [[0,"a",12], [1,"b",10], [2,"c",14]]);
|
||||
}
|
||||
test_enumerate();
|
||||
|
||||
|
||||
module test_shuffle() {
|
||||
nums1 = [for (i=list_range(100)) i];
|
||||
nums2 = shuffle(nums1);
|
||||
nums3 = shuffle(nums2);
|
||||
assert(len(nums2)==len(nums1));
|
||||
assert(len(nums3)==len(nums2));
|
||||
assert(nums1!=nums2);
|
||||
assert(nums2!=nums3);
|
||||
assert(nums1!=nums3);
|
||||
nums1 = [for (i=list_range(100)) i];
|
||||
nums2 = shuffle(nums1);
|
||||
nums3 = shuffle(nums2);
|
||||
assert(len(nums2)==len(nums1));
|
||||
assert(len(nums3)==len(nums2));
|
||||
assert(nums1!=nums2);
|
||||
assert(nums2!=nums3);
|
||||
assert(nums1!=nums3);
|
||||
}
|
||||
test_shuffle();
|
||||
|
||||
|
||||
module test_sort() {
|
||||
assert(sort([7,3,9,4,3,1,8]) == [1,3,3,4,7,8,9]);
|
||||
assert(sort(["cat", "oat", "sat", "bat", "vat", "rat", "pat", "mat", "fat", "hat", "eat"]) == ["bat", "cat", "eat", "fat", "hat", "mat", "oat", "pat", "rat", "sat", "vat"]);
|
||||
assert(sort(enumerate([[2,3,4],[1,2,3],[2,4,3]]),idx=1)==[[1,[1,2,3]], [0,[2,3,4]], [2,[2,4,3]]]);
|
||||
assert(sort([7,3,9,4,3,1,8]) == [1,3,3,4,7,8,9]);
|
||||
assert(sort(["cat", "oat", "sat", "bat", "vat", "rat", "pat", "mat", "fat", "hat", "eat"]) == ["bat", "cat", "eat", "fat", "hat", "mat", "oat", "pat", "rat", "sat", "vat"]);
|
||||
assert(sort(enumerate([[2,3,4],[1,2,3],[2,4,3]]),idx=1)==[[1,[1,2,3]], [0,[2,3,4]], [2,[2,4,3]]]);
|
||||
}
|
||||
test_sort();
|
||||
|
||||
|
||||
module test_sortidx() {
|
||||
lst1 = ["d","b","e","c"];
|
||||
assert(sortidx(lst1) == [1,3,0,2]);
|
||||
lst2 = [
|
||||
["foo", 88, [0,0,1], false],
|
||||
["bar", 90, [0,1,0], true],
|
||||
["baz", 89, [1,0,0], false],
|
||||
["qux", 23, [1,1,1], true]
|
||||
];
|
||||
assert(sortidx(lst2, idx=1) == [3,0,2,1]);
|
||||
assert(sortidx(lst2, idx=0) == [1,2,0,3]);
|
||||
assert(sortidx(lst2, idx=[1,3]) == [3,0,2,1]);
|
||||
lst3 = [[-4, 0, 0], [0, 0, -4], [0, -4, 0], [-4, 0, 0], [0, -4, 0], [0, 0, 4], [0, 0, -4], [0, 4, 0], [4, 0, 0], [0, 0, 4], [0, 4, 0], [4, 0, 0]];
|
||||
assert(sortidx(lst3)==[0,3,2,4,1,6,5,9,7,10,8,11]);
|
||||
lst1 = ["d","b","e","c"];
|
||||
assert(sortidx(lst1) == [1,3,0,2]);
|
||||
lst2 = [
|
||||
["foo", 88, [0,0,1], false],
|
||||
["bar", 90, [0,1,0], true],
|
||||
["baz", 89, [1,0,0], false],
|
||||
["qux", 23, [1,1,1], true]
|
||||
];
|
||||
assert(sortidx(lst2, idx=1) == [3,0,2,1]);
|
||||
assert(sortidx(lst2, idx=0) == [1,2,0,3]);
|
||||
assert(sortidx(lst2, idx=[1,3]) == [3,0,2,1]);
|
||||
lst3 = [[-4, 0, 0], [0, 0, -4], [0, -4, 0], [-4, 0, 0], [0, -4, 0], [0, 0, 4], [0, 0, -4], [0, 4, 0], [4, 0, 0], [0, 0, 4], [0, 4, 0], [4, 0, 0]];
|
||||
assert(sortidx(lst3)==[0,3,2,4,1,6,5,9,7,10,8,11]);
|
||||
}
|
||||
test_sortidx();
|
||||
|
||||
|
||||
module test_unique() {
|
||||
assert(unique([]) == []);
|
||||
assert(unique([8]) == [8]);
|
||||
assert(unique([7,3,9,4,3,1,8]) == [1,3,4,7,8,9]);
|
||||
assert(unique([]) == []);
|
||||
assert(unique([8]) == [8]);
|
||||
assert(unique([7,3,9,4,3,1,8]) == [1,3,4,7,8,9]);
|
||||
}
|
||||
test_unique();
|
||||
|
||||
@ -265,100 +265,100 @@ test_unique();
|
||||
|
||||
|
||||
module test_subindex() {
|
||||
v = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]];
|
||||
assert(subindex(v,2) == [3, 7, 11, 15]);
|
||||
assert(subindex(v,[2,1]) == [[3, 2], [7, 6], [11, 10], [15, 14]]);
|
||||
assert(subindex(v,[1:3]) == [[2, 3, 4], [6, 7, 8], [10, 11, 12], [14, 15, 16]]);
|
||||
v = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]];
|
||||
assert(subindex(v,2) == [3, 7, 11, 15]);
|
||||
assert(subindex(v,[2,1]) == [[3, 2], [7, 6], [11, 10], [15, 14]]);
|
||||
assert(subindex(v,[1:3]) == [[2, 3, 4], [6, 7, 8], [10, 11, 12], [14, 15, 16]]);
|
||||
}
|
||||
test_subindex();
|
||||
|
||||
|
||||
module test_pair() {
|
||||
assert(pair([3,4,5,6]) == [[3,4], [4,5], [5,6]]);
|
||||
assert(pair("ABCD") == [["A","B"], ["B","C"], ["C","D"]]);
|
||||
assert(pair([3,4,5,6]) == [[3,4], [4,5], [5,6]]);
|
||||
assert(pair("ABCD") == [["A","B"], ["B","C"], ["C","D"]]);
|
||||
}
|
||||
test_pair();
|
||||
|
||||
|
||||
module test_pair_wrap() {
|
||||
assert(pair_wrap([3,4,5,6]) == [[3,4], [4,5], [5,6], [6,3]]);
|
||||
assert(pair_wrap("ABCD") == [["A","B"], ["B","C"], ["C","D"], ["D","A"]]);
|
||||
assert(pair_wrap([3,4,5,6]) == [[3,4], [4,5], [5,6], [6,3]]);
|
||||
assert(pair_wrap("ABCD") == [["A","B"], ["B","C"], ["C","D"], ["D","A"]]);
|
||||
}
|
||||
test_pair_wrap();
|
||||
|
||||
|
||||
module test_triplet() {
|
||||
assert(triplet([3,4,5,6,7]) == [[3,4,5], [4,5,6], [5,6,7]]);
|
||||
assert(triplet("ABCDE") == [["A","B","C"], ["B","C","D"], ["C","D","E"]]);
|
||||
assert(triplet([3,4,5,6,7]) == [[3,4,5], [4,5,6], [5,6,7]]);
|
||||
assert(triplet("ABCDE") == [["A","B","C"], ["B","C","D"], ["C","D","E"]]);
|
||||
}
|
||||
test_triplet();
|
||||
|
||||
|
||||
module test_triplet_wrap() {
|
||||
assert(triplet_wrap([3,4,5,6]) == [[3,4,5], [4,5,6], [5,6,3], [6,3,4]]);
|
||||
assert(triplet_wrap("ABCD") == [["A","B","C"], ["B","C","D"], ["C","D","A"], ["D","A","B"]]);
|
||||
assert(triplet_wrap([3,4,5,6]) == [[3,4,5], [4,5,6], [5,6,3], [6,3,4]]);
|
||||
assert(triplet_wrap("ABCD") == [["A","B","C"], ["B","C","D"], ["C","D","A"], ["D","A","B"]]);
|
||||
}
|
||||
test_triplet_wrap();
|
||||
|
||||
|
||||
module test_permute() {
|
||||
assert(permute([3,4,5,6]) == [[3,4],[3,5],[3,6],[4,5],[4,6],[5,6]]);
|
||||
assert(permute([3,4,5,6],n=3) == [[3,4,5],[3,4,6],[3,5,6],[4,5,6]]);
|
||||
assert(permute([3,4,5,6]) == [[3,4],[3,5],[3,6],[4,5],[4,6],[5,6]]);
|
||||
assert(permute([3,4,5,6],n=3) == [[3,4,5],[3,4,6],[3,5,6],[4,5,6]]);
|
||||
}
|
||||
test_permute();
|
||||
|
||||
|
||||
module test_repeat_entries() {
|
||||
list = [0,1,2,3];
|
||||
assert(repeat_entries(list, 6) == [0,0,1,2,2,3]);
|
||||
assert(repeat_entries(list, 6, exact=false) == [0,0,1,1,2,2,3,3]);
|
||||
assert(repeat_entries(list, [1,1,2,1], exact=false) == [0,1,2,2,3]);
|
||||
list = [0,1,2,3];
|
||||
assert(repeat_entries(list, 6) == [0,0,1,2,2,3]);
|
||||
assert(repeat_entries(list, 6, exact=false) == [0,0,1,1,2,2,3,3]);
|
||||
assert(repeat_entries(list, [1,1,2,1], exact=false) == [0,1,2,2,3]);
|
||||
}
|
||||
test_repeat_entries();
|
||||
|
||||
|
||||
module test_zip() {
|
||||
v1 = [1,2,3,4];
|
||||
v2 = [5,6,7];
|
||||
v3 = [8,9,10,11];
|
||||
assert(zip(v1,v3) == [[1,8],[2,9],[3,10],[4,11]]);
|
||||
assert(zip([v1,v3]) == [[1,8],[2,9],[3,10],[4,11]]);
|
||||
assert(zip([v1,v2],fit="short") == [[1,5],[2,6],[3,7]]);
|
||||
assert(zip([v1,v2],fit="long") == [[1,5],[2,6],[3,7],[4,undef]]);
|
||||
assert(zip([v1,v2],fit="long", fill=0) == [[1,5],[2,6],[3,7],[4,0]]);
|
||||
assert(zip([v1,v2,v3],fit="long") == [[1,5,8],[2,6,9],[3,7,10],[4,undef,11]]);
|
||||
v1 = [1,2,3,4];
|
||||
v2 = [5,6,7];
|
||||
v3 = [8,9,10,11];
|
||||
assert(zip(v1,v3) == [[1,8],[2,9],[3,10],[4,11]]);
|
||||
assert(zip([v1,v3]) == [[1,8],[2,9],[3,10],[4,11]]);
|
||||
assert(zip([v1,v2],fit="short") == [[1,5],[2,6],[3,7]]);
|
||||
assert(zip([v1,v2],fit="long") == [[1,5],[2,6],[3,7],[4,undef]]);
|
||||
assert(zip([v1,v2],fit="long", fill=0) == [[1,5],[2,6],[3,7],[4,0]]);
|
||||
assert(zip([v1,v2,v3],fit="long") == [[1,5,8],[2,6,9],[3,7,10],[4,undef,11]]);
|
||||
}
|
||||
test_zip();
|
||||
|
||||
|
||||
module test_array_group() {
|
||||
v = [1,2,3,4,5,6];
|
||||
assert(array_group(v,2) == [[1,2], [3,4], [5,6]]);
|
||||
assert(array_group(v,3) == [[1,2,3], [4,5,6]]);
|
||||
assert(array_group(v,4,0) == [[1,2,3,4], [5,6,0,0]]);
|
||||
v = [1,2,3,4,5,6];
|
||||
assert(array_group(v,2) == [[1,2], [3,4], [5,6]]);
|
||||
assert(array_group(v,3) == [[1,2,3], [4,5,6]]);
|
||||
assert(array_group(v,4,0) == [[1,2,3,4], [5,6,0,0]]);
|
||||
}
|
||||
test_array_group();
|
||||
|
||||
|
||||
module test_flatten() {
|
||||
assert(flatten([[1,2,3], [4,5,[6,7,8]]]) == [1,2,3,4,5,[6,7,8]]);
|
||||
assert(flatten([[1,2,3], [4,5,[6,7,8]]]) == [1,2,3,4,5,[6,7,8]]);
|
||||
}
|
||||
test_flatten();
|
||||
|
||||
|
||||
module test_array_dim() {
|
||||
assert(array_dim([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]]) == [2,2,3]);
|
||||
assert(array_dim([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]], 0) == 2);
|
||||
assert(array_dim([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]], 2) == 3);
|
||||
assert(array_dim([[[1,2,3],[4,5,6]],[[7,8,9]]]) == [2,undef,3]);
|
||||
assert(array_dim([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]]) == [2,2,3]);
|
||||
assert(array_dim([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]], 0) == 2);
|
||||
assert(array_dim([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]], 2) == 3);
|
||||
assert(array_dim([[[1,2,3],[4,5,6]],[[7,8,9]]]) == [2,undef,3]);
|
||||
}
|
||||
test_array_dim();
|
||||
|
||||
|
||||
module test_transpose() {
|
||||
assert(transpose([[1,2,3],[4,5,6],[7,8,9]]) == [[1,4,7],[2,5,8],[3,6,9]]);
|
||||
assert(transpose([[1,2,3],[4,5,6]]) == [[1,4],[2,5],[3,6]]);
|
||||
assert(transpose([3,4,5]) == [3,4,5]);
|
||||
assert(transpose([[1,2,3],[4,5,6],[7,8,9]]) == [[1,4,7],[2,5,8],[3,6,9]]);
|
||||
assert(transpose([[1,2,3],[4,5,6]]) == [[1,4],[2,5],[3,6]]);
|
||||
assert(transpose([3,4,5]) == [3,4,5]);
|
||||
}
|
||||
test_transpose();
|
||||
|
||||
@ -366,4 +366,4 @@ test_transpose();
|
||||
cube();
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -2,254 +2,254 @@ include <BOSL2/std.scad>
|
||||
|
||||
|
||||
module test_typeof() {
|
||||
assert(typeof(undef) == "undef");
|
||||
assert(typeof(true) == "boolean");
|
||||
assert(typeof(false) == "boolean");
|
||||
assert(typeof(-123) == "number");
|
||||
assert(typeof(0) == "number");
|
||||
assert(typeof(123) == "number");
|
||||
assert(typeof("") == "string");
|
||||
assert(typeof("foo") == "string");
|
||||
assert(typeof([]) == "list");
|
||||
assert(typeof(["foo","bar"]) == "list");
|
||||
assert(typeof([123,849,32]) == "list");
|
||||
assert(typeof([0:5]) == "range");
|
||||
assert(typeof([-3:0]) == "range");
|
||||
assert(typeof([0:1:5]) == "range");
|
||||
assert(typeof([-3:2:5]) == "range");
|
||||
assert(typeof([10:-2:-10]) == "range");
|
||||
assert(typeof(undef) == "undef");
|
||||
assert(typeof(true) == "boolean");
|
||||
assert(typeof(false) == "boolean");
|
||||
assert(typeof(-123) == "number");
|
||||
assert(typeof(0) == "number");
|
||||
assert(typeof(123) == "number");
|
||||
assert(typeof("") == "string");
|
||||
assert(typeof("foo") == "string");
|
||||
assert(typeof([]) == "list");
|
||||
assert(typeof(["foo","bar"]) == "list");
|
||||
assert(typeof([123,849,32]) == "list");
|
||||
assert(typeof([0:5]) == "range");
|
||||
assert(typeof([-3:0]) == "range");
|
||||
assert(typeof([0:1:5]) == "range");
|
||||
assert(typeof([-3:2:5]) == "range");
|
||||
assert(typeof([10:-2:-10]) == "range");
|
||||
}
|
||||
test_typeof();
|
||||
|
||||
|
||||
module test_is_type() {
|
||||
assert(is_type(undef,"undef"));
|
||||
assert(is_type(true,"boolean"));
|
||||
assert(is_type(false,"boolean"));
|
||||
assert(is_type(-123,"number"));
|
||||
assert(is_type(0,"number"));
|
||||
assert(is_type(123,"number"));
|
||||
assert(is_type("","string"));
|
||||
assert(is_type("foo","string"));
|
||||
assert(is_type([],"list"));
|
||||
assert(is_type([1,2,3],"list"));
|
||||
assert(is_type(["foo","bar"],"list"));
|
||||
assert(is_type([0:5],"range"));
|
||||
assert(is_type(undef,"undef"));
|
||||
assert(is_type(true,"boolean"));
|
||||
assert(is_type(false,"boolean"));
|
||||
assert(is_type(-123,"number"));
|
||||
assert(is_type(0,"number"));
|
||||
assert(is_type(123,"number"));
|
||||
assert(is_type("","string"));
|
||||
assert(is_type("foo","string"));
|
||||
assert(is_type([],"list"));
|
||||
assert(is_type([1,2,3],"list"));
|
||||
assert(is_type(["foo","bar"],"list"));
|
||||
assert(is_type([0:5],"range"));
|
||||
|
||||
assert(is_type(undef,["undef"]));
|
||||
assert(is_type(true,["boolean"]));
|
||||
assert(is_type(false,["boolean"]));
|
||||
assert(is_type(-123,["number"]));
|
||||
assert(is_type(0,["number"]));
|
||||
assert(is_type(123,["number"]));
|
||||
assert(is_type("",["string"]));
|
||||
assert(is_type("foo",["string"]));
|
||||
assert(is_type([],["list"]));
|
||||
assert(is_type([1,2,3],["list"]));
|
||||
assert(is_type(["foo","bar"],["list"]));
|
||||
assert(is_type([0:5],["range"]));
|
||||
assert(is_type(undef,["undef"]));
|
||||
assert(is_type(true,["boolean"]));
|
||||
assert(is_type(false,["boolean"]));
|
||||
assert(is_type(-123,["number"]));
|
||||
assert(is_type(0,["number"]));
|
||||
assert(is_type(123,["number"]));
|
||||
assert(is_type("",["string"]));
|
||||
assert(is_type("foo",["string"]));
|
||||
assert(is_type([],["list"]));
|
||||
assert(is_type([1,2,3],["list"]));
|
||||
assert(is_type(["foo","bar"],["list"]));
|
||||
assert(is_type([0:5],["range"]));
|
||||
|
||||
assert(is_type(123,["number","string"]));
|
||||
assert(is_type("foo",["number","string"]));
|
||||
assert(is_type(123,["number","string"]));
|
||||
assert(is_type("foo",["number","string"]));
|
||||
}
|
||||
test_is_type();
|
||||
|
||||
|
||||
module test_is_def() {
|
||||
assert(!is_def(undef));
|
||||
assert(is_def(true));
|
||||
assert(is_def(false));
|
||||
assert(is_def(-123));
|
||||
assert(is_def(0));
|
||||
assert(is_def(123));
|
||||
assert(is_def(""));
|
||||
assert(is_def("foo"));
|
||||
assert(is_def([]));
|
||||
assert(is_def([3,4,5]));
|
||||
assert(is_def(["foo","bar","baz"]));
|
||||
assert(is_def([0:5]));
|
||||
assert(!is_def(undef));
|
||||
assert(is_def(true));
|
||||
assert(is_def(false));
|
||||
assert(is_def(-123));
|
||||
assert(is_def(0));
|
||||
assert(is_def(123));
|
||||
assert(is_def(""));
|
||||
assert(is_def("foo"));
|
||||
assert(is_def([]));
|
||||
assert(is_def([3,4,5]));
|
||||
assert(is_def(["foo","bar","baz"]));
|
||||
assert(is_def([0:5]));
|
||||
}
|
||||
test_is_def();
|
||||
|
||||
|
||||
module test_is_str() {
|
||||
assert(!is_str(undef));
|
||||
assert(!is_str(true));
|
||||
assert(!is_str(false));
|
||||
assert(!is_str(-123));
|
||||
assert(!is_str(0));
|
||||
assert(!is_str(123));
|
||||
assert(is_str(""));
|
||||
assert(is_str("foo"));
|
||||
assert(!is_str([]));
|
||||
assert(!is_str([3,4,5]));
|
||||
assert(!is_str(["foo","bar","baz"]));
|
||||
assert(!is_str([0:5]));
|
||||
assert(!is_str(undef));
|
||||
assert(!is_str(true));
|
||||
assert(!is_str(false));
|
||||
assert(!is_str(-123));
|
||||
assert(!is_str(0));
|
||||
assert(!is_str(123));
|
||||
assert(is_str(""));
|
||||
assert(is_str("foo"));
|
||||
assert(!is_str([]));
|
||||
assert(!is_str([3,4,5]));
|
||||
assert(!is_str(["foo","bar","baz"]));
|
||||
assert(!is_str([0:5]));
|
||||
}
|
||||
test_is_str();
|
||||
|
||||
|
||||
module test_is_int() {
|
||||
assert(is_int(-999));
|
||||
assert(is_int(-1));
|
||||
assert(is_int(0));
|
||||
assert(is_int(1));
|
||||
assert(is_int(999));
|
||||
assert(!is_int(-1.1));
|
||||
assert(!is_int(1.1));
|
||||
assert(!is_int(-0.1));
|
||||
assert(!is_int(0.1));
|
||||
assert(!is_int(-99.1));
|
||||
assert(!is_int(99.1));
|
||||
assert(!is_int(undef));
|
||||
assert(!is_int(false));
|
||||
assert(!is_int(true));
|
||||
assert(!is_int("foo"));
|
||||
assert(!is_int([0,1,2]));
|
||||
assert(!is_int([0:1:2]));
|
||||
assert(is_int(-999));
|
||||
assert(is_int(-1));
|
||||
assert(is_int(0));
|
||||
assert(is_int(1));
|
||||
assert(is_int(999));
|
||||
assert(!is_int(-1.1));
|
||||
assert(!is_int(1.1));
|
||||
assert(!is_int(-0.1));
|
||||
assert(!is_int(0.1));
|
||||
assert(!is_int(-99.1));
|
||||
assert(!is_int(99.1));
|
||||
assert(!is_int(undef));
|
||||
assert(!is_int(false));
|
||||
assert(!is_int(true));
|
||||
assert(!is_int("foo"));
|
||||
assert(!is_int([0,1,2]));
|
||||
assert(!is_int([0:1:2]));
|
||||
}
|
||||
test_is_int();
|
||||
|
||||
|
||||
module test_is_integer() {
|
||||
assert(is_integer(-999));
|
||||
assert(is_integer(-1));
|
||||
assert(is_integer(0));
|
||||
assert(is_integer(1));
|
||||
assert(is_integer(999));
|
||||
assert(!is_integer(-1.1));
|
||||
assert(!is_integer(1.1));
|
||||
assert(!is_integer(-0.1));
|
||||
assert(!is_integer(0.1));
|
||||
assert(!is_integer(-99.1));
|
||||
assert(!is_integer(99.1));
|
||||
assert(!is_integer(undef));
|
||||
assert(!is_integer(false));
|
||||
assert(!is_integer(true));
|
||||
assert(!is_integer("foo"));
|
||||
assert(!is_integer([0,1,2]));
|
||||
assert(!is_integer([0:1:2]));
|
||||
assert(is_integer(-999));
|
||||
assert(is_integer(-1));
|
||||
assert(is_integer(0));
|
||||
assert(is_integer(1));
|
||||
assert(is_integer(999));
|
||||
assert(!is_integer(-1.1));
|
||||
assert(!is_integer(1.1));
|
||||
assert(!is_integer(-0.1));
|
||||
assert(!is_integer(0.1));
|
||||
assert(!is_integer(-99.1));
|
||||
assert(!is_integer(99.1));
|
||||
assert(!is_integer(undef));
|
||||
assert(!is_integer(false));
|
||||
assert(!is_integer(true));
|
||||
assert(!is_integer("foo"));
|
||||
assert(!is_integer([0,1,2]));
|
||||
assert(!is_integer([0:1:2]));
|
||||
}
|
||||
test_is_integer();
|
||||
|
||||
|
||||
module test_default() {
|
||||
assert(default(undef,23) == 23);
|
||||
assert(default(true,23) == true);
|
||||
assert(default(false,23) == false);
|
||||
assert(default(-123,23) == -123);
|
||||
assert(default(0,23) == 0);
|
||||
assert(default(123,23) == 123);
|
||||
assert(default("",23) == "");
|
||||
assert(default("foo",23) == "foo");
|
||||
assert(default(undef,23) == 23);
|
||||
assert(default(true,23) == true);
|
||||
assert(default(false,23) == false);
|
||||
assert(default(-123,23) == -123);
|
||||
assert(default(0,23) == 0);
|
||||
assert(default(123,23) == 123);
|
||||
assert(default("",23) == "");
|
||||
assert(default("foo",23) == "foo");
|
||||
}
|
||||
test_default();
|
||||
|
||||
|
||||
module test_first_defined() {
|
||||
assert(first_defined([undef,undef,true,false,undef]) == true);
|
||||
assert(first_defined([undef,undef,false,true,undef]) == false);
|
||||
assert(first_defined([undef,undef,0,1,undef]) == 0);
|
||||
assert(first_defined([undef,undef,43,44,undef]) == 43);
|
||||
assert(first_defined([undef,undef,"foo","bar",undef]) == "foo");
|
||||
assert(first_defined([0,1,2,3,4]) == 0);
|
||||
assert(first_defined([2,3,4]) == 2);
|
||||
assert(first_defined([[undef,undef],[undef,true],[false,undef]],recursive=true) == [undef, true]);
|
||||
assert(first_defined([undef,undef,true,false,undef]) == true);
|
||||
assert(first_defined([undef,undef,false,true,undef]) == false);
|
||||
assert(first_defined([undef,undef,0,1,undef]) == 0);
|
||||
assert(first_defined([undef,undef,43,44,undef]) == 43);
|
||||
assert(first_defined([undef,undef,"foo","bar",undef]) == "foo");
|
||||
assert(first_defined([0,1,2,3,4]) == 0);
|
||||
assert(first_defined([2,3,4]) == 2);
|
||||
assert(first_defined([[undef,undef],[undef,true],[false,undef]],recursive=true) == [undef, true]);
|
||||
}
|
||||
test_first_defined();
|
||||
|
||||
|
||||
module test_num_defined() {
|
||||
assert(num_defined([undef,undef,true,false,undef]) == 2);
|
||||
assert(num_defined([9,undef,true,false,undef]) == 3);
|
||||
assert(num_defined([undef,9,true,false,undef]) == 3);
|
||||
assert(num_defined(["foo",9,true,false,undef]) == 4);
|
||||
assert(num_defined([undef,undef,true,false,undef]) == 2);
|
||||
assert(num_defined([9,undef,true,false,undef]) == 3);
|
||||
assert(num_defined([undef,9,true,false,undef]) == 3);
|
||||
assert(num_defined(["foo",9,true,false,undef]) == 4);
|
||||
}
|
||||
test_num_defined();
|
||||
|
||||
|
||||
module test_any_defined() {
|
||||
assert(!any_defined([undef,undef,undef,undef,undef]));
|
||||
assert(any_defined([3,undef,undef,undef,undef]));
|
||||
assert(any_defined([undef,3,undef,undef,undef]));
|
||||
assert(any_defined([undef,undef,3,undef,undef]));
|
||||
assert(any_defined([undef,undef,undef,3,undef]));
|
||||
assert(any_defined([undef,undef,undef,undef,3]));
|
||||
assert(any_defined([3,undef,undef,undef,3]));
|
||||
assert(any_defined([3,3,3,3,3]));
|
||||
assert(any_defined(["foo",undef,undef,undef,undef]));
|
||||
assert(any_defined([undef,"foo",undef,undef,undef]));
|
||||
assert(any_defined([undef,undef,"foo",undef,undef]));
|
||||
assert(any_defined([undef,undef,undef,"foo",undef]));
|
||||
assert(any_defined([undef,undef,undef,undef,"foo"]));
|
||||
assert(any_defined(["foo",undef,undef,undef,"foo"]));
|
||||
assert(any_defined(["foo","foo","foo","foo","foo"]));
|
||||
assert(any_defined([undef,undef,true,false,undef]));
|
||||
assert(!any_defined([undef,undef,undef,undef,undef]));
|
||||
assert(any_defined([3,undef,undef,undef,undef]));
|
||||
assert(any_defined([undef,3,undef,undef,undef]));
|
||||
assert(any_defined([undef,undef,3,undef,undef]));
|
||||
assert(any_defined([undef,undef,undef,3,undef]));
|
||||
assert(any_defined([undef,undef,undef,undef,3]));
|
||||
assert(any_defined([3,undef,undef,undef,3]));
|
||||
assert(any_defined([3,3,3,3,3]));
|
||||
assert(any_defined(["foo",undef,undef,undef,undef]));
|
||||
assert(any_defined([undef,"foo",undef,undef,undef]));
|
||||
assert(any_defined([undef,undef,"foo",undef,undef]));
|
||||
assert(any_defined([undef,undef,undef,"foo",undef]));
|
||||
assert(any_defined([undef,undef,undef,undef,"foo"]));
|
||||
assert(any_defined(["foo",undef,undef,undef,"foo"]));
|
||||
assert(any_defined(["foo","foo","foo","foo","foo"]));
|
||||
assert(any_defined([undef,undef,true,false,undef]));
|
||||
}
|
||||
test_any_defined();
|
||||
|
||||
|
||||
module test_all_defined() {
|
||||
assert(!all_defined([undef,undef,undef,undef,undef]));
|
||||
assert(!all_defined([3,undef,undef,undef,undef]));
|
||||
assert(!all_defined([undef,3,undef,undef,undef]));
|
||||
assert(!all_defined([undef,undef,3,undef,undef]));
|
||||
assert(!all_defined([undef,undef,undef,3,undef]));
|
||||
assert(!all_defined([undef,undef,undef,undef,3]));
|
||||
assert(!all_defined([3,undef,undef,undef,3]));
|
||||
assert(all_defined([3,3,3,3,3]));
|
||||
assert(!all_defined(["foo",undef,undef,undef,undef]));
|
||||
assert(!all_defined([undef,"foo",undef,undef,undef]));
|
||||
assert(!all_defined([undef,undef,"foo",undef,undef]));
|
||||
assert(!all_defined([undef,undef,undef,"foo",undef]));
|
||||
assert(!all_defined([undef,undef,undef,undef,"foo"]));
|
||||
assert(!all_defined(["foo",undef,undef,undef,"foo"]));
|
||||
assert(all_defined(["foo","foo","foo","foo","foo"]));
|
||||
assert(!all_defined([undef,undef,true,false,undef]));
|
||||
assert(!all_defined([undef,undef,undef,undef,undef]));
|
||||
assert(!all_defined([3,undef,undef,undef,undef]));
|
||||
assert(!all_defined([undef,3,undef,undef,undef]));
|
||||
assert(!all_defined([undef,undef,3,undef,undef]));
|
||||
assert(!all_defined([undef,undef,undef,3,undef]));
|
||||
assert(!all_defined([undef,undef,undef,undef,3]));
|
||||
assert(!all_defined([3,undef,undef,undef,3]));
|
||||
assert(all_defined([3,3,3,3,3]));
|
||||
assert(!all_defined(["foo",undef,undef,undef,undef]));
|
||||
assert(!all_defined([undef,"foo",undef,undef,undef]));
|
||||
assert(!all_defined([undef,undef,"foo",undef,undef]));
|
||||
assert(!all_defined([undef,undef,undef,"foo",undef]));
|
||||
assert(!all_defined([undef,undef,undef,undef,"foo"]));
|
||||
assert(!all_defined(["foo",undef,undef,undef,"foo"]));
|
||||
assert(all_defined(["foo","foo","foo","foo","foo"]));
|
||||
assert(!all_defined([undef,undef,true,false,undef]));
|
||||
}
|
||||
test_all_defined();
|
||||
|
||||
|
||||
module test_get_radius() {
|
||||
assert(get_radius(r1=100,d1=undef,r=undef,d=undef,dflt=23) == 100);
|
||||
assert(get_radius(r1=undef,d1=200,r=undef,d=undef,dflt=23) == 100);
|
||||
assert(get_radius(r1=undef,d1=undef,r=100,d=undef,dflt=23) == 100);
|
||||
assert(get_radius(r1=undef,d1=undef,r=undef,d=200,dflt=23) == 100);
|
||||
assert(get_radius(r1=50,d1=undef,r=undef,d=undef,dflt=23) == 50);
|
||||
assert(get_radius(r1=undef,d1=100,r=undef,d=undef,dflt=23) == 50);
|
||||
assert(get_radius(r1=undef,d1=undef,r=50,d=undef,dflt=23) == 50);
|
||||
assert(get_radius(r1=undef,d1=undef,r=undef,d=100,dflt=23) == 50);
|
||||
assert(get_radius(r1=undef,d1=undef,r=undef,d=undef,dflt=23) == 23);
|
||||
assert(get_radius(r1=undef,d1=undef,r=undef,d=undef,dflt=undef) == undef);
|
||||
assert(get_radius(r1=100,d1=undef,r=undef,d=undef,dflt=23) == 100);
|
||||
assert(get_radius(r1=undef,d1=200,r=undef,d=undef,dflt=23) == 100);
|
||||
assert(get_radius(r1=undef,d1=undef,r=100,d=undef,dflt=23) == 100);
|
||||
assert(get_radius(r1=undef,d1=undef,r=undef,d=200,dflt=23) == 100);
|
||||
assert(get_radius(r1=50,d1=undef,r=undef,d=undef,dflt=23) == 50);
|
||||
assert(get_radius(r1=undef,d1=100,r=undef,d=undef,dflt=23) == 50);
|
||||
assert(get_radius(r1=undef,d1=undef,r=50,d=undef,dflt=23) == 50);
|
||||
assert(get_radius(r1=undef,d1=undef,r=undef,d=100,dflt=23) == 50);
|
||||
assert(get_radius(r1=undef,d1=undef,r=undef,d=undef,dflt=23) == 23);
|
||||
assert(get_radius(r1=undef,d1=undef,r=undef,d=undef,dflt=undef) == undef);
|
||||
}
|
||||
test_get_radius();
|
||||
|
||||
|
||||
module test_get_height() {
|
||||
assert(get_height(h=undef, l=undef, height=undef, dflt=undef) == undef);
|
||||
assert(get_height(h=undef, l=undef, height=undef, dflt=23) == 23);
|
||||
assert(get_height(h=undef, l=undef, height=50, dflt=23) == 50);
|
||||
assert(get_height(h=undef, l=50, height=undef, dflt=23) == 50);
|
||||
assert(get_height(h=50, l=undef, height=undef, dflt=23) == 50);
|
||||
assert(get_height(h=undef, l=undef, height=75, dflt=23) == 75);
|
||||
assert(get_height(h=undef, l=75, height=undef, dflt=23) == 75);
|
||||
assert(get_height(h=75, l=undef, height=undef, dflt=23) == 75);
|
||||
assert(get_height(h=undef, l=undef, height=undef, dflt=undef) == undef);
|
||||
assert(get_height(h=undef, l=undef, height=undef, dflt=23) == 23);
|
||||
assert(get_height(h=undef, l=undef, height=50, dflt=23) == 50);
|
||||
assert(get_height(h=undef, l=50, height=undef, dflt=23) == 50);
|
||||
assert(get_height(h=50, l=undef, height=undef, dflt=23) == 50);
|
||||
assert(get_height(h=undef, l=undef, height=75, dflt=23) == 75);
|
||||
assert(get_height(h=undef, l=75, height=undef, dflt=23) == 75);
|
||||
assert(get_height(h=75, l=undef, height=undef, dflt=23) == 75);
|
||||
}
|
||||
test_get_height();
|
||||
|
||||
|
||||
module test_scalar_vec3() {
|
||||
assert(scalar_vec3(undef) == undef);
|
||||
assert(scalar_vec3(3) == [3,3,3]);
|
||||
assert(scalar_vec3(3,dflt=1) == [3,1,1]);
|
||||
assert(scalar_vec3([3]) == [3,0,0]);
|
||||
assert(scalar_vec3([3,4]) == [3,4,0]);
|
||||
assert(scalar_vec3([3,4],dflt=1) == [3,4,1]);
|
||||
assert(scalar_vec3([3],dflt=1) == [3,1,1]);
|
||||
assert(scalar_vec3([3,4,5]) == [3,4,5]);
|
||||
assert(scalar_vec3([3,4,5,6]) == [3,4,5]);
|
||||
assert(scalar_vec3(undef) == undef);
|
||||
assert(scalar_vec3(3) == [3,3,3]);
|
||||
assert(scalar_vec3(3,dflt=1) == [3,1,1]);
|
||||
assert(scalar_vec3([3]) == [3,0,0]);
|
||||
assert(scalar_vec3([3,4]) == [3,4,0]);
|
||||
assert(scalar_vec3([3,4],dflt=1) == [3,4,1]);
|
||||
assert(scalar_vec3([3],dflt=1) == [3,1,1]);
|
||||
assert(scalar_vec3([3,4,5]) == [3,4,5]);
|
||||
assert(scalar_vec3([3,4,5,6]) == [3,4,5]);
|
||||
}
|
||||
test_scalar_vec3();
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -2,208 +2,208 @@ include <BOSL2/std.scad>
|
||||
|
||||
|
||||
module test_point2d() {
|
||||
assert(point2d([1,2,3])==[1,2]);
|
||||
assert(point2d([2,3])==[2,3]);
|
||||
assert(point2d([1])==[1,0]);
|
||||
assert(point2d([1,2,3])==[1,2]);
|
||||
assert(point2d([2,3])==[2,3]);
|
||||
assert(point2d([1])==[1,0]);
|
||||
}
|
||||
test_point2d();
|
||||
|
||||
|
||||
module test_path2d() {
|
||||
assert(path2d([[1,2], [3,4], [5,6], [7,8]])==[[1,2],[3,4],[5,6],[7,8]]);
|
||||
assert(path2d([[1,2,3], [2,3,4], [3,4,5], [4,5,6]])==[[1,2],[2,3],[3,4],[4,5]]);
|
||||
assert(path2d([[1,2,3,4], [2,3,4,5], [3,4,5,6], [4,5,6,7]])==[[1,2],[2,3],[3,4],[4,5]]);
|
||||
assert(path2d([[1,2], [3,4], [5,6], [7,8]])==[[1,2],[3,4],[5,6],[7,8]]);
|
||||
assert(path2d([[1,2,3], [2,3,4], [3,4,5], [4,5,6]])==[[1,2],[2,3],[3,4],[4,5]]);
|
||||
assert(path2d([[1,2,3,4], [2,3,4,5], [3,4,5,6], [4,5,6,7]])==[[1,2],[2,3],[3,4],[4,5]]);
|
||||
}
|
||||
test_path2d();
|
||||
|
||||
|
||||
module test_point3d() {
|
||||
assert(point3d([1,2,3,4,5])==[1,2,3]);
|
||||
assert(point3d([1,2,3,4])==[1,2,3]);
|
||||
assert(point3d([1,2,3])==[1,2,3]);
|
||||
assert(point3d([2,3])==[2,3,0]);
|
||||
assert(point3d([1])==[1,0,0]);
|
||||
assert(point3d([1,2,3,4,5])==[1,2,3]);
|
||||
assert(point3d([1,2,3,4])==[1,2,3]);
|
||||
assert(point3d([1,2,3])==[1,2,3]);
|
||||
assert(point3d([2,3])==[2,3,0]);
|
||||
assert(point3d([1])==[1,0,0]);
|
||||
}
|
||||
test_point3d();
|
||||
|
||||
|
||||
module test_path3d() {
|
||||
assert(path3d([[1,2], [3,4], [5,6], [7,8]])==[[1,2,0],[3,4,0],[5,6,0],[7,8,0]]);
|
||||
assert(path3d([[1,2,3], [2,3,4], [3,4,5], [4,5,6]])==[[1,2,3],[2,3,4],[3,4,5],[4,5,6]]);
|
||||
assert(path3d([[1,2,3,4], [2,3,4,5], [3,4,5,6], [4,5,6,7]])==[[1,2,3],[2,3,4],[3,4,5],[4,5,6]]);
|
||||
assert(path3d([[1,2], [3,4], [5,6], [7,8]])==[[1,2,0],[3,4,0],[5,6,0],[7,8,0]]);
|
||||
assert(path3d([[1,2,3], [2,3,4], [3,4,5], [4,5,6]])==[[1,2,3],[2,3,4],[3,4,5],[4,5,6]]);
|
||||
assert(path3d([[1,2,3,4], [2,3,4,5], [3,4,5,6], [4,5,6,7]])==[[1,2,3],[2,3,4],[3,4,5],[4,5,6]]);
|
||||
}
|
||||
test_path3d();
|
||||
|
||||
|
||||
module test_point4d() {
|
||||
assert(point4d([1,2,3,4,5])==[1,2,3,4]);
|
||||
assert(point4d([1,2,3,4])==[1,2,3,4]);
|
||||
assert(point4d([1,2,3])==[1,2,3,0]);
|
||||
assert(point4d([2,3])==[2,3,0,0]);
|
||||
assert(point4d([1])==[1,0,0,0]);
|
||||
assert(point4d([1,2,3,4,5])==[1,2,3,4]);
|
||||
assert(point4d([1,2,3,4])==[1,2,3,4]);
|
||||
assert(point4d([1,2,3])==[1,2,3,0]);
|
||||
assert(point4d([2,3])==[2,3,0,0]);
|
||||
assert(point4d([1])==[1,0,0,0]);
|
||||
}
|
||||
test_point4d();
|
||||
|
||||
|
||||
module test_path4d() {
|
||||
assert(path4d([[1,2], [3,4], [5,6], [7,8]])==[[1,2,0,0],[3,4,0,0],[5,6,0,0],[7,8,0,0]]);
|
||||
assert(path4d([[1,2,3], [2,3,4], [3,4,5], [4,5,6]])==[[1,2,3,0],[2,3,4,0],[3,4,5,0],[4,5,6,0]]);
|
||||
assert(path4d([[1,2,3,4], [2,3,4,5], [3,4,5,6], [4,5,6,7]])==[[1,2,3,4],[2,3,4,5],[3,4,5,6],[4,5,6,7]]);
|
||||
assert(path4d([[1,2,3,4,5], [2,3,4,5,6], [3,4,5,6,7], [4,5,6,7,8]])==[[1,2,3,4],[2,3,4,5],[3,4,5,6],[4,5,6,7]]);
|
||||
assert(path4d([[1,2], [3,4], [5,6], [7,8]])==[[1,2,0,0],[3,4,0,0],[5,6,0,0],[7,8,0,0]]);
|
||||
assert(path4d([[1,2,3], [2,3,4], [3,4,5], [4,5,6]])==[[1,2,3,0],[2,3,4,0],[3,4,5,0],[4,5,6,0]]);
|
||||
assert(path4d([[1,2,3,4], [2,3,4,5], [3,4,5,6], [4,5,6,7]])==[[1,2,3,4],[2,3,4,5],[3,4,5,6],[4,5,6,7]]);
|
||||
assert(path4d([[1,2,3,4,5], [2,3,4,5,6], [3,4,5,6,7], [4,5,6,7,8]])==[[1,2,3,4],[2,3,4,5],[3,4,5,6],[4,5,6,7]]);
|
||||
}
|
||||
test_path4d();
|
||||
|
||||
|
||||
module test_polar_to_xy() {
|
||||
assert(approx(polar_to_xy(20,45), [20/sqrt(2), 20/sqrt(2)]));
|
||||
assert(approx(polar_to_xy(20,135), [-20/sqrt(2), 20/sqrt(2)]));
|
||||
assert(approx(polar_to_xy(20,-135), [-20/sqrt(2), -20/sqrt(2)]));
|
||||
assert(approx(polar_to_xy(20,-45), [20/sqrt(2), -20/sqrt(2)]));
|
||||
assert(approx(polar_to_xy(40,30), [40*sqrt(3)/2, 40/2]));
|
||||
assert(approx(polar_to_xy([40,30]), [40*sqrt(3)/2, 40/2]));
|
||||
assert(approx(polar_to_xy(20,45), [20/sqrt(2), 20/sqrt(2)]));
|
||||
assert(approx(polar_to_xy(20,135), [-20/sqrt(2), 20/sqrt(2)]));
|
||||
assert(approx(polar_to_xy(20,-135), [-20/sqrt(2), -20/sqrt(2)]));
|
||||
assert(approx(polar_to_xy(20,-45), [20/sqrt(2), -20/sqrt(2)]));
|
||||
assert(approx(polar_to_xy(40,30), [40*sqrt(3)/2, 40/2]));
|
||||
assert(approx(polar_to_xy([40,30]), [40*sqrt(3)/2, 40/2]));
|
||||
}
|
||||
test_polar_to_xy();
|
||||
|
||||
|
||||
module test_xy_to_polar() {
|
||||
assert(approx(xy_to_polar([20/sqrt(2), 20/sqrt(2)]),[20,45]));
|
||||
assert(approx(xy_to_polar([-20/sqrt(2), 20/sqrt(2)]),[20,135]));
|
||||
assert(approx(xy_to_polar([-20/sqrt(2), -20/sqrt(2)]),[20,-135]));
|
||||
assert(approx(xy_to_polar([20/sqrt(2), -20/sqrt(2)]),[20,-45]));
|
||||
assert(approx(xy_to_polar([40*sqrt(3)/2, 40/2]),[40,30]));
|
||||
assert(approx(xy_to_polar([-40*sqrt(3)/2, 40/2]),[40,150]));
|
||||
assert(approx(xy_to_polar([-40*sqrt(3)/2, -40/2]),[40,-150]));
|
||||
assert(approx(xy_to_polar([40*sqrt(3)/2, -40/2]),[40,-30]));
|
||||
assert(approx(xy_to_polar([20/sqrt(2), 20/sqrt(2)]),[20,45]));
|
||||
assert(approx(xy_to_polar([-20/sqrt(2), 20/sqrt(2)]),[20,135]));
|
||||
assert(approx(xy_to_polar([-20/sqrt(2), -20/sqrt(2)]),[20,-135]));
|
||||
assert(approx(xy_to_polar([20/sqrt(2), -20/sqrt(2)]),[20,-45]));
|
||||
assert(approx(xy_to_polar([40*sqrt(3)/2, 40/2]),[40,30]));
|
||||
assert(approx(xy_to_polar([-40*sqrt(3)/2, 40/2]),[40,150]));
|
||||
assert(approx(xy_to_polar([-40*sqrt(3)/2, -40/2]),[40,-150]));
|
||||
assert(approx(xy_to_polar([40*sqrt(3)/2, -40/2]),[40,-30]));
|
||||
}
|
||||
test_xy_to_polar();
|
||||
|
||||
|
||||
module test_project_plane() {
|
||||
assert(approx(project_plane([-5,0,-5], [-10,0,-10], [0,0,0], [0,-10,-10]),[0,10*sqrt(2)/2]));
|
||||
assert(approx(project_plane([0,-5,-5], [-10,0,-10], [0,0,0], [0,-10,-10]),[6.12372, 10.6066],eps=1e-5));
|
||||
assert(approx(project_plane([-5,0,-5], [-10,0,-10], [0,0,0], [0,-10,-10]),[0,10*sqrt(2)/2]));
|
||||
assert(approx(project_plane([0,-5,-5], [-10,0,-10], [0,0,0], [0,-10,-10]),[6.12372, 10.6066],eps=1e-5));
|
||||
}
|
||||
test_project_plane();
|
||||
|
||||
|
||||
module test_lift_plane() {
|
||||
assert(approx(lift_plane([0,10*sqrt(2)/2], [-10,0,-10], [0,0,0], [0,-10,-10]),[-5,0,-5]));
|
||||
assert(approx(lift_plane([6.12372, 10.6066], [-10,0,-10], [0,0,0], [0,-10,-10]),[0,-5,-5],eps=1e-5));
|
||||
assert(approx(lift_plane([0,10*sqrt(2)/2], [-10,0,-10], [0,0,0], [0,-10,-10]),[-5,0,-5]));
|
||||
assert(approx(lift_plane([6.12372, 10.6066], [-10,0,-10], [0,0,0], [0,-10,-10]),[0,-5,-5],eps=1e-5));
|
||||
}
|
||||
test_lift_plane();
|
||||
|
||||
|
||||
module test_cylindrical_to_xyz() {
|
||||
assert(approx(cylindrical_to_xyz(100,90,10),[0,100,10]));
|
||||
assert(approx(cylindrical_to_xyz(100,270,-10),[0,-100,-10]));
|
||||
assert(approx(cylindrical_to_xyz(100,-90,-10),[0,-100,-10]));
|
||||
assert(approx(cylindrical_to_xyz(100,180,0),[-100,0,0]));
|
||||
assert(approx(cylindrical_to_xyz(100,0,0),[100,0,0]));
|
||||
assert(approx(cylindrical_to_xyz(100,45,10),[100*sqrt(2)/2,100*sqrt(2)/2,10]));
|
||||
assert(approx(cylindrical_to_xyz([100,90,10]),[0,100,10]));
|
||||
assert(approx(cylindrical_to_xyz([100,270,-10]),[0,-100,-10]));
|
||||
assert(approx(cylindrical_to_xyz([100,-90,-10]),[0,-100,-10]));
|
||||
assert(approx(cylindrical_to_xyz([100,180,0]),[-100,0,0]));
|
||||
assert(approx(cylindrical_to_xyz([100,0,0]),[100,0,0]));
|
||||
assert(approx(cylindrical_to_xyz([100,45,10]),[100*sqrt(2)/2,100*sqrt(2)/2,10]));
|
||||
assert(approx(cylindrical_to_xyz(100,90,10),[0,100,10]));
|
||||
assert(approx(cylindrical_to_xyz(100,270,-10),[0,-100,-10]));
|
||||
assert(approx(cylindrical_to_xyz(100,-90,-10),[0,-100,-10]));
|
||||
assert(approx(cylindrical_to_xyz(100,180,0),[-100,0,0]));
|
||||
assert(approx(cylindrical_to_xyz(100,0,0),[100,0,0]));
|
||||
assert(approx(cylindrical_to_xyz(100,45,10),[100*sqrt(2)/2,100*sqrt(2)/2,10]));
|
||||
assert(approx(cylindrical_to_xyz([100,90,10]),[0,100,10]));
|
||||
assert(approx(cylindrical_to_xyz([100,270,-10]),[0,-100,-10]));
|
||||
assert(approx(cylindrical_to_xyz([100,-90,-10]),[0,-100,-10]));
|
||||
assert(approx(cylindrical_to_xyz([100,180,0]),[-100,0,0]));
|
||||
assert(approx(cylindrical_to_xyz([100,0,0]),[100,0,0]));
|
||||
assert(approx(cylindrical_to_xyz([100,45,10]),[100*sqrt(2)/2,100*sqrt(2)/2,10]));
|
||||
}
|
||||
test_cylindrical_to_xyz();
|
||||
|
||||
|
||||
module test_xyz_to_cylindrical() {
|
||||
assert(approx(xyz_to_cylindrical(0,100,10),[100,90,10]));
|
||||
assert(approx(xyz_to_cylindrical(0,-100,-10),[100,-90,-10]));
|
||||
assert(approx(xyz_to_cylindrical(-100,0,0),[100,180,0]));
|
||||
assert(approx(xyz_to_cylindrical(100,0,0),[100,0,0]));
|
||||
assert(approx(xyz_to_cylindrical(100*sqrt(2)/2,100*sqrt(2)/2,10),[100,45,10]));
|
||||
assert(approx(xyz_to_cylindrical([0,100,10]),[100,90,10]));
|
||||
assert(approx(xyz_to_cylindrical([0,-100,-10]),[100,-90,-10]));
|
||||
assert(approx(xyz_to_cylindrical([-100,0,0]),[100,180,0]));
|
||||
assert(approx(xyz_to_cylindrical([100,0,0]),[100,0,0]));
|
||||
assert(approx(xyz_to_cylindrical([100*sqrt(2)/2,100*sqrt(2)/2,10]),[100,45,10]));
|
||||
assert(approx(xyz_to_cylindrical(0,100,10),[100,90,10]));
|
||||
assert(approx(xyz_to_cylindrical(0,-100,-10),[100,-90,-10]));
|
||||
assert(approx(xyz_to_cylindrical(-100,0,0),[100,180,0]));
|
||||
assert(approx(xyz_to_cylindrical(100,0,0),[100,0,0]));
|
||||
assert(approx(xyz_to_cylindrical(100*sqrt(2)/2,100*sqrt(2)/2,10),[100,45,10]));
|
||||
assert(approx(xyz_to_cylindrical([0,100,10]),[100,90,10]));
|
||||
assert(approx(xyz_to_cylindrical([0,-100,-10]),[100,-90,-10]));
|
||||
assert(approx(xyz_to_cylindrical([-100,0,0]),[100,180,0]));
|
||||
assert(approx(xyz_to_cylindrical([100,0,0]),[100,0,0]));
|
||||
assert(approx(xyz_to_cylindrical([100*sqrt(2)/2,100*sqrt(2)/2,10]),[100,45,10]));
|
||||
}
|
||||
test_xyz_to_cylindrical();
|
||||
|
||||
|
||||
module test_spherical_to_xyz() {
|
||||
assert(approx(spherical_to_xyz(100,90,45),100*[0,sqrt(2)/2,sqrt(2)/2]));
|
||||
assert(approx(spherical_to_xyz(100,270,45),100*[0,-sqrt(2)/2,sqrt(2)/2]));
|
||||
assert(approx(spherical_to_xyz(100,-90,45),100*[0,-sqrt(2)/2,sqrt(2)/2]));
|
||||
assert(approx(spherical_to_xyz(100,90,90),100*[0,1,0]));
|
||||
assert(approx(spherical_to_xyz(100,-90,90),100*[0,-1,0]));
|
||||
assert(approx(spherical_to_xyz(100,180,90),100*[-1,0,0]));
|
||||
assert(approx(spherical_to_xyz(100,0,90),100*[1,0,0]));
|
||||
assert(approx(spherical_to_xyz(100,0,0),100*[0,0,1]));
|
||||
assert(approx(spherical_to_xyz(100,0,180),100*[0,0,-1]));
|
||||
assert(approx(spherical_to_xyz([100,90,45]),100*[0,sqrt(2)/2,sqrt(2)/2]));
|
||||
assert(approx(spherical_to_xyz([100,270,45]),100*[0,-sqrt(2)/2,sqrt(2)/2]));
|
||||
assert(approx(spherical_to_xyz([100,-90,45]),100*[0,-sqrt(2)/2,sqrt(2)/2]));
|
||||
assert(approx(spherical_to_xyz([100,90,90]),100*[0,1,0]));
|
||||
assert(approx(spherical_to_xyz([100,-90,90]),100*[0,-1,0]));
|
||||
assert(approx(spherical_to_xyz([100,180,90]),100*[-1,0,0]));
|
||||
assert(approx(spherical_to_xyz([100,0,90]),100*[1,0,0]));
|
||||
assert(approx(spherical_to_xyz([100,0,0]),100*[0,0,1]));
|
||||
assert(approx(spherical_to_xyz([100,0,180]),100*[0,0,-1]));
|
||||
assert(approx(spherical_to_xyz(100,90,45),100*[0,sqrt(2)/2,sqrt(2)/2]));
|
||||
assert(approx(spherical_to_xyz(100,270,45),100*[0,-sqrt(2)/2,sqrt(2)/2]));
|
||||
assert(approx(spherical_to_xyz(100,-90,45),100*[0,-sqrt(2)/2,sqrt(2)/2]));
|
||||
assert(approx(spherical_to_xyz(100,90,90),100*[0,1,0]));
|
||||
assert(approx(spherical_to_xyz(100,-90,90),100*[0,-1,0]));
|
||||
assert(approx(spherical_to_xyz(100,180,90),100*[-1,0,0]));
|
||||
assert(approx(spherical_to_xyz(100,0,90),100*[1,0,0]));
|
||||
assert(approx(spherical_to_xyz(100,0,0),100*[0,0,1]));
|
||||
assert(approx(spherical_to_xyz(100,0,180),100*[0,0,-1]));
|
||||
assert(approx(spherical_to_xyz([100,90,45]),100*[0,sqrt(2)/2,sqrt(2)/2]));
|
||||
assert(approx(spherical_to_xyz([100,270,45]),100*[0,-sqrt(2)/2,sqrt(2)/2]));
|
||||
assert(approx(spherical_to_xyz([100,-90,45]),100*[0,-sqrt(2)/2,sqrt(2)/2]));
|
||||
assert(approx(spherical_to_xyz([100,90,90]),100*[0,1,0]));
|
||||
assert(approx(spherical_to_xyz([100,-90,90]),100*[0,-1,0]));
|
||||
assert(approx(spherical_to_xyz([100,180,90]),100*[-1,0,0]));
|
||||
assert(approx(spherical_to_xyz([100,0,90]),100*[1,0,0]));
|
||||
assert(approx(spherical_to_xyz([100,0,0]),100*[0,0,1]));
|
||||
assert(approx(spherical_to_xyz([100,0,180]),100*[0,0,-1]));
|
||||
}
|
||||
test_spherical_to_xyz();
|
||||
|
||||
|
||||
module test_xyz_to_spherical() {
|
||||
assert(approx(xyz_to_spherical(0, 100*sqrt(2)/2,100*sqrt(2)/2),[100, 90,45]));
|
||||
assert(approx(xyz_to_spherical(0,-100*sqrt(2)/2,100*sqrt(2)/2),[100,-90,45]));
|
||||
assert(approx(xyz_to_spherical( 0, 100, 0),[100, 90, 90]));
|
||||
assert(approx(xyz_to_spherical( 0,-100, 0),[100,-90, 90]));
|
||||
assert(approx(xyz_to_spherical(-100, 0, 0),[100,180, 90]));
|
||||
assert(approx(xyz_to_spherical( 100, 0, 0),[100, 0, 90]));
|
||||
assert(approx(xyz_to_spherical( 0, 0, 100),[100, 0, 0]));
|
||||
assert(approx(xyz_to_spherical( 0, 0,-100),[100, 0,180]));
|
||||
assert(approx(xyz_to_spherical([0, 100*sqrt(2)/2,100*sqrt(2)/2]),[100, 90,45]));
|
||||
assert(approx(xyz_to_spherical([0,-100*sqrt(2)/2,100*sqrt(2)/2]),[100,-90,45]));
|
||||
assert(approx(xyz_to_spherical([ 0, 100, 0]),[100, 90, 90]));
|
||||
assert(approx(xyz_to_spherical([ 0,-100, 0]),[100,-90, 90]));
|
||||
assert(approx(xyz_to_spherical([-100, 0, 0]),[100,180, 90]));
|
||||
assert(approx(xyz_to_spherical([ 100, 0, 0]),[100, 0, 90]));
|
||||
assert(approx(xyz_to_spherical([ 0, 0, 100]),[100, 0, 0]));
|
||||
assert(approx(xyz_to_spherical([ 0, 0,-100]),[100, 0,180]));
|
||||
assert(approx(xyz_to_spherical(0, 100*sqrt(2)/2,100*sqrt(2)/2),[100, 90,45]));
|
||||
assert(approx(xyz_to_spherical(0,-100*sqrt(2)/2,100*sqrt(2)/2),[100,-90,45]));
|
||||
assert(approx(xyz_to_spherical( 0, 100, 0),[100, 90, 90]));
|
||||
assert(approx(xyz_to_spherical( 0,-100, 0),[100,-90, 90]));
|
||||
assert(approx(xyz_to_spherical(-100, 0, 0),[100,180, 90]));
|
||||
assert(approx(xyz_to_spherical( 100, 0, 0),[100, 0, 90]));
|
||||
assert(approx(xyz_to_spherical( 0, 0, 100),[100, 0, 0]));
|
||||
assert(approx(xyz_to_spherical( 0, 0,-100),[100, 0,180]));
|
||||
assert(approx(xyz_to_spherical([0, 100*sqrt(2)/2,100*sqrt(2)/2]),[100, 90,45]));
|
||||
assert(approx(xyz_to_spherical([0,-100*sqrt(2)/2,100*sqrt(2)/2]),[100,-90,45]));
|
||||
assert(approx(xyz_to_spherical([ 0, 100, 0]),[100, 90, 90]));
|
||||
assert(approx(xyz_to_spherical([ 0,-100, 0]),[100,-90, 90]));
|
||||
assert(approx(xyz_to_spherical([-100, 0, 0]),[100,180, 90]));
|
||||
assert(approx(xyz_to_spherical([ 100, 0, 0]),[100, 0, 90]));
|
||||
assert(approx(xyz_to_spherical([ 0, 0, 100]),[100, 0, 0]));
|
||||
assert(approx(xyz_to_spherical([ 0, 0,-100]),[100, 0,180]));
|
||||
}
|
||||
test_xyz_to_spherical();
|
||||
|
||||
|
||||
module test_altaz_to_xyz() {
|
||||
assert(approx(altaz_to_xyz( 0, 0,100),[ 0,100, 0]));
|
||||
assert(approx(altaz_to_xyz( 90, 0,100),[ 0, 0, 100]));
|
||||
assert(approx(altaz_to_xyz(-90, 0,100),[ 0, 0,-100]));
|
||||
assert(approx(altaz_to_xyz( 0, 90,100),[ 100, 0, 0]));
|
||||
assert(approx(altaz_to_xyz( 0,-90,100),[-100, 0, 0]));
|
||||
assert(approx(altaz_to_xyz( 45, 90,100),[100*sqrt(2)/2,0,100*sqrt(2)/2]));
|
||||
assert(approx(altaz_to_xyz(-45, 90,100),[100*sqrt(2)/2,0,-100*sqrt(2)/2]));
|
||||
assert(approx(altaz_to_xyz([ 0, 0,100]),[ 0,100, 0]));
|
||||
assert(approx(altaz_to_xyz([ 90, 0,100]),[ 0, 0, 100]));
|
||||
assert(approx(altaz_to_xyz([-90, 0,100]),[ 0, 0,-100]));
|
||||
assert(approx(altaz_to_xyz([ 0, 90,100]),[ 100, 0, 0]));
|
||||
assert(approx(altaz_to_xyz([ 0,-90,100]),[-100, 0, 0]));
|
||||
assert(approx(altaz_to_xyz([ 45, 90,100]),[100*sqrt(2)/2,0,100*sqrt(2)/2]));
|
||||
assert(approx(altaz_to_xyz([-45, 90,100]),[100*sqrt(2)/2,0,-100*sqrt(2)/2]));
|
||||
assert(approx(altaz_to_xyz( 0, 0,100),[ 0,100, 0]));
|
||||
assert(approx(altaz_to_xyz( 90, 0,100),[ 0, 0, 100]));
|
||||
assert(approx(altaz_to_xyz(-90, 0,100),[ 0, 0,-100]));
|
||||
assert(approx(altaz_to_xyz( 0, 90,100),[ 100, 0, 0]));
|
||||
assert(approx(altaz_to_xyz( 0,-90,100),[-100, 0, 0]));
|
||||
assert(approx(altaz_to_xyz( 45, 90,100),[100*sqrt(2)/2,0,100*sqrt(2)/2]));
|
||||
assert(approx(altaz_to_xyz(-45, 90,100),[100*sqrt(2)/2,0,-100*sqrt(2)/2]));
|
||||
assert(approx(altaz_to_xyz([ 0, 0,100]),[ 0,100, 0]));
|
||||
assert(approx(altaz_to_xyz([ 90, 0,100]),[ 0, 0, 100]));
|
||||
assert(approx(altaz_to_xyz([-90, 0,100]),[ 0, 0,-100]));
|
||||
assert(approx(altaz_to_xyz([ 0, 90,100]),[ 100, 0, 0]));
|
||||
assert(approx(altaz_to_xyz([ 0,-90,100]),[-100, 0, 0]));
|
||||
assert(approx(altaz_to_xyz([ 45, 90,100]),[100*sqrt(2)/2,0,100*sqrt(2)/2]));
|
||||
assert(approx(altaz_to_xyz([-45, 90,100]),[100*sqrt(2)/2,0,-100*sqrt(2)/2]));
|
||||
}
|
||||
test_altaz_to_xyz();
|
||||
|
||||
|
||||
module test_xyz_to_altaz() {
|
||||
assert(approx(xyz_to_altaz( 0,100, 0),[ 0, 0,100]));
|
||||
assert(approx(xyz_to_altaz( 0, 0, 100),[ 90, 0,100]));
|
||||
assert(approx(xyz_to_altaz( 0, 0,-100),[-90, 0,100]));
|
||||
assert(approx(xyz_to_altaz( 100, 0, 0),[ 0, 90,100]));
|
||||
assert(approx(xyz_to_altaz(-100, 0, 0),[ 0,-90,100]));
|
||||
assert(approx(xyz_to_altaz(100*sqrt(2)/2,0,100*sqrt(2)/2),[ 45, 90,100]));
|
||||
assert(approx(xyz_to_altaz(100*sqrt(2)/2,0,-100*sqrt(2)/2),[-45, 90,100]));
|
||||
assert(approx(xyz_to_altaz([ 0,100, 0]),[ 0, 0,100]));
|
||||
assert(approx(xyz_to_altaz([ 0, 0, 100]),[ 90, 0,100]));
|
||||
assert(approx(xyz_to_altaz([ 0, 0,-100]),[-90, 0,100]));
|
||||
assert(approx(xyz_to_altaz([ 100, 0, 0]),[ 0, 90,100]));
|
||||
assert(approx(xyz_to_altaz([-100, 0, 0]),[ 0,-90,100]));
|
||||
assert(approx(xyz_to_altaz([100*sqrt(2)/2,0,100*sqrt(2)/2]),[ 45, 90,100]));
|
||||
assert(approx(xyz_to_altaz([100*sqrt(2)/2,0,-100*sqrt(2)/2]),[-45, 90,100]));
|
||||
assert(approx(xyz_to_altaz( 0,100, 0),[ 0, 0,100]));
|
||||
assert(approx(xyz_to_altaz( 0, 0, 100),[ 90, 0,100]));
|
||||
assert(approx(xyz_to_altaz( 0, 0,-100),[-90, 0,100]));
|
||||
assert(approx(xyz_to_altaz( 100, 0, 0),[ 0, 90,100]));
|
||||
assert(approx(xyz_to_altaz(-100, 0, 0),[ 0,-90,100]));
|
||||
assert(approx(xyz_to_altaz(100*sqrt(2)/2,0,100*sqrt(2)/2),[ 45, 90,100]));
|
||||
assert(approx(xyz_to_altaz(100*sqrt(2)/2,0,-100*sqrt(2)/2),[-45, 90,100]));
|
||||
assert(approx(xyz_to_altaz([ 0,100, 0]),[ 0, 0,100]));
|
||||
assert(approx(xyz_to_altaz([ 0, 0, 100]),[ 90, 0,100]));
|
||||
assert(approx(xyz_to_altaz([ 0, 0,-100]),[-90, 0,100]));
|
||||
assert(approx(xyz_to_altaz([ 100, 0, 0]),[ 0, 90,100]));
|
||||
assert(approx(xyz_to_altaz([-100, 0, 0]),[ 0,-90,100]));
|
||||
assert(approx(xyz_to_altaz([100*sqrt(2)/2,0,100*sqrt(2)/2]),[ 45, 90,100]));
|
||||
assert(approx(xyz_to_altaz([100*sqrt(2)/2,0,-100*sqrt(2)/2]),[-45, 90,100]));
|
||||
}
|
||||
test_xyz_to_altaz();
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -3,12 +3,12 @@ include <BOSL2/cubetruss.scad>
|
||||
|
||||
|
||||
module test_cubetruss_dist() {
|
||||
assert(cubetruss_dist(5,1,size=30,strut=3) == 138);
|
||||
assert(cubetruss_dist(3,2,size=30,strut=3) == 87);
|
||||
assert(cubetruss_dist(5,1,size=20,strut=2) == 92);
|
||||
assert(cubetruss_dist(3,2,size=20,strut=2) == 58);
|
||||
assert(cubetruss_dist(5,1,size=30,strut=3) == 138);
|
||||
assert(cubetruss_dist(3,2,size=30,strut=3) == 87);
|
||||
assert(cubetruss_dist(5,1,size=20,strut=2) == 92);
|
||||
assert(cubetruss_dist(3,2,size=20,strut=2) == 58);
|
||||
}
|
||||
test_cubetruss_dist();
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -2,103 +2,103 @@ include <BOSL2/std.scad>
|
||||
|
||||
|
||||
module test_is_edge_array() {
|
||||
assert(is_edge_array([[0,0,0,0],[0,0,0,0],[0,0,0,0]]));
|
||||
assert(is_edge_array([[1,1,1,1],[1,1,1,1],[1,1,1,1]]));
|
||||
assert(!is_edge_array([[1,1,1],[1,1,1],[1,1,1]]));
|
||||
assert(!is_edge_array([[1,1,1,1,1],[1,1,1,1,1],[1,1,1,1,1]]));
|
||||
assert(!is_edge_array([[1,1,1,1],[1,1,1,1]]));
|
||||
assert(!is_edge_array([1,1,1,1]));
|
||||
assert(!is_edge_array("foo"));
|
||||
assert(!is_edge_array(42));
|
||||
assert(!is_edge_array(true));
|
||||
assert(is_edge_array(edges(["X","Y"])));
|
||||
assert(is_edge_array([[0,0,0,0],[0,0,0,0],[0,0,0,0]]));
|
||||
assert(is_edge_array([[1,1,1,1],[1,1,1,1],[1,1,1,1]]));
|
||||
assert(!is_edge_array([[1,1,1],[1,1,1],[1,1,1]]));
|
||||
assert(!is_edge_array([[1,1,1,1,1],[1,1,1,1,1],[1,1,1,1,1]]));
|
||||
assert(!is_edge_array([[1,1,1,1],[1,1,1,1]]));
|
||||
assert(!is_edge_array([1,1,1,1]));
|
||||
assert(!is_edge_array("foo"));
|
||||
assert(!is_edge_array(42));
|
||||
assert(!is_edge_array(true));
|
||||
assert(is_edge_array(edges(["X","Y"])));
|
||||
}
|
||||
test_is_edge_array();
|
||||
|
||||
|
||||
module test__edge_set() {
|
||||
// Edge set pass through
|
||||
assert(_edge_set([[1,1,1,1],[0,1,0,1],[0,0,0,0]]) == [[1,1,1,1],[0,1,0,1],[0,0,0,0]]);
|
||||
// Edge set pass through
|
||||
assert(_edge_set([[1,1,1,1],[0,1,0,1],[0,0,0,0]]) == [[1,1,1,1],[0,1,0,1],[0,0,0,0]]);
|
||||
|
||||
// Vectors towards corners
|
||||
assert(_edge_set([-1,-1,-1]) == [[1,0,0,0],[1,0,0,0],[1,0,0,0]]);
|
||||
assert(_edge_set([-1,-1, 1]) == [[0,0,1,0],[0,0,1,0],[1,0,0,0]]);
|
||||
assert(_edge_set([-1, 1,-1]) == [[0,1,0,0],[1,0,0,0],[0,0,1,0]]);
|
||||
assert(_edge_set([-1, 1, 1]) == [[0,0,0,1],[0,0,1,0],[0,0,1,0]]);
|
||||
assert(_edge_set([ 1,-1,-1]) == [[1,0,0,0],[0,1,0,0],[0,1,0,0]]);
|
||||
assert(_edge_set([ 1,-1, 1]) == [[0,0,1,0],[0,0,0,1],[0,1,0,0]]);
|
||||
assert(_edge_set([ 1, 1,-1]) == [[0,1,0,0],[0,1,0,0],[0,0,0,1]]);
|
||||
assert(_edge_set([ 1, 1, 1]) == [[0,0,0,1],[0,0,0,1],[0,0,0,1]]);
|
||||
// Vectors towards corners
|
||||
assert(_edge_set([-1,-1,-1]) == [[1,0,0,0],[1,0,0,0],[1,0,0,0]]);
|
||||
assert(_edge_set([-1,-1, 1]) == [[0,0,1,0],[0,0,1,0],[1,0,0,0]]);
|
||||
assert(_edge_set([-1, 1,-1]) == [[0,1,0,0],[1,0,0,0],[0,0,1,0]]);
|
||||
assert(_edge_set([-1, 1, 1]) == [[0,0,0,1],[0,0,1,0],[0,0,1,0]]);
|
||||
assert(_edge_set([ 1,-1,-1]) == [[1,0,0,0],[0,1,0,0],[0,1,0,0]]);
|
||||
assert(_edge_set([ 1,-1, 1]) == [[0,0,1,0],[0,0,0,1],[0,1,0,0]]);
|
||||
assert(_edge_set([ 1, 1,-1]) == [[0,1,0,0],[0,1,0,0],[0,0,0,1]]);
|
||||
assert(_edge_set([ 1, 1, 1]) == [[0,0,0,1],[0,0,0,1],[0,0,0,1]]);
|
||||
|
||||
// Vectors towards edges
|
||||
assert(_edge_set([ 0,-1,-1]) == [[1,0,0,0],[0,0,0,0],[0,0,0,0]]);
|
||||
assert(_edge_set([ 0, 1,-1]) == [[0,1,0,0],[0,0,0,0],[0,0,0,0]]);
|
||||
assert(_edge_set([ 0,-1, 1]) == [[0,0,1,0],[0,0,0,0],[0,0,0,0]]);
|
||||
assert(_edge_set([ 0, 1, 1]) == [[0,0,0,1],[0,0,0,0],[0,0,0,0]]);
|
||||
assert(_edge_set([-1, 0,-1]) == [[0,0,0,0],[1,0,0,0],[0,0,0,0]]);
|
||||
assert(_edge_set([ 1, 0,-1]) == [[0,0,0,0],[0,1,0,0],[0,0,0,0]]);
|
||||
assert(_edge_set([-1, 0, 1]) == [[0,0,0,0],[0,0,1,0],[0,0,0,0]]);
|
||||
assert(_edge_set([ 1, 0, 1]) == [[0,0,0,0],[0,0,0,1],[0,0,0,0]]);
|
||||
assert(_edge_set([-1,-1, 0]) == [[0,0,0,0],[0,0,0,0],[1,0,0,0]]);
|
||||
assert(_edge_set([ 1,-1, 0]) == [[0,0,0,0],[0,0,0,0],[0,1,0,0]]);
|
||||
assert(_edge_set([-1, 1, 0]) == [[0,0,0,0],[0,0,0,0],[0,0,1,0]]);
|
||||
assert(_edge_set([ 1, 1, 0]) == [[0,0,0,0],[0,0,0,0],[0,0,0,1]]);
|
||||
// Vectors towards edges
|
||||
assert(_edge_set([ 0,-1,-1]) == [[1,0,0,0],[0,0,0,0],[0,0,0,0]]);
|
||||
assert(_edge_set([ 0, 1,-1]) == [[0,1,0,0],[0,0,0,0],[0,0,0,0]]);
|
||||
assert(_edge_set([ 0,-1, 1]) == [[0,0,1,0],[0,0,0,0],[0,0,0,0]]);
|
||||
assert(_edge_set([ 0, 1, 1]) == [[0,0,0,1],[0,0,0,0],[0,0,0,0]]);
|
||||
assert(_edge_set([-1, 0,-1]) == [[0,0,0,0],[1,0,0,0],[0,0,0,0]]);
|
||||
assert(_edge_set([ 1, 0,-1]) == [[0,0,0,0],[0,1,0,0],[0,0,0,0]]);
|
||||
assert(_edge_set([-1, 0, 1]) == [[0,0,0,0],[0,0,1,0],[0,0,0,0]]);
|
||||
assert(_edge_set([ 1, 0, 1]) == [[0,0,0,0],[0,0,0,1],[0,0,0,0]]);
|
||||
assert(_edge_set([-1,-1, 0]) == [[0,0,0,0],[0,0,0,0],[1,0,0,0]]);
|
||||
assert(_edge_set([ 1,-1, 0]) == [[0,0,0,0],[0,0,0,0],[0,1,0,0]]);
|
||||
assert(_edge_set([-1, 1, 0]) == [[0,0,0,0],[0,0,0,0],[0,0,1,0]]);
|
||||
assert(_edge_set([ 1, 1, 0]) == [[0,0,0,0],[0,0,0,0],[0,0,0,1]]);
|
||||
|
||||
// Vectors towards faces
|
||||
assert(_edge_set([ 0, 0,-1]) == [[1,1,0,0],[1,1,0,0],[0,0,0,0]]);
|
||||
assert(_edge_set([ 0, 0, 1]) == [[0,0,1,1],[0,0,1,1],[0,0,0,0]]);
|
||||
assert(_edge_set([ 0,-1, 0]) == [[1,0,1,0],[0,0,0,0],[1,1,0,0]]);
|
||||
assert(_edge_set([ 0, 1, 0]) == [[0,1,0,1],[0,0,0,0],[0,0,1,1]]);
|
||||
assert(_edge_set([-1, 0, 0]) == [[0,0,0,0],[1,0,1,0],[1,0,1,0]]);
|
||||
assert(_edge_set([ 1, 0, 0]) == [[0,0,0,0],[0,1,0,1],[0,1,0,1]]);
|
||||
// Vectors towards faces
|
||||
assert(_edge_set([ 0, 0,-1]) == [[1,1,0,0],[1,1,0,0],[0,0,0,0]]);
|
||||
assert(_edge_set([ 0, 0, 1]) == [[0,0,1,1],[0,0,1,1],[0,0,0,0]]);
|
||||
assert(_edge_set([ 0,-1, 0]) == [[1,0,1,0],[0,0,0,0],[1,1,0,0]]);
|
||||
assert(_edge_set([ 0, 1, 0]) == [[0,1,0,1],[0,0,0,0],[0,0,1,1]]);
|
||||
assert(_edge_set([-1, 0, 0]) == [[0,0,0,0],[1,0,1,0],[1,0,1,0]]);
|
||||
assert(_edge_set([ 1, 0, 0]) == [[0,0,0,0],[0,1,0,1],[0,1,0,1]]);
|
||||
|
||||
// Named edge sets
|
||||
assert(_edge_set("X") == [[1,1,1,1],[0,0,0,0],[0,0,0,0]]);
|
||||
assert(_edge_set("Y") == [[0,0,0,0],[1,1,1,1],[0,0,0,0]]);
|
||||
assert(_edge_set("Z") == [[0,0,0,0],[0,0,0,0],[1,1,1,1]]);
|
||||
assert(_edge_set("NONE") == [[0,0,0,0],[0,0,0,0],[0,0,0,0]]);
|
||||
assert(_edge_set("ALL") == [[1,1,1,1],[1,1,1,1],[1,1,1,1]]);
|
||||
// Named edge sets
|
||||
assert(_edge_set("X") == [[1,1,1,1],[0,0,0,0],[0,0,0,0]]);
|
||||
assert(_edge_set("Y") == [[0,0,0,0],[1,1,1,1],[0,0,0,0]]);
|
||||
assert(_edge_set("Z") == [[0,0,0,0],[0,0,0,0],[1,1,1,1]]);
|
||||
assert(_edge_set("NONE") == [[0,0,0,0],[0,0,0,0],[0,0,0,0]]);
|
||||
assert(_edge_set("ALL") == [[1,1,1,1],[1,1,1,1],[1,1,1,1]]);
|
||||
}
|
||||
test__edge_set();
|
||||
|
||||
|
||||
module test_normalize_edges() {
|
||||
assert(normalize_edges([[-2,-2,-2,-2],[-2,-2,-2,-2],[-2,-2,-2,-2]]) == [[0,0,0,0],[0,0,0,0],[0,0,0,0]]);
|
||||
assert(normalize_edges([[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1]]) == [[0,0,0,0],[0,0,0,0],[0,0,0,0]]);
|
||||
assert(normalize_edges([[0,0,0,0],[0,0,0,0],[0,0,0,0]]) == [[0,0,0,0],[0,0,0,0],[0,0,0,0]]);
|
||||
assert(normalize_edges([[1,1,1,1],[1,1,1,1],[1,1,1,1]]) == [[1,1,1,1],[1,1,1,1],[1,1,1,1]]);
|
||||
assert(normalize_edges([[2,2,2,2],[2,2,2,2],[2,2,2,2]]) == [[1,1,1,1],[1,1,1,1],[1,1,1,1]]);
|
||||
assert(normalize_edges([[-2,-2,-2,-2],[-2,-2,-2,-2],[-2,-2,-2,-2]]) == [[0,0,0,0],[0,0,0,0],[0,0,0,0]]);
|
||||
assert(normalize_edges([[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1]]) == [[0,0,0,0],[0,0,0,0],[0,0,0,0]]);
|
||||
assert(normalize_edges([[0,0,0,0],[0,0,0,0],[0,0,0,0]]) == [[0,0,0,0],[0,0,0,0],[0,0,0,0]]);
|
||||
assert(normalize_edges([[1,1,1,1],[1,1,1,1],[1,1,1,1]]) == [[1,1,1,1],[1,1,1,1],[1,1,1,1]]);
|
||||
assert(normalize_edges([[2,2,2,2],[2,2,2,2],[2,2,2,2]]) == [[1,1,1,1],[1,1,1,1],[1,1,1,1]]);
|
||||
}
|
||||
test_normalize_edges();
|
||||
|
||||
|
||||
module test_edges() {
|
||||
assert(edges("X")==[[1,1,1,1],[0,0,0,0],[0,0,0,0]]);
|
||||
assert(edges("Y")==[[0,0,0,0],[1,1,1,1],[0,0,0,0]]);
|
||||
assert(edges("Z")==[[0,0,0,0],[0,0,0,0],[1,1,1,1]]);
|
||||
assert(edges(["X"])==[[1,1,1,1],[0,0,0,0],[0,0,0,0]]);
|
||||
assert(edges(["Y"])==[[0,0,0,0],[1,1,1,1],[0,0,0,0]]);
|
||||
assert(edges(["Z"])==[[0,0,0,0],[0,0,0,0],[1,1,1,1]]);
|
||||
assert(edges(["X","Y"])==[[1,1,1,1],[1,1,1,1],[0,0,0,0]]);
|
||||
assert(edges(["X","Z"])==[[1,1,1,1],[0,0,0,0],[1,1,1,1]]);
|
||||
assert(edges(["Y","Z"])==[[0,0,0,0],[1,1,1,1],[1,1,1,1]]);
|
||||
assert(edges("ALL",except="X")==[[0,0,0,0],[1,1,1,1],[1,1,1,1]]);
|
||||
assert(edges("ALL",except="Y")==[[1,1,1,1],[0,0,0,0],[1,1,1,1]]);
|
||||
assert(edges("ALL",except="Z")==[[1,1,1,1],[1,1,1,1],[0,0,0,0]]);
|
||||
assert(edges(["Y","Z"],except=[FRONT+RIGHT,FRONT+LEFT])==[[0,0,0,0],[1,1,1,1],[0,0,1,1]]);
|
||||
assert(edges("X")==[[1,1,1,1],[0,0,0,0],[0,0,0,0]]);
|
||||
assert(edges("Y")==[[0,0,0,0],[1,1,1,1],[0,0,0,0]]);
|
||||
assert(edges("Z")==[[0,0,0,0],[0,0,0,0],[1,1,1,1]]);
|
||||
assert(edges(["X"])==[[1,1,1,1],[0,0,0,0],[0,0,0,0]]);
|
||||
assert(edges(["Y"])==[[0,0,0,0],[1,1,1,1],[0,0,0,0]]);
|
||||
assert(edges(["Z"])==[[0,0,0,0],[0,0,0,0],[1,1,1,1]]);
|
||||
assert(edges(["X","Y"])==[[1,1,1,1],[1,1,1,1],[0,0,0,0]]);
|
||||
assert(edges(["X","Z"])==[[1,1,1,1],[0,0,0,0],[1,1,1,1]]);
|
||||
assert(edges(["Y","Z"])==[[0,0,0,0],[1,1,1,1],[1,1,1,1]]);
|
||||
assert(edges("ALL",except="X")==[[0,0,0,0],[1,1,1,1],[1,1,1,1]]);
|
||||
assert(edges("ALL",except="Y")==[[1,1,1,1],[0,0,0,0],[1,1,1,1]]);
|
||||
assert(edges("ALL",except="Z")==[[1,1,1,1],[1,1,1,1],[0,0,0,0]]);
|
||||
assert(edges(["Y","Z"],except=[FRONT+RIGHT,FRONT+LEFT])==[[0,0,0,0],[1,1,1,1],[0,0,1,1]]);
|
||||
}
|
||||
test_edges();
|
||||
|
||||
|
||||
module test_corner_edge_count() {
|
||||
edges = edges([TOP,FRONT+RIGHT]);
|
||||
assert(corner_edge_count(edges,TOP+FRONT+RIGHT) == 3);
|
||||
assert(corner_edge_count(edges,TOP+FRONT+LEFT) == 2);
|
||||
assert(corner_edge_count(edges,BOTTOM+FRONT+RIGHT) == 1);
|
||||
assert(corner_edge_count(edges,BOTTOM+FRONT+LEFT) == 0);
|
||||
edges = edges([TOP,FRONT+RIGHT]);
|
||||
assert(corner_edge_count(edges,TOP+FRONT+RIGHT) == 3);
|
||||
assert(corner_edge_count(edges,TOP+FRONT+LEFT) == 2);
|
||||
assert(corner_edge_count(edges,BOTTOM+FRONT+RIGHT) == 1);
|
||||
assert(corner_edge_count(edges,BOTTOM+FRONT+LEFT) == 0);
|
||||
}
|
||||
test_corner_edge_count();
|
||||
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -8,4 +8,4 @@ module test_deprecate() {}
|
||||
module test_deprecate_argument() {}
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -3,377 +3,377 @@ include <BOSL2/std.scad>
|
||||
// Simple Calculations
|
||||
|
||||
module test_quant() {
|
||||
assert(quant(-4,3) == -3);
|
||||
assert(quant(-3,3) == -3);
|
||||
assert(quant(-2,3) == -3);
|
||||
assert(quant(-1,3) == 0);
|
||||
assert(quant(0,3) == 0);
|
||||
assert(quant(1,3) == 0);
|
||||
assert(quant(2,3) == 3);
|
||||
assert(quant(3,3) == 3);
|
||||
assert(quant(4,3) == 3);
|
||||
assert(quant(7,3) == 6);
|
||||
assert(quant([12,13,13.1,14,14.1,15,16],4) == [12,12,12,16,16,16,16]);
|
||||
assert(quant([9,10,10.4,10.5,11,12],3) == [9,9,9,12,12,12]);
|
||||
assert(quant([[9,10,10.4],[10.5,11,12]],3) == [[9,9,9],[12,12,12]]);
|
||||
assert(quant(-4,3) == -3);
|
||||
assert(quant(-3,3) == -3);
|
||||
assert(quant(-2,3) == -3);
|
||||
assert(quant(-1,3) == 0);
|
||||
assert(quant(0,3) == 0);
|
||||
assert(quant(1,3) == 0);
|
||||
assert(quant(2,3) == 3);
|
||||
assert(quant(3,3) == 3);
|
||||
assert(quant(4,3) == 3);
|
||||
assert(quant(7,3) == 6);
|
||||
assert(quant([12,13,13.1,14,14.1,15,16],4) == [12,12,12,16,16,16,16]);
|
||||
assert(quant([9,10,10.4,10.5,11,12],3) == [9,9,9,12,12,12]);
|
||||
assert(quant([[9,10,10.4],[10.5,11,12]],3) == [[9,9,9],[12,12,12]]);
|
||||
}
|
||||
test_quant();
|
||||
|
||||
|
||||
module test_quantdn() {
|
||||
assert(quantdn(-4,3) == -6);
|
||||
assert(quantdn(-3,3) == -3);
|
||||
assert(quantdn(-2,3) == -3);
|
||||
assert(quantdn(-1,3) == -3);
|
||||
assert(quantdn(0,3) == 0);
|
||||
assert(quantdn(1,3) == 0);
|
||||
assert(quantdn(2,3) == 0);
|
||||
assert(quantdn(3,3) == 3);
|
||||
assert(quantdn(4,3) == 3);
|
||||
assert(quantdn(7,3) == 6);
|
||||
assert(quantdn([12,13,13.1,14,14.1,15,16],4) == [12,12,12,12,12,12,16]);
|
||||
assert(quantdn([9,10,10.4,10.5,11,12],3) == [9,9,9,9,9,12]);
|
||||
assert(quantdn([[9,10,10.4],[10.5,11,12]],3) == [[9,9,9],[9,9,12]]);
|
||||
assert(quantdn(-4,3) == -6);
|
||||
assert(quantdn(-3,3) == -3);
|
||||
assert(quantdn(-2,3) == -3);
|
||||
assert(quantdn(-1,3) == -3);
|
||||
assert(quantdn(0,3) == 0);
|
||||
assert(quantdn(1,3) == 0);
|
||||
assert(quantdn(2,3) == 0);
|
||||
assert(quantdn(3,3) == 3);
|
||||
assert(quantdn(4,3) == 3);
|
||||
assert(quantdn(7,3) == 6);
|
||||
assert(quantdn([12,13,13.1,14,14.1,15,16],4) == [12,12,12,12,12,12,16]);
|
||||
assert(quantdn([9,10,10.4,10.5,11,12],3) == [9,9,9,9,9,12]);
|
||||
assert(quantdn([[9,10,10.4],[10.5,11,12]],3) == [[9,9,9],[9,9,12]]);
|
||||
}
|
||||
test_quantdn();
|
||||
|
||||
|
||||
module test_quantup() {
|
||||
assert(quantup(-4,3) == -3);
|
||||
assert(quantup(-3,3) == -3);
|
||||
assert(quantup(-2,3) == 0);
|
||||
assert(quantup(-1,3) == 0);
|
||||
assert(quantup(0,3) == 0);
|
||||
assert(quantup(1,3) == 3);
|
||||
assert(quantup(2,3) == 3);
|
||||
assert(quantup(3,3) == 3);
|
||||
assert(quantup(4,3) == 6);
|
||||
assert(quantup(7,3) == 9);
|
||||
assert(quantup([12,13,13.1,14,14.1,15,16],4) == [12,16,16,16,16,16,16]);
|
||||
assert(quantup([9,10,10.4,10.5,11,12],3) == [9,12,12,12,12,12]);
|
||||
assert(quantup([[9,10,10.4],[10.5,11,12]],3) == [[9,12,12],[12,12,12]]);
|
||||
assert(quantup(-4,3) == -3);
|
||||
assert(quantup(-3,3) == -3);
|
||||
assert(quantup(-2,3) == 0);
|
||||
assert(quantup(-1,3) == 0);
|
||||
assert(quantup(0,3) == 0);
|
||||
assert(quantup(1,3) == 3);
|
||||
assert(quantup(2,3) == 3);
|
||||
assert(quantup(3,3) == 3);
|
||||
assert(quantup(4,3) == 6);
|
||||
assert(quantup(7,3) == 9);
|
||||
assert(quantup([12,13,13.1,14,14.1,15,16],4) == [12,16,16,16,16,16,16]);
|
||||
assert(quantup([9,10,10.4,10.5,11,12],3) == [9,12,12,12,12,12]);
|
||||
assert(quantup([[9,10,10.4],[10.5,11,12]],3) == [[9,12,12],[12,12,12]]);
|
||||
}
|
||||
test_quantup();
|
||||
|
||||
|
||||
module test_constrain() {
|
||||
assert(constrain(-2,-1,1) == -1);
|
||||
assert(constrain(-1.75,-1,1) == -1);
|
||||
assert(constrain(-1,-1,1) == -1);
|
||||
assert(constrain(-0.75,-1,1) == -0.75);
|
||||
assert(constrain(0,-1,1) == 0);
|
||||
assert(constrain(0.75,-1,1) == 0.75);
|
||||
assert(constrain(1,-1,1) == 1);
|
||||
assert(constrain(1.75,-1,1) == 1);
|
||||
assert(constrain(2,-1,1) == 1);
|
||||
assert(constrain(-2,-1,1) == -1);
|
||||
assert(constrain(-1.75,-1,1) == -1);
|
||||
assert(constrain(-1,-1,1) == -1);
|
||||
assert(constrain(-0.75,-1,1) == -0.75);
|
||||
assert(constrain(0,-1,1) == 0);
|
||||
assert(constrain(0.75,-1,1) == 0.75);
|
||||
assert(constrain(1,-1,1) == 1);
|
||||
assert(constrain(1.75,-1,1) == 1);
|
||||
assert(constrain(2,-1,1) == 1);
|
||||
}
|
||||
test_constrain();
|
||||
|
||||
|
||||
module test_approx() {
|
||||
assert(approx(PI, 3.141592653589793236) == true);
|
||||
assert(approx(PI, 3.1415926) == false);
|
||||
assert(approx(PI, 3.1415926, eps=1e-6) == true);
|
||||
assert(approx(-PI, -3.141592653589793236) == true);
|
||||
assert(approx(-PI, -3.1415926) == false);
|
||||
assert(approx(-PI, -3.1415926, eps=1e-6) == true);
|
||||
assert(approx(1/3, 0.3333333333) == true);
|
||||
assert(approx(-1/3, -0.3333333333) == true);
|
||||
assert(approx(10*[cos(30),sin(30)], 10*[sqrt(3)/2, 1/2]) == true);
|
||||
assert(approx(PI, 3.141592653589793236) == true);
|
||||
assert(approx(PI, 3.1415926) == false);
|
||||
assert(approx(PI, 3.1415926, eps=1e-6) == true);
|
||||
assert(approx(-PI, -3.141592653589793236) == true);
|
||||
assert(approx(-PI, -3.1415926) == false);
|
||||
assert(approx(-PI, -3.1415926, eps=1e-6) == true);
|
||||
assert(approx(1/3, 0.3333333333) == true);
|
||||
assert(approx(-1/3, -0.3333333333) == true);
|
||||
assert(approx(10*[cos(30),sin(30)], 10*[sqrt(3)/2, 1/2]) == true);
|
||||
}
|
||||
test_approx();
|
||||
|
||||
|
||||
module test_min_index() {
|
||||
vals = rands(-100,100,100);
|
||||
minval = min(vals);
|
||||
minidx = min_index(vals);
|
||||
assert(vals[minidx] == minval);
|
||||
assert(min_index([3,4,5,6]) == 0);
|
||||
assert(min_index([4,3,5,6]) == 1);
|
||||
assert(min_index([4,5,3,6]) == 2);
|
||||
assert(min_index([4,5,6,3]) == 3);
|
||||
assert(min_index([6,5,4,3]) == 3);
|
||||
assert(min_index([6,3,4,5]) == 1);
|
||||
assert(min_index([-56,72,-874,5]) == 2);
|
||||
vals = rands(-100,100,100);
|
||||
minval = min(vals);
|
||||
minidx = min_index(vals);
|
||||
assert(vals[minidx] == minval);
|
||||
assert(min_index([3,4,5,6]) == 0);
|
||||
assert(min_index([4,3,5,6]) == 1);
|
||||
assert(min_index([4,5,3,6]) == 2);
|
||||
assert(min_index([4,5,6,3]) == 3);
|
||||
assert(min_index([6,5,4,3]) == 3);
|
||||
assert(min_index([6,3,4,5]) == 1);
|
||||
assert(min_index([-56,72,-874,5]) == 2);
|
||||
}
|
||||
test_min_index();
|
||||
|
||||
|
||||
module test_max_index() {
|
||||
vals = rands(-100,100,100);
|
||||
maxval = max(vals);
|
||||
maxidx = max_index(vals);
|
||||
assert(vals[maxidx] == maxval);
|
||||
assert(max_index([3,4,5,6]) == 3);
|
||||
assert(max_index([3,4,6,5]) == 2);
|
||||
assert(max_index([3,6,4,5]) == 1);
|
||||
assert(max_index([6,3,4,5]) == 0);
|
||||
assert(max_index([5,6,4,3]) == 1);
|
||||
assert(max_index([-56,72,-874,5]) == 1);
|
||||
vals = rands(-100,100,100);
|
||||
maxval = max(vals);
|
||||
maxidx = max_index(vals);
|
||||
assert(vals[maxidx] == maxval);
|
||||
assert(max_index([3,4,5,6]) == 3);
|
||||
assert(max_index([3,4,6,5]) == 2);
|
||||
assert(max_index([3,6,4,5]) == 1);
|
||||
assert(max_index([6,3,4,5]) == 0);
|
||||
assert(max_index([5,6,4,3]) == 1);
|
||||
assert(max_index([-56,72,-874,5]) == 1);
|
||||
}
|
||||
test_max_index();
|
||||
|
||||
|
||||
module test_posmod() {
|
||||
assert(posmod(-5,3) == 1);
|
||||
assert(posmod(-4,3) == 2);
|
||||
assert(posmod(-3,3) == 0);
|
||||
assert(posmod(-2,3) == 1);
|
||||
assert(posmod(-1,3) == 2);
|
||||
assert(posmod(0,3) == 0);
|
||||
assert(posmod(1,3) == 1);
|
||||
assert(posmod(2,3) == 2);
|
||||
assert(posmod(3,3) == 0);
|
||||
assert(posmod(-5,3) == 1);
|
||||
assert(posmod(-4,3) == 2);
|
||||
assert(posmod(-3,3) == 0);
|
||||
assert(posmod(-2,3) == 1);
|
||||
assert(posmod(-1,3) == 2);
|
||||
assert(posmod(0,3) == 0);
|
||||
assert(posmod(1,3) == 1);
|
||||
assert(posmod(2,3) == 2);
|
||||
assert(posmod(3,3) == 0);
|
||||
}
|
||||
test_posmod();
|
||||
|
||||
|
||||
module test_modang() {
|
||||
assert(modang(-700) == 20);
|
||||
assert(modang(-270) == 90);
|
||||
assert(modang(-120) == -120);
|
||||
assert(modang(120) == 120);
|
||||
assert(modang(270) == -90);
|
||||
assert(modang(700) == -20);
|
||||
assert(modang(-700) == 20);
|
||||
assert(modang(-270) == 90);
|
||||
assert(modang(-120) == -120);
|
||||
assert(modang(120) == 120);
|
||||
assert(modang(270) == -90);
|
||||
assert(modang(700) == -20);
|
||||
}
|
||||
test_modang();
|
||||
|
||||
|
||||
module test_modrange() {
|
||||
assert(modrange(-5,5,3) == [1,2]);
|
||||
assert(modrange(-1,4,3) == [2,0,1]);
|
||||
assert(modrange(1,8,10,step=2) == [1,3,5,7]);
|
||||
assert(modrange(5,12,10,step=2) == [5,7,9,1]);
|
||||
assert(modrange(-5,5,3) == [1,2]);
|
||||
assert(modrange(-1,4,3) == [2,0,1]);
|
||||
assert(modrange(1,8,10,step=2) == [1,3,5,7]);
|
||||
assert(modrange(5,12,10,step=2) == [5,7,9,1]);
|
||||
}
|
||||
test_modrange();
|
||||
|
||||
|
||||
module test_sqr() {
|
||||
assert(sqr(-3) == 9);
|
||||
assert(sqr(0) == 0);
|
||||
assert(sqr(1) == 1);
|
||||
assert(sqr(2) == 4);
|
||||
assert(sqr(3) == 9);
|
||||
assert(sqr(16) == 256);
|
||||
assert(sqr(-3) == 9);
|
||||
assert(sqr(0) == 0);
|
||||
assert(sqr(1) == 1);
|
||||
assert(sqr(2) == 4);
|
||||
assert(sqr(3) == 9);
|
||||
assert(sqr(16) == 256);
|
||||
}
|
||||
test_sqr();
|
||||
|
||||
|
||||
module test_log2() {
|
||||
assert(log2(0.125) == -3);
|
||||
assert(log2(16) == 4);
|
||||
assert(log2(256) == 8);
|
||||
assert(log2(0.125) == -3);
|
||||
assert(log2(16) == 4);
|
||||
assert(log2(256) == 8);
|
||||
}
|
||||
test_log2();
|
||||
|
||||
|
||||
module test_rand_int() {
|
||||
nums = rand_int(-100,100,1000,seed=2134);
|
||||
assert(len(nums)==1000);
|
||||
for (num = nums) {
|
||||
assert(num>=-100);
|
||||
assert(num<=100);
|
||||
assert(num==floor(num));
|
||||
}
|
||||
nums = rand_int(-100,100,1000,seed=2134);
|
||||
assert(len(nums)==1000);
|
||||
for (num = nums) {
|
||||
assert(num>=-100);
|
||||
assert(num<=100);
|
||||
assert(num==floor(num));
|
||||
}
|
||||
}
|
||||
test_rand_int();
|
||||
|
||||
|
||||
module test_gaussian_rands() {
|
||||
nums1 = gaussian_rands(0,10,1000,seed=2132);
|
||||
nums2 = gaussian_rands(0,10,1000,seed=2130);
|
||||
nums3 = gaussian_rands(0,10,1000,seed=2132);
|
||||
assert(len(nums1)==1000);
|
||||
assert(len(nums2)==1000);
|
||||
assert(len(nums3)==1000);
|
||||
assert(nums1==nums3);
|
||||
assert(nums1!=nums2);
|
||||
nums1 = gaussian_rands(0,10,1000,seed=2132);
|
||||
nums2 = gaussian_rands(0,10,1000,seed=2130);
|
||||
nums3 = gaussian_rands(0,10,1000,seed=2132);
|
||||
assert(len(nums1)==1000);
|
||||
assert(len(nums2)==1000);
|
||||
assert(len(nums3)==1000);
|
||||
assert(nums1==nums3);
|
||||
assert(nums1!=nums2);
|
||||
}
|
||||
test_gaussian_rands();
|
||||
|
||||
|
||||
module test_log_rands() {
|
||||
nums1 = log_rands(0,100,10,1000,seed=2189);
|
||||
nums2 = log_rands(0,100,10,1000,seed=2310);
|
||||
nums3 = log_rands(0,100,10,1000,seed=2189);
|
||||
assert(len(nums1)==1000);
|
||||
assert(len(nums2)==1000);
|
||||
assert(len(nums3)==1000);
|
||||
assert(nums1==nums3);
|
||||
assert(nums1!=nums2);
|
||||
nums1 = log_rands(0,100,10,1000,seed=2189);
|
||||
nums2 = log_rands(0,100,10,1000,seed=2310);
|
||||
nums3 = log_rands(0,100,10,1000,seed=2189);
|
||||
assert(len(nums1)==1000);
|
||||
assert(len(nums2)==1000);
|
||||
assert(len(nums3)==1000);
|
||||
assert(nums1==nums3);
|
||||
assert(nums1!=nums2);
|
||||
}
|
||||
test_log_rands();
|
||||
|
||||
|
||||
module test_segs() {
|
||||
assert(segs(50,$fn=8) == 8);
|
||||
assert(segs(50,$fa=2,$fs=2) == 158);
|
||||
assert(segs(50,$fn=8) == 8);
|
||||
assert(segs(50,$fa=2,$fs=2) == 158);
|
||||
}
|
||||
test_segs();
|
||||
|
||||
|
||||
module test_lerp() {
|
||||
assert(lerp(-20,20,0) == -20);
|
||||
assert(lerp(-20,20,0.25) == -10);
|
||||
assert(lerp(-20,20,0.5) == 0);
|
||||
assert(lerp(-20,20,0.75) == 10);
|
||||
assert(lerp(-20,20,1) == 20);
|
||||
assert(lerp(-20,20,[0,0.25,0.5,0.75,1]) == [-20,-10,0,10,20]);
|
||||
assert(lerp(-20,20,[0:0.25:1]) == [-20,-10,0,10,20]);
|
||||
assert(lerp([10,10],[30,-10],0.5) == [20,0]);
|
||||
assert(lerp(-20,20,0) == -20);
|
||||
assert(lerp(-20,20,0.25) == -10);
|
||||
assert(lerp(-20,20,0.5) == 0);
|
||||
assert(lerp(-20,20,0.75) == 10);
|
||||
assert(lerp(-20,20,1) == 20);
|
||||
assert(lerp(-20,20,[0,0.25,0.5,0.75,1]) == [-20,-10,0,10,20]);
|
||||
assert(lerp(-20,20,[0:0.25:1]) == [-20,-10,0,10,20]);
|
||||
assert(lerp([10,10],[30,-10],0.5) == [20,0]);
|
||||
}
|
||||
test_lerp();
|
||||
|
||||
|
||||
module test_hypot() {
|
||||
assert(hypot(20,30) == norm([20,30]));
|
||||
assert(hypot(20,30) == norm([20,30]));
|
||||
}
|
||||
test_hypot();
|
||||
|
||||
|
||||
module test_sinh() {
|
||||
assert(abs(sinh(-2)+3.6268604078) < EPSILON);
|
||||
assert(abs(sinh(-1)+1.1752011936) < EPSILON);
|
||||
assert(abs(sinh(0)) < EPSILON);
|
||||
assert(abs(sinh(1)-1.1752011936) < EPSILON);
|
||||
assert(abs(sinh(2)-3.6268604078) < EPSILON);
|
||||
assert(abs(sinh(-2)+3.6268604078) < EPSILON);
|
||||
assert(abs(sinh(-1)+1.1752011936) < EPSILON);
|
||||
assert(abs(sinh(0)) < EPSILON);
|
||||
assert(abs(sinh(1)-1.1752011936) < EPSILON);
|
||||
assert(abs(sinh(2)-3.6268604078) < EPSILON);
|
||||
}
|
||||
test_sinh();
|
||||
|
||||
|
||||
module test_cosh() {
|
||||
assert(abs(cosh(-2)-3.7621956911) < EPSILON);
|
||||
assert(abs(cosh(-1)-1.5430806348) < EPSILON);
|
||||
assert(abs(cosh(0)-1) < EPSILON);
|
||||
assert(abs(cosh(1)-1.5430806348) < EPSILON);
|
||||
assert(abs(cosh(2)-3.7621956911) < EPSILON);
|
||||
assert(abs(cosh(-2)-3.7621956911) < EPSILON);
|
||||
assert(abs(cosh(-1)-1.5430806348) < EPSILON);
|
||||
assert(abs(cosh(0)-1) < EPSILON);
|
||||
assert(abs(cosh(1)-1.5430806348) < EPSILON);
|
||||
assert(abs(cosh(2)-3.7621956911) < EPSILON);
|
||||
}
|
||||
test_cosh();
|
||||
|
||||
|
||||
module test_tanh() {
|
||||
assert(abs(tanh(-2)+0.9640275801) < EPSILON);
|
||||
assert(abs(tanh(-1)+0.761594156) < EPSILON);
|
||||
assert(abs(tanh(0)) < EPSILON);
|
||||
assert(abs(tanh(1)-0.761594156) < EPSILON);
|
||||
assert(abs(tanh(2)-0.9640275801) < EPSILON);
|
||||
assert(abs(tanh(-2)+0.9640275801) < EPSILON);
|
||||
assert(abs(tanh(-1)+0.761594156) < EPSILON);
|
||||
assert(abs(tanh(0)) < EPSILON);
|
||||
assert(abs(tanh(1)-0.761594156) < EPSILON);
|
||||
assert(abs(tanh(2)-0.9640275801) < EPSILON);
|
||||
}
|
||||
test_tanh();
|
||||
|
||||
|
||||
module test_asinh() {
|
||||
assert(abs(asinh(sinh(-2))+2) < EPSILON);
|
||||
assert(abs(asinh(sinh(-1))+1) < EPSILON);
|
||||
assert(abs(asinh(sinh(0))) < EPSILON);
|
||||
assert(abs(asinh(sinh(1))-1) < EPSILON);
|
||||
assert(abs(asinh(sinh(2))-2) < EPSILON);
|
||||
assert(abs(asinh(sinh(-2))+2) < EPSILON);
|
||||
assert(abs(asinh(sinh(-1))+1) < EPSILON);
|
||||
assert(abs(asinh(sinh(0))) < EPSILON);
|
||||
assert(abs(asinh(sinh(1))-1) < EPSILON);
|
||||
assert(abs(asinh(sinh(2))-2) < EPSILON);
|
||||
}
|
||||
test_asinh();
|
||||
|
||||
|
||||
module test_acosh() {
|
||||
assert(abs(acosh(cosh(-2))-2) < EPSILON);
|
||||
assert(abs(acosh(cosh(-1))-1) < EPSILON);
|
||||
assert(abs(acosh(cosh(0))) < EPSILON);
|
||||
assert(abs(acosh(cosh(1))-1) < EPSILON);
|
||||
assert(abs(acosh(cosh(2))-2) < EPSILON);
|
||||
assert(abs(acosh(cosh(-2))-2) < EPSILON);
|
||||
assert(abs(acosh(cosh(-1))-1) < EPSILON);
|
||||
assert(abs(acosh(cosh(0))) < EPSILON);
|
||||
assert(abs(acosh(cosh(1))-1) < EPSILON);
|
||||
assert(abs(acosh(cosh(2))-2) < EPSILON);
|
||||
}
|
||||
test_acosh();
|
||||
|
||||
|
||||
module test_atanh() {
|
||||
assert(abs(atanh(tanh(-2))+2) < EPSILON);
|
||||
assert(abs(atanh(tanh(-1))+1) < EPSILON);
|
||||
assert(abs(atanh(tanh(0))) < EPSILON);
|
||||
assert(abs(atanh(tanh(1))-1) < EPSILON);
|
||||
assert(abs(atanh(tanh(2))-2) < EPSILON);
|
||||
assert(abs(atanh(tanh(-2))+2) < EPSILON);
|
||||
assert(abs(atanh(tanh(-1))+1) < EPSILON);
|
||||
assert(abs(atanh(tanh(0))) < EPSILON);
|
||||
assert(abs(atanh(tanh(1))-1) < EPSILON);
|
||||
assert(abs(atanh(tanh(2))-2) < EPSILON);
|
||||
}
|
||||
test_atanh();
|
||||
|
||||
|
||||
module test_sum() {
|
||||
assert(sum([]) == 0);
|
||||
assert(sum([],dflt=undef) == undef);
|
||||
assert(sum([1,2,3]) == 6);
|
||||
assert(sum([-2,-1,0,1,2]) == 0);
|
||||
assert(sum([[1,2,3], [3,4,5], [5,6,7]]) == [9,12,15]);
|
||||
assert(sum([]) == 0);
|
||||
assert(sum([],dflt=undef) == undef);
|
||||
assert(sum([1,2,3]) == 6);
|
||||
assert(sum([-2,-1,0,1,2]) == 0);
|
||||
assert(sum([[1,2,3], [3,4,5], [5,6,7]]) == [9,12,15]);
|
||||
}
|
||||
test_sum();
|
||||
|
||||
|
||||
module test_cumsum() {
|
||||
assert(cumsum([]) == []);
|
||||
assert(cumsum([1,1,1]) == [1,2,3]);
|
||||
assert(cumsum([2,2,2]) == [2,4,6]);
|
||||
assert(cumsum([1,2,3]) == [1,3,6]);
|
||||
assert(cumsum([-2,-1,0,1,2]) == [-2,-3,-3,-2,0]);
|
||||
assert(cumsum([[1,2,3], [3,4,5], [5,6,7]]) == [[1,2,3],[4,6,8],[9,12,15]]);
|
||||
assert(cumsum([]) == []);
|
||||
assert(cumsum([1,1,1]) == [1,2,3]);
|
||||
assert(cumsum([2,2,2]) == [2,4,6]);
|
||||
assert(cumsum([1,2,3]) == [1,3,6]);
|
||||
assert(cumsum([-2,-1,0,1,2]) == [-2,-3,-3,-2,0]);
|
||||
assert(cumsum([[1,2,3], [3,4,5], [5,6,7]]) == [[1,2,3],[4,6,8],[9,12,15]]);
|
||||
}
|
||||
test_cumsum();
|
||||
|
||||
|
||||
module test_sum_of_squares() {
|
||||
assert(sum_of_squares([1,2,3]) == 14);
|
||||
assert(sum_of_squares([1,2,4]) == 21);
|
||||
assert(sum_of_squares([-3,-2,-1]) == 14);
|
||||
assert(sum_of_squares([1,2,3]) == 14);
|
||||
assert(sum_of_squares([1,2,4]) == 21);
|
||||
assert(sum_of_squares([-3,-2,-1]) == 14);
|
||||
}
|
||||
test_sum_of_squares();
|
||||
|
||||
|
||||
module test_sum_of_sines() {
|
||||
assert(sum_of_sines(0, [[3,4,0],[2,2,0]]) == 0);
|
||||
assert(sum_of_sines(45, [[3,4,0],[2,2,0]]) == 2);
|
||||
assert(sum_of_sines(90, [[3,4,0],[2,2,0]]) == 0);
|
||||
assert(sum_of_sines(135, [[3,4,0],[2,2,0]]) == -2);
|
||||
assert(sum_of_sines(180, [[3,4,0],[2,2,0]]) == 0);
|
||||
assert(sum_of_sines(0, [[3,4,0],[2,2,0]]) == 0);
|
||||
assert(sum_of_sines(45, [[3,4,0],[2,2,0]]) == 2);
|
||||
assert(sum_of_sines(90, [[3,4,0],[2,2,0]]) == 0);
|
||||
assert(sum_of_sines(135, [[3,4,0],[2,2,0]]) == -2);
|
||||
assert(sum_of_sines(180, [[3,4,0],[2,2,0]]) == 0);
|
||||
}
|
||||
test_sum_of_sines();
|
||||
|
||||
|
||||
module test_deltas() {
|
||||
assert(deltas([2,5,9,17]) == [3,4,8]);
|
||||
assert(deltas([[1,2,3], [3,6,8], [4,8,11]]) == [[2,4,5], [1,2,3]]);
|
||||
assert(deltas([2,5,9,17]) == [3,4,8]);
|
||||
assert(deltas([[1,2,3], [3,6,8], [4,8,11]]) == [[2,4,5], [1,2,3]]);
|
||||
}
|
||||
test_deltas();
|
||||
|
||||
|
||||
module test_product() {
|
||||
assert(product([2,3,4]) == 24);
|
||||
assert(product([[1,2,3], [3,4,5], [5,6,7]]) == [15, 48, 105]);
|
||||
m1 = [[2,3,4],[4,5,6],[6,7,8]];
|
||||
m2 = [[4,1,2],[3,7,2],[8,7,4]];
|
||||
m3 = [[3,7,8],[9,2,4],[5,8,3]];
|
||||
assert(product([m1,m2,m3]) == m1*m2*m3);
|
||||
assert(product([2,3,4]) == 24);
|
||||
assert(product([[1,2,3], [3,4,5], [5,6,7]]) == [15, 48, 105]);
|
||||
m1 = [[2,3,4],[4,5,6],[6,7,8]];
|
||||
m2 = [[4,1,2],[3,7,2],[8,7,4]];
|
||||
m3 = [[3,7,8],[9,2,4],[5,8,3]];
|
||||
assert(product([m1,m2,m3]) == m1*m2*m3);
|
||||
}
|
||||
test_product();
|
||||
|
||||
|
||||
module test_mean() {
|
||||
assert(mean([2,3,4]) == 3);
|
||||
assert(mean([[1,2,3], [3,4,5], [5,6,7]]) == [3,4,5]);
|
||||
assert(mean([2,3,4]) == 3);
|
||||
assert(mean([[1,2,3], [3,4,5], [5,6,7]]) == [3,4,5]);
|
||||
}
|
||||
test_mean();
|
||||
|
||||
|
||||
module test_det2() {
|
||||
assert(det2([[6,-2], [1,8]]) == 50);
|
||||
assert(det2([[4,7], [3,2]]) == -13);
|
||||
assert(det2([[4,3], [3,4]]) == 7);
|
||||
assert(det2([[6,-2], [1,8]]) == 50);
|
||||
assert(det2([[4,7], [3,2]]) == -13);
|
||||
assert(det2([[4,3], [3,4]]) == 7);
|
||||
}
|
||||
test_det2();
|
||||
|
||||
|
||||
module test_det3() {
|
||||
M = [ [6,4,-2], [1,-2,8], [1,5,7] ];
|
||||
assert(det3(M) == -334);
|
||||
M = [ [6,4,-2], [1,-2,8], [1,5,7] ];
|
||||
assert(det3(M) == -334);
|
||||
}
|
||||
test_det3();
|
||||
|
||||
|
||||
module test_determinant() {
|
||||
M = [ [6,4,-2,9], [1,-2,8,3], [1,5,7,6], [4,2,5,1] ];
|
||||
assert(determinant(M) == 2267);
|
||||
M = [ [6,4,-2,9], [1,-2,8,3], [1,5,7,6], [4,2,5,1] ];
|
||||
assert(determinant(M) == 2267);
|
||||
}
|
||||
test_determinant();
|
||||
|
||||
@ -382,167 +382,167 @@ test_determinant();
|
||||
|
||||
|
||||
module test_compare_vals() {
|
||||
assert(compare_vals(-10,0) < 0);
|
||||
assert(compare_vals(10,0) > 0);
|
||||
assert(compare_vals(10,10) == 0);
|
||||
assert(compare_vals(-10,0) < 0);
|
||||
assert(compare_vals(10,0) > 0);
|
||||
assert(compare_vals(10,10) == 0);
|
||||
|
||||
assert(compare_vals("abc","abcd") < 0);
|
||||
assert(compare_vals("abcd","abc") > 0);
|
||||
assert(compare_vals("abcd","abcd") == 0);
|
||||
assert(compare_vals("abc","abcd") < 0);
|
||||
assert(compare_vals("abcd","abc") > 0);
|
||||
assert(compare_vals("abcd","abcd") == 0);
|
||||
|
||||
assert(compare_vals(false,false) == 0);
|
||||
assert(compare_vals(true,false) > 0);
|
||||
assert(compare_vals(false,true) < 0);
|
||||
assert(compare_vals(true,true) == 0);
|
||||
assert(compare_vals(false,false) == 0);
|
||||
assert(compare_vals(true,false) > 0);
|
||||
assert(compare_vals(false,true) < 0);
|
||||
assert(compare_vals(true,true) == 0);
|
||||
|
||||
assert(compare_vals([2,3,4], [2,3,4,5]) < 0);
|
||||
assert(compare_vals([2,3,4,5], [2,3,4,5]) == 0);
|
||||
assert(compare_vals([2,3,4,5], [2,3,4]) > 0);
|
||||
assert(compare_vals([2,3,4,5], [2,3,5,5]) < 0);
|
||||
assert(compare_vals([[2,3,4,5]], [[2,3,5,5]]) < 0);
|
||||
assert(compare_vals([2,3,4], [2,3,4,5]) < 0);
|
||||
assert(compare_vals([2,3,4,5], [2,3,4,5]) == 0);
|
||||
assert(compare_vals([2,3,4,5], [2,3,4]) > 0);
|
||||
assert(compare_vals([2,3,4,5], [2,3,5,5]) < 0);
|
||||
assert(compare_vals([[2,3,4,5]], [[2,3,5,5]]) < 0);
|
||||
|
||||
assert(compare_vals([[2,3,4],[3,4,5]], [[2,3,4], [3,4,5]]) == 0);
|
||||
assert(compare_vals([[2,3,4],[3,4,5]], [[2,3,4,5], [3,4,5]]) < 0);
|
||||
assert(compare_vals([[2,3,4],[3,4,5]], [[2,3,4], [3,4,5,6]]) < 0);
|
||||
assert(compare_vals([[2,3,4,5],[3,4,5]], [[2,3,4], [3,4,5]]) > 0);
|
||||
assert(compare_vals([[2,3,4],[3,4,5,6]], [[2,3,4], [3,4,5]]) > 0);
|
||||
assert(compare_vals([[2,3,4],[3,5,5]], [[2,3,4], [3,4,5]]) > 0);
|
||||
assert(compare_vals([[2,3,4],[3,4,5]], [[2,3,4], [3,5,5]]) < 0);
|
||||
assert(compare_vals([[2,3,4],[3,4,5]], [[2,3,4], [3,4,5]]) == 0);
|
||||
assert(compare_vals([[2,3,4],[3,4,5]], [[2,3,4,5], [3,4,5]]) < 0);
|
||||
assert(compare_vals([[2,3,4],[3,4,5]], [[2,3,4], [3,4,5,6]]) < 0);
|
||||
assert(compare_vals([[2,3,4,5],[3,4,5]], [[2,3,4], [3,4,5]]) > 0);
|
||||
assert(compare_vals([[2,3,4],[3,4,5,6]], [[2,3,4], [3,4,5]]) > 0);
|
||||
assert(compare_vals([[2,3,4],[3,5,5]], [[2,3,4], [3,4,5]]) > 0);
|
||||
assert(compare_vals([[2,3,4],[3,4,5]], [[2,3,4], [3,5,5]]) < 0);
|
||||
|
||||
assert(compare_vals(undef, undef) == 0);
|
||||
assert(compare_vals(undef, true) < 0);
|
||||
assert(compare_vals(undef, 0) < 0);
|
||||
assert(compare_vals(undef, "foo") < 0);
|
||||
assert(compare_vals(undef, [2,3,4]) < 0);
|
||||
assert(compare_vals(undef, [0:3]) < 0);
|
||||
assert(compare_vals(undef, undef) == 0);
|
||||
assert(compare_vals(undef, true) < 0);
|
||||
assert(compare_vals(undef, 0) < 0);
|
||||
assert(compare_vals(undef, "foo") < 0);
|
||||
assert(compare_vals(undef, [2,3,4]) < 0);
|
||||
assert(compare_vals(undef, [0:3]) < 0);
|
||||
|
||||
assert(compare_vals(true, undef) > 0);
|
||||
assert(compare_vals(true, true) == 0);
|
||||
assert(compare_vals(true, 0) < 0);
|
||||
assert(compare_vals(true, "foo") < 0);
|
||||
assert(compare_vals(true, [2,3,4]) < 0);
|
||||
assert(compare_vals(true, [0:3]) < 0);
|
||||
assert(compare_vals(true, undef) > 0);
|
||||
assert(compare_vals(true, true) == 0);
|
||||
assert(compare_vals(true, 0) < 0);
|
||||
assert(compare_vals(true, "foo") < 0);
|
||||
assert(compare_vals(true, [2,3,4]) < 0);
|
||||
assert(compare_vals(true, [0:3]) < 0);
|
||||
|
||||
assert(compare_vals(0, undef) > 0);
|
||||
assert(compare_vals(0, true) > 0);
|
||||
assert(compare_vals(0, 0) == 0);
|
||||
assert(compare_vals(0, "foo") < 0);
|
||||
assert(compare_vals(0, [2,3,4]) < 0);
|
||||
assert(compare_vals(0, [0:3]) < 0);
|
||||
assert(compare_vals(0, undef) > 0);
|
||||
assert(compare_vals(0, true) > 0);
|
||||
assert(compare_vals(0, 0) == 0);
|
||||
assert(compare_vals(0, "foo") < 0);
|
||||
assert(compare_vals(0, [2,3,4]) < 0);
|
||||
assert(compare_vals(0, [0:3]) < 0);
|
||||
|
||||
assert(compare_vals(1, undef) > 0);
|
||||
assert(compare_vals(1, true) > 0);
|
||||
assert(compare_vals(1, 1) == 0);
|
||||
assert(compare_vals(1, "foo") < 0);
|
||||
assert(compare_vals(1, [2,3,4]) < 0);
|
||||
assert(compare_vals(1, [0:3]) < 0);
|
||||
assert(compare_vals(1, undef) > 0);
|
||||
assert(compare_vals(1, true) > 0);
|
||||
assert(compare_vals(1, 1) == 0);
|
||||
assert(compare_vals(1, "foo") < 0);
|
||||
assert(compare_vals(1, [2,3,4]) < 0);
|
||||
assert(compare_vals(1, [0:3]) < 0);
|
||||
|
||||
assert(compare_vals("foo", undef) > 0);
|
||||
assert(compare_vals("foo", true) > 0);
|
||||
assert(compare_vals("foo", 1) > 0);
|
||||
assert(compare_vals("foo", "foo") == 0);
|
||||
assert(compare_vals("foo", [2,3,4]) < 0);
|
||||
assert(compare_vals("foo", [0:3]) < 0);
|
||||
assert(compare_vals("foo", undef) > 0);
|
||||
assert(compare_vals("foo", true) > 0);
|
||||
assert(compare_vals("foo", 1) > 0);
|
||||
assert(compare_vals("foo", "foo") == 0);
|
||||
assert(compare_vals("foo", [2,3,4]) < 0);
|
||||
assert(compare_vals("foo", [0:3]) < 0);
|
||||
|
||||
assert(compare_vals([2,3,4], undef) > 0);
|
||||
assert(compare_vals([2,3,4], true) > 0);
|
||||
assert(compare_vals([2,3,4], 1) > 0);
|
||||
assert(compare_vals([2,3,4], "foo") > 0);
|
||||
assert(compare_vals([2,3,4], [2,3,4]) == 0);
|
||||
assert(compare_vals([2,3,4], [0:3]) < 0);
|
||||
assert(compare_vals([2,3,4], undef) > 0);
|
||||
assert(compare_vals([2,3,4], true) > 0);
|
||||
assert(compare_vals([2,3,4], 1) > 0);
|
||||
assert(compare_vals([2,3,4], "foo") > 0);
|
||||
assert(compare_vals([2,3,4], [2,3,4]) == 0);
|
||||
assert(compare_vals([2,3,4], [0:3]) < 0);
|
||||
|
||||
assert(compare_vals([0:3], undef) > 0);
|
||||
assert(compare_vals([0:3], true) > 0);
|
||||
assert(compare_vals([0:3], 1) > 0);
|
||||
assert(compare_vals([0:3], "foo") > 0);
|
||||
assert(compare_vals([0:3], [2,3,4]) > 0);
|
||||
assert(compare_vals([0:3], [0:3]) == 0);
|
||||
assert(compare_vals([0:3], undef) > 0);
|
||||
assert(compare_vals([0:3], true) > 0);
|
||||
assert(compare_vals([0:3], 1) > 0);
|
||||
assert(compare_vals([0:3], "foo") > 0);
|
||||
assert(compare_vals([0:3], [2,3,4]) > 0);
|
||||
assert(compare_vals([0:3], [0:3]) == 0);
|
||||
}
|
||||
test_compare_vals();
|
||||
|
||||
|
||||
module test_compare_lists() {
|
||||
assert(compare_lists([2,3,4], [2,3,4,5]) < 0);
|
||||
assert(compare_lists([2,3,4,5], [2,3,4,5]) == 0);
|
||||
assert(compare_lists([2,3,4,5], [2,3,4]) > 0);
|
||||
assert(compare_lists([2,3,4,5], [2,3,5,5]) < 0);
|
||||
assert(compare_lists([2,3,4], [2,3,4,5]) < 0);
|
||||
assert(compare_lists([2,3,4,5], [2,3,4,5]) == 0);
|
||||
assert(compare_lists([2,3,4,5], [2,3,4]) > 0);
|
||||
assert(compare_lists([2,3,4,5], [2,3,5,5]) < 0);
|
||||
|
||||
assert(compare_lists([[2,3,4],[3,4,5]], [[2,3,4], [3,4,5]]) == 0);
|
||||
assert(compare_lists([[2,3,4],[3,4,5]], [[2,3,4,5], [3,4,5]]) < 0);
|
||||
assert(compare_lists([[2,3,4],[3,4,5]], [[2,3,4], [3,4,5,6]]) < 0);
|
||||
assert(compare_lists([[2,3,4,5],[3,4,5]], [[2,3,4], [3,4,5]]) > 0);
|
||||
assert(compare_lists([[2,3,4],[3,4,5,6]], [[2,3,4], [3,4,5]]) > 0);
|
||||
assert(compare_lists([[2,3,4],[3,5,5]], [[2,3,4], [3,4,5]]) > 0);
|
||||
assert(compare_lists([[2,3,4],[3,4,5]], [[2,3,4], [3,5,5]]) < 0);
|
||||
assert(compare_lists([[2,3,4],[3,4,5]], [[2,3,4], [3,4,5]]) == 0);
|
||||
assert(compare_lists([[2,3,4],[3,4,5]], [[2,3,4,5], [3,4,5]]) < 0);
|
||||
assert(compare_lists([[2,3,4],[3,4,5]], [[2,3,4], [3,4,5,6]]) < 0);
|
||||
assert(compare_lists([[2,3,4,5],[3,4,5]], [[2,3,4], [3,4,5]]) > 0);
|
||||
assert(compare_lists([[2,3,4],[3,4,5,6]], [[2,3,4], [3,4,5]]) > 0);
|
||||
assert(compare_lists([[2,3,4],[3,5,5]], [[2,3,4], [3,4,5]]) > 0);
|
||||
assert(compare_lists([[2,3,4],[3,4,5]], [[2,3,4], [3,5,5]]) < 0);
|
||||
|
||||
assert(compare_lists("cat", "bat") > 0);
|
||||
assert(compare_lists(["cat"], ["bat"]) > 0);
|
||||
assert(compare_lists("cat", "bat") > 0);
|
||||
assert(compare_lists(["cat"], ["bat"]) > 0);
|
||||
}
|
||||
test_compare_lists();
|
||||
|
||||
|
||||
module test_any() {
|
||||
assert(any([0,false,undef]) == false);
|
||||
assert(any([1,false,undef]) == true);
|
||||
assert(any([1,5,true]) == true);
|
||||
assert(any([[0,0], [0,0]]) == false);
|
||||
assert(any([[0,0], [1,0]]) == true);
|
||||
assert(any([0,false,undef]) == false);
|
||||
assert(any([1,false,undef]) == true);
|
||||
assert(any([1,5,true]) == true);
|
||||
assert(any([[0,0], [0,0]]) == false);
|
||||
assert(any([[0,0], [1,0]]) == true);
|
||||
}
|
||||
test_any();
|
||||
|
||||
|
||||
module test_all() {
|
||||
assert(all([0,false,undef]) == false);
|
||||
assert(all([1,false,undef]) == false);
|
||||
assert(all([1,5,true]) == true);
|
||||
assert(all([[0,0], [0,0]]) == false);
|
||||
assert(all([[0,0], [1,0]]) == false);
|
||||
assert(all([[1,1], [1,1]]) == true);
|
||||
assert(all([0,false,undef]) == false);
|
||||
assert(all([1,false,undef]) == false);
|
||||
assert(all([1,5,true]) == true);
|
||||
assert(all([[0,0], [0,0]]) == false);
|
||||
assert(all([[0,0], [1,0]]) == false);
|
||||
assert(all([[1,1], [1,1]]) == true);
|
||||
}
|
||||
test_all();
|
||||
|
||||
|
||||
module test_count_true() {
|
||||
assert(count_true([0,false,undef]) == 0);
|
||||
assert(count_true([1,false,undef]) == 1);
|
||||
assert(count_true([1,5,false]) == 2);
|
||||
assert(count_true([1,5,true]) == 3);
|
||||
assert(count_true([[0,0], [0,0]]) == 0);
|
||||
assert(count_true([[0,0], [1,0]]) == 1);
|
||||
assert(count_true([[1,1], [1,1]]) == 4);
|
||||
assert(count_true([[1,1], [1,1]], nmax=3) == 3);
|
||||
assert(count_true([0,false,undef]) == 0);
|
||||
assert(count_true([1,false,undef]) == 1);
|
||||
assert(count_true([1,5,false]) == 2);
|
||||
assert(count_true([1,5,true]) == 3);
|
||||
assert(count_true([[0,0], [0,0]]) == 0);
|
||||
assert(count_true([[0,0], [1,0]]) == 1);
|
||||
assert(count_true([[1,1], [1,1]]) == 4);
|
||||
assert(count_true([[1,1], [1,1]], nmax=3) == 3);
|
||||
}
|
||||
test_count_true();
|
||||
|
||||
|
||||
module test_factorial() {
|
||||
assert(factorial(1) == 1);
|
||||
assert(factorial(2) == 2);
|
||||
assert(factorial(3) == 6);
|
||||
assert(factorial(4) == 24);
|
||||
assert(factorial(5) == 120);
|
||||
assert(factorial(6) == 720);
|
||||
assert(factorial(7) == 5040);
|
||||
assert(factorial(8) == 40320);
|
||||
assert(factorial(1) == 1);
|
||||
assert(factorial(2) == 2);
|
||||
assert(factorial(3) == 6);
|
||||
assert(factorial(4) == 24);
|
||||
assert(factorial(5) == 120);
|
||||
assert(factorial(6) == 720);
|
||||
assert(factorial(7) == 5040);
|
||||
assert(factorial(8) == 40320);
|
||||
}
|
||||
test_factorial();
|
||||
|
||||
|
||||
module test_gcd() {
|
||||
assert(gcd(15,25) == 5);
|
||||
assert(gcd(15,27) == 3);
|
||||
assert(gcd(270,405) == 135);
|
||||
assert(gcd(15,25) == 5);
|
||||
assert(gcd(15,27) == 3);
|
||||
assert(gcd(270,405) == 135);
|
||||
}
|
||||
test_gcd();
|
||||
|
||||
|
||||
module test_lcm() {
|
||||
assert(lcm(15,25) == 75);
|
||||
assert(lcm(15,27) == 135);
|
||||
assert(lcm(270,405) == 810);
|
||||
assert(lcm(15,25) == 75);
|
||||
assert(lcm(15,27) == 135);
|
||||
assert(lcm(270,405) == 810);
|
||||
}
|
||||
test_lcm();
|
||||
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -2,27 +2,27 @@ include <BOSL2/std.scad>
|
||||
|
||||
|
||||
module test_square() {
|
||||
assert(square(100, center=true) == [[50,-50],[-50,-50],[-50,50],[50,50]]);
|
||||
assert(square(100, center=false) == [[100,0],[0,0],[0,100],[100,100]]);
|
||||
assert(square(100, anchor=FWD+LEFT) == [[100,0],[0,0],[0,100],[100,100]]);
|
||||
assert(square(100, anchor=BACK+RIGHT) == [[0,-100],[-100,-100],[-100,0],[0,0]]);
|
||||
assert(square(100, center=true) == [[50,-50],[-50,-50],[-50,50],[50,50]]);
|
||||
assert(square(100, center=false) == [[100,0],[0,0],[0,100],[100,100]]);
|
||||
assert(square(100, anchor=FWD+LEFT) == [[100,0],[0,0],[0,100],[100,100]]);
|
||||
assert(square(100, anchor=BACK+RIGHT) == [[0,-100],[-100,-100],[-100,0],[0,0]]);
|
||||
}
|
||||
test_square();
|
||||
|
||||
|
||||
module test_circle() {
|
||||
for (pt = circle(d=200)) {
|
||||
assert(approx(norm(pt),100));
|
||||
}
|
||||
for (pt = circle(r=100)) {
|
||||
assert(approx(norm(pt),100));
|
||||
}
|
||||
assert(polygon_is_clockwise(circle(d=200)));
|
||||
assert(polygon_is_clockwise(circle(r=100)));
|
||||
assert(len(circle(d=100,$fn=6)) == 6);
|
||||
assert(len(circle(d=100,$fn=36)) == 36);
|
||||
for (pt = circle(d=200)) {
|
||||
assert(approx(norm(pt),100));
|
||||
}
|
||||
for (pt = circle(r=100)) {
|
||||
assert(approx(norm(pt),100));
|
||||
}
|
||||
assert(polygon_is_clockwise(circle(d=200)));
|
||||
assert(polygon_is_clockwise(circle(r=100)));
|
||||
assert(len(circle(d=100,$fn=6)) == 6);
|
||||
assert(len(circle(d=100,$fn=36)) == 36);
|
||||
}
|
||||
test_circle();
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -3,283 +3,283 @@ include <BOSL2/strings.scad>
|
||||
|
||||
|
||||
function rec_cmp(a,b,eps=1e-9) =
|
||||
typeof(a)!=typeof(b)? false :
|
||||
is_num(a)? approx(a,b,eps=eps) :
|
||||
is_list(a)? len(a)==len(b) && all([for (i=idx(a)) rec_cmp(a[i],b[i],eps=eps)]) :
|
||||
a == b;
|
||||
typeof(a)!=typeof(b)? false :
|
||||
is_num(a)? approx(a,b,eps=eps) :
|
||||
is_list(a)? len(a)==len(b) && all([for (i=idx(a)) rec_cmp(a[i],b[i],eps=eps)]) :
|
||||
a == b;
|
||||
|
||||
|
||||
module verify_f(actual,expected) {
|
||||
if (!rec_cmp(actual,expected)) {
|
||||
echo(str("Expected: ",fmt_float(expected,10)));
|
||||
echo(str(" : ",expected));
|
||||
echo(str("Actual : ",fmt_float(actual,10)));
|
||||
echo(str(" : ",actual));
|
||||
echo(str("Delta : ",fmt_float(expected-actual,10)));
|
||||
echo(str(" : ",expected-actual));
|
||||
assert(approx(expected,actual));
|
||||
}
|
||||
if (!rec_cmp(actual,expected)) {
|
||||
echo(str("Expected: ",fmt_float(expected,10)));
|
||||
echo(str(" : ",expected));
|
||||
echo(str("Actual : ",fmt_float(actual,10)));
|
||||
echo(str(" : ",actual));
|
||||
echo(str("Delta : ",fmt_float(expected-actual,10)));
|
||||
echo(str(" : ",expected-actual));
|
||||
assert(approx(expected,actual));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module test_Quat() {
|
||||
verify_f(Quat(UP,0),[0,0,0,1]);
|
||||
verify_f(Quat(FWD,0),[0,0,0,1]);
|
||||
verify_f(Quat(LEFT,0),[0,0,0,1]);
|
||||
verify_f(Quat(UP,45),[0,0,0.3826834324,0.9238795325]);
|
||||
verify_f(Quat(LEFT,45),[-0.3826834324, 0, 0, 0.9238795325]);
|
||||
verify_f(Quat(BACK,45),[0,0.3826834323,0,0.9238795325]);
|
||||
verify_f(Quat(FWD+RIGHT,30),[0.1830127019, -0.1830127019, 0, 0.9659258263]);
|
||||
verify_f(Quat(UP,0),[0,0,0,1]);
|
||||
verify_f(Quat(FWD,0),[0,0,0,1]);
|
||||
verify_f(Quat(LEFT,0),[0,0,0,1]);
|
||||
verify_f(Quat(UP,45),[0,0,0.3826834324,0.9238795325]);
|
||||
verify_f(Quat(LEFT,45),[-0.3826834324, 0, 0, 0.9238795325]);
|
||||
verify_f(Quat(BACK,45),[0,0.3826834323,0,0.9238795325]);
|
||||
verify_f(Quat(FWD+RIGHT,30),[0.1830127019, -0.1830127019, 0, 0.9659258263]);
|
||||
}
|
||||
test_Quat();
|
||||
|
||||
|
||||
module test_QuatX() {
|
||||
verify_f(QuatX(0),[0,0,0,1]);
|
||||
verify_f(QuatX(35),[0.3007057995,0,0,0.9537169507]);
|
||||
verify_f(QuatX(45),[0.3826834324,0,0,0.9238795325]);
|
||||
verify_f(QuatX(0),[0,0,0,1]);
|
||||
verify_f(QuatX(35),[0.3007057995,0,0,0.9537169507]);
|
||||
verify_f(QuatX(45),[0.3826834324,0,0,0.9238795325]);
|
||||
}
|
||||
test_QuatX();
|
||||
|
||||
|
||||
module test_QuatY() {
|
||||
verify_f(QuatY(0),[0,0,0,1]);
|
||||
verify_f(QuatY(35),[0,0.3007057995,0,0.9537169507]);
|
||||
verify_f(QuatY(45),[0,0.3826834323,0,0.9238795325]);
|
||||
verify_f(QuatY(0),[0,0,0,1]);
|
||||
verify_f(QuatY(35),[0,0.3007057995,0,0.9537169507]);
|
||||
verify_f(QuatY(45),[0,0.3826834323,0,0.9238795325]);
|
||||
}
|
||||
test_QuatY();
|
||||
|
||||
|
||||
module test_QuatZ() {
|
||||
verify_f(QuatZ(0),[0,0,0,1]);
|
||||
verify_f(QuatZ(36),[0,0,0.3090169944,0.9510565163]);
|
||||
verify_f(QuatZ(45),[0,0,0.3826834324,0.9238795325]);
|
||||
verify_f(QuatZ(0),[0,0,0,1]);
|
||||
verify_f(QuatZ(36),[0,0,0.3090169944,0.9510565163]);
|
||||
verify_f(QuatZ(45),[0,0,0.3826834324,0.9238795325]);
|
||||
}
|
||||
test_QuatZ();
|
||||
|
||||
|
||||
module test_QuatXYZ() {
|
||||
verify_f(QuatXYZ([0,0,0]), [0,0,0,1]);
|
||||
verify_f(QuatXYZ([30,0,0]), [0.2588190451, 0, 0, 0.9659258263]);
|
||||
verify_f(QuatXYZ([90,0,0]), [0.7071067812, 0, 0, 0.7071067812]);
|
||||
verify_f(QuatXYZ([-270,0,0]), [-0.7071067812, 0, 0, -0.7071067812]);
|
||||
verify_f(QuatXYZ([180,0,0]), [1,0,0,0]);
|
||||
verify_f(QuatXYZ([270,0,0]), [0.7071067812, 0, 0, -0.7071067812]);
|
||||
verify_f(QuatXYZ([-90,0,0]), [-0.7071067812, 0, 0, 0.7071067812]);
|
||||
verify_f(QuatXYZ([360,0,0]), [0,0,0,-1]);
|
||||
verify_f(QuatXYZ([0,0,0]), [0,0,0,1]);
|
||||
verify_f(QuatXYZ([30,0,0]), [0.2588190451, 0, 0, 0.9659258263]);
|
||||
verify_f(QuatXYZ([90,0,0]), [0.7071067812, 0, 0, 0.7071067812]);
|
||||
verify_f(QuatXYZ([-270,0,0]), [-0.7071067812, 0, 0, -0.7071067812]);
|
||||
verify_f(QuatXYZ([180,0,0]), [1,0,0,0]);
|
||||
verify_f(QuatXYZ([270,0,0]), [0.7071067812, 0, 0, -0.7071067812]);
|
||||
verify_f(QuatXYZ([-90,0,0]), [-0.7071067812, 0, 0, 0.7071067812]);
|
||||
verify_f(QuatXYZ([360,0,0]), [0,0,0,-1]);
|
||||
|
||||
verify_f(QuatXYZ([0,0,0]), [0,0,0,1]);
|
||||
verify_f(QuatXYZ([0,30,0]), [0, 0.2588190451, 0, 0.9659258263]);
|
||||
verify_f(QuatXYZ([0,90,0]), [0, 0.7071067812, 0, 0.7071067812]);
|
||||
verify_f(QuatXYZ([0,-270,0]), [0, -0.7071067812, 0, -0.7071067812]);
|
||||
verify_f(QuatXYZ([0,180,0]), [0,1,0,0]);
|
||||
verify_f(QuatXYZ([0,270,0]), [0, 0.7071067812, 0, -0.7071067812]);
|
||||
verify_f(QuatXYZ([0,-90,0]), [0, -0.7071067812, 0, 0.7071067812]);
|
||||
verify_f(QuatXYZ([0,360,0]), [0,0,0,-1]);
|
||||
verify_f(QuatXYZ([0,0,0]), [0,0,0,1]);
|
||||
verify_f(QuatXYZ([0,30,0]), [0, 0.2588190451, 0, 0.9659258263]);
|
||||
verify_f(QuatXYZ([0,90,0]), [0, 0.7071067812, 0, 0.7071067812]);
|
||||
verify_f(QuatXYZ([0,-270,0]), [0, -0.7071067812, 0, -0.7071067812]);
|
||||
verify_f(QuatXYZ([0,180,0]), [0,1,0,0]);
|
||||
verify_f(QuatXYZ([0,270,0]), [0, 0.7071067812, 0, -0.7071067812]);
|
||||
verify_f(QuatXYZ([0,-90,0]), [0, -0.7071067812, 0, 0.7071067812]);
|
||||
verify_f(QuatXYZ([0,360,0]), [0,0,0,-1]);
|
||||
|
||||
verify_f(QuatXYZ([0,0,0]), [0,0,0,1]);
|
||||
verify_f(QuatXYZ([0,0,30]), [0, 0, 0.2588190451, 0.9659258263]);
|
||||
verify_f(QuatXYZ([0,0,90]), [0, 0, 0.7071067812, 0.7071067812]);
|
||||
verify_f(QuatXYZ([0,0,-270]), [0, 0, -0.7071067812, -0.7071067812]);
|
||||
verify_f(QuatXYZ([0,0,180]), [0,0,1,0]);
|
||||
verify_f(QuatXYZ([0,0,270]), [0, 0, 0.7071067812, -0.7071067812]);
|
||||
verify_f(QuatXYZ([0,0,-90]), [0, 0, -0.7071067812, 0.7071067812]);
|
||||
verify_f(QuatXYZ([0,0,360]), [0,0,0,-1]);
|
||||
verify_f(QuatXYZ([0,0,0]), [0,0,0,1]);
|
||||
verify_f(QuatXYZ([0,0,30]), [0, 0, 0.2588190451, 0.9659258263]);
|
||||
verify_f(QuatXYZ([0,0,90]), [0, 0, 0.7071067812, 0.7071067812]);
|
||||
verify_f(QuatXYZ([0,0,-270]), [0, 0, -0.7071067812, -0.7071067812]);
|
||||
verify_f(QuatXYZ([0,0,180]), [0,0,1,0]);
|
||||
verify_f(QuatXYZ([0,0,270]), [0, 0, 0.7071067812, -0.7071067812]);
|
||||
verify_f(QuatXYZ([0,0,-90]), [0, 0, -0.7071067812, 0.7071067812]);
|
||||
verify_f(QuatXYZ([0,0,360]), [0,0,0,-1]);
|
||||
|
||||
verify_f(QuatXYZ([30,30,30]), [0.1767766953, 0.3061862178, 0.1767766953, 0.9185586535]);
|
||||
verify_f(QuatXYZ([12,34,56]), [-0.04824789229, 0.3036636044, 0.4195145429, 0.8540890495]);
|
||||
verify_f(QuatXYZ([30,30,30]), [0.1767766953, 0.3061862178, 0.1767766953, 0.9185586535]);
|
||||
verify_f(QuatXYZ([12,34,56]), [-0.04824789229, 0.3036636044, 0.4195145429, 0.8540890495]);
|
||||
}
|
||||
test_QuatXYZ();
|
||||
|
||||
|
||||
module test_Q_Ident() {
|
||||
verify_f(Q_Ident(), [0,0,0,1]);
|
||||
verify_f(Q_Ident(), [0,0,0,1]);
|
||||
}
|
||||
test_Q_Ident();
|
||||
|
||||
|
||||
module test_Q_Add_S() {
|
||||
verify_f(Q_Add_S([0,0,0,1],3),[0,0,0,4]);
|
||||
verify_f(Q_Add_S([0,0,1,0],3),[0,0,1,3]);
|
||||
verify_f(Q_Add_S([0,1,0,0],3),[0,1,0,3]);
|
||||
verify_f(Q_Add_S([1,0,0,0],3),[1,0,0,3]);
|
||||
verify_f(Q_Add_S(Quat(LEFT+FWD,23),1),[-0.1409744184, -0.1409744184, 0, 1.979924705]);
|
||||
verify_f(Q_Add_S([0,0,0,1],3),[0,0,0,4]);
|
||||
verify_f(Q_Add_S([0,0,1,0],3),[0,0,1,3]);
|
||||
verify_f(Q_Add_S([0,1,0,0],3),[0,1,0,3]);
|
||||
verify_f(Q_Add_S([1,0,0,0],3),[1,0,0,3]);
|
||||
verify_f(Q_Add_S(Quat(LEFT+FWD,23),1),[-0.1409744184, -0.1409744184, 0, 1.979924705]);
|
||||
}
|
||||
test_Q_Add_S();
|
||||
|
||||
|
||||
module test_Q_Sub_S() {
|
||||
verify_f(Q_Sub_S([0,0,0,1],3),[0,0,0,-2]);
|
||||
verify_f(Q_Sub_S([0,0,1,0],3),[0,0,1,-3]);
|
||||
verify_f(Q_Sub_S([0,1,0,0],3),[0,1,0,-3]);
|
||||
verify_f(Q_Sub_S([1,0,0,0],3),[1,0,0,-3]);
|
||||
verify_f(Q_Sub_S(Quat(LEFT+FWD,23),1),[-0.1409744184, -0.1409744184, 0, -0.02007529538]);
|
||||
verify_f(Q_Sub_S([0,0,0,1],3),[0,0,0,-2]);
|
||||
verify_f(Q_Sub_S([0,0,1,0],3),[0,0,1,-3]);
|
||||
verify_f(Q_Sub_S([0,1,0,0],3),[0,1,0,-3]);
|
||||
verify_f(Q_Sub_S([1,0,0,0],3),[1,0,0,-3]);
|
||||
verify_f(Q_Sub_S(Quat(LEFT+FWD,23),1),[-0.1409744184, -0.1409744184, 0, -0.02007529538]);
|
||||
}
|
||||
test_Q_Sub_S();
|
||||
|
||||
|
||||
module test_Q_Mul_S() {
|
||||
verify_f(Q_Mul_S([0,0,0,1],3),[0,0,0,3]);
|
||||
verify_f(Q_Mul_S([0,0,1,0],3),[0,0,3,0]);
|
||||
verify_f(Q_Mul_S([0,1,0,0],3),[0,3,0,0]);
|
||||
verify_f(Q_Mul_S([1,0,0,0],3),[3,0,0,0]);
|
||||
verify_f(Q_Mul_S([1,0,0,1],3),[3,0,0,3]);
|
||||
verify_f(Q_Mul_S(Quat(LEFT+FWD,23),4),[-0.5638976735, -0.5638976735, 0, 3.919698818]);
|
||||
verify_f(Q_Mul_S([0,0,0,1],3),[0,0,0,3]);
|
||||
verify_f(Q_Mul_S([0,0,1,0],3),[0,0,3,0]);
|
||||
verify_f(Q_Mul_S([0,1,0,0],3),[0,3,0,0]);
|
||||
verify_f(Q_Mul_S([1,0,0,0],3),[3,0,0,0]);
|
||||
verify_f(Q_Mul_S([1,0,0,1],3),[3,0,0,3]);
|
||||
verify_f(Q_Mul_S(Quat(LEFT+FWD,23),4),[-0.5638976735, -0.5638976735, 0, 3.919698818]);
|
||||
}
|
||||
test_Q_Mul_S();
|
||||
|
||||
|
||||
|
||||
module test_Q_Div_S() {
|
||||
verify_f(Q_Div_S([0,0,0,1],3),[0,0,0,1/3]);
|
||||
verify_f(Q_Div_S([0,0,1,0],3),[0,0,1/3,0]);
|
||||
verify_f(Q_Div_S([0,1,0,0],3),[0,1/3,0,0]);
|
||||
verify_f(Q_Div_S([1,0,0,0],3),[1/3,0,0,0]);
|
||||
verify_f(Q_Div_S([1,0,0,1],3),[1/3,0,0,1/3]);
|
||||
verify_f(Q_Div_S(Quat(LEFT+FWD,23),4),[-0.03524360459, -0.03524360459, 0, 0.2449811762]);
|
||||
verify_f(Q_Div_S([0,0,0,1],3),[0,0,0,1/3]);
|
||||
verify_f(Q_Div_S([0,0,1,0],3),[0,0,1/3,0]);
|
||||
verify_f(Q_Div_S([0,1,0,0],3),[0,1/3,0,0]);
|
||||
verify_f(Q_Div_S([1,0,0,0],3),[1/3,0,0,0]);
|
||||
verify_f(Q_Div_S([1,0,0,1],3),[1/3,0,0,1/3]);
|
||||
verify_f(Q_Div_S(Quat(LEFT+FWD,23),4),[-0.03524360459, -0.03524360459, 0, 0.2449811762]);
|
||||
}
|
||||
test_Q_Div_S();
|
||||
|
||||
|
||||
module test_Q_Add() {
|
||||
verify_f(Q_Add([2,3,4,5],[-1,-1,-1,-1]),[1,2,3,4]);
|
||||
verify_f(Q_Add([2,3,4,5],[-3,-3,-3,-3]),[-1,0,1,2]);
|
||||
verify_f(Q_Add([2,3,4,5],[0,0,0,0]),[2,3,4,5]);
|
||||
verify_f(Q_Add([2,3,4,5],[1,1,1,1]),[3,4,5,6]);
|
||||
verify_f(Q_Add([2,3,4,5],[1,0,0,0]),[3,3,4,5]);
|
||||
verify_f(Q_Add([2,3,4,5],[0,1,0,0]),[2,4,4,5]);
|
||||
verify_f(Q_Add([2,3,4,5],[0,0,1,0]),[2,3,5,5]);
|
||||
verify_f(Q_Add([2,3,4,5],[0,0,0,1]),[2,3,4,6]);
|
||||
verify_f(Q_Add([2,3,4,5],[2,1,2,1]),[4,4,6,6]);
|
||||
verify_f(Q_Add([2,3,4,5],[1,2,1,2]),[3,5,5,7]);
|
||||
verify_f(Q_Add([2,3,4,5],[-1,-1,-1,-1]),[1,2,3,4]);
|
||||
verify_f(Q_Add([2,3,4,5],[-3,-3,-3,-3]),[-1,0,1,2]);
|
||||
verify_f(Q_Add([2,3,4,5],[0,0,0,0]),[2,3,4,5]);
|
||||
verify_f(Q_Add([2,3,4,5],[1,1,1,1]),[3,4,5,6]);
|
||||
verify_f(Q_Add([2,3,4,5],[1,0,0,0]),[3,3,4,5]);
|
||||
verify_f(Q_Add([2,3,4,5],[0,1,0,0]),[2,4,4,5]);
|
||||
verify_f(Q_Add([2,3,4,5],[0,0,1,0]),[2,3,5,5]);
|
||||
verify_f(Q_Add([2,3,4,5],[0,0,0,1]),[2,3,4,6]);
|
||||
verify_f(Q_Add([2,3,4,5],[2,1,2,1]),[4,4,6,6]);
|
||||
verify_f(Q_Add([2,3,4,5],[1,2,1,2]),[3,5,5,7]);
|
||||
}
|
||||
test_Q_Add();
|
||||
|
||||
|
||||
module test_Q_Sub() {
|
||||
verify_f(Q_Sub([2,3,4,5],[-1,-1,-1,-1]),[3,4,5,6]);
|
||||
verify_f(Q_Sub([2,3,4,5],[-3,-3,-3,-3]),[5,6,7,8]);
|
||||
verify_f(Q_Sub([2,3,4,5],[0,0,0,0]),[2,3,4,5]);
|
||||
verify_f(Q_Sub([2,3,4,5],[1,1,1,1]),[1,2,3,4]);
|
||||
verify_f(Q_Sub([2,3,4,5],[1,0,0,0]),[1,3,4,5]);
|
||||
verify_f(Q_Sub([2,3,4,5],[0,1,0,0]),[2,2,4,5]);
|
||||
verify_f(Q_Sub([2,3,4,5],[0,0,1,0]),[2,3,3,5]);
|
||||
verify_f(Q_Sub([2,3,4,5],[0,0,0,1]),[2,3,4,4]);
|
||||
verify_f(Q_Sub([2,3,4,5],[2,1,2,1]),[0,2,2,4]);
|
||||
verify_f(Q_Sub([2,3,4,5],[1,2,1,2]),[1,1,3,3]);
|
||||
verify_f(Q_Sub([2,3,4,5],[-1,-1,-1,-1]),[3,4,5,6]);
|
||||
verify_f(Q_Sub([2,3,4,5],[-3,-3,-3,-3]),[5,6,7,8]);
|
||||
verify_f(Q_Sub([2,3,4,5],[0,0,0,0]),[2,3,4,5]);
|
||||
verify_f(Q_Sub([2,3,4,5],[1,1,1,1]),[1,2,3,4]);
|
||||
verify_f(Q_Sub([2,3,4,5],[1,0,0,0]),[1,3,4,5]);
|
||||
verify_f(Q_Sub([2,3,4,5],[0,1,0,0]),[2,2,4,5]);
|
||||
verify_f(Q_Sub([2,3,4,5],[0,0,1,0]),[2,3,3,5]);
|
||||
verify_f(Q_Sub([2,3,4,5],[0,0,0,1]),[2,3,4,4]);
|
||||
verify_f(Q_Sub([2,3,4,5],[2,1,2,1]),[0,2,2,4]);
|
||||
verify_f(Q_Sub([2,3,4,5],[1,2,1,2]),[1,1,3,3]);
|
||||
}
|
||||
test_Q_Sub();
|
||||
|
||||
|
||||
module test_Q_Mul() {
|
||||
verify_f(Q_Mul(QuatZ(30),QuatX(57)),[0.4608999698, 0.1234977747, 0.2274546059, 0.8488721457]);
|
||||
verify_f(Q_Mul(QuatY(30),QuatZ(23)),[0.05160021841, 0.2536231763, 0.1925746368, 0.94653458]);
|
||||
verify_f(Q_Mul(QuatZ(30),QuatX(57)),[0.4608999698, 0.1234977747, 0.2274546059, 0.8488721457]);
|
||||
verify_f(Q_Mul(QuatY(30),QuatZ(23)),[0.05160021841, 0.2536231763, 0.1925746368, 0.94653458]);
|
||||
}
|
||||
test_Q_Mul();
|
||||
|
||||
|
||||
module test_Q_Dot() {
|
||||
verify_f(Q_Dot(QuatZ(30),QuatX(57)),0.8488721457);
|
||||
verify_f(Q_Dot(QuatY(30),QuatZ(23)),0.94653458);
|
||||
verify_f(Q_Dot(QuatZ(30),QuatX(57)),0.8488721457);
|
||||
verify_f(Q_Dot(QuatY(30),QuatZ(23)),0.94653458);
|
||||
}
|
||||
test_Q_Dot();
|
||||
|
||||
|
||||
module test_Q_Neg() {
|
||||
verify_f(Q_Neg([1,0,0,1]),[-1,0,0,-1]);
|
||||
verify_f(Q_Neg([0,1,1,0]),[0,-1,-1,0]);
|
||||
verify_f(Q_Neg(QuatXYZ([23,45,67])),[0.0533818345,-0.4143703268,-0.4360652669,-0.7970537592]);
|
||||
verify_f(Q_Neg([1,0,0,1]),[-1,0,0,-1]);
|
||||
verify_f(Q_Neg([0,1,1,0]),[0,-1,-1,0]);
|
||||
verify_f(Q_Neg(QuatXYZ([23,45,67])),[0.0533818345,-0.4143703268,-0.4360652669,-0.7970537592]);
|
||||
}
|
||||
test_Q_Neg();
|
||||
|
||||
|
||||
module test_Q_Conj() {
|
||||
verify_f(Q_Conj([1,0,0,1]),[-1,0,0,1]);
|
||||
verify_f(Q_Conj([0,1,1,0]),[0,-1,-1,0]);
|
||||
verify_f(Q_Conj(QuatXYZ([23,45,67])),[0.0533818345, -0.4143703268, -0.4360652669, 0.7970537592]);
|
||||
verify_f(Q_Conj([1,0,0,1]),[-1,0,0,1]);
|
||||
verify_f(Q_Conj([0,1,1,0]),[0,-1,-1,0]);
|
||||
verify_f(Q_Conj(QuatXYZ([23,45,67])),[0.0533818345, -0.4143703268, -0.4360652669, 0.7970537592]);
|
||||
}
|
||||
test_Q_Conj();
|
||||
|
||||
|
||||
module test_Q_Norm() {
|
||||
verify_f(Q_Norm([1,0,0,1]),1.414213562);
|
||||
verify_f(Q_Norm([0,1,1,0]),1.414213562);
|
||||
verify_f(Q_Norm(QuatXYZ([23,45,67])),1);
|
||||
verify_f(Q_Norm([1,0,0,1]),1.414213562);
|
||||
verify_f(Q_Norm([0,1,1,0]),1.414213562);
|
||||
verify_f(Q_Norm(QuatXYZ([23,45,67])),1);
|
||||
}
|
||||
test_Q_Norm();
|
||||
|
||||
|
||||
module test_Q_Normalize() {
|
||||
verify_f(Q_Normalize([1,0,0,1]),[0.7071067812, 0, 0, 0.7071067812]);
|
||||
verify_f(Q_Normalize([0,1,1,0]),[0, 0.7071067812, 0.7071067812, 0]);
|
||||
verify_f(Q_Normalize(QuatXYZ([23,45,67])),[-0.0533818345, 0.4143703268, 0.4360652669, 0.7970537592]);
|
||||
verify_f(Q_Normalize([1,0,0,1]),[0.7071067812, 0, 0, 0.7071067812]);
|
||||
verify_f(Q_Normalize([0,1,1,0]),[0, 0.7071067812, 0.7071067812, 0]);
|
||||
verify_f(Q_Normalize(QuatXYZ([23,45,67])),[-0.0533818345, 0.4143703268, 0.4360652669, 0.7970537592]);
|
||||
}
|
||||
test_Q_Normalize();
|
||||
|
||||
|
||||
module test_Q_Dist() {
|
||||
verify_f(Q_Dist(QuatXYZ([23,45,67]),QuatXYZ([23,45,67])),0);
|
||||
verify_f(Q_Dist(QuatXYZ([23,45,67]),QuatXYZ([12,34,56])),0.1257349854);
|
||||
verify_f(Q_Dist(QuatXYZ([23,45,67]),QuatXYZ([23,45,67])),0);
|
||||
verify_f(Q_Dist(QuatXYZ([23,45,67]),QuatXYZ([12,34,56])),0.1257349854);
|
||||
}
|
||||
test_Q_Dist();
|
||||
|
||||
|
||||
module test_Q_Slerp() {
|
||||
verify_f(Q_Slerp(QuatX(45),QuatY(30),0.0),QuatX(45));
|
||||
verify_f(Q_Slerp(QuatX(45),QuatY(30),0.5),[0.1967063121, 0.1330377423, 0, 0.9713946602]);
|
||||
verify_f(Q_Slerp(QuatX(45),QuatY(30),1.0),QuatY(30));
|
||||
verify_f(Q_Slerp(QuatX(45),QuatY(30),0.0),QuatX(45));
|
||||
verify_f(Q_Slerp(QuatX(45),QuatY(30),0.5),[0.1967063121, 0.1330377423, 0, 0.9713946602]);
|
||||
verify_f(Q_Slerp(QuatX(45),QuatY(30),1.0),QuatY(30));
|
||||
}
|
||||
test_Q_Slerp();
|
||||
|
||||
|
||||
module test_Q_Matrix3() {
|
||||
verify_f(Q_Matrix3(QuatZ(37)),rot(37,planar=true));
|
||||
verify_f(Q_Matrix3(QuatZ(-49)),rot(-49,planar=true));
|
||||
verify_f(Q_Matrix3(QuatZ(37)),rot(37,planar=true));
|
||||
verify_f(Q_Matrix3(QuatZ(-49)),rot(-49,planar=true));
|
||||
}
|
||||
test_Q_Matrix3();
|
||||
|
||||
|
||||
module test_Q_Matrix4() {
|
||||
verify_f(Q_Matrix4(QuatZ(37)),rot(37));
|
||||
verify_f(Q_Matrix4(QuatZ(-49)),rot(-49));
|
||||
verify_f(Q_Matrix4(QuatX(37)),rot([37,0,0]));
|
||||
verify_f(Q_Matrix4(QuatY(37)),rot([0,37,0]));
|
||||
verify_f(Q_Matrix4(QuatXYZ([12,34,56])),rot([12,34,56]));
|
||||
verify_f(Q_Matrix4(QuatZ(37)),rot(37));
|
||||
verify_f(Q_Matrix4(QuatZ(-49)),rot(-49));
|
||||
verify_f(Q_Matrix4(QuatX(37)),rot([37,0,0]));
|
||||
verify_f(Q_Matrix4(QuatY(37)),rot([0,37,0]));
|
||||
verify_f(Q_Matrix4(QuatXYZ([12,34,56])),rot([12,34,56]));
|
||||
}
|
||||
test_Q_Matrix4();
|
||||
|
||||
|
||||
module test_Q_Axis() {
|
||||
verify_f(Q_Axis(QuatX(37)),RIGHT);
|
||||
verify_f(Q_Axis(QuatX(-37)),LEFT);
|
||||
verify_f(Q_Axis(QuatY(37)),BACK);
|
||||
verify_f(Q_Axis(QuatY(-37)),FWD);
|
||||
verify_f(Q_Axis(QuatZ(37)),UP);
|
||||
verify_f(Q_Axis(QuatZ(-37)),DOWN);
|
||||
verify_f(Q_Axis(QuatX(37)),RIGHT);
|
||||
verify_f(Q_Axis(QuatX(-37)),LEFT);
|
||||
verify_f(Q_Axis(QuatY(37)),BACK);
|
||||
verify_f(Q_Axis(QuatY(-37)),FWD);
|
||||
verify_f(Q_Axis(QuatZ(37)),UP);
|
||||
verify_f(Q_Axis(QuatZ(-37)),DOWN);
|
||||
}
|
||||
test_Q_Axis();
|
||||
|
||||
|
||||
module test_Q_Angle() {
|
||||
verify_f(Q_Angle(QuatX(0)),0);
|
||||
verify_f(Q_Angle(QuatY(0)),0);
|
||||
verify_f(Q_Angle(QuatZ(0)),0);
|
||||
verify_f(Q_Angle(QuatX(37)),37);
|
||||
verify_f(Q_Angle(QuatX(-37)),37);
|
||||
verify_f(Q_Angle(QuatY(37)),37);
|
||||
verify_f(Q_Angle(QuatY(-37)),37);
|
||||
verify_f(Q_Angle(QuatZ(37)),37);
|
||||
verify_f(Q_Angle(QuatZ(-37)),37);
|
||||
verify_f(Q_Angle(QuatX(0)),0);
|
||||
verify_f(Q_Angle(QuatY(0)),0);
|
||||
verify_f(Q_Angle(QuatZ(0)),0);
|
||||
verify_f(Q_Angle(QuatX(37)),37);
|
||||
verify_f(Q_Angle(QuatX(-37)),37);
|
||||
verify_f(Q_Angle(QuatY(37)),37);
|
||||
verify_f(Q_Angle(QuatY(-37)),37);
|
||||
verify_f(Q_Angle(QuatZ(37)),37);
|
||||
verify_f(Q_Angle(QuatZ(-37)),37);
|
||||
}
|
||||
test_Q_Angle();
|
||||
|
||||
|
||||
module test_Qrot() {
|
||||
verify_f(Qrot(QuatXYZ([12,34,56])),rot([12,34,56]));
|
||||
verify_f(Qrot(QuatXYZ([12,34,56]),p=[2,3,4]),rot([12,34,56],p=[2,3,4]));
|
||||
verify_f(Qrot(QuatXYZ([12,34,56]),p=[[2,3,4],[4,9,6]]),rot([12,34,56],p=[[2,3,4],[4,9,6]]));
|
||||
verify_f(Qrot(QuatXYZ([12,34,56])),rot([12,34,56]));
|
||||
verify_f(Qrot(QuatXYZ([12,34,56]),p=[2,3,4]),rot([12,34,56],p=[2,3,4]));
|
||||
verify_f(Qrot(QuatXYZ([12,34,56]),p=[[2,3,4],[4,9,6]]),rot([12,34,56],p=[[2,3,4],[4,9,6]]));
|
||||
}
|
||||
test_Qrot();
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -3,75 +3,75 @@ include <BOSL2/queues.scad>
|
||||
|
||||
|
||||
module test_queue_init() {
|
||||
assert(queue_init()==[]);
|
||||
assert(queue_init()==[]);
|
||||
}
|
||||
test_queue_init();
|
||||
|
||||
|
||||
module test_queue_empty() {
|
||||
assert(queue_empty([]));
|
||||
assert(!queue_empty([3]));
|
||||
assert(!queue_empty([2,4,8]));
|
||||
assert(queue_empty([]));
|
||||
assert(!queue_empty([3]));
|
||||
assert(!queue_empty([2,4,8]));
|
||||
}
|
||||
test_queue_empty();
|
||||
|
||||
|
||||
module test_queue_size() {
|
||||
assert(queue_size([]) == 0);
|
||||
assert(queue_size([3]) == 1);
|
||||
assert(queue_size([2,4,8]) == 3);
|
||||
assert(queue_size([]) == 0);
|
||||
assert(queue_size([3]) == 1);
|
||||
assert(queue_size([2,4,8]) == 3);
|
||||
}
|
||||
test_queue_size();
|
||||
|
||||
|
||||
module test_queue_head() {
|
||||
assert(queue_head([]) == undef);
|
||||
assert(queue_head([3,5,7,9]) == 3);
|
||||
assert(queue_head([3,5,7,9], 3) == [3,5,7]);
|
||||
assert(queue_head([]) == undef);
|
||||
assert(queue_head([3,5,7,9]) == 3);
|
||||
assert(queue_head([3,5,7,9], 3) == [3,5,7]);
|
||||
}
|
||||
test_queue_head();
|
||||
|
||||
|
||||
module test_queue_tail() {
|
||||
assert(queue_tail([]) == undef);
|
||||
assert(queue_tail([3,5,7,9]) == 9);
|
||||
assert(queue_tail([3,5,7,9], 3) == [5,7,9]);
|
||||
assert(queue_tail([]) == undef);
|
||||
assert(queue_tail([3,5,7,9]) == 9);
|
||||
assert(queue_tail([3,5,7,9], 3) == [5,7,9]);
|
||||
}
|
||||
test_queue_tail();
|
||||
|
||||
|
||||
module test_queue_peek() {
|
||||
q = [8,5,4,3,2,3,7];
|
||||
assert(queue_peek(q,0) == 8);
|
||||
assert(queue_peek(q,2) == 4);
|
||||
assert(queue_peek(q,2,1) == [4]);
|
||||
assert(queue_peek(q,2,3) == [4,3,2]);
|
||||
q = [8,5,4,3,2,3,7];
|
||||
assert(queue_peek(q,0) == 8);
|
||||
assert(queue_peek(q,2) == 4);
|
||||
assert(queue_peek(q,2,1) == [4]);
|
||||
assert(queue_peek(q,2,3) == [4,3,2]);
|
||||
}
|
||||
test_queue_peek();
|
||||
|
||||
|
||||
module test_queue_add() {
|
||||
q1 = queue_init();
|
||||
q2 = queue_add(q1, "Foo");
|
||||
assert(q2==["Foo"]);
|
||||
q3 = queue_add(q2, "Bar");
|
||||
assert(q3==["Foo","Bar"]);
|
||||
q4 = queue_add(q3, "Baz");
|
||||
assert(q4==["Foo","Bar","Baz"]);
|
||||
q1 = queue_init();
|
||||
q2 = queue_add(q1, "Foo");
|
||||
assert(q2==["Foo"]);
|
||||
q3 = queue_add(q2, "Bar");
|
||||
assert(q3==["Foo","Bar"]);
|
||||
q4 = queue_add(q3, "Baz");
|
||||
assert(q4==["Foo","Bar","Baz"]);
|
||||
}
|
||||
test_queue_add();
|
||||
|
||||
|
||||
module test_queue_pop() {
|
||||
q = ["Foo", "Bar", "Baz", "Qux"];
|
||||
q1 = queue_pop(q);
|
||||
assert(q1 == ["Bar", "Baz", "Qux"]);
|
||||
q2 = queue_pop(q,2);
|
||||
assert(q2 == ["Baz", "Qux"]);
|
||||
q3 = queue_pop(q,3);
|
||||
assert(q3 == ["Qux"]);
|
||||
q = ["Foo", "Bar", "Baz", "Qux"];
|
||||
q1 = queue_pop(q);
|
||||
assert(q1 == ["Bar", "Baz", "Qux"]);
|
||||
q2 = queue_pop(q,2);
|
||||
assert(q2 == ["Baz", "Qux"]);
|
||||
q3 = queue_pop(q,3);
|
||||
assert(q3 == ["Qux"]);
|
||||
}
|
||||
test_queue_pop();
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -3,17 +3,17 @@ include <BOSL2/skin.scad>
|
||||
|
||||
|
||||
module test_skin() {
|
||||
profiles = [
|
||||
[[-100,-100,0], [0,100,0], [100,-100,0]],
|
||||
[[-100,-100,100], [-100,100,100], [100,100,100], [100,-100,100]],
|
||||
];
|
||||
vnf1 = skin(profiles, caps=false, method="distance");
|
||||
assert(vnf1 == [[[-100,-100,0],[-100,100,100],[-100,-100,100],[0,100,0],[100,100,100],[100,-100,0],[100,-100,100]],[[0,1,2],[0,3,1],[3,4,1],[3,5,4],[5,6,4],[5,2,6],[5,0,2]]]);
|
||||
vnf2 = skin(profiles, caps=true, method="distance");
|
||||
assert(vnf2 == [[[-100,-100,0],[-100,100,100],[-100,-100,100],[0,100,0],[100,100,100],[100,-100,0],[100,-100,100],[100,-100,0],[0,100,0],[-100,-100,0],[-100,-100,100],[-100,100,100],[100,100,100],[100,-100,100]],[[0,1,2],[0,3,1],[3,4,1],[3,5,4],[5,6,4],[5,2,6],[5,0,2],[7,8,9],[10,11,12],[12,13,10]]]);
|
||||
vnf_polyhedron(vnf2);
|
||||
profiles = [
|
||||
[[-100,-100,0], [0,100,0], [100,-100,0]],
|
||||
[[-100,-100,100], [-100,100,100], [100,100,100], [100,-100,100]],
|
||||
];
|
||||
vnf1 = skin(profiles, caps=false, method="distance");
|
||||
assert(vnf1 == [[[-100,-100,0],[-100,100,100],[-100,-100,100],[0,100,0],[100,100,100],[100,-100,0],[100,-100,100]],[[0,1,2],[0,3,1],[3,4,1],[3,5,4],[5,6,4],[5,2,6],[5,0,2]]]);
|
||||
vnf2 = skin(profiles, caps=true, method="distance");
|
||||
assert(vnf2 == [[[-100,-100,0],[-100,100,100],[-100,-100,100],[0,100,0],[100,100,100],[100,-100,0],[100,-100,100],[100,-100,0],[0,100,0],[-100,-100,0],[-100,-100,100],[-100,100,100],[100,100,100],[100,-100,100]],[[0,1,2],[0,3,1],[3,4,1],[3,5,4],[5,6,4],[5,2,6],[5,0,2],[7,8,9],[10,11,12],[12,13,10]]]);
|
||||
vnf_polyhedron(vnf2);
|
||||
}
|
||||
test_skin();
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -3,77 +3,77 @@ include <BOSL2/stacks.scad>
|
||||
|
||||
|
||||
module test_stack_init() {
|
||||
assert(stack_init()==[]);
|
||||
assert(stack_init()==[]);
|
||||
}
|
||||
test_stack_init();
|
||||
|
||||
|
||||
module test_stack_empty() {
|
||||
assert(stack_empty([]));
|
||||
assert(!stack_empty([3]));
|
||||
assert(!stack_empty([2,4,8]));
|
||||
assert(stack_empty([]));
|
||||
assert(!stack_empty([3]));
|
||||
assert(!stack_empty([2,4,8]));
|
||||
}
|
||||
test_stack_empty();
|
||||
|
||||
|
||||
module test_stack_depth() {
|
||||
assert(stack_depth([]) == 0);
|
||||
assert(stack_depth([3]) == 1);
|
||||
assert(stack_depth([2,4,8]) == 3);
|
||||
assert(stack_depth([]) == 0);
|
||||
assert(stack_depth([3]) == 1);
|
||||
assert(stack_depth([2,4,8]) == 3);
|
||||
}
|
||||
test_stack_depth();
|
||||
|
||||
|
||||
module test_stack_top() {
|
||||
assert(stack_top([]) == undef);
|
||||
assert(stack_top([3,5,7,9]) == 9);
|
||||
assert(stack_top([3,5,7,9], 3) == [5,7,9]);
|
||||
assert(stack_top([]) == undef);
|
||||
assert(stack_top([3,5,7,9]) == 9);
|
||||
assert(stack_top([3,5,7,9], 3) == [5,7,9]);
|
||||
}
|
||||
test_stack_top();
|
||||
|
||||
|
||||
module test_stack_peek() {
|
||||
s = [8,5,4,3,2,3,7];
|
||||
assert(stack_peek(s,0) == 7);
|
||||
assert(stack_peek(s,2) == 2);
|
||||
assert(stack_peek(s,2,1) == [2]);
|
||||
assert(stack_peek(s,2,3) == [2,3,7]);
|
||||
s = [8,5,4,3,2,3,7];
|
||||
assert(stack_peek(s,0) == 7);
|
||||
assert(stack_peek(s,2) == 2);
|
||||
assert(stack_peek(s,2,1) == [2]);
|
||||
assert(stack_peek(s,2,3) == [2,3,7]);
|
||||
}
|
||||
test_stack_peek();
|
||||
|
||||
|
||||
module test_stack_push() {
|
||||
s1 = stack_init();
|
||||
s2 = stack_push(s1, "Foo");
|
||||
assert(s2==["Foo"]);
|
||||
s3 = stack_push(s2, "Bar");
|
||||
assert(s3==["Foo","Bar"]);
|
||||
s4 = stack_push(s3, "Baz");
|
||||
assert(s4==["Foo","Bar","Baz"]);
|
||||
s1 = stack_init();
|
||||
s2 = stack_push(s1, "Foo");
|
||||
assert(s2==["Foo"]);
|
||||
s3 = stack_push(s2, "Bar");
|
||||
assert(s3==["Foo","Bar"]);
|
||||
s4 = stack_push(s3, "Baz");
|
||||
assert(s4==["Foo","Bar","Baz"]);
|
||||
}
|
||||
test_stack_push();
|
||||
|
||||
|
||||
module test_stack_pop() {
|
||||
s = ["Foo", "Bar", "Baz", "Qux"];
|
||||
s1 = stack_pop(s);
|
||||
assert(s1 == ["Foo", "Bar", "Baz"]);
|
||||
s2 = stack_pop(s,2);
|
||||
assert(s2 == ["Foo", "Bar"]);
|
||||
s3 = stack_pop(s,3);
|
||||
assert(s3 == ["Foo"]);
|
||||
s = ["Foo", "Bar", "Baz", "Qux"];
|
||||
s1 = stack_pop(s);
|
||||
assert(s1 == ["Foo", "Bar", "Baz"]);
|
||||
s2 = stack_pop(s,2);
|
||||
assert(s2 == ["Foo", "Bar"]);
|
||||
s3 = stack_pop(s,3);
|
||||
assert(s3 == ["Foo"]);
|
||||
}
|
||||
test_stack_pop();
|
||||
|
||||
|
||||
module test_stack_rotate() {
|
||||
s = ["Foo", "Bar", "Baz", "Qux", "Quux"];
|
||||
s1 = stack_rotate(s,4);
|
||||
assert(s1 == ["Foo", "Baz", "Qux", "Quux", "Bar"]);
|
||||
s2 = stack_rotate(s,-4);
|
||||
assert(s2 == ["Foo", "Quux", "Bar", "Baz", "Qux"]);
|
||||
s = ["Foo", "Bar", "Baz", "Qux", "Quux"];
|
||||
s1 = stack_rotate(s,4);
|
||||
assert(s1 == ["Foo", "Baz", "Qux", "Quux", "Bar"]);
|
||||
s2 = stack_rotate(s,-4);
|
||||
assert(s2 == ["Foo", "Quux", "Bar", "Baz", "Qux"]);
|
||||
}
|
||||
test_stack_rotate();
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -3,57 +3,57 @@ include <BOSL2/structs.scad>
|
||||
|
||||
|
||||
module test_struct_set() {
|
||||
st = struct_set([], "Foo", 42);
|
||||
assert(st == [["Foo",42]]);
|
||||
st2 = struct_set(st, "Bar", 28);
|
||||
assert(st2 == [["Foo",42],["Bar",28]]);
|
||||
st3 = struct_set(st2, "Foo", 91);
|
||||
assert(st3 == [["Foo",91],["Bar",28]]);
|
||||
st = struct_set([], "Foo", 42);
|
||||
assert(st == [["Foo",42]]);
|
||||
st2 = struct_set(st, "Bar", 28);
|
||||
assert(st2 == [["Foo",42],["Bar",28]]);
|
||||
st3 = struct_set(st2, "Foo", 91);
|
||||
assert(st3 == [["Foo",91],["Bar",28]]);
|
||||
}
|
||||
test_struct_set();
|
||||
|
||||
|
||||
module test_struct_remove() {
|
||||
st = [["Foo",91],["Bar",28],["Baz",9]];
|
||||
assert(struct_remove(st, "Foo") == [["Bar",28],["Baz",9]]);
|
||||
assert(struct_remove(st, "Bar") == [["Foo",91],["Baz",9]]);
|
||||
assert(struct_remove(st, "Baz") == [["Foo",91],["Bar",28]]);
|
||||
st = [["Foo",91],["Bar",28],["Baz",9]];
|
||||
assert(struct_remove(st, "Foo") == [["Bar",28],["Baz",9]]);
|
||||
assert(struct_remove(st, "Bar") == [["Foo",91],["Baz",9]]);
|
||||
assert(struct_remove(st, "Baz") == [["Foo",91],["Bar",28]]);
|
||||
}
|
||||
test_struct_remove();
|
||||
|
||||
|
||||
module test_struct_val() {
|
||||
st = [["Foo",91],["Bar",28],["Baz",9]];
|
||||
assert(struct_val(st,"Foo") == 91);
|
||||
assert(struct_val(st,"Bar") == 28);
|
||||
assert(struct_val(st,"Baz") == 9);
|
||||
st = [["Foo",91],["Bar",28],["Baz",9]];
|
||||
assert(struct_val(st,"Foo") == 91);
|
||||
assert(struct_val(st,"Bar") == 28);
|
||||
assert(struct_val(st,"Baz") == 9);
|
||||
}
|
||||
test_struct_val();
|
||||
|
||||
|
||||
module test_struct_keys() {
|
||||
assert(struct_keys([["Foo",3],["Bar",2],["Baz",1]]) == ["Foo","Bar","Baz"]);
|
||||
assert(struct_keys([["Zee",1],["Why",2],["Exx",3]]) == ["Zee","Why","Exx"]);
|
||||
assert(struct_keys([["Foo",3],["Bar",2],["Baz",1]]) == ["Foo","Bar","Baz"]);
|
||||
assert(struct_keys([["Zee",1],["Why",2],["Exx",3]]) == ["Zee","Why","Exx"]);
|
||||
}
|
||||
test_struct_keys();
|
||||
|
||||
|
||||
module test_struct_echo() {
|
||||
// Can't yet test echo output
|
||||
// Can't yet test echo output
|
||||
}
|
||||
test_struct_echo();
|
||||
|
||||
|
||||
module test_is_struct() {
|
||||
assert(is_struct([["Foo",1],["Bar",2],["Baz",3]]));
|
||||
assert(!is_struct([["Foo"],["Bar"],["Baz"]]));
|
||||
assert(!is_struct(["Foo","Bar","Baz"]));
|
||||
assert(!is_struct([3,4,5]));
|
||||
assert(!is_struct(3));
|
||||
assert(!is_struct(true));
|
||||
assert(!is_struct("foo"));
|
||||
assert(is_struct([["Foo",1],["Bar",2],["Baz",3]]));
|
||||
assert(!is_struct([["Foo"],["Bar"],["Baz"]]));
|
||||
assert(!is_struct(["Foo","Bar","Baz"]));
|
||||
assert(!is_struct([3,4,5]));
|
||||
assert(!is_struct(3));
|
||||
assert(!is_struct(true));
|
||||
assert(!is_struct("foo"));
|
||||
}
|
||||
test_is_struct();
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -1,159 +1,159 @@
|
||||
include <BOSL2/std.scad>
|
||||
|
||||
module test(got,expect,extra_info) {
|
||||
if (
|
||||
is_undef(expect) != is_undef(got) ||
|
||||
expect*0 != got*0 ||
|
||||
(is_vnf(expect) && !all([for (i=idx(expect[0])) approx(got[0][i],expect[0][i])]) && got[1]!=expect[1]) ||
|
||||
(is_matrix(expect) && !all([for (i=idx(expect)) approx(got[i],expect[i])])) ||
|
||||
(got!=expect && !approx(got, expect))
|
||||
) {
|
||||
fmt = is_int(expect)? "{:.14i}" :
|
||||
is_num(expect)? "{:.14g}" :
|
||||
is_vector(expect)? "{:.14g}" :
|
||||
"{}";
|
||||
echofmt(str("Expected: ",fmt),[expect]);
|
||||
echofmt(str("But Got : ",fmt),[got]);
|
||||
if (expect*0 == got*0) {
|
||||
echofmt(str("Delta is: ",fmt),[expect-got]);
|
||||
}
|
||||
if (!is_undef(extra_info)) {
|
||||
echo(str("Extra Info: ",extra_info));
|
||||
}
|
||||
assert(false, "TEST FAILED!");
|
||||
}
|
||||
if (
|
||||
is_undef(expect) != is_undef(got) ||
|
||||
expect*0 != got*0 ||
|
||||
(is_vnf(expect) && !all([for (i=idx(expect[0])) approx(got[0][i],expect[0][i])]) && got[1]!=expect[1]) ||
|
||||
(is_matrix(expect) && !all([for (i=idx(expect)) approx(got[i],expect[i])])) ||
|
||||
(got!=expect && !approx(got, expect))
|
||||
) {
|
||||
fmt = is_int(expect)? "{:.14i}" :
|
||||
is_num(expect)? "{:.14g}" :
|
||||
is_vector(expect)? "{:.14g}" :
|
||||
"{}";
|
||||
echofmt(str("Expected: ",fmt),[expect]);
|
||||
echofmt(str("But Got : ",fmt),[got]);
|
||||
if (expect*0 == got*0) {
|
||||
echofmt(str("Delta is: ",fmt),[expect-got]);
|
||||
}
|
||||
if (!is_undef(extra_info)) {
|
||||
echo(str("Extra Info: ",extra_info));
|
||||
}
|
||||
assert(false, "TEST FAILED!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module test_rot() {
|
||||
pts2d = 50 * [for (x=[-1,0,1],y=[-1,0,1]) [x,y]];
|
||||
pts3d = 50 * [for (x=[-1,0,1],y=[-1,0,1],z=[-1,0,1]) [x,y,z]];
|
||||
vecs2d = [
|
||||
for (x=[-1,0,1], y=[-1,0,1]) if(x!=0||y!=0) [x,y],
|
||||
polar_to_xy(1, -75),
|
||||
polar_to_xy(1, 75)
|
||||
];
|
||||
vecs3d = [
|
||||
LEFT, RIGHT, FRONT, BACK, DOWN, UP,
|
||||
spherical_to_xyz(1, -30, 45),
|
||||
spherical_to_xyz(1, 0, 45),
|
||||
spherical_to_xyz(1, 30, 45),
|
||||
spherical_to_xyz(2, 30, 45),
|
||||
spherical_to_xyz(1, -30, 135),
|
||||
spherical_to_xyz(2, -30, 135),
|
||||
spherical_to_xyz(1, 0, 135),
|
||||
spherical_to_xyz(1, 30, 135),
|
||||
spherical_to_xyz(1, -30, 75),
|
||||
spherical_to_xyz(1, 45, 45),
|
||||
];
|
||||
angs = [-180, -90, -45, 0, 30, 45, 90];
|
||||
for (a = [-360*3:360:360*3]) {
|
||||
test(rot(a), affine3d_identity(), extra_info=str("rot(",a,") != identity"));
|
||||
test(rot(a,p=pts2d), pts2d, extra_info=str("rot(",a,",p=...), 2D"));
|
||||
test(rot(a,p=pts3d), pts3d, extra_info=str("rot(",a,",p=...), 3D"));
|
||||
}
|
||||
test(rot(90), [[0,-1,0,0],[1,0,0,0],[0,0,1,0],[0,0,0,1]])
|
||||
for (a=angs) {
|
||||
test(rot(a), affine3d_zrot(a), extra_info=str("Z angle (only) = ",a));
|
||||
test(rot([a,0,0]), affine3d_xrot(a), extra_info=str("X angle = ",a));
|
||||
test(rot([0,a,0]), affine3d_yrot(a), extra_info=str("Y angle = ",a));
|
||||
test(rot([0,0,a]), affine3d_zrot(a), extra_info=str("Z angle = ",a));
|
||||
pts2d = 50 * [for (x=[-1,0,1],y=[-1,0,1]) [x,y]];
|
||||
pts3d = 50 * [for (x=[-1,0,1],y=[-1,0,1],z=[-1,0,1]) [x,y,z]];
|
||||
vecs2d = [
|
||||
for (x=[-1,0,1], y=[-1,0,1]) if(x!=0||y!=0) [x,y],
|
||||
polar_to_xy(1, -75),
|
||||
polar_to_xy(1, 75)
|
||||
];
|
||||
vecs3d = [
|
||||
LEFT, RIGHT, FRONT, BACK, DOWN, UP,
|
||||
spherical_to_xyz(1, -30, 45),
|
||||
spherical_to_xyz(1, 0, 45),
|
||||
spherical_to_xyz(1, 30, 45),
|
||||
spherical_to_xyz(2, 30, 45),
|
||||
spherical_to_xyz(1, -30, 135),
|
||||
spherical_to_xyz(2, -30, 135),
|
||||
spherical_to_xyz(1, 0, 135),
|
||||
spherical_to_xyz(1, 30, 135),
|
||||
spherical_to_xyz(1, -30, 75),
|
||||
spherical_to_xyz(1, 45, 45),
|
||||
];
|
||||
angs = [-180, -90, -45, 0, 30, 45, 90];
|
||||
for (a = [-360*3:360:360*3]) {
|
||||
test(rot(a), affine3d_identity(), extra_info=str("rot(",a,") != identity"));
|
||||
test(rot(a,p=pts2d), pts2d, extra_info=str("rot(",a,",p=...), 2D"));
|
||||
test(rot(a,p=pts3d), pts3d, extra_info=str("rot(",a,",p=...), 3D"));
|
||||
}
|
||||
test(rot(90), [[0,-1,0,0],[1,0,0,0],[0,0,1,0],[0,0,0,1]])
|
||||
for (a=angs) {
|
||||
test(rot(a), affine3d_zrot(a), extra_info=str("Z angle (only) = ",a));
|
||||
test(rot([a,0,0]), affine3d_xrot(a), extra_info=str("X angle = ",a));
|
||||
test(rot([0,a,0]), affine3d_yrot(a), extra_info=str("Y angle = ",a));
|
||||
test(rot([0,0,a]), affine3d_zrot(a), extra_info=str("Z angle = ",a));
|
||||
|
||||
test(rot(a,p=pts2d), apply(affine3d_zrot(a),pts2d), extra_info=str("Z angle (only) = ",a, ", p=..., 2D"));
|
||||
test(rot([0,0,a],p=pts2d), apply(affine3d_zrot(a),pts2d), extra_info=str("Z angle = ",a, ", p=..., 2D"));
|
||||
test(rot(a,p=pts2d), apply(affine3d_zrot(a),pts2d), extra_info=str("Z angle (only) = ",a, ", p=..., 2D"));
|
||||
test(rot([0,0,a],p=pts2d), apply(affine3d_zrot(a),pts2d), extra_info=str("Z angle = ",a, ", p=..., 2D"));
|
||||
|
||||
test(rot(a,p=pts3d), apply(affine3d_zrot(a),pts3d), extra_info=str("Z angle (only) = ",a, ", p=..., 3D"));
|
||||
test(rot([a,0,0],p=pts3d), apply(affine3d_xrot(a),pts3d), extra_info=str("X angle = ",a, ", p=..., 3D"));
|
||||
test(rot([0,a,0],p=pts3d), apply(affine3d_yrot(a),pts3d), extra_info=str("Y angle = ",a, ", p=..., 3D"));
|
||||
test(rot([0,0,a],p=pts3d), apply(affine3d_zrot(a),pts3d), extra_info=str("Z angle = ",a, ", p=..., 3D"));
|
||||
}
|
||||
for (xa=angs, ya=angs, za=angs) {
|
||||
test(
|
||||
rot([xa,ya,za]),
|
||||
affine3d_chain([
|
||||
affine3d_xrot(xa),
|
||||
affine3d_yrot(ya),
|
||||
affine3d_zrot(za)
|
||||
]),
|
||||
extra_info=str("[X,Y,Z] = ",[xa,ya,za])
|
||||
);
|
||||
test(
|
||||
rot([xa,ya,za],p=pts3d),
|
||||
apply(
|
||||
affine3d_chain([
|
||||
affine3d_xrot(xa),
|
||||
affine3d_yrot(ya),
|
||||
affine3d_zrot(za)
|
||||
]),
|
||||
pts3d
|
||||
),
|
||||
extra_info=str("[X,Y,Z] = ",[xa,ya,za], ", p=...")
|
||||
);
|
||||
}
|
||||
for (vec1 = vecs3d) {
|
||||
for (ang = angs) {
|
||||
test(
|
||||
rot(a=ang, v=vec1),
|
||||
affine3d_rot_by_axis(vec1,ang),
|
||||
extra_info=str("a = ",ang,", v = ", vec1)
|
||||
);
|
||||
test(
|
||||
rot(a=ang, v=vec1, p=pts3d),
|
||||
apply(affine3d_rot_by_axis(vec1,ang), pts3d),
|
||||
extra_info=str("a = ",ang,", v = ", vec1, ", p=...")
|
||||
);
|
||||
}
|
||||
}
|
||||
for (vec1 = vecs2d) {
|
||||
for (vec2 = vecs2d) {
|
||||
test(
|
||||
rot(from=vec1, to=vec2, p=pts2d, planar=true),
|
||||
apply(affine2d_zrot(vang(vec2)-vang(vec1)), pts2d),
|
||||
extra_info=str(
|
||||
"from = ", vec1, ", ",
|
||||
"to = ", vec2, ", ",
|
||||
"planar = ", true, ", ",
|
||||
"p=..., 2D"
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
for (vec1 = vecs3d) {
|
||||
for (vec2 = vecs3d) {
|
||||
for (a = angs) {
|
||||
test(
|
||||
rot(from=vec1, to=vec2, a=a),
|
||||
affine3d_chain([
|
||||
affine3d_zrot(a),
|
||||
affine3d_rot_from_to(vec1,vec2)
|
||||
]),
|
||||
extra_info=str(
|
||||
"from = ", vec1, ", ",
|
||||
"to = ", vec2, ", ",
|
||||
"a = ", a
|
||||
)
|
||||
);
|
||||
test(
|
||||
rot(from=vec1, to=vec2, a=a, p=pts3d),
|
||||
apply(
|
||||
affine3d_chain([
|
||||
affine3d_zrot(a),
|
||||
affine3d_rot_from_to(vec1,vec2)
|
||||
]),
|
||||
pts3d
|
||||
),
|
||||
extra_info=str(
|
||||
"from = ", vec1, ", ",
|
||||
"to = ", vec2, ", ",
|
||||
"a = ", a, ", ",
|
||||
"p=..., 3D"
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
test(rot(a,p=pts3d), apply(affine3d_zrot(a),pts3d), extra_info=str("Z angle (only) = ",a, ", p=..., 3D"));
|
||||
test(rot([a,0,0],p=pts3d), apply(affine3d_xrot(a),pts3d), extra_info=str("X angle = ",a, ", p=..., 3D"));
|
||||
test(rot([0,a,0],p=pts3d), apply(affine3d_yrot(a),pts3d), extra_info=str("Y angle = ",a, ", p=..., 3D"));
|
||||
test(rot([0,0,a],p=pts3d), apply(affine3d_zrot(a),pts3d), extra_info=str("Z angle = ",a, ", p=..., 3D"));
|
||||
}
|
||||
for (xa=angs, ya=angs, za=angs) {
|
||||
test(
|
||||
rot([xa,ya,za]),
|
||||
affine3d_chain([
|
||||
affine3d_xrot(xa),
|
||||
affine3d_yrot(ya),
|
||||
affine3d_zrot(za)
|
||||
]),
|
||||
extra_info=str("[X,Y,Z] = ",[xa,ya,za])
|
||||
);
|
||||
test(
|
||||
rot([xa,ya,za],p=pts3d),
|
||||
apply(
|
||||
affine3d_chain([
|
||||
affine3d_xrot(xa),
|
||||
affine3d_yrot(ya),
|
||||
affine3d_zrot(za)
|
||||
]),
|
||||
pts3d
|
||||
),
|
||||
extra_info=str("[X,Y,Z] = ",[xa,ya,za], ", p=...")
|
||||
);
|
||||
}
|
||||
for (vec1 = vecs3d) {
|
||||
for (ang = angs) {
|
||||
test(
|
||||
rot(a=ang, v=vec1),
|
||||
affine3d_rot_by_axis(vec1,ang),
|
||||
extra_info=str("a = ",ang,", v = ", vec1)
|
||||
);
|
||||
test(
|
||||
rot(a=ang, v=vec1, p=pts3d),
|
||||
apply(affine3d_rot_by_axis(vec1,ang), pts3d),
|
||||
extra_info=str("a = ",ang,", v = ", vec1, ", p=...")
|
||||
);
|
||||
}
|
||||
}
|
||||
for (vec1 = vecs2d) {
|
||||
for (vec2 = vecs2d) {
|
||||
test(
|
||||
rot(from=vec1, to=vec2, p=pts2d, planar=true),
|
||||
apply(affine2d_zrot(vang(vec2)-vang(vec1)), pts2d),
|
||||
extra_info=str(
|
||||
"from = ", vec1, ", ",
|
||||
"to = ", vec2, ", ",
|
||||
"planar = ", true, ", ",
|
||||
"p=..., 2D"
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
for (vec1 = vecs3d) {
|
||||
for (vec2 = vecs3d) {
|
||||
for (a = angs) {
|
||||
test(
|
||||
rot(from=vec1, to=vec2, a=a),
|
||||
affine3d_chain([
|
||||
affine3d_zrot(a),
|
||||
affine3d_rot_from_to(vec1,vec2)
|
||||
]),
|
||||
extra_info=str(
|
||||
"from = ", vec1, ", ",
|
||||
"to = ", vec2, ", ",
|
||||
"a = ", a
|
||||
)
|
||||
);
|
||||
test(
|
||||
rot(from=vec1, to=vec2, a=a, p=pts3d),
|
||||
apply(
|
||||
affine3d_chain([
|
||||
affine3d_zrot(a),
|
||||
affine3d_rot_from_to(vec1,vec2)
|
||||
]),
|
||||
pts3d
|
||||
),
|
||||
extra_info=str(
|
||||
"from = ", vec1, ", ",
|
||||
"to = ", vec2, ", ",
|
||||
"a = ", a, ", ",
|
||||
"p=..., 3D"
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
test_rot();
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -2,121 +2,121 @@ include <BOSL2/std.scad>
|
||||
|
||||
|
||||
module test_is_vector() {
|
||||
assert(is_vector([1,2,3]) == true);
|
||||
assert(is_vector([[1,2,3]]) == false);
|
||||
assert(is_vector(["foo"]) == false);
|
||||
assert(is_vector([]) == false);
|
||||
assert(is_vector(1) == false);
|
||||
assert(is_vector("foo") == false);
|
||||
assert(is_vector(true) == false);
|
||||
assert(is_vector([1,2,3]) == true);
|
||||
assert(is_vector([[1,2,3]]) == false);
|
||||
assert(is_vector(["foo"]) == false);
|
||||
assert(is_vector([]) == false);
|
||||
assert(is_vector(1) == false);
|
||||
assert(is_vector("foo") == false);
|
||||
assert(is_vector(true) == false);
|
||||
}
|
||||
test_is_vector();
|
||||
|
||||
|
||||
module test_add_scalar() {
|
||||
assert(add_scalar([1,2,3],3) == [4,5,6]);
|
||||
assert(add_scalar([[1,2,3],[3,4,5]],3) == [[4,5,6],[6,7,8]]);
|
||||
assert(add_scalar([1,2,3],3) == [4,5,6]);
|
||||
assert(add_scalar([[1,2,3],[3,4,5]],3) == [[4,5,6],[6,7,8]]);
|
||||
}
|
||||
test_add_scalar();
|
||||
|
||||
|
||||
module test_vmul() {
|
||||
assert(vmul([3,4,5], [8,7,6]) == [24,28,30]);
|
||||
assert(vmul([1,2,3], [4,5,6]) == [4,10,18]);
|
||||
assert(vmul([3,4,5], [8,7,6]) == [24,28,30]);
|
||||
assert(vmul([1,2,3], [4,5,6]) == [4,10,18]);
|
||||
}
|
||||
test_vmul();
|
||||
|
||||
|
||||
module test_vdiv() {
|
||||
assert(vdiv([24,28,30], [8,7,6]) == [3, 4, 5]);
|
||||
assert(vdiv([24,28,30], [8,7,6]) == [3, 4, 5]);
|
||||
}
|
||||
test_vdiv();
|
||||
|
||||
|
||||
module test_vabs() {
|
||||
assert(vabs([2,4,8]) == [2,4,8]);
|
||||
assert(vabs([-2,-4,-8]) == [2,4,8]);
|
||||
assert(vabs([-2,4,8]) == [2,4,8]);
|
||||
assert(vabs([2,-4,8]) == [2,4,8]);
|
||||
assert(vabs([2,4,-8]) == [2,4,8]);
|
||||
assert(vabs([2,4,8]) == [2,4,8]);
|
||||
assert(vabs([-2,-4,-8]) == [2,4,8]);
|
||||
assert(vabs([-2,4,8]) == [2,4,8]);
|
||||
assert(vabs([2,-4,8]) == [2,4,8]);
|
||||
assert(vabs([2,4,-8]) == [2,4,8]);
|
||||
}
|
||||
test_vabs();
|
||||
|
||||
include <BOSL2/strings.scad>
|
||||
module test_vang() {
|
||||
assert(vang([1,0])==0);
|
||||
assert(vang([0,1])==90);
|
||||
assert(vang([-1,0])==180);
|
||||
assert(vang([0,-1])==-90);
|
||||
assert(vang([1,1])==45);
|
||||
assert(vang([-1,1])==135);
|
||||
assert(vang([1,-1])==-45);
|
||||
assert(vang([-1,-1])==-135);
|
||||
assert(vang([0,0,1])==[0,90]);
|
||||
assert(vang([0,1,1])==[90,45]);
|
||||
assert(vang([0,1,-1])==[90,-45]);
|
||||
assert(vang([1,0,0])==[0,0]);
|
||||
assert(vang([0,1,0])==[90,0]);
|
||||
assert(vang([0,-1,0])==[-90,0]);
|
||||
assert(vang([-1,0,0])==[180,0]);
|
||||
assert(vang([1,0,1])==[0,45]);
|
||||
assert(vang([0,1,1])==[90,45]);
|
||||
assert(vang([0,-1,1])==[-90,45]);
|
||||
assert(approx(vang([1,1,1]),[45, 35.2643896828]));
|
||||
assert(vang([1,0])==0);
|
||||
assert(vang([0,1])==90);
|
||||
assert(vang([-1,0])==180);
|
||||
assert(vang([0,-1])==-90);
|
||||
assert(vang([1,1])==45);
|
||||
assert(vang([-1,1])==135);
|
||||
assert(vang([1,-1])==-45);
|
||||
assert(vang([-1,-1])==-135);
|
||||
assert(vang([0,0,1])==[0,90]);
|
||||
assert(vang([0,1,1])==[90,45]);
|
||||
assert(vang([0,1,-1])==[90,-45]);
|
||||
assert(vang([1,0,0])==[0,0]);
|
||||
assert(vang([0,1,0])==[90,0]);
|
||||
assert(vang([0,-1,0])==[-90,0]);
|
||||
assert(vang([-1,0,0])==[180,0]);
|
||||
assert(vang([1,0,1])==[0,45]);
|
||||
assert(vang([0,1,1])==[90,45]);
|
||||
assert(vang([0,-1,1])==[-90,45]);
|
||||
assert(approx(vang([1,1,1]),[45, 35.2643896828]));
|
||||
}
|
||||
test_vang();
|
||||
|
||||
|
||||
module test_unit() {
|
||||
assert(unit([10,0,0]) == [1,0,0]);
|
||||
assert(unit([0,10,0]) == [0,1,0]);
|
||||
assert(unit([0,0,10]) == [0,0,1]);
|
||||
assert(abs(norm(unit([10,10,10]))-1) < EPSILON);
|
||||
assert(abs(norm(unit([-10,-10,-10]))-1) < EPSILON);
|
||||
assert(abs(norm(unit([-10,0,0]))-1) < EPSILON);
|
||||
assert(abs(norm(unit([0,-10,0]))-1) < EPSILON);
|
||||
assert(abs(norm(unit([0,0,-10]))-1) < EPSILON);
|
||||
assert(unit([10,0,0]) == [1,0,0]);
|
||||
assert(unit([0,10,0]) == [0,1,0]);
|
||||
assert(unit([0,0,10]) == [0,0,1]);
|
||||
assert(abs(norm(unit([10,10,10]))-1) < EPSILON);
|
||||
assert(abs(norm(unit([-10,-10,-10]))-1) < EPSILON);
|
||||
assert(abs(norm(unit([-10,0,0]))-1) < EPSILON);
|
||||
assert(abs(norm(unit([0,-10,0]))-1) < EPSILON);
|
||||
assert(abs(norm(unit([0,0,-10]))-1) < EPSILON);
|
||||
}
|
||||
test_unit();
|
||||
|
||||
|
||||
module test_vector_angle() {
|
||||
vecs = [[10,0,0], [-10,0,0], [0,10,0], [0,-10,0], [0,0,10], [0,0,-10]];
|
||||
for (a=vecs, b=vecs) {
|
||||
if(a==b) {
|
||||
assert(vector_angle(a,b)==0);
|
||||
assert(vector_angle([a,b])==0);
|
||||
} else if(a==-b) {
|
||||
assert(vector_angle(a,b)==180);
|
||||
assert(vector_angle([a,b])==180);
|
||||
} else {
|
||||
assert(vector_angle(a,b)==90);
|
||||
assert(vector_angle([a,b])==90);
|
||||
}
|
||||
}
|
||||
assert(abs(vector_angle([10,10,0],[10,0,0])-45) < EPSILON);
|
||||
assert(abs(vector_angle([[10,10,0],[10,0,0]])-45) < EPSILON);
|
||||
assert(abs(vector_angle([11,11,1],[1,1,1],[11,-9,1])-90) < EPSILON);
|
||||
assert(abs(vector_angle([[11,11,1],[1,1,1],[11,-9,1]])-90) < EPSILON);
|
||||
vecs = [[10,0,0], [-10,0,0], [0,10,0], [0,-10,0], [0,0,10], [0,0,-10]];
|
||||
for (a=vecs, b=vecs) {
|
||||
if(a==b) {
|
||||
assert(vector_angle(a,b)==0);
|
||||
assert(vector_angle([a,b])==0);
|
||||
} else if(a==-b) {
|
||||
assert(vector_angle(a,b)==180);
|
||||
assert(vector_angle([a,b])==180);
|
||||
} else {
|
||||
assert(vector_angle(a,b)==90);
|
||||
assert(vector_angle([a,b])==90);
|
||||
}
|
||||
}
|
||||
assert(abs(vector_angle([10,10,0],[10,0,0])-45) < EPSILON);
|
||||
assert(abs(vector_angle([[10,10,0],[10,0,0]])-45) < EPSILON);
|
||||
assert(abs(vector_angle([11,11,1],[1,1,1],[11,-9,1])-90) < EPSILON);
|
||||
assert(abs(vector_angle([[11,11,1],[1,1,1],[11,-9,1]])-90) < EPSILON);
|
||||
}
|
||||
test_vector_angle();
|
||||
|
||||
|
||||
module test_vector_axis() {
|
||||
assert(norm(vector_axis([10,0,0],[10,10,0]) - [0,0,1]) < EPSILON);
|
||||
assert(norm(vector_axis([[10,0,0],[10,10,0]]) - [0,0,1]) < EPSILON);
|
||||
assert(norm(vector_axis([10,0,0],[0,10,0]) - [0,0,1]) < EPSILON);
|
||||
assert(norm(vector_axis([[10,0,0],[0,10,0]]) - [0,0,1]) < EPSILON);
|
||||
assert(norm(vector_axis([0,10,0],[10,0,0]) - [0,0,-1]) < EPSILON);
|
||||
assert(norm(vector_axis([[0,10,0],[10,0,0]]) - [0,0,-1]) < EPSILON);
|
||||
assert(norm(vector_axis([0,0,10],[10,0,0]) - [0,1,0]) < EPSILON);
|
||||
assert(norm(vector_axis([[0,0,10],[10,0,0]]) - [0,1,0]) < EPSILON);
|
||||
assert(norm(vector_axis([10,0,0],[0,0,10]) - [0,-1,0]) < EPSILON);
|
||||
assert(norm(vector_axis([[10,0,0],[0,0,10]]) - [0,-1,0]) < EPSILON);
|
||||
assert(norm(vector_axis([10,0,10],[0,-10,0]) - [sin(45),0,-sin(45)]) < EPSILON);
|
||||
assert(norm(vector_axis([[10,0,10],[0,-10,0]]) - [sin(45),0,-sin(45)]) < EPSILON);
|
||||
assert(norm(vector_axis([11,1,11],[1,1,1],[1,-9,1]) - [sin(45),0,-sin(45)]) < EPSILON);
|
||||
assert(norm(vector_axis([[11,1,11],[1,1,1],[1,-9,1]]) - [sin(45),0,-sin(45)]) < EPSILON);
|
||||
assert(norm(vector_axis([10,0,0],[10,10,0]) - [0,0,1]) < EPSILON);
|
||||
assert(norm(vector_axis([[10,0,0],[10,10,0]]) - [0,0,1]) < EPSILON);
|
||||
assert(norm(vector_axis([10,0,0],[0,10,0]) - [0,0,1]) < EPSILON);
|
||||
assert(norm(vector_axis([[10,0,0],[0,10,0]]) - [0,0,1]) < EPSILON);
|
||||
assert(norm(vector_axis([0,10,0],[10,0,0]) - [0,0,-1]) < EPSILON);
|
||||
assert(norm(vector_axis([[0,10,0],[10,0,0]]) - [0,0,-1]) < EPSILON);
|
||||
assert(norm(vector_axis([0,0,10],[10,0,0]) - [0,1,0]) < EPSILON);
|
||||
assert(norm(vector_axis([[0,0,10],[10,0,0]]) - [0,1,0]) < EPSILON);
|
||||
assert(norm(vector_axis([10,0,0],[0,0,10]) - [0,-1,0]) < EPSILON);
|
||||
assert(norm(vector_axis([[10,0,0],[0,0,10]]) - [0,-1,0]) < EPSILON);
|
||||
assert(norm(vector_axis([10,0,10],[0,-10,0]) - [sin(45),0,-sin(45)]) < EPSILON);
|
||||
assert(norm(vector_axis([[10,0,10],[0,-10,0]]) - [sin(45),0,-sin(45)]) < EPSILON);
|
||||
assert(norm(vector_axis([11,1,11],[1,1,1],[1,-9,1]) - [sin(45),0,-sin(45)]) < EPSILON);
|
||||
assert(norm(vector_axis([[11,1,11],[1,1,1],[1,-9,1]]) - [sin(45),0,-sin(45)]) < EPSILON);
|
||||
}
|
||||
test_vector_axis();
|
||||
|
||||
@ -124,4 +124,4 @@ test_vector_axis();
|
||||
cube();
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -2,116 +2,116 @@ include <BOSL2/std.scad>
|
||||
|
||||
|
||||
module test_bosl_version() {
|
||||
assert(is_vector(bosl_version())); // Returned value is a vector.
|
||||
assert(len(bosl_version())==3); // of three numbers.
|
||||
assert(bosl_version()[0]==2); // The major version is 2.
|
||||
for (v=bosl_version()) {
|
||||
assert(floor(v)==v); // All version parts are integers.
|
||||
}
|
||||
assert(is_vector(bosl_version())); // Returned value is a vector.
|
||||
assert(len(bosl_version())==3); // of three numbers.
|
||||
assert(bosl_version()[0]==2); // The major version is 2.
|
||||
for (v=bosl_version()) {
|
||||
assert(floor(v)==v); // All version parts are integers.
|
||||
}
|
||||
}
|
||||
test_bosl_version();
|
||||
|
||||
|
||||
module test_bosl_version_num() {
|
||||
assert(is_num(bosl_version_num()));
|
||||
v = bosl_version();
|
||||
assert(bosl_version_num() == v[0]+v[1]/100+v[2]/1000000);
|
||||
assert(is_num(bosl_version_num()));
|
||||
v = bosl_version();
|
||||
assert(bosl_version_num() == v[0]+v[1]/100+v[2]/1000000);
|
||||
}
|
||||
test_bosl_version_num();
|
||||
|
||||
|
||||
module test_bosl_version_str() {
|
||||
assert(is_string(bosl_version_str()));
|
||||
v = bosl_version();
|
||||
assert(bosl_version_str() == str(v[0],".",v[1],".",v[2]));
|
||||
assert(is_string(bosl_version_str()));
|
||||
v = bosl_version();
|
||||
assert(bosl_version_str() == str(v[0],".",v[1],".",v[2]));
|
||||
}
|
||||
test_bosl_version_str();
|
||||
|
||||
|
||||
module test_bosl_required() {
|
||||
bosl_required(2.000001);
|
||||
bosl_required("2.0.1");
|
||||
bosl_required([2,0,1]);
|
||||
bosl_required(2.000001);
|
||||
bosl_required("2.0.1");
|
||||
bosl_required([2,0,1]);
|
||||
}
|
||||
test_bosl_required();
|
||||
|
||||
|
||||
module test_version_to_list() {
|
||||
assert(is_list(version_to_list(2.010001)));
|
||||
assert(is_list(version_to_list("2.1.1")));
|
||||
assert(is_list(version_to_list([2,1,1])));
|
||||
assert(version_to_list(2.010001)==[2,1,1]);
|
||||
assert(version_to_list("2.1.1")==[2,1,1]);
|
||||
assert(version_to_list([2,1,1])==[2,1,1]);
|
||||
assert(version_to_list(2.010035)==[2,1,35]);
|
||||
assert(version_to_list(2.345678)==[2,34,5678]);
|
||||
assert(version_to_list("2.34.5678")==[2,34,5678]);
|
||||
assert(version_to_list([2,34,5678])==[2,34,5678]);
|
||||
assert(version_to_list([2,34,56,78])==[2,34,56]);
|
||||
assert(is_list(version_to_list(2.010001)));
|
||||
assert(is_list(version_to_list("2.1.1")));
|
||||
assert(is_list(version_to_list([2,1,1])));
|
||||
assert(version_to_list(2.010001)==[2,1,1]);
|
||||
assert(version_to_list("2.1.1")==[2,1,1]);
|
||||
assert(version_to_list([2,1,1])==[2,1,1]);
|
||||
assert(version_to_list(2.010035)==[2,1,35]);
|
||||
assert(version_to_list(2.345678)==[2,34,5678]);
|
||||
assert(version_to_list("2.34.5678")==[2,34,5678]);
|
||||
assert(version_to_list([2,34,5678])==[2,34,5678]);
|
||||
assert(version_to_list([2,34,56,78])==[2,34,56]);
|
||||
}
|
||||
test_version_to_list();
|
||||
|
||||
|
||||
module test_version_to_str() {
|
||||
assert(is_string(version_to_str(2.010001)));
|
||||
assert(is_string(version_to_str("2.1.1")));
|
||||
assert(is_string(version_to_str([2,1,1])));
|
||||
assert(version_to_str(2.010001)=="2.1.1");
|
||||
assert(version_to_str("2.1.1")=="2.1.1");
|
||||
assert(version_to_str([2,1,1])=="2.1.1");
|
||||
assert(version_to_str(2.345678)=="2.34.5678");
|
||||
assert(version_to_str("2.34.5678")=="2.34.5678");
|
||||
assert(version_to_str([2,34,5678])=="2.34.5678");
|
||||
assert(version_to_str([2,34,56,78])=="2.34.56");
|
||||
assert(is_string(version_to_str(2.010001)));
|
||||
assert(is_string(version_to_str("2.1.1")));
|
||||
assert(is_string(version_to_str([2,1,1])));
|
||||
assert(version_to_str(2.010001)=="2.1.1");
|
||||
assert(version_to_str("2.1.1")=="2.1.1");
|
||||
assert(version_to_str([2,1,1])=="2.1.1");
|
||||
assert(version_to_str(2.345678)=="2.34.5678");
|
||||
assert(version_to_str("2.34.5678")=="2.34.5678");
|
||||
assert(version_to_str([2,34,5678])=="2.34.5678");
|
||||
assert(version_to_str([2,34,56,78])=="2.34.56");
|
||||
}
|
||||
test_version_to_str();
|
||||
|
||||
|
||||
module test_version_to_num() {
|
||||
assert(is_num(version_to_num(2.010001)));
|
||||
assert(is_num(version_to_num("2.1.1")));
|
||||
assert(is_num(version_to_num([2,1,1])));
|
||||
assert(version_to_num(2.010001)==2.010001);
|
||||
assert(version_to_num("2.1.1")==2.010001);
|
||||
assert(version_to_num([2,1,1])==2.010001);
|
||||
assert(version_to_num(2.345678)==2.345678);
|
||||
assert(version_to_num("2.34.5678")==2.345678);
|
||||
assert(version_to_num([2,34,5678])==2.345678);
|
||||
assert(version_to_num([2,34,56,78])==2.340056);
|
||||
assert(is_num(version_to_num(2.010001)));
|
||||
assert(is_num(version_to_num("2.1.1")));
|
||||
assert(is_num(version_to_num([2,1,1])));
|
||||
assert(version_to_num(2.010001)==2.010001);
|
||||
assert(version_to_num("2.1.1")==2.010001);
|
||||
assert(version_to_num([2,1,1])==2.010001);
|
||||
assert(version_to_num(2.345678)==2.345678);
|
||||
assert(version_to_num("2.34.5678")==2.345678);
|
||||
assert(version_to_num([2,34,5678])==2.345678);
|
||||
assert(version_to_num([2,34,56,78])==2.340056);
|
||||
}
|
||||
test_version_to_num();
|
||||
|
||||
|
||||
module test_version_cmp() {
|
||||
function diversify(x) = [
|
||||
version_to_num(x),
|
||||
version_to_str(x),
|
||||
version_to_list(x)
|
||||
];
|
||||
function diversify(x) = [
|
||||
version_to_num(x),
|
||||
version_to_str(x),
|
||||
version_to_list(x)
|
||||
];
|
||||
|
||||
module testvercmp(x,y,z) {
|
||||
for (a = diversify(y)) {
|
||||
for (b = diversify(x)) {
|
||||
assert(version_cmp(a,b)>0);
|
||||
}
|
||||
for (b = diversify(y)) {
|
||||
assert(version_cmp(a,b)==0);
|
||||
}
|
||||
for (b = diversify(z)) {
|
||||
assert(version_cmp(a,b)<0);
|
||||
}
|
||||
}
|
||||
}
|
||||
module testvercmp(x,y,z) {
|
||||
for (a = diversify(y)) {
|
||||
for (b = diversify(x)) {
|
||||
assert(version_cmp(a,b)>0);
|
||||
}
|
||||
for (b = diversify(y)) {
|
||||
assert(version_cmp(a,b)==0);
|
||||
}
|
||||
for (b = diversify(z)) {
|
||||
assert(version_cmp(a,b)<0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
testvercmp([2,1,33],[2,1,34],[2,1,35]);
|
||||
testvercmp([2,2,1],[2,2,34],[2,2,67]);
|
||||
testvercmp([2,2,34],[2,3,34],[2,4,34]);
|
||||
testvercmp([2,3,34],[3,3,34],[4,3,34]);
|
||||
testvercmp([2,3,34],[3,1,1],[4,1,1]);
|
||||
testvercmp([2,1,1],[3,3,34],[4,1,1]);
|
||||
testvercmp([2,1,1],[3,1,1],[4,3,34]);
|
||||
testvercmp([2,1,33],[2,1,34],[2,1,35]);
|
||||
testvercmp([2,2,1],[2,2,34],[2,2,67]);
|
||||
testvercmp([2,2,34],[2,3,34],[2,4,34]);
|
||||
testvercmp([2,3,34],[3,3,34],[4,3,34]);
|
||||
testvercmp([2,3,34],[3,1,1],[4,1,1]);
|
||||
testvercmp([2,1,1],[3,3,34],[4,1,1]);
|
||||
testvercmp([2,1,1],[3,1,1],[4,3,34]);
|
||||
}
|
||||
test_version_cmp();
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -3,101 +3,101 @@ include <BOSL2/vnf.scad>
|
||||
|
||||
|
||||
module test_is_vnf() {
|
||||
assert(is_vnf([[],[]]));
|
||||
assert(!is_vnf([]));
|
||||
assert(is_vnf([[[-1,-1,-1],[1,-1,-1],[0,1,-1],[0,0,1]],[[0,1,2],[0,3,1],[1,3,2],[2,3,0]]]));
|
||||
assert(is_vnf([[],[]]));
|
||||
assert(!is_vnf([]));
|
||||
assert(is_vnf([[[-1,-1,-1],[1,-1,-1],[0,1,-1],[0,0,1]],[[0,1,2],[0,3,1],[1,3,2],[2,3,0]]]));
|
||||
}
|
||||
test_is_vnf();
|
||||
|
||||
|
||||
module test_is_vnf_list() {
|
||||
assert(is_vnf_list([]));
|
||||
assert(!is_vnf_list([[],[]]));
|
||||
assert(is_vnf_list([[[],[]]]));
|
||||
assert(!is_vnf_list([[[-1,-1,-1],[1,-1,-1],[0,1,-1],[0,0,1]],[[0,1,2],[0,3,1],[1,3,2],[2,3,0]]]));
|
||||
assert(is_vnf_list([[[[-1,-1,-1],[1,-1,-1],[0,1,-1],[0,0,1]],[[0,1,2],[0,3,1],[1,3,2],[2,3,0]]]]));
|
||||
assert(is_vnf_list([]));
|
||||
assert(!is_vnf_list([[],[]]));
|
||||
assert(is_vnf_list([[[],[]]]));
|
||||
assert(!is_vnf_list([[[-1,-1,-1],[1,-1,-1],[0,1,-1],[0,0,1]],[[0,1,2],[0,3,1],[1,3,2],[2,3,0]]]));
|
||||
assert(is_vnf_list([[[[-1,-1,-1],[1,-1,-1],[0,1,-1],[0,0,1]],[[0,1,2],[0,3,1],[1,3,2],[2,3,0]]]]));
|
||||
}
|
||||
test_is_vnf_list();
|
||||
|
||||
|
||||
module test_vnf_vertices() {
|
||||
vnf = [[[-1,-1,-1],[1,-1,-1],[0,1,-1],[0,0,1]],[[0,1,2],[0,3,1],[1,3,2],[2,3,0]]];
|
||||
assert(vnf_vertices(vnf) == vnf[0]);
|
||||
vnf = [[[-1,-1,-1],[1,-1,-1],[0,1,-1],[0,0,1]],[[0,1,2],[0,3,1],[1,3,2],[2,3,0]]];
|
||||
assert(vnf_vertices(vnf) == vnf[0]);
|
||||
}
|
||||
test_vnf_vertices();
|
||||
|
||||
|
||||
module test_vnf_faces() {
|
||||
vnf = [[[-1,-1,-1],[1,-1,-1],[0,1,-1],[0,0,1]],[[0,1,2],[0,3,1],[1,3,2],[2,3,0]]];
|
||||
assert(vnf_faces(vnf) == vnf[1]);
|
||||
vnf = [[[-1,-1,-1],[1,-1,-1],[0,1,-1],[0,0,1]],[[0,1,2],[0,3,1],[1,3,2],[2,3,0]]];
|
||||
assert(vnf_faces(vnf) == vnf[1]);
|
||||
}
|
||||
test_vnf_faces();
|
||||
|
||||
|
||||
module test_vnf_get_vertex() {
|
||||
vnf = [[[-1,-1,-1],[1,-1,-1],[0,1,-1],[0,0,1]],[[0,1,2],[0,3,1],[1,3,2],[2,3,0]]];
|
||||
assert(vnf_get_vertex(vnf,[0,1,-1]) == [2,vnf]);
|
||||
assert(vnf_get_vertex(vnf,[0,1,2]) == [4,[concat(vnf[0],[[0,1,2]]),vnf[1]]]);
|
||||
vnf = [[[-1,-1,-1],[1,-1,-1],[0,1,-1],[0,0,1]],[[0,1,2],[0,3,1],[1,3,2],[2,3,0]]];
|
||||
assert(vnf_get_vertex(vnf,[0,1,-1]) == [2,vnf]);
|
||||
assert(vnf_get_vertex(vnf,[0,1,2]) == [4,[concat(vnf[0],[[0,1,2]]),vnf[1]]]);
|
||||
}
|
||||
test_vnf_get_vertex();
|
||||
|
||||
|
||||
module test_vnf_add_face() {
|
||||
verts = [[-1,-1,-1],[1,-1,-1],[0,1,-1],[0,0,1]];
|
||||
faces = [[0,1,2],[0,3,1],[1,3,2],[2,3,0]];
|
||||
vnf1 = vnf_add_face(pts=select(verts,faces[0]));
|
||||
vnf2 = vnf_add_face(vnf1, pts=select(verts,faces[1]));
|
||||
vnf3 = vnf_add_face(vnf2, pts=select(verts,faces[2]));
|
||||
vnf4 = vnf_add_face(vnf3, pts=select(verts,faces[3]));
|
||||
assert(vnf1 == [select(verts,0,2),select(faces,[0])]);
|
||||
assert(vnf2 == [verts,select(faces,[0:1])]);
|
||||
assert(vnf3 == [verts,select(faces,[0:2])]);
|
||||
assert(vnf4 == [verts,faces]);
|
||||
verts = [[-1,-1,-1],[1,-1,-1],[0,1,-1],[0,0,1]];
|
||||
faces = [[0,1,2],[0,3,1],[1,3,2],[2,3,0]];
|
||||
vnf1 = vnf_add_face(pts=select(verts,faces[0]));
|
||||
vnf2 = vnf_add_face(vnf1, pts=select(verts,faces[1]));
|
||||
vnf3 = vnf_add_face(vnf2, pts=select(verts,faces[2]));
|
||||
vnf4 = vnf_add_face(vnf3, pts=select(verts,faces[3]));
|
||||
assert(vnf1 == [select(verts,0,2),select(faces,[0])]);
|
||||
assert(vnf2 == [verts,select(faces,[0:1])]);
|
||||
assert(vnf3 == [verts,select(faces,[0:2])]);
|
||||
assert(vnf4 == [verts,faces]);
|
||||
}
|
||||
test_vnf_add_face();
|
||||
|
||||
|
||||
module test_vnf_add_faces() {
|
||||
verts = [[-1,-1,-1],[1,-1,-1],[0,1,-1],[0,0,1]];
|
||||
faces = [[0,1,2],[0,3,1],[1,3,2],[2,3,0]];
|
||||
assert(vnf_add_faces(faces=[for (face=faces) select(verts,face)]) == [verts,faces]);
|
||||
verts = [[-1,-1,-1],[1,-1,-1],[0,1,-1],[0,0,1]];
|
||||
faces = [[0,1,2],[0,3,1],[1,3,2],[2,3,0]];
|
||||
assert(vnf_add_faces(faces=[for (face=faces) select(verts,face)]) == [verts,faces]);
|
||||
}
|
||||
test_vnf_add_faces();
|
||||
|
||||
|
||||
module test_vnf_merge() {
|
||||
vnf1 = vnf_add_face(pts=[[-1,-1,-1],[1,-1,-1],[0,1,-1]]);
|
||||
vnf2 = vnf_add_face(pts=[[1,1,1],[-1,1,1],[0,1,-1]]);
|
||||
assert(vnf_merge([vnf1,vnf2]) == [[[-1,-1,-1],[1,-1,-1],[0,1,-1],[1,1,1],[-1,1,1],[0,1,-1]],[[0,1,2],[3,4,5]]]);
|
||||
vnf1 = vnf_add_face(pts=[[-1,-1,-1],[1,-1,-1],[0,1,-1]]);
|
||||
vnf2 = vnf_add_face(pts=[[1,1,1],[-1,1,1],[0,1,-1]]);
|
||||
assert(vnf_merge([vnf1,vnf2]) == [[[-1,-1,-1],[1,-1,-1],[0,1,-1],[1,1,1],[-1,1,1],[0,1,-1]],[[0,1,2],[3,4,5]]]);
|
||||
}
|
||||
test_vnf_merge();
|
||||
|
||||
|
||||
module test_vnf_triangulate() {
|
||||
vnf = [[[-1,-1,0],[1,-1,0],[1,1,0],[-1,1,0]],[[0,1,2,3]]];
|
||||
assert(vnf_triangulate(vnf) == [[[-1,-1,0],[1,-1,0],[1,1,0],[-1,1,0]], [[0,1,2],[2,3,0]]]);
|
||||
vnf = [[[-1,-1,0],[1,-1,0],[1,1,0],[-1,1,0]],[[0,1,2,3]]];
|
||||
assert(vnf_triangulate(vnf) == [[[-1,-1,0],[1,-1,0],[1,1,0],[-1,1,0]], [[0,1,2],[2,3,0]]]);
|
||||
}
|
||||
test_vnf_triangulate();
|
||||
|
||||
|
||||
module test_vnf_vertex_array() {
|
||||
vnf1 = vnf_vertex_array(
|
||||
points=[for (h=[0:100:100]) [[100,-50,h],[-100,-50,h],[0,100,h]]],
|
||||
col_wrap=true, caps=true
|
||||
);
|
||||
vnf2 = vnf_vertex_array(
|
||||
points=[for (h=[0:100:100]) [[100,-50,h],[-100,-50,h],[0,100,h]]],
|
||||
col_wrap=true, caps=true, style="alt"
|
||||
);
|
||||
vnf3 = vnf_vertex_array(
|
||||
points=[for (h=[0:100:100]) [[100,-50,h],[-100,-50,h],[0,100,h]]],
|
||||
col_wrap=true, caps=true, style="quincunx"
|
||||
);
|
||||
assert(vnf1 == [[[100,-50,0],[-100,-50,0],[0,100,0],[100,-50,100],[-100,-50,100],[0,100,100]],[[0,4,3],[0,1,4],[1,5,4],[1,2,5],[2,3,5],[2,0,3],[2,1,0],[3,4,5]]]);
|
||||
assert(vnf2 == [[[100,-50,0],[-100,-50,0],[0,100,0],[100,-50,100],[-100,-50,100],[0,100,100]],[[0,1,3],[3,1,4],[1,2,4],[4,2,5],[2,0,5],[5,0,3],[2,1,0],[3,4,5]]]);
|
||||
assert(vnf3 == [[[100,-50,0],[-100,-50,0],[0,100,0],[100,-50,100],[-100,-50,100],[0,100,100],[0,-50,50],[-50,25,50],[50,25,50]],[[0,6,3],[3,6,4],[4,6,1],[1,6,0],[1,7,4],[4,7,5],[5,7,2],[2,7,1],[2,8,5],[5,8,3],[3,8,0],[0,8,2],[2,1,0],[3,4,5]]]);
|
||||
vnf1 = vnf_vertex_array(
|
||||
points=[for (h=[0:100:100]) [[100,-50,h],[-100,-50,h],[0,100,h]]],
|
||||
col_wrap=true, caps=true
|
||||
);
|
||||
vnf2 = vnf_vertex_array(
|
||||
points=[for (h=[0:100:100]) [[100,-50,h],[-100,-50,h],[0,100,h]]],
|
||||
col_wrap=true, caps=true, style="alt"
|
||||
);
|
||||
vnf3 = vnf_vertex_array(
|
||||
points=[for (h=[0:100:100]) [[100,-50,h],[-100,-50,h],[0,100,h]]],
|
||||
col_wrap=true, caps=true, style="quincunx"
|
||||
);
|
||||
assert(vnf1 == [[[100,-50,0],[-100,-50,0],[0,100,0],[100,-50,100],[-100,-50,100],[0,100,100]],[[0,4,3],[0,1,4],[1,5,4],[1,2,5],[2,3,5],[2,0,3],[2,1,0],[3,4,5]]]);
|
||||
assert(vnf2 == [[[100,-50,0],[-100,-50,0],[0,100,0],[100,-50,100],[-100,-50,100],[0,100,100]],[[0,1,3],[3,1,4],[1,2,4],[4,2,5],[2,0,5],[5,0,3],[2,1,0],[3,4,5]]]);
|
||||
assert(vnf3 == [[[100,-50,0],[-100,-50,0],[0,100,0],[100,-50,100],[-100,-50,100],[0,100,100],[0,-50,50],[-50,25,50],[50,25,50]],[[0,6,3],[3,6,4],[4,6,1],[1,6,0],[1,7,4],[4,7,5],[5,7,2],[2,7,1],[2,8,5],[5,8,3],[3,8,0],[0,8,2],[2,1,0],[3,4,5]]]);
|
||||
}
|
||||
test_vnf_vertex_array();
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
936
threading.scad
936
threading.scad
File diff suppressed because it is too large
Load Diff
232
torx_drive.scad
232
torx_drive.scad
@ -17,22 +17,22 @@
|
||||
// Arguments:
|
||||
// size = Torx size.
|
||||
function torx_outer_diam(size) = lookup(size, [
|
||||
[ 6, 1.75],
|
||||
[ 8, 2.40],
|
||||
[ 10, 2.80],
|
||||
[ 15, 3.35],
|
||||
[ 20, 3.95],
|
||||
[ 25, 4.50],
|
||||
[ 30, 5.60],
|
||||
[ 40, 6.75],
|
||||
[ 45, 7.93],
|
||||
[ 50, 8.95],
|
||||
[ 55, 11.35],
|
||||
[ 60, 13.45],
|
||||
[ 70, 15.70],
|
||||
[ 80, 17.75],
|
||||
[ 90, 20.20],
|
||||
[100, 22.40]
|
||||
[ 6, 1.75],
|
||||
[ 8, 2.40],
|
||||
[ 10, 2.80],
|
||||
[ 15, 3.35],
|
||||
[ 20, 3.95],
|
||||
[ 25, 4.50],
|
||||
[ 30, 5.60],
|
||||
[ 40, 6.75],
|
||||
[ 45, 7.93],
|
||||
[ 50, 8.95],
|
||||
[ 55, 11.35],
|
||||
[ 60, 13.45],
|
||||
[ 70, 15.70],
|
||||
[ 80, 17.75],
|
||||
[ 90, 20.20],
|
||||
[100, 22.40]
|
||||
]);
|
||||
|
||||
|
||||
@ -41,22 +41,22 @@ function torx_outer_diam(size) = lookup(size, [
|
||||
// Arguments:
|
||||
// size = Torx size.
|
||||
function torx_inner_diam(size) = lookup(size, [
|
||||
[ 6, 1.27],
|
||||
[ 8, 1.75],
|
||||
[ 10, 2.05],
|
||||
[ 15, 2.40],
|
||||
[ 20, 2.85],
|
||||
[ 25, 3.25],
|
||||
[ 30, 4.05],
|
||||
[ 40, 4.85],
|
||||
[ 45, 5.64],
|
||||
[ 50, 6.45],
|
||||
[ 55, 8.05],
|
||||
[ 60, 9.60],
|
||||
[ 70, 11.20],
|
||||
[ 80, 12.80],
|
||||
[ 90, 14.40],
|
||||
[100, 16.00]
|
||||
[ 6, 1.27],
|
||||
[ 8, 1.75],
|
||||
[ 10, 2.05],
|
||||
[ 15, 2.40],
|
||||
[ 20, 2.85],
|
||||
[ 25, 3.25],
|
||||
[ 30, 4.05],
|
||||
[ 40, 4.85],
|
||||
[ 45, 5.64],
|
||||
[ 50, 6.45],
|
||||
[ 55, 8.05],
|
||||
[ 60, 9.60],
|
||||
[ 70, 11.20],
|
||||
[ 80, 12.80],
|
||||
[ 90, 14.40],
|
||||
[100, 16.00]
|
||||
]);
|
||||
|
||||
|
||||
@ -65,22 +65,22 @@ function torx_inner_diam(size) = lookup(size, [
|
||||
// Arguments:
|
||||
// size = Torx size.
|
||||
function torx_depth(size) = lookup(size, [
|
||||
[ 6, 1.82],
|
||||
[ 8, 3.05],
|
||||
[ 10, 3.56],
|
||||
[ 15, 3.81],
|
||||
[ 20, 4.07],
|
||||
[ 25, 4.45],
|
||||
[ 30, 4.95],
|
||||
[ 40, 5.59],
|
||||
[ 45, 6.22],
|
||||
[ 50, 6.48],
|
||||
[ 55, 6.73],
|
||||
[ 60, 8.17],
|
||||
[ 70, 8.96],
|
||||
[ 80, 9.90],
|
||||
[ 90, 10.56],
|
||||
[100, 11.35]
|
||||
[ 6, 1.82],
|
||||
[ 8, 3.05],
|
||||
[ 10, 3.56],
|
||||
[ 15, 3.81],
|
||||
[ 20, 4.07],
|
||||
[ 25, 4.45],
|
||||
[ 30, 4.95],
|
||||
[ 40, 5.59],
|
||||
[ 45, 6.22],
|
||||
[ 50, 6.48],
|
||||
[ 55, 6.73],
|
||||
[ 60, 8.17],
|
||||
[ 70, 8.96],
|
||||
[ 80, 9.90],
|
||||
[ 90, 10.56],
|
||||
[100, 11.35]
|
||||
]);
|
||||
|
||||
|
||||
@ -89,22 +89,22 @@ function torx_depth(size) = lookup(size, [
|
||||
// Arguments:
|
||||
// size = Torx size.
|
||||
function torx_tip_radius(size) = lookup(size, [
|
||||
[ 6, 0.132],
|
||||
[ 8, 0.190],
|
||||
[ 10, 0.229],
|
||||
[ 15, 0.267],
|
||||
[ 20, 0.305],
|
||||
[ 25, 0.375],
|
||||
[ 30, 0.451],
|
||||
[ 40, 0.546],
|
||||
[ 45, 0.574],
|
||||
[ 50, 0.775],
|
||||
[ 55, 0.867],
|
||||
[ 60, 1.067],
|
||||
[ 70, 1.194],
|
||||
[ 80, 1.526],
|
||||
[ 90, 1.530],
|
||||
[100, 1.720]
|
||||
[ 6, 0.132],
|
||||
[ 8, 0.190],
|
||||
[ 10, 0.229],
|
||||
[ 15, 0.267],
|
||||
[ 20, 0.305],
|
||||
[ 25, 0.375],
|
||||
[ 30, 0.451],
|
||||
[ 40, 0.546],
|
||||
[ 45, 0.574],
|
||||
[ 50, 0.775],
|
||||
[ 55, 0.867],
|
||||
[ 60, 1.067],
|
||||
[ 70, 1.194],
|
||||
[ 80, 1.526],
|
||||
[ 90, 1.530],
|
||||
[100, 1.720]
|
||||
]);
|
||||
|
||||
|
||||
@ -113,22 +113,22 @@ function torx_tip_radius(size) = lookup(size, [
|
||||
// Arguments:
|
||||
// size = Torx size.
|
||||
function torx_rounding_radius(size) = lookup(size, [
|
||||
[ 6, 0.383],
|
||||
[ 8, 0.510],
|
||||
[ 10, 0.598],
|
||||
[ 15, 0.716],
|
||||
[ 20, 0.859],
|
||||
[ 25, 0.920],
|
||||
[ 30, 1.194],
|
||||
[ 40, 1.428],
|
||||
[ 45, 1.796],
|
||||
[ 50, 1.816],
|
||||
[ 55, 2.667],
|
||||
[ 60, 2.883],
|
||||
[ 70, 3.477],
|
||||
[ 80, 3.627],
|
||||
[ 90, 4.468],
|
||||
[100, 4.925]
|
||||
[ 6, 0.383],
|
||||
[ 8, 0.510],
|
||||
[ 10, 0.598],
|
||||
[ 15, 0.716],
|
||||
[ 20, 0.859],
|
||||
[ 25, 0.920],
|
||||
[ 30, 1.194],
|
||||
[ 40, 1.428],
|
||||
[ 45, 1.796],
|
||||
[ 50, 1.816],
|
||||
[ 55, 2.667],
|
||||
[ 60, 2.883],
|
||||
[ 70, 3.477],
|
||||
[ 80, 3.627],
|
||||
[ 90, 4.468],
|
||||
[100, 4.925]
|
||||
]);
|
||||
|
||||
|
||||
@ -142,33 +142,33 @@ function torx_rounding_radius(size) = lookup(size, [
|
||||
// Example(2D):
|
||||
// torx_drive2d(size=30, $fa=1, $fs=1);
|
||||
module torx_drive2d(size) {
|
||||
od = torx_outer_diam(size);
|
||||
id = torx_inner_diam(size);
|
||||
tip = torx_tip_radius(size);
|
||||
rounding = torx_rounding_radius(size);
|
||||
base = od - 2*tip;
|
||||
$fn = quantup(segs(od/2),12);
|
||||
difference() {
|
||||
union() {
|
||||
circle(d=base);
|
||||
zrot_copies(n=2) {
|
||||
hull() {
|
||||
zrot_copies(n=3) {
|
||||
translate([base/2,0,0]) {
|
||||
circle(r=tip, $fn=$fn/2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
zrot_copies(n=6) {
|
||||
zrot(180/6) {
|
||||
translate([id/2+rounding,0,0]) {
|
||||
circle(r=rounding);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
od = torx_outer_diam(size);
|
||||
id = torx_inner_diam(size);
|
||||
tip = torx_tip_radius(size);
|
||||
rounding = torx_rounding_radius(size);
|
||||
base = od - 2*tip;
|
||||
$fn = quantup(segs(od/2),12);
|
||||
difference() {
|
||||
union() {
|
||||
circle(d=base);
|
||||
zrot_copies(n=2) {
|
||||
hull() {
|
||||
zrot_copies(n=3) {
|
||||
translate([base/2,0,0]) {
|
||||
circle(r=tip, $fn=$fn/2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
zrot_copies(n=6) {
|
||||
zrot(180/6) {
|
||||
translate([id/2+rounding,0,0]) {
|
||||
circle(r=rounding);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -185,17 +185,17 @@ module torx_drive2d(size) {
|
||||
// Examples:
|
||||
// torx_drive(size=30, l=10, $fa=1, $fs=1);
|
||||
module torx_drive(size, l=5, center, anchor, spin=0, orient=UP) {
|
||||
anchor = get_anchor(anchor, center, BOT, BOT);
|
||||
od = torx_outer_diam(size);
|
||||
attachable(anchor,spin,orient, d=od, l=l) {
|
||||
linear_extrude(height=l, convexity=4, center=true) {
|
||||
torx_drive2d(size);
|
||||
}
|
||||
children();
|
||||
}
|
||||
anchor = get_anchor(anchor, center, BOT, BOT);
|
||||
od = torx_outer_diam(size);
|
||||
attachable(anchor,spin,orient, d=od, l=l) {
|
||||
linear_extrude(height=l, convexity=4, center=true) {
|
||||
torx_drive2d(size);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
||||
|
256
transforms.scad
256
transforms.scad
@ -68,20 +68,20 @@
|
||||
// mat3d = move([2,3,4]); // Returns: [[1,0,0,2],[0,1,0,3],[0,0,1,4],[0,0,0,1]]
|
||||
module move(v=[0,0,0], x=0, y=0, z=0)
|
||||
{
|
||||
translate(point3d(v)+[x,y,z]) children();
|
||||
translate(point3d(v)+[x,y,z]) children();
|
||||
}
|
||||
|
||||
function move(v=[0,0,0], p=undef, x=0, y=0, z=0) =
|
||||
is_undef(p)? (
|
||||
len(v)==2? affine2d_translate(v+[x,y]) :
|
||||
affine3d_translate(point3d(v)+[x,y,z])
|
||||
) : (
|
||||
assert(is_list(p))
|
||||
let(v=v+[x,y,z])
|
||||
is_num(p.x)? p+v :
|
||||
is_vnf(p)? [move(v=v,p=p.x), p.y] :
|
||||
[for (l=p) is_vector(l)? l+v : move(v=v, p=l)]
|
||||
);
|
||||
is_undef(p)? (
|
||||
len(v)==2? affine2d_translate(v+[x,y]) :
|
||||
affine3d_translate(point3d(v)+[x,y,z])
|
||||
) : (
|
||||
assert(is_list(p))
|
||||
let(v=v+[x,y,z])
|
||||
is_num(p.x)? p+v :
|
||||
is_vnf(p)? [move(v=v,p=p.x), p.y] :
|
||||
[for (l=p) is_vector(l)? l+v : move(v=v, p=l)]
|
||||
);
|
||||
|
||||
function translate(v=[0,0,0], p=undef) = move(v=v, p=p);
|
||||
|
||||
@ -337,57 +337,57 @@ function up(z=0,p=undef) = move([0,0,z],p=p);
|
||||
// stroke(rot(30,p=path), closed=true);
|
||||
module rot(a=0, v=undef, cp=undef, from=undef, to=undef, reverse=false)
|
||||
{
|
||||
m = rot(a=a, v=v, cp=cp, from=from, to=to, reverse=reverse, planar=false);
|
||||
multmatrix(m) children();
|
||||
m = rot(a=a, v=v, cp=cp, from=from, to=to, reverse=reverse, planar=false);
|
||||
multmatrix(m) children();
|
||||
}
|
||||
|
||||
function rot(a=0, v, cp, from, to, reverse=false, planar=false, p, _m) =
|
||||
assert(is_undef(from)==is_undef(to), "from and to must be specified together.")
|
||||
is_undef(p)? (
|
||||
planar? let(
|
||||
cp = is_undef(cp)? cp : point2d(cp),
|
||||
m1 = is_undef(from)? affine2d_zrot(a) :
|
||||
assert(is_vector(from))
|
||||
assert(!approx(norm(from),0))
|
||||
assert(approx(point3d(from).z, 0))
|
||||
assert(is_vector(to))
|
||||
assert(!approx(norm(to),0))
|
||||
assert(approx(point3d(to).z, 0))
|
||||
affine2d_zrot(
|
||||
vang(point2d(to)) -
|
||||
vang(point2d(from))
|
||||
),
|
||||
m2 = is_undef(cp)? m1 : (move(cp) * m1 * move(-cp)),
|
||||
m3 = reverse? matrix_inverse(m2) : m2
|
||||
) m3 : let(
|
||||
from = is_undef(from)? undef : point3d(from),
|
||||
to = is_undef(to)? undef : point3d(to),
|
||||
cp = is_undef(cp)? undef : point3d(cp),
|
||||
m1 = !is_undef(from)? (
|
||||
assert(is_vector(from))
|
||||
assert(!approx(norm(from),0))
|
||||
assert(is_vector(to))
|
||||
assert(!approx(norm(to),0))
|
||||
affine3d_rot_from_to(from,to) * affine3d_zrot(a)
|
||||
) :
|
||||
!is_undef(v)? affine3d_rot_by_axis(v,a) :
|
||||
is_num(a)? affine3d_zrot(a) :
|
||||
affine3d_zrot(a.z) * affine3d_yrot(a.y) * affine3d_xrot(a.x),
|
||||
m2 = is_undef(cp)? m1 : (move(cp) * m1 * move(-cp)),
|
||||
m3 = reverse? matrix_inverse(m2) : m2
|
||||
) m3
|
||||
) : (
|
||||
assert(is_list(p))
|
||||
let(
|
||||
m = !is_undef(_m)? _m :
|
||||
rot(a=a, v=v, cp=cp, from=from, to=to, reverse=reverse, planar=planar),
|
||||
res = p==[]? [] :
|
||||
is_vector(p)? apply(m, p) :
|
||||
is_vnf(p)? [apply(m, p[0]), p[1]] :
|
||||
is_list(p[0])? [for (pp=p) rot(p=pp, _m=m)] :
|
||||
assert(false, "The p argument for rot() is not a point, path, patch, matrix, or VNF.")
|
||||
) res
|
||||
);
|
||||
assert(is_undef(from)==is_undef(to), "from and to must be specified together.")
|
||||
is_undef(p)? (
|
||||
planar? let(
|
||||
cp = is_undef(cp)? cp : point2d(cp),
|
||||
m1 = is_undef(from)? affine2d_zrot(a) :
|
||||
assert(is_vector(from))
|
||||
assert(!approx(norm(from),0))
|
||||
assert(approx(point3d(from).z, 0))
|
||||
assert(is_vector(to))
|
||||
assert(!approx(norm(to),0))
|
||||
assert(approx(point3d(to).z, 0))
|
||||
affine2d_zrot(
|
||||
vang(point2d(to)) -
|
||||
vang(point2d(from))
|
||||
),
|
||||
m2 = is_undef(cp)? m1 : (move(cp) * m1 * move(-cp)),
|
||||
m3 = reverse? matrix_inverse(m2) : m2
|
||||
) m3 : let(
|
||||
from = is_undef(from)? undef : point3d(from),
|
||||
to = is_undef(to)? undef : point3d(to),
|
||||
cp = is_undef(cp)? undef : point3d(cp),
|
||||
m1 = !is_undef(from)? (
|
||||
assert(is_vector(from))
|
||||
assert(!approx(norm(from),0))
|
||||
assert(is_vector(to))
|
||||
assert(!approx(norm(to),0))
|
||||
affine3d_rot_from_to(from,to) * affine3d_zrot(a)
|
||||
) :
|
||||
!is_undef(v)? affine3d_rot_by_axis(v,a) :
|
||||
is_num(a)? affine3d_zrot(a) :
|
||||
affine3d_zrot(a.z) * affine3d_yrot(a.y) * affine3d_xrot(a.x),
|
||||
m2 = is_undef(cp)? m1 : (move(cp) * m1 * move(-cp)),
|
||||
m3 = reverse? matrix_inverse(m2) : m2
|
||||
) m3
|
||||
) : (
|
||||
assert(is_list(p))
|
||||
let(
|
||||
m = !is_undef(_m)? _m :
|
||||
rot(a=a, v=v, cp=cp, from=from, to=to, reverse=reverse, planar=planar),
|
||||
res = p==[]? [] :
|
||||
is_vector(p)? apply(m, p) :
|
||||
is_vnf(p)? [apply(m, p[0]), p[1]] :
|
||||
is_list(p[0])? [for (pp=p) rot(p=pp, _m=m)] :
|
||||
assert(false, "The p argument for rot() is not a point, path, patch, matrix, or VNF.")
|
||||
) res
|
||||
);
|
||||
|
||||
|
||||
|
||||
@ -421,13 +421,13 @@ function rot(a=0, v, cp, from, to, reverse=false, planar=false, p, _m) =
|
||||
// xrot(90) cylinder(h=50, r=10, center=true);
|
||||
module xrot(a=0, cp=undef)
|
||||
{
|
||||
if (a==0) {
|
||||
children(); // May be slightly faster?
|
||||
} else if (!is_undef(cp)) {
|
||||
translate(cp) rotate([a, 0, 0]) translate(-cp) children();
|
||||
} else {
|
||||
rotate([a, 0, 0]) children();
|
||||
}
|
||||
if (a==0) {
|
||||
children(); // May be slightly faster?
|
||||
} else if (!is_undef(cp)) {
|
||||
translate(cp) rotate([a, 0, 0]) translate(-cp) children();
|
||||
} else {
|
||||
rotate([a, 0, 0]) children();
|
||||
}
|
||||
}
|
||||
|
||||
function xrot(a=0, cp=undef, p=undef) = rot([a,0,0], cp=cp, p=p);
|
||||
@ -462,13 +462,13 @@ function xrot(a=0, cp=undef, p=undef) = rot([a,0,0], cp=cp, p=p);
|
||||
// yrot(90) cylinder(h=50, r=10, center=true);
|
||||
module yrot(a=0, cp=undef)
|
||||
{
|
||||
if (a==0) {
|
||||
children(); // May be slightly faster?
|
||||
} else if (!is_undef(cp)) {
|
||||
translate(cp) rotate([0, a, 0]) translate(-cp) children();
|
||||
} else {
|
||||
rotate([0, a, 0]) children();
|
||||
}
|
||||
if (a==0) {
|
||||
children(); // May be slightly faster?
|
||||
} else if (!is_undef(cp)) {
|
||||
translate(cp) rotate([0, a, 0]) translate(-cp) children();
|
||||
} else {
|
||||
rotate([0, a, 0]) children();
|
||||
}
|
||||
}
|
||||
|
||||
function yrot(a=0, cp=undef, p=undef) = rot([0,a,0], cp=cp, p=p);
|
||||
@ -503,13 +503,13 @@ function yrot(a=0, cp=undef, p=undef) = rot([0,a,0], cp=cp, p=p);
|
||||
// zrot(90) cube(size=[60,20,40], center=true);
|
||||
module zrot(a=0, cp=undef)
|
||||
{
|
||||
if (a==0) {
|
||||
children(); // May be slightly faster?
|
||||
} else if (!is_undef(cp)) {
|
||||
translate(cp) rotate(a) translate(-cp) children();
|
||||
} else {
|
||||
rotate(a) children();
|
||||
}
|
||||
if (a==0) {
|
||||
children(); // May be slightly faster?
|
||||
} else if (!is_undef(cp)) {
|
||||
translate(cp) rotate(a) translate(-cp) children();
|
||||
} else {
|
||||
rotate(a) children();
|
||||
}
|
||||
}
|
||||
|
||||
function zrot(a=0, cp=undef, p=undef) = rot(a, cp=cp, p=p);
|
||||
@ -551,20 +551,20 @@ function zrot(a=0, cp=undef, p=undef) = rot(a, cp=cp, p=p);
|
||||
// #stroke(path,closed=true);
|
||||
// stroke(scale([1.5,3],p=path),closed=true);
|
||||
function scale(v=1, p=undef) =
|
||||
assert(is_num(v) || is_vector(v))
|
||||
assert(is_undef(p) || is_list(p))
|
||||
let(v = is_num(v)? [v,v,v] : v)
|
||||
is_undef(p)? (
|
||||
len(v)==2? affine2d_scale(v) : affine3d_scale(point3d(v))
|
||||
) : (
|
||||
assert(is_list(p))
|
||||
is_num(p.x)? vmul(p,v) :
|
||||
is_vnf(p)? let(inv=product([for (x=v) x<0? -1 : 1])) [
|
||||
scale(v=v,p=p.x),
|
||||
inv>=0? p.y : [for (l=p.y) reverse(l)]
|
||||
] :
|
||||
[for (l=p) is_vector(l)? vmul(l,v) : scale(v=v, p=l)]
|
||||
);
|
||||
assert(is_num(v) || is_vector(v))
|
||||
assert(is_undef(p) || is_list(p))
|
||||
let(v = is_num(v)? [v,v,v] : v)
|
||||
is_undef(p)? (
|
||||
len(v)==2? affine2d_scale(v) : affine3d_scale(point3d(v))
|
||||
) : (
|
||||
assert(is_list(p))
|
||||
is_num(p.x)? vmul(p,v) :
|
||||
is_vnf(p)? let(inv=product([for (x=v) x<0? -1 : 1])) [
|
||||
scale(v=v,p=p.x),
|
||||
inv>=0? p.y : [for (l=p.y) reverse(l)]
|
||||
] :
|
||||
[for (l=p) is_vector(l)? vmul(l,v) : scale(v=v, p=l)]
|
||||
);
|
||||
|
||||
|
||||
// Function&Module: xscale()
|
||||
@ -737,13 +737,13 @@ function zscale(z=1, p=undef) = scale([1,1,z],p=p);
|
||||
// #stroke(path,closed=true);
|
||||
// stroke(mirror(n, p=path),closed=true);
|
||||
function mirror(v, p) =
|
||||
assert(is_vector(v))
|
||||
assert(is_undef(p) || is_list(p))
|
||||
let(m = len(v)==2? affine2d_mirror(v) : affine3d_mirror(v))
|
||||
is_undef(p)? m :
|
||||
is_num(p.x)? apply(m,p) :
|
||||
is_vnf(p)? [mirror(v=v,p=p[0]), [for (face=p[1]) reverse(face)]] :
|
||||
[for (l=p) is_vector(l)? apply(m,l) : mirror(v=v, p=l)];
|
||||
assert(is_vector(v))
|
||||
assert(is_undef(p) || is_list(p))
|
||||
let(m = len(v)==2? affine2d_mirror(v) : affine3d_mirror(v))
|
||||
is_undef(p)? m :
|
||||
is_num(p.x)? apply(m,p) :
|
||||
is_vnf(p)? [mirror(v=v,p=p[0]), [for (face=p[1]) reverse(face)]] :
|
||||
[for (l=p) is_vector(l)? apply(m,l) : mirror(v=v, p=l)];
|
||||
|
||||
|
||||
// Function&Module: xflip()
|
||||
@ -780,8 +780,8 @@ function mirror(v, p) =
|
||||
module xflip(x=0) translate([x,0,0]) mirror([1,0,0]) translate([-x,0,0]) children();
|
||||
|
||||
function xflip(x=0,p) =
|
||||
x==0? mirror([1,0,0],p=p) :
|
||||
move([x,0,0],p=mirror([1,0,0],p=move([-x,0,0],p=p)));
|
||||
x==0? mirror([1,0,0],p=p) :
|
||||
move([x,0,0],p=mirror([1,0,0],p=move([-x,0,0],p=p)));
|
||||
|
||||
|
||||
// Function&Module: yflip()
|
||||
@ -818,8 +818,8 @@ function xflip(x=0,p) =
|
||||
module yflip(y=0) translate([0,y,0]) mirror([0,1,0]) translate([0,-y,0]) children();
|
||||
|
||||
function yflip(y=0,p) =
|
||||
y==0? mirror([0,1,0],p=p) :
|
||||
move([0,y,0],p=mirror([0,1,0],p=move([0,-y,0],p=p)));
|
||||
y==0? mirror([0,1,0],p=p) :
|
||||
move([0,y,0],p=mirror([0,1,0],p=move([0,-y,0],p=p)));
|
||||
|
||||
|
||||
|
||||
@ -857,8 +857,8 @@ function yflip(y=0,p) =
|
||||
module zflip(z=0) translate([0,0,z]) mirror([0,0,1]) translate([0,0,-z]) children();
|
||||
|
||||
function zflip(z=0,p) =
|
||||
z==0? mirror([0,0,1],p=p) :
|
||||
move([0,0,z],p=mirror([0,0,1],p=move([0,0,-z],p=p)));
|
||||
z==0? mirror([0,0,1],p=p) :
|
||||
move([0,0,z],p=mirror([0,0,1],p=move([0,0,-z],p=p)));
|
||||
|
||||
|
||||
|
||||
@ -918,29 +918,29 @@ function zflip(z=0,p) =
|
||||
// trace_polyline(close_path(pts), showpts=true);
|
||||
module skew(sxy=0, sxz=0, syx=0, syz=0, szx=0, szy=0)
|
||||
{
|
||||
multmatrix(
|
||||
affine3d_skew(sxy=sxy, sxz=sxz, syx=syx, syz=syz, szx=szx, szy=szy)
|
||||
) children();
|
||||
multmatrix(
|
||||
affine3d_skew(sxy=sxy, sxz=sxz, syx=syx, syz=syz, szx=szx, szy=szy)
|
||||
) children();
|
||||
}
|
||||
|
||||
function skew(p, sxy=0, sxz=0, syx=0, syz=0, szx=0, szy=0, planar=false) =
|
||||
let(
|
||||
planar = planar || (is_list(p) && is_num(p.x) && len(p)==2),
|
||||
m = planar? [
|
||||
[ 1, sxy, 0],
|
||||
[syx, 1, 0],
|
||||
[ 0, 0, 1]
|
||||
] : affine3d_skew(sxy=sxy, sxz=sxz, syx=syx, syz=syz, szx=szx, szy=szy)
|
||||
)
|
||||
is_undef(p)? m :
|
||||
assert(is_list(p))
|
||||
is_num(p.x)? (
|
||||
planar?
|
||||
point2d(m*concat(point2d(p),[1])) :
|
||||
point3d(m*concat(point3d(p),[1]))
|
||||
) :
|
||||
is_vnf(p)? [skew(sxy=sxy, sxz=sxz, syx=syx, syz=syz, szx=szx, szy=szy, planar=planar, p=p.x), p.y] :
|
||||
[for (l=p) skew(sxy=sxy, sxz=sxz, syx=syx, syz=syz, szx=szx, szy=szy, planar=planar, p=l)];
|
||||
let(
|
||||
planar = planar || (is_list(p) && is_num(p.x) && len(p)==2),
|
||||
m = planar? [
|
||||
[ 1, sxy, 0],
|
||||
[syx, 1, 0],
|
||||
[ 0, 0, 1]
|
||||
] : affine3d_skew(sxy=sxy, sxz=sxz, syx=syx, syz=syz, szx=szx, szy=szy)
|
||||
)
|
||||
is_undef(p)? m :
|
||||
assert(is_list(p))
|
||||
is_num(p.x)? (
|
||||
planar?
|
||||
point2d(m*concat(point2d(p),[1])) :
|
||||
point3d(m*concat(point3d(p),[1]))
|
||||
) :
|
||||
is_vnf(p)? [skew(sxy=sxy, sxz=sxz, syx=syx, syz=syz, szx=szx, szy=szy, planar=planar, p=p.x), p.y] :
|
||||
[for (l=p) skew(sxy=sxy, sxz=sxz, syx=syx, syz=syz, szx=szx, szy=szy, planar=planar, p=l)];
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
@ -20,17 +20,17 @@
|
||||
// points = Array of vertices for the polyhedron.
|
||||
// face = The face, given as a list of indices into the vertex array `points`.
|
||||
function face_normal(points, face) =
|
||||
let(count=len(face))
|
||||
unit(
|
||||
sum(
|
||||
[
|
||||
for(i=[0:1:count-1]) cross(
|
||||
points[face[(i+1)%count]]-points[face[0]],
|
||||
points[face[(i+2)%count]]-points[face[(i+1)%count]]
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
let(count=len(face))
|
||||
unit(
|
||||
sum(
|
||||
[
|
||||
for(i=[0:1:count-1]) cross(
|
||||
points[face[(i+1)%count]]-points[face[0]],
|
||||
points[face[(i+2)%count]]-points[face[(i+1)%count]]
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
;
|
||||
|
||||
|
||||
@ -42,16 +42,16 @@ function face_normal(points, face) =
|
||||
// face = The face, given as a list of indices into the vertex array `points`.
|
||||
// facenorm = The normal vector of the face.
|
||||
function find_convex_vertex(points, face, facenorm, i=0) =
|
||||
let(count=len(face),
|
||||
p0=points[face[i]],
|
||||
p1=points[face[(i+1)%count]],
|
||||
p2=points[face[(i+2)%count]]
|
||||
)
|
||||
(len(face)>i)? (
|
||||
(cross(p1-p0, p2-p1)*facenorm>0)? (i+1)%count :
|
||||
find_convex_vertex(points, face, facenorm, i+1)
|
||||
) : //This should never happen since there is at least 1 convex vertex.
|
||||
undef
|
||||
let(count=len(face),
|
||||
p0=points[face[i]],
|
||||
p1=points[face[(i+1)%count]],
|
||||
p2=points[face[(i+2)%count]]
|
||||
)
|
||||
(len(face)>i)? (
|
||||
(cross(p1-p0, p2-p1)*facenorm>0)? (i+1)%count :
|
||||
find_convex_vertex(points, face, facenorm, i+1)
|
||||
) : //This should never happen since there is at least 1 convex vertex.
|
||||
undef
|
||||
;
|
||||
|
||||
|
||||
@ -61,27 +61,27 @@ function find_convex_vertex(points, face, facenorm, i=0) =
|
||||
// points = Array of vertices for the polyhedron.
|
||||
// face = The face, given as a list of indices into the vertex array `points`.
|
||||
function point_in_ear(points, face, tests, i=0) =
|
||||
(i<len(face)-1)?
|
||||
let(
|
||||
prev=point_in_ear(points, face, tests, i+1),
|
||||
test=_check_point_in_ear(points[face[i]], tests)
|
||||
)
|
||||
(test>prev[0])? [test, i] : prev
|
||||
:
|
||||
[_check_point_in_ear(points[face[i]], tests), i]
|
||||
(i<len(face)-1)?
|
||||
let(
|
||||
prev=point_in_ear(points, face, tests, i+1),
|
||||
test=_check_point_in_ear(points[face[i]], tests)
|
||||
)
|
||||
(test>prev[0])? [test, i] : prev
|
||||
:
|
||||
[_check_point_in_ear(points[face[i]], tests), i]
|
||||
;
|
||||
|
||||
|
||||
// Internal non-exposed function.
|
||||
function _check_point_in_ear(point, tests) =
|
||||
let(
|
||||
result=[
|
||||
(point*tests[0][0])-tests[0][1],
|
||||
(point*tests[1][0])-tests[1][1],
|
||||
(point*tests[2][0])-tests[2][1]
|
||||
]
|
||||
)
|
||||
(result[0]>0 && result[1]>0 && result[2]>0)? result[0] : -1
|
||||
let(
|
||||
result=[
|
||||
(point*tests[0][0])-tests[0][1],
|
||||
(point*tests[1][0])-tests[1][1],
|
||||
(point*tests[2][0])-tests[2][1]
|
||||
]
|
||||
)
|
||||
(result[0]>0 && result[1]>0 && result[2]>0)? result[0] : -1
|
||||
;
|
||||
|
||||
|
||||
@ -90,10 +90,10 @@ function _check_point_in_ear(point, tests) =
|
||||
// Arguments:
|
||||
// v = The array to normalize.
|
||||
function normalize_vertex_perimeter(v) =
|
||||
let(lv = len(v))
|
||||
(lv < 2)? v :
|
||||
(v[lv-1] != v[0])? v :
|
||||
[for (i=[0:1:lv-2]) v[i]]
|
||||
let(lv = len(v))
|
||||
(lv < 2)? v :
|
||||
(v[lv-1] != v[0])? v :
|
||||
[for (i=[0:1:lv-2]) v[i]]
|
||||
;
|
||||
|
||||
|
||||
@ -106,20 +106,20 @@ function normalize_vertex_perimeter(v) =
|
||||
// facelist = The face, given as a list of indices into the vertex array `points`.
|
||||
// vertex = The index into `facelist`, of the vertex to test.
|
||||
function is_only_noncolinear_vertex(points, facelist, vertex) =
|
||||
let(
|
||||
face=select(facelist, vertex+1, vertex-1),
|
||||
count=len(face)
|
||||
)
|
||||
0==sum(
|
||||
[
|
||||
for(i=[0:1:count-1]) norm(
|
||||
cross(
|
||||
points[face[(i+1)%count]]-points[face[0]],
|
||||
points[face[(i+2)%count]]-points[face[(i+1)%count]]
|
||||
)
|
||||
)
|
||||
]
|
||||
)
|
||||
let(
|
||||
face=select(facelist, vertex+1, vertex-1),
|
||||
count=len(face)
|
||||
)
|
||||
0==sum(
|
||||
[
|
||||
for(i=[0:1:count-1]) norm(
|
||||
cross(
|
||||
points[face[(i+1)%count]]-points[face[0]],
|
||||
points[face[(i+2)%count]]-points[face[(i+1)%count]]
|
||||
)
|
||||
)
|
||||
]
|
||||
)
|
||||
;
|
||||
|
||||
|
||||
@ -131,50 +131,50 @@ function is_only_noncolinear_vertex(points, facelist, vertex) =
|
||||
// points = Array of vertices for the polyhedron.
|
||||
// face = The face, given as a list of indices into the vertex array `points`.
|
||||
function triangulate_face(points, face) =
|
||||
let(
|
||||
face = deduplicate_indexed(points,face),
|
||||
count = len(face)
|
||||
)
|
||||
(count < 3)? [] :
|
||||
(count == 3)? [face] :
|
||||
let(
|
||||
facenorm=face_normal(points, face),
|
||||
cv=find_convex_vertex(points, face, facenorm)
|
||||
)
|
||||
assert(!is_undef(cv), "Cannot triangulate self-crossing face perimeters.")
|
||||
let(
|
||||
pv=(count+cv-1)%count,
|
||||
nv=(cv+1)%count,
|
||||
p0=points[face[pv]],
|
||||
p1=points[face[cv]],
|
||||
p2=points[face[nv]],
|
||||
tests=[
|
||||
[cross(facenorm, p0-p2), cross(facenorm, p0-p2)*p0],
|
||||
[cross(facenorm, p1-p0), cross(facenorm, p1-p0)*p1],
|
||||
[cross(facenorm, p2-p1), cross(facenorm, p2-p1)*p2]
|
||||
],
|
||||
ear_test=point_in_ear(points, face, tests),
|
||||
clipable_ear=(ear_test[0]<0),
|
||||
diagonal_point=ear_test[1]
|
||||
)
|
||||
(clipable_ear)? // There is no point inside the ear.
|
||||
is_only_noncolinear_vertex(points, face, cv)?
|
||||
// In the point&line degeneracy clip to somewhere in the middle of the line.
|
||||
flatten([
|
||||
triangulate_face(points, select(face, cv, (cv+2)%count)),
|
||||
triangulate_face(points, select(face, (cv+2)%count, cv))
|
||||
])
|
||||
:
|
||||
// Otherwise the ear is safe to clip.
|
||||
flatten([
|
||||
[select(face, pv, nv)],
|
||||
triangulate_face(points, select(face, nv, pv))
|
||||
])
|
||||
: // If there is a point inside the ear, make a diagonal and clip along that.
|
||||
flatten([
|
||||
triangulate_face(points, select(face, cv, diagonal_point)),
|
||||
triangulate_face(points, select(face, diagonal_point, cv))
|
||||
]);
|
||||
let(
|
||||
face = deduplicate_indexed(points,face),
|
||||
count = len(face)
|
||||
)
|
||||
(count < 3)? [] :
|
||||
(count == 3)? [face] :
|
||||
let(
|
||||
facenorm=face_normal(points, face),
|
||||
cv=find_convex_vertex(points, face, facenorm)
|
||||
)
|
||||
assert(!is_undef(cv), "Cannot triangulate self-crossing face perimeters.")
|
||||
let(
|
||||
pv=(count+cv-1)%count,
|
||||
nv=(cv+1)%count,
|
||||
p0=points[face[pv]],
|
||||
p1=points[face[cv]],
|
||||
p2=points[face[nv]],
|
||||
tests=[
|
||||
[cross(facenorm, p0-p2), cross(facenorm, p0-p2)*p0],
|
||||
[cross(facenorm, p1-p0), cross(facenorm, p1-p0)*p1],
|
||||
[cross(facenorm, p2-p1), cross(facenorm, p2-p1)*p2]
|
||||
],
|
||||
ear_test=point_in_ear(points, face, tests),
|
||||
clipable_ear=(ear_test[0]<0),
|
||||
diagonal_point=ear_test[1]
|
||||
)
|
||||
(clipable_ear)? // There is no point inside the ear.
|
||||
is_only_noncolinear_vertex(points, face, cv)?
|
||||
// In the point&line degeneracy clip to somewhere in the middle of the line.
|
||||
flatten([
|
||||
triangulate_face(points, select(face, cv, (cv+2)%count)),
|
||||
triangulate_face(points, select(face, (cv+2)%count, cv))
|
||||
])
|
||||
:
|
||||
// Otherwise the ear is safe to clip.
|
||||
flatten([
|
||||
[select(face, pv, nv)],
|
||||
triangulate_face(points, select(face, nv, pv))
|
||||
])
|
||||
: // If there is a point inside the ear, make a diagonal and clip along that.
|
||||
flatten([
|
||||
triangulate_face(points, select(face, cv, diagonal_point)),
|
||||
triangulate_face(points, select(face, diagonal_point, cv))
|
||||
]);
|
||||
|
||||
|
||||
// Function: triangulate_faces()
|
||||
@ -185,11 +185,11 @@ function triangulate_face(points, face) =
|
||||
// points = Array of vertices for the polyhedron.
|
||||
// faces = Array of faces for the polyhedron. Each face is a list of 3 or more indices into the `points` array.
|
||||
function triangulate_faces(points, faces) =
|
||||
[
|
||||
for (face=faces) each
|
||||
len(face)==3? [face] :
|
||||
triangulate_face(points, normalize_vertex_perimeter(face))
|
||||
];
|
||||
[
|
||||
for (face=faces) each
|
||||
len(face)==3? [face] :
|
||||
triangulate_face(points, normalize_vertex_perimeter(face))
|
||||
];
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
74
vectors.scad
74
vectors.scad
@ -31,8 +31,8 @@
|
||||
// is_vector([]); // Returns false
|
||||
// is_vector([3,undef,undef,true], fast=true); // Returns true
|
||||
function is_vector(v,length,fast=false) =
|
||||
(fast? (is_list(v) && is_num(v[0])) : is_list_of(v,0)) &&
|
||||
len(v) && (is_undef(length) || length==len(v));
|
||||
(fast? (is_list(v) && is_num(v[0])) : is_list_of(v,0)) &&
|
||||
len(v) && (is_undef(length) || length==len(v));
|
||||
|
||||
|
||||
// Function: add_scalar()
|
||||
@ -58,8 +58,8 @@ function add_scalar(v,s) = [for (x=v) is_list(x)? add_scalar(x,s) : x+s];
|
||||
// Given a 2D vector, returns the angle in degrees counter-clockwise from X+ on the XY plane.
|
||||
// Given a 3D vector, returns [THETA,PHI] where THETA is the number of degrees counter-clockwise from X+ on the XY plane, and PHI is the number of degrees up from the X+ axis along the XZ plane.
|
||||
function vang(v) =
|
||||
len(v)==2? atan2(v.y,v.x) :
|
||||
let(res=xyz_to_spherical(v)) [res[1], 90-res[2]];
|
||||
len(v)==2? atan2(v.y,v.x) :
|
||||
let(res=xyz_to_spherical(v)) [res[1], 90-res[2]];
|
||||
|
||||
|
||||
// Function: vmul()
|
||||
@ -144,22 +144,22 @@ function unit(v) = assert(is_vector(v),str(v)) norm(v)<=EPSILON? v : v/norm(v);
|
||||
// vector_angle([10,0,10], [0,0,0], [-10,10,0]); // Returns: 120
|
||||
// vector_angle([[10,0,10], [0,0,0], [-10,10,0]]); // Returns: 120
|
||||
function vector_angle(v1,v2,v3) =
|
||||
let(
|
||||
vecs = !is_undef(v3)? [v1-v2,v3-v2] :
|
||||
!is_undef(v2)? [v1,v2] :
|
||||
len(v1) == 3? [v1[0]-v1[1],v1[2]-v1[1]] :
|
||||
len(v1) == 2? v1 :
|
||||
assert(false, "Bad arguments to vector_angle()"),
|
||||
is_valid = is_vector(vecs[0]) && is_vector(vecs[1]) && vecs[0]*0 == vecs[1]*0
|
||||
)
|
||||
assert(is_valid, "Bad arguments to vector_angle()")
|
||||
let(
|
||||
norm0 = norm(vecs[0]),
|
||||
norm1 = norm(vecs[1])
|
||||
)
|
||||
assert(norm0>0 && norm1>0,"Zero length vector given to vector_angle()")
|
||||
// NOTE: constrain() corrects crazy FP rounding errors that exceed acos()'s domain.
|
||||
acos(constrain((vecs[0]*vecs[1])/(norm0*norm1), -1, 1));
|
||||
let(
|
||||
vecs = !is_undef(v3)? [v1-v2,v3-v2] :
|
||||
!is_undef(v2)? [v1,v2] :
|
||||
len(v1) == 3? [v1[0]-v1[1],v1[2]-v1[1]] :
|
||||
len(v1) == 2? v1 :
|
||||
assert(false, "Bad arguments to vector_angle()"),
|
||||
is_valid = is_vector(vecs[0]) && is_vector(vecs[1]) && vecs[0]*0 == vecs[1]*0
|
||||
)
|
||||
assert(is_valid, "Bad arguments to vector_angle()")
|
||||
let(
|
||||
norm0 = norm(vecs[0]),
|
||||
norm1 = norm(vecs[1])
|
||||
)
|
||||
assert(norm0>0 && norm1>0,"Zero length vector given to vector_angle()")
|
||||
// NOTE: constrain() corrects crazy FP rounding errors that exceed acos()'s domain.
|
||||
acos(constrain((vecs[0]*vecs[1])/(norm0*norm1), -1, 1));
|
||||
|
||||
|
||||
// Function: vector_axis()
|
||||
@ -184,22 +184,22 @@ function vector_angle(v1,v2,v3) =
|
||||
// vector_axis([10,0,10], [0,0,0], [-10,10,0]); // Returns: [-0.57735, -0.57735, 0.57735]
|
||||
// vector_axis([[10,0,10], [0,0,0], [-10,10,0]]); // Returns: [-0.57735, -0.57735, 0.57735]
|
||||
function vector_axis(v1,v2=undef,v3=undef) =
|
||||
(is_list(v1) && is_list(v1[0]) && is_undef(v2) && is_undef(v3))? (
|
||||
assert(is_vector(v1.x))
|
||||
assert(is_vector(v1.y))
|
||||
len(v1)==3? assert(is_vector(v1.z)) vector_axis(v1.x, v1.y, v1.z) :
|
||||
len(v1)==2? vector_axis(v1.x, v1.y) :
|
||||
assert(false, "Bad arguments.")
|
||||
) :
|
||||
(is_vector(v1) && is_vector(v2) && is_vector(v3))? vector_axis(v1-v2, v3-v2) :
|
||||
(is_vector(v1) && is_vector(v2) && is_undef(v3))? let(
|
||||
eps = 1e-6,
|
||||
v1 = point3d(v1/norm(v1)),
|
||||
v2 = point3d(v2/norm(v2)),
|
||||
v3 = (norm(v1-v2) > eps && norm(v1+v2) > eps)? v2 :
|
||||
(norm(vabs(v2)-UP) > eps)? UP :
|
||||
RIGHT
|
||||
) unit(cross(v1,v3)) : assert(false, "Bad arguments.");
|
||||
(is_list(v1) && is_list(v1[0]) && is_undef(v2) && is_undef(v3))? (
|
||||
assert(is_vector(v1.x))
|
||||
assert(is_vector(v1.y))
|
||||
len(v1)==3? assert(is_vector(v1.z)) vector_axis(v1.x, v1.y, v1.z) :
|
||||
len(v1)==2? vector_axis(v1.x, v1.y) :
|
||||
assert(false, "Bad arguments.")
|
||||
) :
|
||||
(is_vector(v1) && is_vector(v2) && is_vector(v3))? vector_axis(v1-v2, v3-v2) :
|
||||
(is_vector(v1) && is_vector(v2) && is_undef(v3))? let(
|
||||
eps = 1e-6,
|
||||
v1 = point3d(v1/norm(v1)),
|
||||
v2 = point3d(v2/norm(v2)),
|
||||
v3 = (norm(v1-v2) > eps && norm(v1+v2) > eps)? v2 :
|
||||
(norm(vabs(v2)-UP) > eps)? UP :
|
||||
RIGHT
|
||||
) unit(cross(v1,v3)) : assert(false, "Bad arguments.");
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
60
version.scad
60
version.scad
@ -8,7 +8,7 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
BOSL_VERSION = [2,0,331];
|
||||
BOSL_VERSION = [2,0,332];
|
||||
|
||||
|
||||
// Section: BOSL Library Version Functions
|
||||
@ -49,27 +49,27 @@ function bosl_version_str() = version_to_str(BOSL_VERSION);
|
||||
// Description:
|
||||
// Given a version as a list, number, or string, asserts that the currently installed BOSL library is at least the given version.
|
||||
module bosl_required(target) {
|
||||
assert(
|
||||
version_cmp(bosl_version(), target) >= 0,
|
||||
str(
|
||||
"BOSL ", bosl_version_str(), " is installed, but BOSL ",
|
||||
version_to_str(target), " or better is required."
|
||||
)
|
||||
);
|
||||
assert(
|
||||
version_cmp(bosl_version(), target) >= 0,
|
||||
str(
|
||||
"BOSL ", bosl_version_str(), " is installed, but BOSL ",
|
||||
version_to_str(target), " or better is required."
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Section: Generic Version Functions
|
||||
|
||||
function _version_split_str(x, _i=0, _out=[], _num=0) =
|
||||
_i>=len(x)? concat(_out,[_num]) :
|
||||
let(
|
||||
cval = ord(x[_i]) - ord("0"),
|
||||
numend = cval<0 || cval>9,
|
||||
_out = numend? concat(_out, [_num]) : _out,
|
||||
_num = numend? 0 : (10*_num + cval)
|
||||
)
|
||||
_version_split_str(x, _i=_i+1, _out=_out, _num=_num);
|
||||
_i>=len(x)? concat(_out,[_num]) :
|
||||
let(
|
||||
cval = ord(x[_i]) - ord("0"),
|
||||
numend = cval<0 || cval>9,
|
||||
_out = numend? concat(_out, [_num]) : _out,
|
||||
_num = numend? 0 : (10*_num + cval)
|
||||
)
|
||||
_version_split_str(x, _i=_i+1, _out=_out, _num=_num);
|
||||
|
||||
|
||||
// Function: version_to_list()
|
||||
@ -83,10 +83,10 @@ function _version_split_str(x, _i=0, _out=[], _num=0) =
|
||||
// v3 = version_to_list([2,3,4]); // Returns: [2,3,4]
|
||||
// v4 = version_to_list([2,3,4,5]); // Returns: [2,3,4]
|
||||
function version_to_list(x) =
|
||||
is_list(x)? [default(x[0],0), default(x[1],0), default(x[2],0)] :
|
||||
is_string(x)? _version_split_str(x) :
|
||||
is_num(x)? [floor(x), floor(x*100%100), floor(x*1000000%10000+0.5)] :
|
||||
assert(is_num(x) || is_vector(x) || is_string(x)) 0;
|
||||
is_list(x)? [default(x[0],0), default(x[1],0), default(x[2],0)] :
|
||||
is_string(x)? _version_split_str(x) :
|
||||
is_num(x)? [floor(x), floor(x*100%100), floor(x*1000000%10000+0.5)] :
|
||||
assert(is_num(x) || is_vector(x) || is_string(x)) 0;
|
||||
|
||||
|
||||
// Function: version_to_str()
|
||||
@ -100,8 +100,8 @@ function version_to_list(x) =
|
||||
// v3 = version_to_str(2.340789); // Returns: "2.34.789"
|
||||
// v4 = version_to_str("2.3.89"); // Returns: "2.3.89"
|
||||
function version_to_str(x) =
|
||||
let(x = version_to_list(x))
|
||||
str(x[0],".",x[1],".",x[2]);
|
||||
let(x = version_to_list(x))
|
||||
str(x[0],".",x[1],".",x[2]);
|
||||
|
||||
|
||||
// Function: version_to_num()
|
||||
@ -115,8 +115,8 @@ function version_to_str(x) =
|
||||
// v3 = version_to_num(2.120567); // Returns: 2.120567
|
||||
// v4 = version_to_num("2.6.79"); // Returns: 2.060079
|
||||
function version_to_num(x) =
|
||||
let(x = version_to_list(x))
|
||||
(x[0]*1000000 + x[1]*10000 + x[2])/1000000;
|
||||
let(x = version_to_list(x))
|
||||
(x[0]*1000000 + x[1]*10000 + x[2])/1000000;
|
||||
|
||||
|
||||
// Function: version_cmp()
|
||||
@ -130,11 +130,11 @@ function version_to_num(x) =
|
||||
// cmp2 = version_cmp(2.010034, "2.1.34"); // Returns: 0
|
||||
// cmp3 = version_cmp(2.010034, "2.1.35"); // Returns: <0
|
||||
function version_cmp(a,b) =
|
||||
let(
|
||||
a = version_to_list(a),
|
||||
b = version_to_list(b),
|
||||
cmps = [for (i=[0:1:2]) if(a[i]!=b[i]) a[i]-b[i]]
|
||||
) cmps==[]? 0 : cmps[0];
|
||||
let(
|
||||
a = version_to_list(a),
|
||||
b = version_to_list(b),
|
||||
cmps = [for (i=[0:1:2]) if(a[i]!=b[i]) a[i]-b[i]]
|
||||
) cmps==[]? 0 : cmps[0];
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
788
vnf.scad
788
vnf.scad
@ -29,12 +29,12 @@ EMPTY_VNF = [[],[]]; // The standard empty VNF with no vertices or faces.
|
||||
// Description:
|
||||
// Returns true if the given value looks like a VNF structure.
|
||||
function is_vnf(x) =
|
||||
is_list(x) &&
|
||||
len(x)==2 &&
|
||||
is_list(x[0]) &&
|
||||
is_list(x[1]) &&
|
||||
(x[0]==[] || (len(x[0])>=3 && is_vector(x[0][0]))) &&
|
||||
(x[1]==[] || is_vector(x[1][0]));
|
||||
is_list(x) &&
|
||||
len(x)==2 &&
|
||||
is_list(x[0]) &&
|
||||
is_list(x[1]) &&
|
||||
(x[0]==[] || (len(x[0])>=3 && is_vector(x[0][0]))) &&
|
||||
(x[1]==[] || is_vector(x[1][0]));
|
||||
|
||||
|
||||
// Function: is_vnf_list()
|
||||
@ -61,7 +61,7 @@ function vnf_faces(vnf) = vnf[1];
|
||||
// vnf = The VNF to quantize.
|
||||
// q = The quanta to quantize the VNF coordinates to.
|
||||
function vnf_quantize(vnf,q=pow(2,-12)) =
|
||||
[[for (pt = vnf[0]) quant(pt,q)], vnf[1]];
|
||||
[[for (pt = vnf[0]) quant(pt,q)], vnf[1]];
|
||||
|
||||
|
||||
// Function: vnf_get_vertex()
|
||||
@ -81,11 +81,11 @@ function vnf_quantize(vnf,q=pow(2,-12)) =
|
||||
// vnf3 = vnf_get_vertex(vnf2, p=[3,5,8]); // Returns: [0, [[[3,5,8],[3,2,1]],[]]]
|
||||
// vnf4 = vnf_get_vertex(vnf3, p=[[1,3,2],[3,2,1]]); // Returns: [[1,2], [[[3,5,8],[3,2,1],[1,3,2]],[]]]
|
||||
function vnf_get_vertex(vnf=EMPTY_VNF, p) =
|
||||
let(
|
||||
p = is_vector(p)? [p] : p,
|
||||
res = set_union(vnf[0], p, get_indices=true)
|
||||
)
|
||||
[res[0], [res[1],vnf[1]]];
|
||||
let(
|
||||
p = is_vector(p)? [p] : p,
|
||||
res = set_union(vnf[0], p, get_indices=true)
|
||||
)
|
||||
[res[0], [res[1],vnf[1]]];
|
||||
|
||||
|
||||
// Function: vnf_add_face()
|
||||
@ -99,15 +99,15 @@ function vnf_get_vertex(vnf=EMPTY_VNF, p) =
|
||||
// vnf = The VNF structure to add a face to.
|
||||
// pts = The vertex points for the face.
|
||||
function vnf_add_face(vnf=EMPTY_VNF, pts) =
|
||||
assert(is_vnf(vnf))
|
||||
assert(is_path(pts))
|
||||
let(
|
||||
res = set_union(vnf[0], pts, get_indices=true),
|
||||
face = deduplicate(res[0], closed=true)
|
||||
) [
|
||||
res[1],
|
||||
concat(vnf[1], len(face)>2? [face] : [])
|
||||
];
|
||||
assert(is_vnf(vnf))
|
||||
assert(is_path(pts))
|
||||
let(
|
||||
res = set_union(vnf[0], pts, get_indices=true),
|
||||
face = deduplicate(res[0], closed=true)
|
||||
) [
|
||||
res[1],
|
||||
concat(vnf[1], len(face)>2? [face] : [])
|
||||
];
|
||||
|
||||
|
||||
// Function: vnf_add_faces()
|
||||
@ -122,23 +122,23 @@ function vnf_add_face(vnf=EMPTY_VNF, pts) =
|
||||
// vnf = The VNF structure to add a face to.
|
||||
// faces = The list of faces, where each face is given as a list of vertex points.
|
||||
function vnf_add_faces(vnf=EMPTY_VNF, faces) =
|
||||
assert(is_vnf(vnf))
|
||||
assert(is_list(faces))
|
||||
let(
|
||||
res = set_union(vnf[0], flatten(faces), get_indices=true),
|
||||
idxs = res[0],
|
||||
nverts = res[1],
|
||||
offs = cumsum([0, for (face=faces) len(face)]),
|
||||
ifaces = [
|
||||
for (i=idx(faces)) [
|
||||
for (j=idx(faces[i]))
|
||||
idxs[offs[i]+j]
|
||||
]
|
||||
]
|
||||
) [
|
||||
nverts,
|
||||
concat(vnf[1],ifaces)
|
||||
];
|
||||
assert(is_vnf(vnf))
|
||||
assert(is_list(faces))
|
||||
let(
|
||||
res = set_union(vnf[0], flatten(faces), get_indices=true),
|
||||
idxs = res[0],
|
||||
nverts = res[1],
|
||||
offs = cumsum([0, for (face=faces) len(face)]),
|
||||
ifaces = [
|
||||
for (i=idx(faces)) [
|
||||
for (j=idx(faces[i]))
|
||||
idxs[offs[i]+j]
|
||||
]
|
||||
]
|
||||
) [
|
||||
nverts,
|
||||
concat(vnf[1],ifaces)
|
||||
];
|
||||
|
||||
|
||||
// Function: vnf_merge()
|
||||
@ -147,14 +147,14 @@ function vnf_add_faces(vnf=EMPTY_VNF, faces) =
|
||||
// Description:
|
||||
// Given a list of VNF structures, merges them all into a single VNF structure.
|
||||
function vnf_merge(vnfs=[],_i=0,_acc=EMPTY_VNF) =
|
||||
(assert(is_vnf_list(vnfs)) _i>=len(vnfs))? _acc :
|
||||
vnf_merge(
|
||||
vnfs, _i=_i+1,
|
||||
_acc = let(base=len(_acc[0])) [
|
||||
concat(_acc[0], vnfs[_i][0]),
|
||||
concat(_acc[1], [for (f=vnfs[_i][1]) [for (i=f) i+base]]),
|
||||
]
|
||||
);
|
||||
(assert(is_vnf_list(vnfs)) _i>=len(vnfs))? _acc :
|
||||
vnf_merge(
|
||||
vnfs, _i=_i+1,
|
||||
_acc = let(base=len(_acc[0])) [
|
||||
concat(_acc[0], vnfs[_i][0]),
|
||||
concat(_acc[1], [for (f=vnfs[_i][1]) [for (i=f) i+base]]),
|
||||
]
|
||||
);
|
||||
|
||||
// Function: vnf_compact()
|
||||
// Usage:
|
||||
@ -162,15 +162,15 @@ function vnf_merge(vnfs=[],_i=0,_acc=EMPTY_VNF) =
|
||||
// Description:
|
||||
// Takes a VNF and consolidates all duplicate vertices, and drops unreferenced vertices.
|
||||
function vnf_compact(vnf) =
|
||||
let(
|
||||
vnf = is_vnf_list(vnf)? vnf_merge(vnf) : vnf,
|
||||
verts = vnf[0],
|
||||
faces = [
|
||||
for (face=vnf[1]) [
|
||||
for (i=face) verts[i]
|
||||
]
|
||||
]
|
||||
) vnf_add_faces(faces=faces);
|
||||
let(
|
||||
vnf = is_vnf_list(vnf)? vnf_merge(vnf) : vnf,
|
||||
verts = vnf[0],
|
||||
faces = [
|
||||
for (face=vnf[1]) [
|
||||
for (i=face) verts[i]
|
||||
]
|
||||
]
|
||||
) vnf_add_faces(faces=faces);
|
||||
|
||||
|
||||
// Function: vnf_triangulate()
|
||||
@ -179,10 +179,10 @@ function vnf_compact(vnf) =
|
||||
// Description:
|
||||
// Forces triangulation of faces in the VNF that have more than 3 vertices.
|
||||
function vnf_triangulate(vnf) =
|
||||
let(
|
||||
vnf = is_vnf_list(vnf)? vnf_merge(vnf) : vnf,
|
||||
verts = vnf[0]
|
||||
) [verts, triangulate_faces(verts, vnf[1])];
|
||||
let(
|
||||
vnf = is_vnf_list(vnf)? vnf_merge(vnf) : vnf,
|
||||
verts = vnf[0]
|
||||
) [verts, triangulate_faces(verts, vnf[1])];
|
||||
|
||||
|
||||
// Function: vnf_vertex_array()
|
||||
@ -257,79 +257,79 @@ function vnf_triangulate(vnf) =
|
||||
// vnf3 = vnf_vertex_array(points=cap2, col_wrap=true, reverse=true);
|
||||
// vnf_polyhedron([vnf1, vnf2, vnf3]);
|
||||
function vnf_vertex_array(
|
||||
points,
|
||||
caps, cap1, cap2,
|
||||
col_wrap=false,
|
||||
row_wrap=false,
|
||||
reverse=false,
|
||||
style="default",
|
||||
vnf=EMPTY_VNF
|
||||
points,
|
||||
caps, cap1, cap2,
|
||||
col_wrap=false,
|
||||
row_wrap=false,
|
||||
reverse=false,
|
||||
style="default",
|
||||
vnf=EMPTY_VNF
|
||||
) =
|
||||
assert((!caps)||(caps&&col_wrap))
|
||||
assert(in_list(style,["default","alt","quincunx"]))
|
||||
assert((!caps)||(caps&&col_wrap))
|
||||
assert(in_list(style,["default","alt","quincunx"]))
|
||||
assert(is_consistent(points), "Non-rectangular or invalid point array")
|
||||
let(
|
||||
pts = flatten(points),
|
||||
pcnt = len(pts),
|
||||
rows = len(points),
|
||||
cols = len(points[0]),
|
||||
cap1 = first_defined([cap1,caps,false]),
|
||||
cap2 = first_defined([cap2,caps,false]),
|
||||
colcnt = cols - (col_wrap?0:1),
|
||||
rowcnt = rows - (row_wrap?0:1)
|
||||
)
|
||||
rows<=1 || cols<=1 ? vnf :
|
||||
vnf_merge([
|
||||
vnf, [
|
||||
concat(
|
||||
pts,
|
||||
style!="quincunx"? [] : [
|
||||
for (r = [0:1:rowcnt-1]) (
|
||||
for (c = [0:1:colcnt-1]) (
|
||||
let(
|
||||
i1 = ((r+0)%rows)*cols + ((c+0)%cols),
|
||||
i2 = ((r+1)%rows)*cols + ((c+0)%cols),
|
||||
i3 = ((r+1)%rows)*cols + ((c+1)%cols),
|
||||
i4 = ((r+0)%rows)*cols + ((c+1)%cols)
|
||||
) mean([pts[i1], pts[i2], pts[i3], pts[i4]])
|
||||
)
|
||||
)
|
||||
]
|
||||
),
|
||||
concat(
|
||||
[
|
||||
for (r = [0:1:rowcnt-1]) (
|
||||
for (c = [0:1:colcnt-1]) each (
|
||||
let(
|
||||
i1 = ((r+0)%rows)*cols + ((c+0)%cols),
|
||||
i2 = ((r+1)%rows)*cols + ((c+0)%cols),
|
||||
i3 = ((r+1)%rows)*cols + ((c+1)%cols),
|
||||
i4 = ((r+0)%rows)*cols + ((c+1)%cols)
|
||||
)
|
||||
style=="quincunx"? (
|
||||
let(i5 = pcnt + r*colcnt + c)
|
||||
reverse? [[i1,i2,i5],[i2,i3,i5],[i3,i4,i5],[i4,i1,i5]] : [[i1,i5,i2],[i2,i5,i3],[i3,i5,i4],[i4,i5,i1]]
|
||||
) : style=="alt"? (
|
||||
reverse? [[i1,i2,i4],[i2,i3,i4]] : [[i1,i4,i2],[i2,i4,i3]]
|
||||
) : (
|
||||
reverse? [[i1,i2,i3],[i1,i3,i4]] : [[i1,i3,i2],[i1,i4,i3]]
|
||||
)
|
||||
)
|
||||
)
|
||||
],
|
||||
!cap1? [] : [
|
||||
reverse?
|
||||
[for (c = [0:1:cols-1]) c] :
|
||||
[for (c = [cols-1:-1:0]) c]
|
||||
],
|
||||
!cap2? [] : [
|
||||
reverse?
|
||||
[for (c = [cols-1:-1:0]) (rows-1)*cols + c] :
|
||||
[for (c = [0:1:cols-1]) (rows-1)*cols + c]
|
||||
]
|
||||
)
|
||||
]
|
||||
]);
|
||||
let(
|
||||
pts = flatten(points),
|
||||
pcnt = len(pts),
|
||||
rows = len(points),
|
||||
cols = len(points[0]),
|
||||
cap1 = first_defined([cap1,caps,false]),
|
||||
cap2 = first_defined([cap2,caps,false]),
|
||||
colcnt = cols - (col_wrap?0:1),
|
||||
rowcnt = rows - (row_wrap?0:1)
|
||||
)
|
||||
rows<=1 || cols<=1 ? vnf :
|
||||
vnf_merge([
|
||||
vnf, [
|
||||
concat(
|
||||
pts,
|
||||
style!="quincunx"? [] : [
|
||||
for (r = [0:1:rowcnt-1]) (
|
||||
for (c = [0:1:colcnt-1]) (
|
||||
let(
|
||||
i1 = ((r+0)%rows)*cols + ((c+0)%cols),
|
||||
i2 = ((r+1)%rows)*cols + ((c+0)%cols),
|
||||
i3 = ((r+1)%rows)*cols + ((c+1)%cols),
|
||||
i4 = ((r+0)%rows)*cols + ((c+1)%cols)
|
||||
) mean([pts[i1], pts[i2], pts[i3], pts[i4]])
|
||||
)
|
||||
)
|
||||
]
|
||||
),
|
||||
concat(
|
||||
[
|
||||
for (r = [0:1:rowcnt-1]) (
|
||||
for (c = [0:1:colcnt-1]) each (
|
||||
let(
|
||||
i1 = ((r+0)%rows)*cols + ((c+0)%cols),
|
||||
i2 = ((r+1)%rows)*cols + ((c+0)%cols),
|
||||
i3 = ((r+1)%rows)*cols + ((c+1)%cols),
|
||||
i4 = ((r+0)%rows)*cols + ((c+1)%cols)
|
||||
)
|
||||
style=="quincunx"? (
|
||||
let(i5 = pcnt + r*colcnt + c)
|
||||
reverse? [[i1,i2,i5],[i2,i3,i5],[i3,i4,i5],[i4,i1,i5]] : [[i1,i5,i2],[i2,i5,i3],[i3,i5,i4],[i4,i5,i1]]
|
||||
) : style=="alt"? (
|
||||
reverse? [[i1,i2,i4],[i2,i3,i4]] : [[i1,i4,i2],[i2,i4,i3]]
|
||||
) : (
|
||||
reverse? [[i1,i2,i3],[i1,i3,i4]] : [[i1,i3,i2],[i1,i4,i3]]
|
||||
)
|
||||
)
|
||||
)
|
||||
],
|
||||
!cap1? [] : [
|
||||
reverse?
|
||||
[for (c = [0:1:cols-1]) c] :
|
||||
[for (c = [cols-1:-1:0]) c]
|
||||
],
|
||||
!cap2? [] : [
|
||||
reverse?
|
||||
[for (c = [cols-1:-1:0]) (rows-1)*cols + c] :
|
||||
[for (c = [0:1:cols-1]) (rows-1)*cols + c]
|
||||
]
|
||||
)
|
||||
]
|
||||
]);
|
||||
|
||||
|
||||
// Module: vnf_polyhedron()
|
||||
@ -342,8 +342,8 @@ function vnf_vertex_array(
|
||||
// vnf = A VNF structure, or list of VNF structures.
|
||||
// convexity = Max number of times a line could intersect a wall of the shape.
|
||||
module vnf_polyhedron(vnf, convexity=2) {
|
||||
vnf = is_vnf_list(vnf)? vnf_merge(vnf) : vnf;
|
||||
polyhedron(vnf[0], vnf[1], convexity=convexity);
|
||||
vnf = is_vnf_list(vnf)? vnf_merge(vnf) : vnf;
|
||||
polyhedron(vnf[0], vnf[1], convexity=convexity);
|
||||
}
|
||||
|
||||
|
||||
@ -358,15 +358,15 @@ module vnf_polyhedron(vnf, convexity=2) {
|
||||
// no holes; otherwise the results are undefined. Returns a positive volume if face direction is clockwise and a negative volume
|
||||
// if face direction is counter-clockwise.
|
||||
function vnf_volume(vnf) =
|
||||
let(
|
||||
vnf = vnf_triangulate(vnf),
|
||||
verts = vnf[0]
|
||||
) sum([
|
||||
for(face_index=vnf[1]) let(
|
||||
face = select(verts, face_index),
|
||||
n = cross(face[2]-face[0],face[1]-face[0])
|
||||
) face[0] * n
|
||||
])/6;
|
||||
let(
|
||||
vnf = vnf_triangulate(vnf),
|
||||
verts = vnf[0]
|
||||
) sum([
|
||||
for(face_index=vnf[1]) let(
|
||||
face = select(verts, face_index),
|
||||
n = cross(face[2]-face[0],face[1]-face[0])
|
||||
) face[0] * n
|
||||
])/6;
|
||||
|
||||
|
||||
// Function: vnf_centroid()
|
||||
@ -378,36 +378,36 @@ function vnf_volume(vnf) =
|
||||
|
||||
// Algorithm from: https://wwwf.imperial.ac.uk/~rn/centroid.pdf
|
||||
function vnf_centroid(vnf) =
|
||||
let(
|
||||
vnf = vnf_triangulate(vnf),
|
||||
verts = vnf[0],
|
||||
val=sum([
|
||||
for(face_index=vnf[1])
|
||||
let(
|
||||
face = select(verts, face_index),
|
||||
n = cross(face[2]-face[0],face[1]-face[0])
|
||||
) [
|
||||
face[0] * n,
|
||||
vmul(n,
|
||||
sqr(face[0] + face[1]) +
|
||||
sqr(face[0] + face[2]) +
|
||||
sqr(face[1] + face[2])
|
||||
)
|
||||
]
|
||||
])
|
||||
) val[1]/val[0]/8;
|
||||
let(
|
||||
vnf = vnf_triangulate(vnf),
|
||||
verts = vnf[0],
|
||||
val=sum([
|
||||
for(face_index=vnf[1])
|
||||
let(
|
||||
face = select(verts, face_index),
|
||||
n = cross(face[2]-face[0],face[1]-face[0])
|
||||
) [
|
||||
face[0] * n,
|
||||
vmul(n,
|
||||
sqr(face[0] + face[1]) +
|
||||
sqr(face[0] + face[2]) +
|
||||
sqr(face[1] + face[2])
|
||||
)
|
||||
]
|
||||
])
|
||||
) val[1]/val[0]/8;
|
||||
|
||||
|
||||
function _triangulate_planar_convex_polygons(polys) =
|
||||
polys==[]? [] :
|
||||
let(
|
||||
tris = [for (poly=polys) if (len(poly)==3) poly],
|
||||
bigs = [for (poly=polys) if (len(poly)>3) poly],
|
||||
newtris = [for (poly=bigs) select(poly,-2,0)],
|
||||
newbigs = [for (poly=bigs) select(poly,0,-2)],
|
||||
newtris2 = _triangulate_planar_convex_polygons(newbigs),
|
||||
outtris = concat(tris, newtris, newtris2)
|
||||
) outtris;
|
||||
polys==[]? [] :
|
||||
let(
|
||||
tris = [for (poly=polys) if (len(poly)==3) poly],
|
||||
bigs = [for (poly=polys) if (len(poly)>3) poly],
|
||||
newtris = [for (poly=bigs) select(poly,-2,0)],
|
||||
newbigs = [for (poly=bigs) select(poly,0,-2)],
|
||||
newtris2 = _triangulate_planar_convex_polygons(newbigs),
|
||||
outtris = concat(tris, newtris, newtris2)
|
||||
) outtris;
|
||||
|
||||
|
||||
// Function: vnf_bend()
|
||||
@ -482,49 +482,49 @@ function _triangulate_planar_convex_polygons(polys) =
|
||||
// bent1 = vnf_bend(vnf1, axis="Z");
|
||||
// vnf_polyhedron([bent1]);
|
||||
function vnf_bend(vnf,r,d,axis="Z") =
|
||||
let(
|
||||
chk_axis = assert(in_list(axis,["X","Y","Z"])),
|
||||
vnf = vnf_triangulate(vnf),
|
||||
verts = vnf[0],
|
||||
bounds = pointlist_bounds(verts),
|
||||
bmin = bounds[0],
|
||||
bmax = bounds[1],
|
||||
dflt = axis=="Z"?
|
||||
max(abs(bmax.y), abs(bmin.y)) :
|
||||
max(abs(bmax.z), abs(bmin.z)),
|
||||
r = get_radius(r=r,d=d,dflt=dflt),
|
||||
width = axis=="X"? (bmax.y-bmin.y) : (bmax.x - bmin.x)
|
||||
)
|
||||
assert(width <= 2*PI*r, "Shape would wrap more than completely around the cylinder.")
|
||||
let(
|
||||
span_chk = axis=="Z"?
|
||||
assert(bmin.y > 0 || bmax.y < 0, "Entire shape MUST be completely in front of or behind y=0.") :
|
||||
assert(bmin.z > 0 || bmax.z < 0, "Entire shape MUST be completely above or below z=0."),
|
||||
min_ang = 180 * bmin.x / (PI * r),
|
||||
max_ang = 180 * bmax.x / (PI * r),
|
||||
ang_span = max_ang-min_ang,
|
||||
steps = ceil(segs(r) * ang_span/360),
|
||||
step = width / steps,
|
||||
bend_at = axis=="X"? [for(i = [1:1:steps-1]) i*step+bmin.y] :
|
||||
[for(i = [1:1:steps-1]) i*step+bmin.x],
|
||||
facepolys = [for (face=vnf[1]) select(verts,face)],
|
||||
splits = axis=="X"?
|
||||
split_polygons_at_each_y(facepolys, bend_at) :
|
||||
split_polygons_at_each_x(facepolys, bend_at),
|
||||
newtris = _triangulate_planar_convex_polygons(splits),
|
||||
bent_faces = [
|
||||
for (tri = newtris) [
|
||||
for (p = tri) let(
|
||||
a = axis=="X"? 180*p.y/(r*PI) * sign(bmax.z) :
|
||||
axis=="Y"? 180*p.x/(r*PI) * sign(bmax.z) :
|
||||
180*p.x/(r*PI) * sign(bmax.y)
|
||||
)
|
||||
axis=="X"? [p.x, p.z*sin(a), p.z*cos(a)] :
|
||||
axis=="Y"? [p.z*sin(a), p.y, p.z*cos(a)] :
|
||||
[p.y*sin(a), p.y*cos(a), p.z]
|
||||
]
|
||||
]
|
||||
) vnf_add_faces(faces=bent_faces);
|
||||
let(
|
||||
chk_axis = assert(in_list(axis,["X","Y","Z"])),
|
||||
vnf = vnf_triangulate(vnf),
|
||||
verts = vnf[0],
|
||||
bounds = pointlist_bounds(verts),
|
||||
bmin = bounds[0],
|
||||
bmax = bounds[1],
|
||||
dflt = axis=="Z"?
|
||||
max(abs(bmax.y), abs(bmin.y)) :
|
||||
max(abs(bmax.z), abs(bmin.z)),
|
||||
r = get_radius(r=r,d=d,dflt=dflt),
|
||||
width = axis=="X"? (bmax.y-bmin.y) : (bmax.x - bmin.x)
|
||||
)
|
||||
assert(width <= 2*PI*r, "Shape would wrap more than completely around the cylinder.")
|
||||
let(
|
||||
span_chk = axis=="Z"?
|
||||
assert(bmin.y > 0 || bmax.y < 0, "Entire shape MUST be completely in front of or behind y=0.") :
|
||||
assert(bmin.z > 0 || bmax.z < 0, "Entire shape MUST be completely above or below z=0."),
|
||||
min_ang = 180 * bmin.x / (PI * r),
|
||||
max_ang = 180 * bmax.x / (PI * r),
|
||||
ang_span = max_ang-min_ang,
|
||||
steps = ceil(segs(r) * ang_span/360),
|
||||
step = width / steps,
|
||||
bend_at = axis=="X"? [for(i = [1:1:steps-1]) i*step+bmin.y] :
|
||||
[for(i = [1:1:steps-1]) i*step+bmin.x],
|
||||
facepolys = [for (face=vnf[1]) select(verts,face)],
|
||||
splits = axis=="X"?
|
||||
split_polygons_at_each_y(facepolys, bend_at) :
|
||||
split_polygons_at_each_x(facepolys, bend_at),
|
||||
newtris = _triangulate_planar_convex_polygons(splits),
|
||||
bent_faces = [
|
||||
for (tri = newtris) [
|
||||
for (p = tri) let(
|
||||
a = axis=="X"? 180*p.y/(r*PI) * sign(bmax.z) :
|
||||
axis=="Y"? 180*p.x/(r*PI) * sign(bmax.z) :
|
||||
180*p.x/(r*PI) * sign(bmax.y)
|
||||
)
|
||||
axis=="X"? [p.x, p.z*sin(a), p.z*cos(a)] :
|
||||
axis=="Y"? [p.z*sin(a), p.y, p.z*cos(a)] :
|
||||
[p.y*sin(a), p.y*cos(a), p.z]
|
||||
]
|
||||
]
|
||||
) vnf_add_faces(faces=bent_faces);
|
||||
|
||||
|
||||
// Function&Module: vnf_validate()
|
||||
@ -614,198 +614,198 @@ function vnf_bend(vnf,r,d,axis="Z") =
|
||||
// ], slices=0, caps=false);
|
||||
// vnf_validate(vnf,size=2);
|
||||
function vnf_validate(vnf, show_warns=true, check_isects=false) =
|
||||
assert(is_path(vnf[0]))
|
||||
let(
|
||||
vnf = vnf_compact(vnf),
|
||||
varr = vnf[0],
|
||||
faces = vnf[1],
|
||||
edges = sort([
|
||||
for (face=faces, edge=pair_wrap(face))
|
||||
edge[0]<edge[1]? edge : [edge[1],edge[0]]
|
||||
]),
|
||||
edgecnts = unique_count(edges),
|
||||
uniq_edges = edgecnts[0],
|
||||
big_faces = !show_warns? [] : [
|
||||
for (face = faces)
|
||||
if (len(face) > 3) [
|
||||
"WARNING",
|
||||
"BIG_FACE",
|
||||
"Face has more than 3 vertices, and may confuse CGAL",
|
||||
[for (i=face) varr[i]],
|
||||
"yellow"
|
||||
]
|
||||
],
|
||||
null_faces = !show_warns? [] : [
|
||||
for (face = faces) let(
|
||||
face = deduplicate(face,closed=true)
|
||||
)
|
||||
if (len(face)>=3) let(
|
||||
faceverts = [for (k=face) varr[k]],
|
||||
area = polygon_area(faceverts)
|
||||
) if (is_num(area) && abs(area) < EPSILON) [
|
||||
"WARNING",
|
||||
"NULL_FACE",
|
||||
str("Face has zero area: ",fmt_float(abs(area),15)),
|
||||
faceverts,
|
||||
"brown"
|
||||
]
|
||||
],
|
||||
nonplanars = unique([
|
||||
for (face = faces) let(
|
||||
faceverts = [for (k=face) varr[k]]
|
||||
) if (!points_are_coplanar(faceverts)) [
|
||||
"ERROR",
|
||||
"NONPLANAR",
|
||||
"Face vertices are not coplanar",
|
||||
faceverts,
|
||||
"cyan"
|
||||
]
|
||||
]),
|
||||
overpop_edges = unique([
|
||||
for (i=idx(uniq_edges))
|
||||
if (edgecnts[1][i]>2) [
|
||||
"ERROR",
|
||||
"OVRPOP_EDGE",
|
||||
"Too many faces attached at Edge",
|
||||
[for (i=uniq_edges[i]) varr[i]],
|
||||
"#f70"
|
||||
]
|
||||
]),
|
||||
reversals = unique([
|
||||
for(i = idx(faces), j = idx(faces)) if(i != j)
|
||||
if(len(deduplicate(faces[i],closed=true))>=3)
|
||||
if(len(deduplicate(faces[j],closed=true))>=3)
|
||||
for(edge1 = pair_wrap(faces[i]))
|
||||
for(edge2 = pair_wrap(faces[j]))
|
||||
if(edge1 == edge2) // Valid adjacent faces will never have the same vertex ordering.
|
||||
if(_edge_not_reported(edge1, varr, overpop_edges))
|
||||
[
|
||||
"ERROR",
|
||||
"REVERSAL",
|
||||
"Faces Reverse Across Edge",
|
||||
[for (i=edge1) varr[i]],
|
||||
"violet"
|
||||
]
|
||||
]),
|
||||
t_juncts = unique([
|
||||
for (v=idx(varr), edge=uniq_edges)
|
||||
if (v!=edge[0] && v!=edge[1]) let(
|
||||
a = varr[edge[0]],
|
||||
b = varr[v],
|
||||
c = varr[edge[1]],
|
||||
pt = segment_closest_point([a,c],b)
|
||||
) if (pt == b) [
|
||||
"ERROR",
|
||||
"T_JUNCTION",
|
||||
"Vertex is mid-edge on another Face",
|
||||
[b],
|
||||
"red"
|
||||
]
|
||||
]),
|
||||
isect_faces = !check_isects? [] : unique([
|
||||
for (i = [0:1:len(faces)-2])
|
||||
for (j = [i+1:1:len(faces)-1]) let(
|
||||
f1 = faces[i],
|
||||
f2 = faces[j],
|
||||
shared_edges = [
|
||||
for (edge1 = pair_wrap(f1), edge2 = pair_wrap(f2)) let(
|
||||
e1 = edge1[0]<edge1[1]? edge1 : [edge1[1],edge1[0]],
|
||||
e2 = edge2[0]<edge2[1]? edge2 : [edge2[1],edge2[0]]
|
||||
) if (e1==e2) 1
|
||||
]
|
||||
)
|
||||
if (!shared_edges) let(
|
||||
plane1 = plane3pt_indexed(varr, f1[0], f1[1], f1[2]),
|
||||
plane2 = plane3pt_indexed(varr, f2[0], f2[1], f2[2]),
|
||||
line = plane_intersection(plane1, plane2)
|
||||
)
|
||||
if (!is_undef(line)) let(
|
||||
poly1 = select(varr,f1),
|
||||
isects = polygon_line_intersection(poly1,line)
|
||||
)
|
||||
if (!is_undef(isects))
|
||||
for (isect=isects)
|
||||
if (len(isect)>1) let(
|
||||
poly2 = select(varr,f2),
|
||||
isects2 = polygon_line_intersection(poly2,isect,bounded=true)
|
||||
)
|
||||
if (!is_undef(isects2))
|
||||
for (seg=isects2)
|
||||
if (seg[0] != seg[1]) [
|
||||
"ERROR",
|
||||
"FACE_ISECT",
|
||||
"Faces intersect",
|
||||
seg,
|
||||
"blue"
|
||||
]
|
||||
]),
|
||||
hole_edges = unique([
|
||||
for (i=idx(uniq_edges))
|
||||
if (edgecnts[1][i]<2)
|
||||
if (_pts_not_reported(uniq_edges[i], varr, t_juncts))
|
||||
if (_pts_not_reported(uniq_edges[i], varr, isect_faces))
|
||||
[
|
||||
"ERROR",
|
||||
"HOLE_EDGE",
|
||||
"Edge bounds Hole",
|
||||
[for (i=uniq_edges[i]) varr[i]],
|
||||
"magenta"
|
||||
]
|
||||
])
|
||||
) concat(
|
||||
big_faces,
|
||||
null_faces,
|
||||
nonplanars,
|
||||
overpop_edges,
|
||||
reversals,
|
||||
t_juncts,
|
||||
isect_faces,
|
||||
hole_edges
|
||||
);
|
||||
assert(is_path(vnf[0]))
|
||||
let(
|
||||
vnf = vnf_compact(vnf),
|
||||
varr = vnf[0],
|
||||
faces = vnf[1],
|
||||
edges = sort([
|
||||
for (face=faces, edge=pair_wrap(face))
|
||||
edge[0]<edge[1]? edge : [edge[1],edge[0]]
|
||||
]),
|
||||
edgecnts = unique_count(edges),
|
||||
uniq_edges = edgecnts[0],
|
||||
big_faces = !show_warns? [] : [
|
||||
for (face = faces)
|
||||
if (len(face) > 3) [
|
||||
"WARNING",
|
||||
"BIG_FACE",
|
||||
"Face has more than 3 vertices, and may confuse CGAL",
|
||||
[for (i=face) varr[i]],
|
||||
"yellow"
|
||||
]
|
||||
],
|
||||
null_faces = !show_warns? [] : [
|
||||
for (face = faces) let(
|
||||
face = deduplicate(face,closed=true)
|
||||
)
|
||||
if (len(face)>=3) let(
|
||||
faceverts = [for (k=face) varr[k]],
|
||||
area = polygon_area(faceverts)
|
||||
) if (is_num(area) && abs(area) < EPSILON) [
|
||||
"WARNING",
|
||||
"NULL_FACE",
|
||||
str("Face has zero area: ",fmt_float(abs(area),15)),
|
||||
faceverts,
|
||||
"brown"
|
||||
]
|
||||
],
|
||||
nonplanars = unique([
|
||||
for (face = faces) let(
|
||||
faceverts = [for (k=face) varr[k]]
|
||||
) if (!points_are_coplanar(faceverts)) [
|
||||
"ERROR",
|
||||
"NONPLANAR",
|
||||
"Face vertices are not coplanar",
|
||||
faceverts,
|
||||
"cyan"
|
||||
]
|
||||
]),
|
||||
overpop_edges = unique([
|
||||
for (i=idx(uniq_edges))
|
||||
if (edgecnts[1][i]>2) [
|
||||
"ERROR",
|
||||
"OVRPOP_EDGE",
|
||||
"Too many faces attached at Edge",
|
||||
[for (i=uniq_edges[i]) varr[i]],
|
||||
"#f70"
|
||||
]
|
||||
]),
|
||||
reversals = unique([
|
||||
for(i = idx(faces), j = idx(faces)) if(i != j)
|
||||
if(len(deduplicate(faces[i],closed=true))>=3)
|
||||
if(len(deduplicate(faces[j],closed=true))>=3)
|
||||
for(edge1 = pair_wrap(faces[i]))
|
||||
for(edge2 = pair_wrap(faces[j]))
|
||||
if(edge1 == edge2) // Valid adjacent faces will never have the same vertex ordering.
|
||||
if(_edge_not_reported(edge1, varr, overpop_edges))
|
||||
[
|
||||
"ERROR",
|
||||
"REVERSAL",
|
||||
"Faces Reverse Across Edge",
|
||||
[for (i=edge1) varr[i]],
|
||||
"violet"
|
||||
]
|
||||
]),
|
||||
t_juncts = unique([
|
||||
for (v=idx(varr), edge=uniq_edges)
|
||||
if (v!=edge[0] && v!=edge[1]) let(
|
||||
a = varr[edge[0]],
|
||||
b = varr[v],
|
||||
c = varr[edge[1]],
|
||||
pt = segment_closest_point([a,c],b)
|
||||
) if (pt == b) [
|
||||
"ERROR",
|
||||
"T_JUNCTION",
|
||||
"Vertex is mid-edge on another Face",
|
||||
[b],
|
||||
"red"
|
||||
]
|
||||
]),
|
||||
isect_faces = !check_isects? [] : unique([
|
||||
for (i = [0:1:len(faces)-2])
|
||||
for (j = [i+1:1:len(faces)-1]) let(
|
||||
f1 = faces[i],
|
||||
f2 = faces[j],
|
||||
shared_edges = [
|
||||
for (edge1 = pair_wrap(f1), edge2 = pair_wrap(f2)) let(
|
||||
e1 = edge1[0]<edge1[1]? edge1 : [edge1[1],edge1[0]],
|
||||
e2 = edge2[0]<edge2[1]? edge2 : [edge2[1],edge2[0]]
|
||||
) if (e1==e2) 1
|
||||
]
|
||||
)
|
||||
if (!shared_edges) let(
|
||||
plane1 = plane3pt_indexed(varr, f1[0], f1[1], f1[2]),
|
||||
plane2 = plane3pt_indexed(varr, f2[0], f2[1], f2[2]),
|
||||
line = plane_intersection(plane1, plane2)
|
||||
)
|
||||
if (!is_undef(line)) let(
|
||||
poly1 = select(varr,f1),
|
||||
isects = polygon_line_intersection(poly1,line)
|
||||
)
|
||||
if (!is_undef(isects))
|
||||
for (isect=isects)
|
||||
if (len(isect)>1) let(
|
||||
poly2 = select(varr,f2),
|
||||
isects2 = polygon_line_intersection(poly2,isect,bounded=true)
|
||||
)
|
||||
if (!is_undef(isects2))
|
||||
for (seg=isects2)
|
||||
if (seg[0] != seg[1]) [
|
||||
"ERROR",
|
||||
"FACE_ISECT",
|
||||
"Faces intersect",
|
||||
seg,
|
||||
"blue"
|
||||
]
|
||||
]),
|
||||
hole_edges = unique([
|
||||
for (i=idx(uniq_edges))
|
||||
if (edgecnts[1][i]<2)
|
||||
if (_pts_not_reported(uniq_edges[i], varr, t_juncts))
|
||||
if (_pts_not_reported(uniq_edges[i], varr, isect_faces))
|
||||
[
|
||||
"ERROR",
|
||||
"HOLE_EDGE",
|
||||
"Edge bounds Hole",
|
||||
[for (i=uniq_edges[i]) varr[i]],
|
||||
"magenta"
|
||||
]
|
||||
])
|
||||
) concat(
|
||||
big_faces,
|
||||
null_faces,
|
||||
nonplanars,
|
||||
overpop_edges,
|
||||
reversals,
|
||||
t_juncts,
|
||||
isect_faces,
|
||||
hole_edges
|
||||
);
|
||||
|
||||
|
||||
function _pts_not_reported(pts, varr, reports) =
|
||||
[
|
||||
for (i = pts, report = reports, pt = report[3])
|
||||
if (varr[i] == pt) 1
|
||||
] == [];
|
||||
[
|
||||
for (i = pts, report = reports, pt = report[3])
|
||||
if (varr[i] == pt) 1
|
||||
] == [];
|
||||
|
||||
|
||||
function _edge_not_reported(edge, varr, reports) =
|
||||
let(
|
||||
edge = sort([for (i=edge) varr[i]])
|
||||
) [
|
||||
for (report = reports) let(
|
||||
pts = sort(report[3])
|
||||
) if (len(pts)==2 && edge == pts) 1
|
||||
] == [];
|
||||
let(
|
||||
edge = sort([for (i=edge) varr[i]])
|
||||
) [
|
||||
for (report = reports) let(
|
||||
pts = sort(report[3])
|
||||
) if (len(pts)==2 && edge == pts) 1
|
||||
] == [];
|
||||
|
||||
|
||||
module vnf_validate(vnf, size=1, show_warns=true, check_isects=false) {
|
||||
faults = vnf_validate(
|
||||
vnf, show_warns=show_warns,
|
||||
check_isects=check_isects
|
||||
);
|
||||
for (fault = faults) {
|
||||
typ = fault[0];
|
||||
err = fault[1];
|
||||
msg = fault[2];
|
||||
pts = fault[3];
|
||||
clr = fault[4];
|
||||
echo(str(typ, " ", err, ": ", msg, " at ", pts));
|
||||
color(clr) {
|
||||
if (len(pts)==2) {
|
||||
stroke(pts, width=size);
|
||||
} else if (len(pts)>2) {
|
||||
stroke(pts, width=size, closed=true);
|
||||
polyhedron(pts,[[for (i=idx(pts)) i]]);
|
||||
} else {
|
||||
move_copies(pts) sphere(d=size*3, $fn=18);
|
||||
}
|
||||
}
|
||||
}
|
||||
color([0.5,0.5,0.5,0.5]) vnf_polyhedron(vnf);
|
||||
faults = vnf_validate(
|
||||
vnf, show_warns=show_warns,
|
||||
check_isects=check_isects
|
||||
);
|
||||
for (fault = faults) {
|
||||
typ = fault[0];
|
||||
err = fault[1];
|
||||
msg = fault[2];
|
||||
pts = fault[3];
|
||||
clr = fault[4];
|
||||
echo(str(typ, " ", err, ": ", msg, " at ", pts));
|
||||
color(clr) {
|
||||
if (len(pts)==2) {
|
||||
stroke(pts, width=size);
|
||||
} else if (len(pts)>2) {
|
||||
stroke(pts, width=size, closed=true);
|
||||
polyhedron(pts,[[for (i=idx(pts)) i]]);
|
||||
} else {
|
||||
move_copies(pts) sphere(d=size*3, $fn=18);
|
||||
}
|
||||
}
|
||||
}
|
||||
color([0.5,0.5,0.5,0.5]) vnf_polyhedron(vnf);
|
||||
}
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
568
walls.scad
568
walls.scad
@ -36,25 +36,25 @@
|
||||
// narrowing_strut(w=10, l=100, wall=5, ang=30);
|
||||
module narrowing_strut(w=10, l=100, wall=5, ang=30, anchor=BOTTOM, spin=0, orient=UP)
|
||||
{
|
||||
h = wall + w/2/tan(ang);
|
||||
size = [w, l, h];
|
||||
attachable(anchor,spin,orient, size=size) {
|
||||
xrot(90)
|
||||
fwd(h/2) {
|
||||
linear_extrude(height=l, center=true, slices=2) {
|
||||
back(wall/2) square([w, wall], center=true);
|
||||
back(wall-0.001) {
|
||||
yscale(1/tan(ang)) {
|
||||
difference() {
|
||||
zrot(45) square(w/sqrt(2), center=true);
|
||||
fwd(w/2) square(w, center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
h = wall + w/2/tan(ang);
|
||||
size = [w, l, h];
|
||||
attachable(anchor,spin,orient, size=size) {
|
||||
xrot(90)
|
||||
fwd(h/2) {
|
||||
linear_extrude(height=l, center=true, slices=2) {
|
||||
back(wall/2) square([w, wall], center=true);
|
||||
back(wall-0.001) {
|
||||
yscale(1/tan(ang)) {
|
||||
difference() {
|
||||
zrot(45) square(w/sqrt(2), center=true);
|
||||
fwd(w/2) square(w, center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -87,152 +87,152 @@ module narrowing_strut(w=10, l=100, wall=5, ang=30, anchor=BOTTOM, spin=0, orien
|
||||
// thinning_wall(h=50, l=[80,50], thick=4, strut=4, wall=2, braces=true);
|
||||
module thinning_wall(h=50, l=100, thick=5, ang=30, braces=false, strut, wall, anchor=CENTER, spin=0, orient=UP)
|
||||
{
|
||||
l1 = (l[0] == undef)? l : l[0];
|
||||
l2 = (l[1] == undef)? l : l[1];
|
||||
strut = is_num(strut)? strut : min(h,l1,l2,thick)/2;
|
||||
wall = is_num(wall)? wall : thick/2;
|
||||
l1 = (l[0] == undef)? l : l[0];
|
||||
l2 = (l[1] == undef)? l : l[1];
|
||||
strut = is_num(strut)? strut : min(h,l1,l2,thick)/2;
|
||||
wall = is_num(wall)? wall : thick/2;
|
||||
|
||||
bevel_h = strut + (thick-wall)/2/tan(ang);
|
||||
cp1 = find_circle_2tangents([0,0,h/2], [l2/2,0,h/2], [l1/2,0,-h/2], r=strut)[0];
|
||||
cp2 = find_circle_2tangents([0,0,h/2], [l2/2,0,h/2], [l1/2,0,-h/2], r=bevel_h)[0];
|
||||
cp3 = find_circle_2tangents([0,0,-h/2], [l1/2,0,-h/2], [l2/2,0,h/2], r=bevel_h)[0];
|
||||
cp4 = find_circle_2tangents([0,0,-h/2], [l1/2,0,-h/2], [l2/2,0,h/2], r=strut)[0];
|
||||
bevel_h = strut + (thick-wall)/2/tan(ang);
|
||||
cp1 = find_circle_2tangents([0,0,h/2], [l2/2,0,h/2], [l1/2,0,-h/2], r=strut)[0];
|
||||
cp2 = find_circle_2tangents([0,0,h/2], [l2/2,0,h/2], [l1/2,0,-h/2], r=bevel_h)[0];
|
||||
cp3 = find_circle_2tangents([0,0,-h/2], [l1/2,0,-h/2], [l2/2,0,h/2], r=bevel_h)[0];
|
||||
cp4 = find_circle_2tangents([0,0,-h/2], [l1/2,0,-h/2], [l2/2,0,h/2], r=strut)[0];
|
||||
|
||||
z1 = h/2;
|
||||
z2 = cp1.z;
|
||||
z3 = cp2.z;
|
||||
z1 = h/2;
|
||||
z2 = cp1.z;
|
||||
z3 = cp2.z;
|
||||
|
||||
x1 = l2/2;
|
||||
x2 = cp1.x;
|
||||
x3 = cp2.x;
|
||||
x4 = l1/2;
|
||||
x5 = cp4.x;
|
||||
x6 = cp3.x;
|
||||
x1 = l2/2;
|
||||
x2 = cp1.x;
|
||||
x3 = cp2.x;
|
||||
x4 = l1/2;
|
||||
x5 = cp4.x;
|
||||
x6 = cp3.x;
|
||||
|
||||
y1 = thick/2;
|
||||
y2 = wall/2;
|
||||
y1 = thick/2;
|
||||
y2 = wall/2;
|
||||
|
||||
corner1 = [ x2, 0, z2];
|
||||
corner2 = [-x5, 0, -z2];
|
||||
brace_len = norm(corner1-corner2);
|
||||
corner1 = [ x2, 0, z2];
|
||||
corner2 = [-x5, 0, -z2];
|
||||
brace_len = norm(corner1-corner2);
|
||||
|
||||
size = [l1, thick, h];
|
||||
attachable(anchor,spin,orient, size=size, size2=[l2,thick]) {
|
||||
union() {
|
||||
polyhedron(
|
||||
points=[
|
||||
[-x4, -y1, -z1],
|
||||
[ x4, -y1, -z1],
|
||||
[ x1, -y1, z1],
|
||||
[-x1, -y1, z1],
|
||||
size = [l1, thick, h];
|
||||
attachable(anchor,spin,orient, size=size, size2=[l2,thick]) {
|
||||
union() {
|
||||
polyhedron(
|
||||
points=[
|
||||
[-x4, -y1, -z1],
|
||||
[ x4, -y1, -z1],
|
||||
[ x1, -y1, z1],
|
||||
[-x1, -y1, z1],
|
||||
|
||||
[-x5, -y1, -z2],
|
||||
[ x5, -y1, -z2],
|
||||
[ x2, -y1, z2],
|
||||
[-x2, -y1, z2],
|
||||
[-x5, -y1, -z2],
|
||||
[ x5, -y1, -z2],
|
||||
[ x2, -y1, z2],
|
||||
[-x2, -y1, z2],
|
||||
|
||||
[-x6, -y2, -z3],
|
||||
[ x6, -y2, -z3],
|
||||
[ x3, -y2, z3],
|
||||
[-x3, -y2, z3],
|
||||
[-x6, -y2, -z3],
|
||||
[ x6, -y2, -z3],
|
||||
[ x3, -y2, z3],
|
||||
[-x3, -y2, z3],
|
||||
|
||||
[-x4, y1, -z1],
|
||||
[ x4, y1, -z1],
|
||||
[ x1, y1, z1],
|
||||
[-x1, y1, z1],
|
||||
[-x4, y1, -z1],
|
||||
[ x4, y1, -z1],
|
||||
[ x1, y1, z1],
|
||||
[-x1, y1, z1],
|
||||
|
||||
[-x5, y1, -z2],
|
||||
[ x5, y1, -z2],
|
||||
[ x2, y1, z2],
|
||||
[-x2, y1, z2],
|
||||
[-x5, y1, -z2],
|
||||
[ x5, y1, -z2],
|
||||
[ x2, y1, z2],
|
||||
[-x2, y1, z2],
|
||||
|
||||
[-x6, y2, -z3],
|
||||
[ x6, y2, -z3],
|
||||
[ x3, y2, z3],
|
||||
[-x3, y2, z3],
|
||||
],
|
||||
faces=[
|
||||
[ 4, 5, 1],
|
||||
[ 5, 6, 2],
|
||||
[ 6, 7, 3],
|
||||
[ 7, 4, 0],
|
||||
[-x6, y2, -z3],
|
||||
[ x6, y2, -z3],
|
||||
[ x3, y2, z3],
|
||||
[-x3, y2, z3],
|
||||
],
|
||||
faces=[
|
||||
[ 4, 5, 1],
|
||||
[ 5, 6, 2],
|
||||
[ 6, 7, 3],
|
||||
[ 7, 4, 0],
|
||||
|
||||
[ 4, 1, 0],
|
||||
[ 5, 2, 1],
|
||||
[ 6, 3, 2],
|
||||
[ 7, 0, 3],
|
||||
[ 4, 1, 0],
|
||||
[ 5, 2, 1],
|
||||
[ 6, 3, 2],
|
||||
[ 7, 0, 3],
|
||||
|
||||
[ 8, 9, 5],
|
||||
[ 9, 10, 6],
|
||||
[10, 11, 7],
|
||||
[11, 8, 4],
|
||||
[ 8, 9, 5],
|
||||
[ 9, 10, 6],
|
||||
[10, 11, 7],
|
||||
[11, 8, 4],
|
||||
|
||||
[ 8, 5, 4],
|
||||
[ 9, 6, 5],
|
||||
[10, 7, 6],
|
||||
[11, 4, 7],
|
||||
[ 8, 5, 4],
|
||||
[ 9, 6, 5],
|
||||
[10, 7, 6],
|
||||
[11, 4, 7],
|
||||
|
||||
[11, 10, 9],
|
||||
[20, 21, 22],
|
||||
[11, 10, 9],
|
||||
[20, 21, 22],
|
||||
|
||||
[11, 9, 8],
|
||||
[20, 22, 23],
|
||||
[11, 9, 8],
|
||||
[20, 22, 23],
|
||||
|
||||
[16, 17, 21],
|
||||
[17, 18, 22],
|
||||
[18, 19, 23],
|
||||
[19, 16, 20],
|
||||
[16, 17, 21],
|
||||
[17, 18, 22],
|
||||
[18, 19, 23],
|
||||
[19, 16, 20],
|
||||
|
||||
[16, 21, 20],
|
||||
[17, 22, 21],
|
||||
[18, 23, 22],
|
||||
[19, 20, 23],
|
||||
[16, 21, 20],
|
||||
[17, 22, 21],
|
||||
[18, 23, 22],
|
||||
[19, 20, 23],
|
||||
|
||||
[12, 13, 17],
|
||||
[13, 14, 18],
|
||||
[14, 15, 19],
|
||||
[15, 12, 16],
|
||||
[12, 13, 17],
|
||||
[13, 14, 18],
|
||||
[14, 15, 19],
|
||||
[15, 12, 16],
|
||||
|
||||
[12, 17, 16],
|
||||
[13, 18, 17],
|
||||
[14, 19, 18],
|
||||
[15, 16, 19],
|
||||
[12, 17, 16],
|
||||
[13, 18, 17],
|
||||
[14, 19, 18],
|
||||
[15, 16, 19],
|
||||
|
||||
[ 0, 1, 13],
|
||||
[ 1, 2, 14],
|
||||
[ 2, 3, 15],
|
||||
[ 3, 0, 12],
|
||||
[ 0, 1, 13],
|
||||
[ 1, 2, 14],
|
||||
[ 2, 3, 15],
|
||||
[ 3, 0, 12],
|
||||
|
||||
[ 0, 13, 12],
|
||||
[ 1, 14, 13],
|
||||
[ 2, 15, 14],
|
||||
[ 3, 12, 15],
|
||||
],
|
||||
convexity=6
|
||||
);
|
||||
if(braces) {
|
||||
bracepath = [
|
||||
[-strut*0.33,thick/2],
|
||||
[ strut*0.33,thick/2],
|
||||
[ strut*0.33+(thick-wall)/2/tan(ang), wall/2],
|
||||
[ strut*0.33+(thick-wall)/2/tan(ang),-wall/2],
|
||||
[ strut*0.33,-thick/2],
|
||||
[-strut*0.33,-thick/2],
|
||||
[-strut*0.33-(thick-wall)/2/tan(ang),-wall/2],
|
||||
[-strut*0.33-(thick-wall)/2/tan(ang), wall/2]
|
||||
];
|
||||
xflip_copy() {
|
||||
intersection() {
|
||||
extrude_from_to(corner1,corner2) {
|
||||
polygon(bracepath);
|
||||
}
|
||||
prismoid([l1,thick],[l2,thick],h=h,anchor=CENTER);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
[ 0, 13, 12],
|
||||
[ 1, 14, 13],
|
||||
[ 2, 15, 14],
|
||||
[ 3, 12, 15],
|
||||
],
|
||||
convexity=6
|
||||
);
|
||||
if(braces) {
|
||||
bracepath = [
|
||||
[-strut*0.33,thick/2],
|
||||
[ strut*0.33,thick/2],
|
||||
[ strut*0.33+(thick-wall)/2/tan(ang), wall/2],
|
||||
[ strut*0.33+(thick-wall)/2/tan(ang),-wall/2],
|
||||
[ strut*0.33,-thick/2],
|
||||
[-strut*0.33,-thick/2],
|
||||
[-strut*0.33-(thick-wall)/2/tan(ang),-wall/2],
|
||||
[-strut*0.33-(thick-wall)/2/tan(ang), wall/2]
|
||||
];
|
||||
xflip_copy() {
|
||||
intersection() {
|
||||
extrude_from_to(corner1,corner2) {
|
||||
polygon(bracepath);
|
||||
}
|
||||
prismoid([l1,thick],[l2,thick],h=h,anchor=CENTER);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -266,35 +266,35 @@ module thinning_wall(h=50, l=100, thick=5, ang=30, braces=false, strut, wall, an
|
||||
// thinning_triangle(h=50, l=80, thick=4, ang=30, strut=5, wall=2, diagonly=true, center=false);
|
||||
module thinning_triangle(h=50, l=100, thick=5, ang=30, strut=5, wall=3, diagonly=false, center, anchor, spin=0, orient=UP)
|
||||
{
|
||||
dang = atan(h/l);
|
||||
dlen = h/sin(dang);
|
||||
size = [thick, l, h];
|
||||
anchor = get_anchor(anchor, center, BOT+FRONT, CENTER);
|
||||
attachable(anchor,spin,orient, size=size) {
|
||||
difference() {
|
||||
union() {
|
||||
if (!diagonly) {
|
||||
translate([0, 0, -h/2])
|
||||
narrowing_strut(w=thick, l=l, wall=strut, ang=ang);
|
||||
translate([0, -l/2, 0])
|
||||
xrot(-90) narrowing_strut(w=thick, l=h-0.1, wall=strut, ang=ang);
|
||||
}
|
||||
intersection() {
|
||||
cube(size=[thick, l, h], center=true);
|
||||
xrot(-dang) yrot(180) {
|
||||
narrowing_strut(w=thick, l=dlen*1.2, wall=strut, ang=ang);
|
||||
}
|
||||
}
|
||||
cube(size=[wall, l-0.1, h-0.1], center=true);
|
||||
}
|
||||
xrot(-dang) {
|
||||
translate([0, 0, h/2]) {
|
||||
cube(size=[thick+0.1, l*2, h], center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
dang = atan(h/l);
|
||||
dlen = h/sin(dang);
|
||||
size = [thick, l, h];
|
||||
anchor = get_anchor(anchor, center, BOT+FRONT, CENTER);
|
||||
attachable(anchor,spin,orient, size=size) {
|
||||
difference() {
|
||||
union() {
|
||||
if (!diagonly) {
|
||||
translate([0, 0, -h/2])
|
||||
narrowing_strut(w=thick, l=l, wall=strut, ang=ang);
|
||||
translate([0, -l/2, 0])
|
||||
xrot(-90) narrowing_strut(w=thick, l=h-0.1, wall=strut, ang=ang);
|
||||
}
|
||||
intersection() {
|
||||
cube(size=[thick, l, h], center=true);
|
||||
xrot(-dang) yrot(180) {
|
||||
narrowing_strut(w=thick, l=dlen*1.2, wall=strut, ang=ang);
|
||||
}
|
||||
}
|
||||
cube(size=[wall, l-0.1, h-0.1], center=true);
|
||||
}
|
||||
xrot(-dang) {
|
||||
translate([0, 0, h/2]) {
|
||||
cube(size=[thick+0.1, l*2, h], center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -328,41 +328,41 @@ module thinning_triangle(h=50, l=100, thick=5, ang=30, strut=5, wall=3, diagonly
|
||||
// sparse_strut(h=40, l=100, thick=3, strut=2, maxang=45, max_bridge=30);
|
||||
module sparse_strut(h=50, l=100, thick=4, maxang=30, strut=5, max_bridge=20, anchor=CENTER, spin=0, orient=UP)
|
||||
{
|
||||
zoff = h/2 - strut/2;
|
||||
yoff = l/2 - strut/2;
|
||||
zoff = h/2 - strut/2;
|
||||
yoff = l/2 - strut/2;
|
||||
|
||||
maxhyp = 1.5 * (max_bridge+strut)/2 / sin(maxang);
|
||||
maxz = 2 * maxhyp * cos(maxang);
|
||||
maxhyp = 1.5 * (max_bridge+strut)/2 / sin(maxang);
|
||||
maxz = 2 * maxhyp * cos(maxang);
|
||||
|
||||
zreps = ceil(2*zoff/maxz);
|
||||
zstep = 2*zoff / zreps;
|
||||
zreps = ceil(2*zoff/maxz);
|
||||
zstep = 2*zoff / zreps;
|
||||
|
||||
hyp = zstep/2 / cos(maxang);
|
||||
maxy = min(2 * hyp * sin(maxang), max_bridge+strut);
|
||||
hyp = zstep/2 / cos(maxang);
|
||||
maxy = min(2 * hyp * sin(maxang), max_bridge+strut);
|
||||
|
||||
yreps = ceil(2*yoff/maxy);
|
||||
ystep = 2*yoff / yreps;
|
||||
yreps = ceil(2*yoff/maxy);
|
||||
ystep = 2*yoff / yreps;
|
||||
|
||||
ang = atan(ystep/zstep);
|
||||
len = zstep / cos(ang);
|
||||
ang = atan(ystep/zstep);
|
||||
len = zstep / cos(ang);
|
||||
|
||||
size = [thick, l, h];
|
||||
attachable(anchor,spin,orient, size=size) {
|
||||
yrot(90)
|
||||
linear_extrude(height=thick, convexity=4*yreps, center=true) {
|
||||
difference() {
|
||||
square([h, l], center=true);
|
||||
square([h-2*strut, l-2*strut], center=true);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
size = [thick, l, h];
|
||||
attachable(anchor,spin,orient, size=size) {
|
||||
yrot(90)
|
||||
linear_extrude(height=thick, convexity=4*yreps, center=true) {
|
||||
difference() {
|
||||
square([h, l], center=true);
|
||||
square([h-2*strut, l-2*strut], center=true);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -398,70 +398,70 @@ module sparse_strut(h=50, l=100, thick=4, maxang=30, strut=5, max_bridge=20, anc
|
||||
module sparse_strut3d(h=50, l=100, w=50, thick=3, maxang=40, strut=3, max_bridge=30, anchor=CENTER, spin=0, orient=UP)
|
||||
{
|
||||
|
||||
xoff = w - thick;
|
||||
yoff = l - thick;
|
||||
zoff = h - thick;
|
||||
xoff = w - thick;
|
||||
yoff = l - thick;
|
||||
zoff = h - thick;
|
||||
|
||||
xreps = ceil(xoff/yoff);
|
||||
yreps = ceil(yoff/xoff);
|
||||
zreps = ceil(zoff/min(xoff, yoff));
|
||||
xreps = ceil(xoff/yoff);
|
||||
yreps = ceil(yoff/xoff);
|
||||
zreps = ceil(zoff/min(xoff, yoff));
|
||||
|
||||
xstep = xoff / xreps;
|
||||
ystep = yoff / yreps;
|
||||
zstep = zoff / zreps;
|
||||
xstep = xoff / xreps;
|
||||
ystep = yoff / yreps;
|
||||
zstep = zoff / zreps;
|
||||
|
||||
cross_ang = atan2(xstep, ystep);
|
||||
cross_len = hypot(xstep, ystep);
|
||||
cross_ang = atan2(xstep, ystep);
|
||||
cross_len = hypot(xstep, ystep);
|
||||
|
||||
supp_ang = min(maxang, min(atan2(max_bridge, zstep), atan2(cross_len/2, zstep)));
|
||||
supp_reps = floor(cross_len/2/(zstep*sin(supp_ang)));
|
||||
supp_step = cross_len/2/supp_reps;
|
||||
supp_ang = min(maxang, min(atan2(max_bridge, zstep), atan2(cross_len/2, zstep)));
|
||||
supp_reps = floor(cross_len/2/(zstep*sin(supp_ang)));
|
||||
supp_step = cross_len/2/supp_reps;
|
||||
|
||||
size = [w, l, h];
|
||||
attachable(anchor,spin,orient, size=size) {
|
||||
intersection() {
|
||||
union() {
|
||||
ybridge = (l - (yreps+1) * strut) / yreps;
|
||||
xcopies(xoff) sparse_strut(h=h, l=l, thick=thick, maxang=maxang, strut=strut, max_bridge=ybridge/ceil(ybridge/max_bridge));
|
||||
ycopies(yoff) zrot(90) sparse_strut(h=h, l=w, thick=thick, maxang=maxang, strut=strut, max_bridge=max_bridge);
|
||||
for(zs = [0:1:zreps-1]) {
|
||||
for(xs = [0:1:xreps-1]) {
|
||||
for(ys = [0:1:yreps-1]) {
|
||||
translate([(xs+0.5)*xstep-xoff/2, (ys+0.5)*ystep-yoff/2, (zs+0.5)*zstep-zoff/2]) {
|
||||
zflip_copy(offset=-(zstep-strut)/2) {
|
||||
xflip_copy() {
|
||||
zrot(cross_ang) {
|
||||
down(strut/2) {
|
||||
cube([strut, cross_len, strut], center=true);
|
||||
}
|
||||
if (zreps>1) {
|
||||
back(cross_len/2) {
|
||||
zrot(-cross_ang) {
|
||||
down(strut) cube([strut, strut, zstep+strut], anchor=BOTTOM);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (soff = [0:1:supp_reps-1] ) {
|
||||
yflip_copy() {
|
||||
back(soff*supp_step) {
|
||||
skew(syz=tan(supp_ang)) {
|
||||
cube([strut, strut, zstep], anchor=BOTTOM);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cube([w,l,h], center=true);
|
||||
}
|
||||
children();
|
||||
}
|
||||
size = [w, l, h];
|
||||
attachable(anchor,spin,orient, size=size) {
|
||||
intersection() {
|
||||
union() {
|
||||
ybridge = (l - (yreps+1) * strut) / yreps;
|
||||
xcopies(xoff) sparse_strut(h=h, l=l, thick=thick, maxang=maxang, strut=strut, max_bridge=ybridge/ceil(ybridge/max_bridge));
|
||||
ycopies(yoff) zrot(90) sparse_strut(h=h, l=w, thick=thick, maxang=maxang, strut=strut, max_bridge=max_bridge);
|
||||
for(zs = [0:1:zreps-1]) {
|
||||
for(xs = [0:1:xreps-1]) {
|
||||
for(ys = [0:1:yreps-1]) {
|
||||
translate([(xs+0.5)*xstep-xoff/2, (ys+0.5)*ystep-yoff/2, (zs+0.5)*zstep-zoff/2]) {
|
||||
zflip_copy(offset=-(zstep-strut)/2) {
|
||||
xflip_copy() {
|
||||
zrot(cross_ang) {
|
||||
down(strut/2) {
|
||||
cube([strut, cross_len, strut], center=true);
|
||||
}
|
||||
if (zreps>1) {
|
||||
back(cross_len/2) {
|
||||
zrot(-cross_ang) {
|
||||
down(strut) cube([strut, strut, zstep+strut], anchor=BOTTOM);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (soff = [0:1:supp_reps-1] ) {
|
||||
yflip_copy() {
|
||||
back(soff*supp_step) {
|
||||
skew(syz=tan(supp_ang)) {
|
||||
cube([strut, strut, zstep], anchor=BOTTOM);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cube([w,l,h], center=true);
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -492,31 +492,31 @@ module sparse_strut3d(h=50, l=100, w=50, thick=3, maxang=40, strut=3, max_bridge
|
||||
// corrugated_wall(h=50, l=100, strut=8, wall=3);
|
||||
module corrugated_wall(h=50, l=100, thick=5, strut=5, wall=2, anchor=CENTER, spin=0, orient=UP)
|
||||
{
|
||||
amplitude = (thick - wall) / 2;
|
||||
period = min(15, thick * 2);
|
||||
steps = quantup(segs(thick/2),4);
|
||||
step = period/steps;
|
||||
il = l - 2*strut + 2*step;
|
||||
size = [thick, l, h];
|
||||
attachable(anchor,spin,orient, size=size) {
|
||||
union() {
|
||||
linear_extrude(height=h-2*strut+0.1, slices=2, convexity=ceil(2*il/period), center=true) {
|
||||
polygon(
|
||||
points=concat(
|
||||
[for (y=[-il/2:step:il/2]) [amplitude*sin(y/period*360)-wall/2, y] ],
|
||||
[for (y=[il/2:-step:-il/2]) [amplitude*sin(y/period*360)+wall/2, y] ]
|
||||
)
|
||||
);
|
||||
}
|
||||
difference() {
|
||||
cube([thick, l, h], center=true);
|
||||
cube([thick+0.5, l-2*strut, h-2*strut], center=true);
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
amplitude = (thick - wall) / 2;
|
||||
period = min(15, thick * 2);
|
||||
steps = quantup(segs(thick/2),4);
|
||||
step = period/steps;
|
||||
il = l - 2*strut + 2*step;
|
||||
size = [thick, l, h];
|
||||
attachable(anchor,spin,orient, size=size) {
|
||||
union() {
|
||||
linear_extrude(height=h-2*strut+0.1, slices=2, convexity=ceil(2*il/period), center=true) {
|
||||
polygon(
|
||||
points=concat(
|
||||
[for (y=[-il/2:step:il/2]) [amplitude*sin(y/period*360)-wall/2, y] ],
|
||||
[for (y=[il/2:-step:-il/2]) [amplitude*sin(y/period*360)+wall/2, y] ]
|
||||
)
|
||||
);
|
||||
}
|
||||
difference() {
|
||||
cube([thick, l, h], center=true);
|
||||
cube([thick+0.5, l-2*strut, h-2*strut], center=true);
|
||||
}
|
||||
}
|
||||
children();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
70
wiring.scad
70
wiring.scad
@ -28,15 +28,15 @@ include <beziers.scad>
|
||||
// Example:
|
||||
// hex_offset_ring(d=1, lev=3); // Returns a hex ring of 18 points.
|
||||
function hex_offset_ring(d, lev=0) =
|
||||
(lev == 0)? [[0,0]] : [
|
||||
for (
|
||||
sideang = [0:60:359.999],
|
||||
sidenum = [1:1:lev]
|
||||
) [
|
||||
lev*d*cos(sideang)+sidenum*d*cos(sideang+120),
|
||||
lev*d*sin(sideang)+sidenum*d*sin(sideang+120)
|
||||
]
|
||||
];
|
||||
(lev == 0)? [[0,0]] : [
|
||||
for (
|
||||
sideang = [0:60:359.999],
|
||||
sidenum = [1:1:lev]
|
||||
) [
|
||||
lev*d*cos(sideang)+sidenum*d*cos(sideang+120),
|
||||
lev*d*sin(sideang)+sidenum*d*sin(sideang+120)
|
||||
]
|
||||
];
|
||||
|
||||
|
||||
// Function: hex_offsets()
|
||||
@ -51,13 +51,13 @@ function hex_offset_ring(d, lev=0) =
|
||||
// n = Number of items to bundle.
|
||||
// d = How far to space each point away from others.
|
||||
function hex_offsets(n, d, lev=0, arr=[]) =
|
||||
(len(arr) >= n)? arr :
|
||||
hex_offsets(
|
||||
n=n,
|
||||
d=d,
|
||||
lev=lev+1,
|
||||
arr=concat(arr, hex_offset_ring(d, lev=lev))
|
||||
);
|
||||
(len(arr) >= n)? arr :
|
||||
hex_offsets(
|
||||
n=n,
|
||||
d=d,
|
||||
lev=lev+1,
|
||||
arr=concat(arr, hex_offset_ring(d, lev=lev))
|
||||
);
|
||||
|
||||
|
||||
|
||||
@ -81,26 +81,26 @@ function hex_offsets(n, d, lev=0, arr=[]) =
|
||||
// Example:
|
||||
// wiring([[50,0,-50], [50,50,-50], [0,50,-50], [0,0,-50], [0,0,0]], rounding=10, wires=13);
|
||||
module wiring(path, wires, wirediam=2, rounding=10, wirenum=0, bezsteps=12) {
|
||||
colors = [
|
||||
[0.2, 0.2, 0.2], [1.0, 0.2, 0.2], [0.0, 0.8, 0.0], [1.0, 1.0, 0.2],
|
||||
[0.3, 0.3, 1.0], [1.0, 1.0, 1.0], [0.7, 0.5, 0.0], [0.5, 0.5, 0.5],
|
||||
[0.2, 0.9, 0.9], [0.8, 0.0, 0.8], [0.0, 0.6, 0.6], [1.0, 0.7, 0.7],
|
||||
[1.0, 0.5, 1.0], [0.5, 0.6, 0.0], [1.0, 0.7, 0.0], [0.7, 1.0, 0.5],
|
||||
[0.6, 0.6, 1.0],
|
||||
];
|
||||
offsets = hex_offsets(wires, wirediam);
|
||||
bezpath = fillet_path(path, rounding);
|
||||
poly = simplify_path(path3d(bezier_polyline(bezpath, bezsteps)));
|
||||
n = max(segs(wirediam), 8);
|
||||
r = wirediam/2;
|
||||
for (i = [0:1:wires-1]) {
|
||||
extpath = [for (j = [0:1:n-1]) let(a=j*360/n) [r*cos(a)+offsets[i][0], r*sin(a)+offsets[i][1]]];
|
||||
color(colors[(i+wirenum)%len(colors)]) {
|
||||
path_sweep(extpath, poly);
|
||||
}
|
||||
}
|
||||
colors = [
|
||||
[0.2, 0.2, 0.2], [1.0, 0.2, 0.2], [0.0, 0.8, 0.0], [1.0, 1.0, 0.2],
|
||||
[0.3, 0.3, 1.0], [1.0, 1.0, 1.0], [0.7, 0.5, 0.0], [0.5, 0.5, 0.5],
|
||||
[0.2, 0.9, 0.9], [0.8, 0.0, 0.8], [0.0, 0.6, 0.6], [1.0, 0.7, 0.7],
|
||||
[1.0, 0.5, 1.0], [0.5, 0.6, 0.0], [1.0, 0.7, 0.0], [0.7, 1.0, 0.5],
|
||||
[0.6, 0.6, 1.0],
|
||||
];
|
||||
offsets = hex_offsets(wires, wirediam);
|
||||
bezpath = fillet_path(path, rounding);
|
||||
poly = simplify_path(path3d(bezier_polyline(bezpath, bezsteps)));
|
||||
n = max(segs(wirediam), 8);
|
||||
r = wirediam/2;
|
||||
for (i = [0:1:wires-1]) {
|
||||
extpath = [for (j = [0:1:n-1]) let(a=j*360/n) [r*cos(a)+offsets[i][0], r*sin(a)+offsets[i][1]]];
|
||||
color(colors[(i+wirenum)%len(colors)]) {
|
||||
path_sweep(extpath, poly);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
Loading…
x
Reference in New Issue
Block a user