mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2024-12-29 16:29:40 +00:00
Anchor calculation fixes. Added wedge() and make right_triangle() be 2D.
This commit is contained in:
parent
9f5214adc0
commit
622a13952b
3 changed files with 187 additions and 83 deletions
179
attachments.scad
179
attachments.scad
|
@ -753,6 +753,8 @@ module corner_profile(corners=CORNERS_ALL, except=[], r, d, convexity=10) {
|
||||||
// attachable(anchor, spin, two_d=true, r=|d=, ...) {...}
|
// attachable(anchor, spin, two_d=true, r=|d=, ...) {...}
|
||||||
// Usage: 2D Path/Polygon Geometry
|
// Usage: 2D Path/Polygon Geometry
|
||||||
// attachable(anchor, spin, two_d=true, path=, [extent=], ...) {...}
|
// attachable(anchor, spin, two_d=true, path=, [extent=], ...) {...}
|
||||||
|
// Usage: 2D Region Geometry
|
||||||
|
// attachable(anchor, spin, two_d=true, region=, [extent=], ...) {...}
|
||||||
// Usage: Cubical/Prismoidal Geometry
|
// Usage: Cubical/Prismoidal Geometry
|
||||||
// attachable(anchor, spin, [orient], size=, [size2=], [shift=], ...) {...}
|
// attachable(anchor, spin, [orient], size=, [size2=], [shift=], ...) {...}
|
||||||
// Usage: Cylindrical Geometry
|
// Usage: Cylindrical Geometry
|
||||||
|
@ -763,6 +765,8 @@ module corner_profile(corners=CORNERS_ALL, except=[], r, d, convexity=10) {
|
||||||
// attachable(anchor, spin, [orient], r=|d=, ...) {...}
|
// attachable(anchor, spin, [orient], r=|d=, ...) {...}
|
||||||
// Usage: Extruded Path/Polygon Geometry
|
// Usage: Extruded Path/Polygon Geometry
|
||||||
// attachable(anchor, spin, path=, l=|h=, [extent=], ...) {...}
|
// attachable(anchor, spin, path=, l=|h=, [extent=], ...) {...}
|
||||||
|
// Usage: Extruded Region Geometry
|
||||||
|
// attachable(anchor, spin, region=, l=|h=, [extent=], ...) {...}
|
||||||
// Usage: VNF Geometry
|
// Usage: VNF Geometry
|
||||||
// attachable(anchor, spin, [orient], vnf=, [extent=], ...) {...}
|
// attachable(anchor, spin, [orient], vnf=, [extent=], ...) {...}
|
||||||
//
|
//
|
||||||
|
@ -815,6 +819,7 @@ module corner_profile(corners=CORNERS_ALL, except=[], r, d, convexity=10) {
|
||||||
// l/h = Length of the cylindrical, conical, or extruded path volume along axis.
|
// l/h = Length of the cylindrical, conical, or extruded path volume along axis.
|
||||||
// vnf = The [VNF](vnf.scad) of the volume.
|
// vnf = The [VNF](vnf.scad) of the volume.
|
||||||
// path = The path to generate a polygon from.
|
// path = The path to generate a polygon from.
|
||||||
|
// region = The region to generate a shape from.
|
||||||
// extent = If true, calculate anchors by extents, rather than intersection, for VNFs and paths. Default: true.
|
// extent = If true, calculate anchors by extents, rather than intersection, for VNFs and paths. Default: true.
|
||||||
// cp = If given, specifies the centerpoint of the volume. Default: `[0,0,0]`
|
// cp = If given, specifies the centerpoint of the volume. Default: `[0,0,0]`
|
||||||
// offset = If given, offsets the perimeter of the volume around the centerpoint.
|
// offset = If given, offsets the perimeter of the volume around the centerpoint.
|
||||||
|
@ -953,7 +958,7 @@ module attachable(
|
||||||
anchor, spin, orient,
|
anchor, spin, orient,
|
||||||
size, size2, shift,
|
size, size2, shift,
|
||||||
r,r1,r2, d,d1,d2, l,h,
|
r,r1,r2, d,d1,d2, l,h,
|
||||||
vnf, path,
|
vnf, path, region,
|
||||||
extent=true,
|
extent=true,
|
||||||
cp=[0,0,0],
|
cp=[0,0,0],
|
||||||
offset=[0,0,0],
|
offset=[0,0,0],
|
||||||
|
@ -969,11 +974,14 @@ module attachable(
|
||||||
anchor = default(anchor, CENTER);
|
anchor = default(anchor, CENTER);
|
||||||
spin = default(spin, 0);
|
spin = default(spin, 0);
|
||||||
orient = default(orient, UP);
|
orient = default(orient, UP);
|
||||||
|
region = !is_undef(region)? region :
|
||||||
|
!is_undef(path)? [path] :
|
||||||
|
undef;
|
||||||
geom = _attach_geom(
|
geom = _attach_geom(
|
||||||
size=size, size2=size2, shift=shift,
|
size=size, size2=size2, shift=shift,
|
||||||
r=r, r1=r1, r2=r2, h=h,
|
r=r, r1=r1, r2=r2, h=h,
|
||||||
d=d, d1=d1, d2=d2, l=l,
|
d=d, d1=d1, d2=d2, l=l,
|
||||||
vnf=vnf, path=path, extent=extent,
|
vnf=vnf, region=region, extent=extent,
|
||||||
cp=cp, offset=offset, anchors=anchors,
|
cp=cp, offset=offset, anchors=anchors,
|
||||||
two_d=two_d, axis=axis
|
two_d=two_d, axis=axis
|
||||||
);
|
);
|
||||||
|
@ -1029,6 +1037,9 @@ function named_anchor(name, pos=[0,0,0], orient=UP, spin=0) = [name, pos, orient
|
||||||
// Usage: 2D Path/Polygon Geometry
|
// Usage: 2D Path/Polygon Geometry
|
||||||
// mat = reorient(anchor, spin, [orient], two_d=true, path=, [extent=], ...);
|
// mat = reorient(anchor, spin, [orient], two_d=true, path=, [extent=], ...);
|
||||||
// pts = reorient(anchor, spin, [orient], two_d=true, path=, [extent=], p=, ...);
|
// pts = reorient(anchor, spin, [orient], two_d=true, path=, [extent=], p=, ...);
|
||||||
|
// Usage: 2D Region/Polygon Geometry
|
||||||
|
// mat = reorient(anchor, spin, [orient], two_d=true, region=, [extent=], ...);
|
||||||
|
// pts = reorient(anchor, spin, [orient], two_d=true, region=, [extent=], p=, ...);
|
||||||
// Usage: Cubical/Prismoidal Geometry
|
// Usage: Cubical/Prismoidal Geometry
|
||||||
// mat = reorient(anchor, spin, [orient], size=, [size2=], [shift=], ...);
|
// mat = reorient(anchor, spin, [orient], size=, [size2=], [shift=], ...);
|
||||||
// pts = reorient(anchor, spin, [orient], size=, [size2=], [shift=], p=, ...);
|
// pts = reorient(anchor, spin, [orient], size=, [size2=], [shift=], p=, ...);
|
||||||
|
@ -1044,6 +1055,9 @@ function named_anchor(name, pos=[0,0,0], orient=UP, spin=0) = [name, pos, orient
|
||||||
// Usage: Extruded Path/Polygon Geometry
|
// Usage: Extruded Path/Polygon Geometry
|
||||||
// mat = reorient(anchor, spin, [orient], path=, l=|h=, [extent=], ...);
|
// mat = reorient(anchor, spin, [orient], path=, l=|h=, [extent=], ...);
|
||||||
// pts = reorient(anchor, spin, [orient], path=, l=|h=, [extent=], p=, ...);
|
// pts = reorient(anchor, spin, [orient], path=, l=|h=, [extent=], p=, ...);
|
||||||
|
// Usage: Extruded Region Geometry
|
||||||
|
// mat = reorient(anchor, spin, [orient], region=, l=|h=, [extent=], ...);
|
||||||
|
// pts = reorient(anchor, spin, [orient], region=, l=|h=, [extent=], p=, ...);
|
||||||
// Usage: VNF Geometry
|
// Usage: VNF Geometry
|
||||||
// mat = reorient(anchor, spin, [orient], vnf, [extent], ...);
|
// mat = reorient(anchor, spin, [orient], vnf, [extent], ...);
|
||||||
// pts = reorient(anchor, spin, [orient], vnf, [extent], p=, ...);
|
// pts = reorient(anchor, spin, [orient], vnf, [extent], p=, ...);
|
||||||
|
@ -1092,6 +1106,7 @@ function named_anchor(name, pos=[0,0,0], orient=UP, spin=0) = [name, pos, orient
|
||||||
// l/h = Length of the cylindrical, conical, or extruded path volume along axis.
|
// l/h = Length of the cylindrical, conical, or extruded path volume along axis.
|
||||||
// vnf = The [VNF](vnf.scad) of the volume.
|
// vnf = The [VNF](vnf.scad) of the volume.
|
||||||
// path = The path to generate a polygon from.
|
// path = The path to generate a polygon from.
|
||||||
|
// region = The region to generate a shape from.
|
||||||
// extent = If true, calculate anchors by extents, rather than intersection. Default: false.
|
// extent = If true, calculate anchors by extents, rather than intersection. Default: false.
|
||||||
// cp = If given, specifies the centerpoint of the volume. Default: `[0,0,0]`
|
// cp = If given, specifies the centerpoint of the volume. Default: `[0,0,0]`
|
||||||
// offset = If given, offsets the perimeter of the volume around the centerpoint.
|
// offset = If given, offsets the perimeter of the volume around the centerpoint.
|
||||||
|
@ -1103,7 +1118,7 @@ function reorient(
|
||||||
anchor, spin, orient,
|
anchor, spin, orient,
|
||||||
size, size2, shift,
|
size, size2, shift,
|
||||||
r,r1,r2, d,d1,d2, l,h,
|
r,r1,r2, d,d1,d2, l,h,
|
||||||
vnf, path,
|
vnf, path, region,
|
||||||
extent=true,
|
extent=true,
|
||||||
offset=[0,0,0],
|
offset=[0,0,0],
|
||||||
cp=[0,0,0],
|
cp=[0,0,0],
|
||||||
|
@ -1118,14 +1133,17 @@ function reorient(
|
||||||
let(
|
let(
|
||||||
anchor = default(anchor, CENTER),
|
anchor = default(anchor, CENTER),
|
||||||
spin = default(spin, 0),
|
spin = default(spin, 0),
|
||||||
orient = default(orient, UP)
|
orient = default(orient, UP),
|
||||||
|
region = !is_undef(region)? region :
|
||||||
|
!is_undef(path)? [path] :
|
||||||
|
undef
|
||||||
)
|
)
|
||||||
(anchor==CENTER && spin==0 && orient==UP && p!=undef)? p : let(
|
(anchor==CENTER && spin==0 && orient==UP && p!=undef)? p : let(
|
||||||
geom = _attach_geom(
|
geom = _attach_geom(
|
||||||
size=size, size2=size2, shift=shift,
|
size=size, size2=size2, shift=shift,
|
||||||
r=r, r1=r1, r2=r2, h=h,
|
r=r, r1=r1, r2=r2, h=h,
|
||||||
d=d, d1=d1, d2=d2, l=l,
|
d=d, d1=d1, d2=d2, l=l,
|
||||||
vnf=vnf, path=path, extent=extent,
|
vnf=vnf, region=region, extent=extent,
|
||||||
cp=cp, offset=offset, anchors=anchors,
|
cp=cp, offset=offset, anchors=anchors,
|
||||||
two_d=two_d, axis=axis
|
two_d=two_d, axis=axis
|
||||||
),
|
),
|
||||||
|
@ -1145,8 +1163,8 @@ function reorient(
|
||||||
// geom = _attach_geom(two_d=true, size=, [size2=], [shift=], ...);
|
// geom = _attach_geom(two_d=true, size=, [size2=], [shift=], ...);
|
||||||
// Usage: Circle/Oval Geometry
|
// Usage: Circle/Oval Geometry
|
||||||
// geom = _attach_geom(two_d=true, r=|d=, ...);
|
// geom = _attach_geom(two_d=true, r=|d=, ...);
|
||||||
// Usage: 2D Path/Polygon Geometry
|
// Usage: 2D Path/Polygon/Region Geometry
|
||||||
// geom = _attach_geom(two_d=true, path=, [extent=], ...);
|
// geom = _attach_geom(two_d=true, region=, [extent=], ...);
|
||||||
// Usage: Cubical/Prismoidal Geometry
|
// Usage: Cubical/Prismoidal Geometry
|
||||||
// geom = _attach_geom(size=, [size2=], [shift=], ...);
|
// geom = _attach_geom(size=, [size2=], [shift=], ...);
|
||||||
// Usage: Cylindrical Geometry
|
// Usage: Cylindrical Geometry
|
||||||
|
@ -1155,8 +1173,8 @@ function reorient(
|
||||||
// geom = _attach_geom(r1|d1=, r2=|d2=, l=, [axis=], ...);
|
// geom = _attach_geom(r1|d1=, r2=|d2=, l=, [axis=], ...);
|
||||||
// Usage: Spheroid/Ovoid Geometry
|
// Usage: Spheroid/Ovoid Geometry
|
||||||
// geom = _attach_geom(r=|d=, ...);
|
// geom = _attach_geom(r=|d=, ...);
|
||||||
// Usage: Extruded 2D Path/Polygon Geometry
|
// Usage: Extruded 2D Path/Polygon/Region Geometry
|
||||||
// geom = _attach_geom(path=, l=|h=, [extent=], ...);
|
// geom = _attach_geom(region=, l=|h=, [extent=], ...);
|
||||||
// Usage: VNF Geometry
|
// Usage: VNF Geometry
|
||||||
// geom = _attach_geom(vnf=, [extent=], ...);
|
// geom = _attach_geom(vnf=, [extent=], ...);
|
||||||
//
|
//
|
||||||
|
@ -1178,9 +1196,9 @@ function reorient(
|
||||||
// r2 = Radius of the top of the conical volume. Can be a scalar, or a list of sizes per axis.
|
// r2 = Radius of the top of the conical volume. Can be a scalar, or a list of sizes per axis.
|
||||||
// d1 = Diameter of the bottom of the conical volume. Can be a scalar, a list of sizes per axis.
|
// d1 = Diameter of the bottom of the conical volume. Can be a scalar, a list of sizes per axis.
|
||||||
// d2 = Diameter of the top of the conical volume. Can be a scalar, a list of sizes per axis.
|
// d2 = Diameter of the top of the conical volume. Can be a scalar, a list of sizes per axis.
|
||||||
// l/h = Length of the cylindrical, conical or extruded path volume along axis.
|
// l/h = Length of the cylindrical, conical or extruded region volume along axis.
|
||||||
// vnf = The [VNF](vnf.scad) of the volume.
|
// vnf = The [VNF](vnf.scad) of the volume.
|
||||||
// path = The path to generate a polygon from.
|
// region = The region to generate a shape from.
|
||||||
// extent = If true, calculate anchors by extents, rather than intersection. Default: true.
|
// extent = If true, calculate anchors by extents, rather than intersection. Default: true.
|
||||||
// cp = If given, specifies the centerpoint of the volume. Default: `[0,0,0]`
|
// cp = If given, specifies the centerpoint of the volume. Default: `[0,0,0]`
|
||||||
// offset = If given, offsets the perimeter of the volume around the centerpoint.
|
// offset = If given, offsets the perimeter of the volume around the centerpoint.
|
||||||
|
@ -1239,22 +1257,22 @@ function reorient(
|
||||||
// Example(NORENDER): 2D Oval Shape
|
// Example(NORENDER): 2D Oval Shape
|
||||||
// geom = _attach_geom(two_d=true, r=[r_x, r_y]);
|
// geom = _attach_geom(two_d=true, r=[r_x, r_y]);
|
||||||
//
|
//
|
||||||
// Example(NORENDER): Arbitrary 2D Polygon Shape, Anchored by Extents
|
// Example(NORENDER): Arbitrary 2D Region Shape, Anchored by Extents
|
||||||
// geom = _attach_geom(two_d=true, path=path);
|
// geom = _attach_geom(two_d=true, region=region);
|
||||||
//
|
//
|
||||||
// Example(NORENDER): Arbitrary 2D Polygon Shape, Anchored by Intersection
|
// Example(NORENDER): Arbitrary 2D Region Shape, Anchored by Intersection
|
||||||
// geom = _attach_geom(two_d=true, path=path, extent=false);
|
// geom = _attach_geom(two_d=true, region=region, extent=false);
|
||||||
//
|
//
|
||||||
// Example(NORENDER): Extruded Polygon Shape, Anchored by Extents
|
// Example(NORENDER): Extruded Region, Anchored by Extents
|
||||||
// geom = _attach_geom(path=path, l=height);
|
// geom = _attach_geom(region=region, l=height);
|
||||||
//
|
//
|
||||||
// Example(NORENDER): Extruded Polygon Shape, Anchored by Intersection
|
// Example(NORENDER): Extruded Region, Anchored by Intersection
|
||||||
// geom = _attach_geom(path=path, l=length, extent=false);
|
// geom = _attach_geom(region=region, l=length, extent=false);
|
||||||
//
|
//
|
||||||
function _attach_geom(
|
function _attach_geom(
|
||||||
size, size2, shift,
|
size, size2, shift,
|
||||||
r,r1,r2, d,d1,d2, l,h,
|
r,r1,r2, d,d1,d2, l,h,
|
||||||
vnf, path,
|
vnf, region,
|
||||||
extent=true,
|
extent=true,
|
||||||
cp=[0,0,0],
|
cp=[0,0,0],
|
||||||
offset=[0,0,0],
|
offset=[0,0,0],
|
||||||
|
@ -1293,18 +1311,18 @@ function _attach_geom(
|
||||||
assert(two_d == false)
|
assert(two_d == false)
|
||||||
extent? ["vnf_extent", vnf, cp, offset, anchors] :
|
extent? ["vnf_extent", vnf, cp, offset, anchors] :
|
||||||
["vnf_isect", vnf, cp, offset, anchors]
|
["vnf_isect", vnf, cp, offset, anchors]
|
||||||
) : !is_undef(path)? (
|
) : !is_undef(region)? (
|
||||||
assert(is_path(path),2)
|
assert(is_region(region),2)
|
||||||
let( l = default(l, h) )
|
let( l = default(l, h) )
|
||||||
two_d==true
|
two_d==true
|
||||||
? assert(is_undef(l))
|
? assert(is_undef(l))
|
||||||
extent==true
|
extent==true
|
||||||
? ["path_extent", path, cp, offset, anchors]
|
? ["rgn_extent", region, cp, offset, anchors]
|
||||||
: ["path_isect", path, cp, offset, anchors]
|
: ["rgn_isect", region, cp, offset, anchors]
|
||||||
: assert(is_finite(l))
|
: assert(is_finite(l))
|
||||||
extent==true
|
extent==true
|
||||||
? ["xpath_extent", path, l, cp, offset, anchors]
|
? ["xrgn_extent", region, l, cp, offset, anchors]
|
||||||
: ["xpath_isect", path, l, cp, offset, anchors]
|
: ["xrgn_isect", region, l, cp, offset, anchors]
|
||||||
) :
|
) :
|
||||||
let(
|
let(
|
||||||
r1 = get_radius(r1=r1,d1=d1,r=r,d=d,dflt=undef)
|
r1 = get_radius(r1=r1,d1=d1,r=r,d=d,dflt=undef)
|
||||||
|
@ -1345,7 +1363,7 @@ function _attach_geom(
|
||||||
function _attach_geom_2d(geom) =
|
function _attach_geom_2d(geom) =
|
||||||
let( type = geom[0] )
|
let( type = geom[0] )
|
||||||
type == "rect" || type == "circle" ||
|
type == "rect" || type == "circle" ||
|
||||||
type == "path_isect" || type == "path_extent";
|
type == "rgn_isect" || type == "rgn_extent";
|
||||||
|
|
||||||
|
|
||||||
/// Internal Function: _attach_geom_size()
|
/// Internal Function: _attach_geom_size()
|
||||||
|
@ -1390,9 +1408,9 @@ function _attach_geom_size(geom) =
|
||||||
mm = pointlist_bounds(geom[1][0]),
|
mm = pointlist_bounds(geom[1][0]),
|
||||||
delt = mm[1]-mm[0]
|
delt = mm[1]-mm[0]
|
||||||
) delt
|
) delt
|
||||||
) : type == "xpath_isect" || type == "xpath_extent"? ( //path, l
|
) : type == "xrgn_isect" || type == "xrgn_extent"? ( //path, l
|
||||||
let(
|
let(
|
||||||
mm = pointlist_bounds(geom[1]),
|
mm = pointlist_bounds(flatten(geom[1])),
|
||||||
delt = mm[1]-mm[0]
|
delt = mm[1]-mm[0]
|
||||||
) [delt.x, delt.y, geom[2]]
|
) [delt.x, delt.y, geom[2]]
|
||||||
) : type == "rect"? ( //size, size2
|
) : type == "rect"? ( //size, size2
|
||||||
|
@ -1403,9 +1421,9 @@ function _attach_geom_size(geom) =
|
||||||
) : type == "circle"? ( //r
|
) : type == "circle"? ( //r
|
||||||
let( r=geom[1] )
|
let( r=geom[1] )
|
||||||
is_num(r)? [2,2]*r : v_mul([2,2],point2d(r))
|
is_num(r)? [2,2]*r : v_mul([2,2],point2d(r))
|
||||||
) : type == "path_isect" || type == "path_extent"? ( //path
|
) : type == "rgn_isect" || type == "rgn_extent"? ( //path
|
||||||
let(
|
let(
|
||||||
mm = pointlist_bounds(geom[1]),
|
mm = pointlist_bounds(flatten(geom[1])),
|
||||||
delt = mm[1]-mm[0]
|
delt = mm[1]-mm[0]
|
||||||
) [delt.x, delt.y]
|
) [delt.x, delt.y]
|
||||||
) :
|
) :
|
||||||
|
@ -1495,7 +1513,7 @@ function _get_cp(geom) =
|
||||||
is_vector(cp) ? cp
|
is_vector(cp) ? cp
|
||||||
: let(
|
: let(
|
||||||
type = in_list(geom[0],["vnf_extent","vnf_isect"]) ? "vnf"
|
type = in_list(geom[0],["vnf_extent","vnf_isect"]) ? "vnf"
|
||||||
: in_list(geom[0],["path_extent","path_isect"]) ? "path"
|
: in_list(geom[0],["rgn_extent","rgn_isect"]) ? "path"
|
||||||
: "other"
|
: "other"
|
||||||
)
|
)
|
||||||
assert(type!="other", "Invalid cp value")
|
assert(type!="other", "Invalid cp value")
|
||||||
|
@ -1548,17 +1566,17 @@ function _find_anchor(anchor, geom) =
|
||||||
shift=point2d(geom[3]), axis=point3d(geom[4]),
|
shift=point2d(geom[3]), axis=point3d(geom[4]),
|
||||||
anch = rot(from=axis, to=UP, p=anchor),
|
anch = rot(from=axis, to=UP, p=anchor),
|
||||||
h = size.z,
|
h = size.z,
|
||||||
u = (anch.z+1)/2,
|
u = (anch.z+1)/2, // u is one of 0, 0.5, or 1
|
||||||
axy = point2d(anch),
|
axy = point2d(anch),
|
||||||
bot = point3d(v_mul(point2d(size)/2,axy),-h/2),
|
bot = point3d(v_mul(point2d(size)/2,axy),-h/2),
|
||||||
top = point3d(v_mul(point2d(size2)/2,axy)+shift,h/2),
|
top = point3d(v_mul(point2d(size2)/2,axy)+shift,h/2),
|
||||||
pos = point3d(cp) + lerp(bot,top,u) + offset,
|
pos = point3d(cp) + lerp(bot,top,u) + offset,
|
||||||
sidevec = unit(rot(from=UP, to=top-bot, p=point3d(axy)),UP),
|
vecs = [
|
||||||
vvec = anch==CENTER? UP : unit([0,0,anch.z],UP),
|
if (anchor.x!=0) unit(rot(from=UP, to=unit([(top-bot).x,0,h]), p=[axy.x,0,0]), UP),
|
||||||
vec = anch==CENTER? UP :
|
if (anchor.y!=0) unit(rot(from=UP, to=unit([0,(top-bot).y,h]), p=[0,axy.y,0]), UP),
|
||||||
approx(axy,[0,0])? unit(anch,UP) :
|
if (anchor.z!=0) anch==CENTER? UP : unit([0,0,anch.z],UP)
|
||||||
approx(anch.z,0)? sidevec :
|
],
|
||||||
unit((sidevec+vvec)/2,UP),
|
vec = unit(sum(vecs) / len(vecs)),
|
||||||
pos2 = rot(from=UP, to=axis, p=pos),
|
pos2 = rot(from=UP, to=axis, p=pos),
|
||||||
vec2 = rot(from=UP, to=axis, p=vec)
|
vec2 = rot(from=UP, to=axis, p=vec)
|
||||||
) [anchor, pos2, vec2, oang]
|
) [anchor, pos2, vec2, oang]
|
||||||
|
@ -1656,11 +1674,22 @@ function _find_anchor(anchor, geom) =
|
||||||
) : type == "rect"? ( //size, size2, shift
|
) : type == "rect"? ( //size, size2, shift
|
||||||
let(
|
let(
|
||||||
size=geom[1], size2=geom[2], shift=geom[3],
|
size=geom[1], size2=geom[2], shift=geom[3],
|
||||||
u = (anchor.y+1)/2,
|
u = (anchor.y+1)/2, // 0<=u<=1
|
||||||
frpt = [size.x/2*anchor.x, -size.y/2],
|
frpt = [size.x/2*anchor.x, -size.y/2],
|
||||||
bkpt = [size2/2*anchor.x+shift, size.y/2],
|
bkpt = [size2/2*anchor.x+shift, size.y/2],
|
||||||
pos = point2d(cp) + lerp(frpt, bkpt, u) + offset,
|
pos = point2d(cp) + lerp(frpt, bkpt, u) + point2d(offset),
|
||||||
vec = unit(rot(from=BACK, to=bkpt-frpt, p=anchor),[0,1])
|
svec = point3d(line_normal(bkpt,frpt)*anchor.x),
|
||||||
|
vec = anchor.y < 0? (
|
||||||
|
anchor.x == 0? FWD :
|
||||||
|
size.x == 0? unit(-[shift,size.y], FWD) :
|
||||||
|
unit((point3d(svec) + FWD) / 2, FWD)
|
||||||
|
) :
|
||||||
|
anchor.y == 0? ( anchor.x == 0? BACK : svec ) :
|
||||||
|
( // anchor.y > 0
|
||||||
|
anchor.x == 0? BACK :
|
||||||
|
size2 == 0? unit([shift,size.y], BACK) :
|
||||||
|
unit((point3d(svec) + BACK) / 2, BACK)
|
||||||
|
)
|
||||||
) [anchor, pos, vec, 0]
|
) [anchor, pos, vec, 0]
|
||||||
) : type == "circle"? ( //r
|
) : type == "circle"? ( //r
|
||||||
let(
|
let(
|
||||||
|
@ -1670,12 +1699,13 @@ function _find_anchor(anchor, geom) =
|
||||||
pos = point2d(cp) + v_mul(r,anchor) + point2d(offset),
|
pos = point2d(cp) + v_mul(r,anchor) + point2d(offset),
|
||||||
vec = unit(v_mul(r,anchor),[0,1])
|
vec = unit(v_mul(r,anchor),[0,1])
|
||||||
) [anchor, pos, vec, 0]
|
) [anchor, pos, vec, 0]
|
||||||
) : type == "path_isect"? ( //path
|
) : type == "rgn_isect"? ( //region
|
||||||
let(
|
let(
|
||||||
path = move(-point2d(cp), p=geom[1]),
|
rgn_raw = move(-point2d(cp), p=geom[1]),
|
||||||
|
rgn = is_region(rgn_raw)? rgn_raw : [rgn_raw],
|
||||||
anchor = point2d(anchor),
|
anchor = point2d(anchor),
|
||||||
isects = [
|
isects = [
|
||||||
for (t=triplet(path,true)) let(
|
for (path=rgn, t=triplet(path,true)) let(
|
||||||
seg1 = [t[0],t[1]],
|
seg1 = [t[0],t[1]],
|
||||||
seg2 = [t[1],t[2]],
|
seg2 = [t[1],t[2]],
|
||||||
isect = line_intersection([[0,0],anchor], seg1,RAY,SEGMENT),
|
isect = line_intersection([[0,0],anchor], seg1,RAY,SEGMENT),
|
||||||
|
@ -1691,26 +1721,31 @@ function _find_anchor(anchor, geom) =
|
||||||
pos = point2d(cp) + isect[1],
|
pos = point2d(cp) + isect[1],
|
||||||
vec = unit(isect[2],[0,1])
|
vec = unit(isect[2],[0,1])
|
||||||
) [anchor, pos, vec, 0]
|
) [anchor, pos, vec, 0]
|
||||||
) : type == "path_extent"? ( //path
|
) : type == "rgn_extent"? ( //region
|
||||||
let(
|
let(
|
||||||
path = geom[1],
|
rgn_raw = geom[1],
|
||||||
|
rgn = is_region(rgn_raw)? rgn_raw : [rgn_raw],
|
||||||
anchor = point2d(anchor),
|
anchor = point2d(anchor),
|
||||||
rpath = rot(from=anchor, to=RIGHT, p=move(point2d(-cp), p=path)),
|
m = rot(from=anchor, to=RIGHT) * move(-[cp.x, cp.y, 0]),
|
||||||
maxx = max(columns(rpath,0)),
|
rpts = apply(m, flatten(rgn)),
|
||||||
idxs = [for (i = idx(rpath)) if (approx(rpath[i].x, maxx)) i],
|
maxx = max(columns(rpts,0)),
|
||||||
miny = min([for (i=idxs) rpath[i].y]),
|
idxs = [for (i = idx(rpts)) if (approx(rpts[i].x, maxx)) i],
|
||||||
maxy = max([for (i=idxs) rpath[i].y]),
|
miny = min([for (i=idxs) rpts[i].y]),
|
||||||
avgy = (miny+maxy)/2,
|
maxy = max([for (i=idxs) rpts[i].y]),
|
||||||
pos = point2d(cp) + rot(from=RIGHT, to=anchor, p=[maxx,avgy])
|
midy = (miny+maxy)/2,
|
||||||
|
pos = point2d(cp) + rot(from=RIGHT, to=anchor, p=[maxx,midy])
|
||||||
) [anchor, pos, anchor, 0]
|
) [anchor, pos, anchor, 0]
|
||||||
) : type == "xpath_isect"? ( //path
|
) : type == "xrgn_isect"? ( //region
|
||||||
let(
|
let(
|
||||||
path = move(-point2d(cp), p=geom[1]),
|
rgn_raw = move(-point2d(cp), p=geom[1]),
|
||||||
l = geom[2],
|
l = geom[2],
|
||||||
|
rgn = is_region(rgn_raw)? rgn_raw : [rgn_raw],
|
||||||
anchor = point3d(anchor),
|
anchor = point3d(anchor),
|
||||||
xyanch = point2d(anchor),
|
xyanch = point2d(anchor)
|
||||||
|
) approx(xyanch,[0,0])? [anchor, [0,0,anchor.z*l/2], unit(anchor,UP), 0] :
|
||||||
|
let(
|
||||||
isects = [
|
isects = [
|
||||||
for (t=triplet(path,true)) let(
|
for (path=rgn, t=triplet(path,true)) let(
|
||||||
seg1 = [t[0],t[1]],
|
seg1 = [t[0],t[1]],
|
||||||
seg2 = [t[1],t[2]],
|
seg2 = [t[1],t[2]],
|
||||||
isect = line_intersection([[0,0],xyanch], seg1, RAY, SEGMENT),
|
isect = line_intersection([[0,0],xyanch], seg1, RAY, SEGMENT),
|
||||||
|
@ -1726,22 +1761,30 @@ function _find_anchor(anchor, geom) =
|
||||||
isect = isects[maxidx],
|
isect = isects[maxidx],
|
||||||
pos = point3d(cp) + point3d(isect[1]) + unit([0,0,anchor.z],CENTER)*l/2,
|
pos = point3d(cp) + point3d(isect[1]) + unit([0,0,anchor.z],CENTER)*l/2,
|
||||||
xyvec = unit(isect[2],[0,1]),
|
xyvec = unit(isect[2],[0,1]),
|
||||||
vec = unit((point3d(xyvec)+UP)/2,UP),
|
vec = unit((point3d(xyvec)+UP*anchor.z)/2,UP),
|
||||||
oang = approx(xyvec, [0,0])? 0 : atan2(xyvec.y, xyvec.x) + 90
|
oang = approx(xyvec, [0,0])? 0 : atan2(xyvec.y, xyvec.x) + 90
|
||||||
) [anchor, pos, vec, oang]
|
) [anchor, pos, vec, oang]
|
||||||
) : type == "xpath_extent"? ( //path
|
) : type == "xrgn_extent"? ( //region
|
||||||
let(
|
let(
|
||||||
path = geom[1], l = geom[2],
|
rgn_raw = geom[1], l = geom[2],
|
||||||
|
rgn = is_region(rgn_raw)? rgn_raw : [rgn_raw],
|
||||||
anchor = point3d(anchor),
|
anchor = point3d(anchor),
|
||||||
xyanch = point2d(anchor),
|
xyanch = point2d(anchor),
|
||||||
rpath = rot(from=xyanch, to=RIGHT, p=move(point2d(-cp), p=path)),
|
m = (
|
||||||
maxx = max(columns(rpath,0)),
|
approx(xyanch,[0,0])? [[1,0,0],[0,1,0],[0,0,1]] :
|
||||||
idxs = [for (i = idx(rpath)) if (approx(rpath[i].x, maxx)) i],
|
rot(from=xyanch, to=RIGHT, planar=true)
|
||||||
ys = [for (i=idxs) rpath[i].y],
|
) * move(-[cp.x, cp.y]),
|
||||||
avgy = (min(ys)+max(ys))/2,
|
rpts = apply(m, flatten(rgn)),
|
||||||
xypos = point2d(cp) + rot(from=RIGHT, to=xyanch, p=[maxx,avgy]),
|
maxx = max(columns(rpts,0)),
|
||||||
|
idxs = [for (i = idx(rpts)) if (approx(rpts[i].x, maxx)) i],
|
||||||
|
ys = [for (i=idxs) rpts[i].y],
|
||||||
|
midy = (min(ys)+max(ys))/2,
|
||||||
|
xypos = point2d(cp) + (
|
||||||
|
approx(xyanch,[0,0])? [0,0] :
|
||||||
|
rot(from=RIGHT, to=xyanch, p=[maxx,midy])
|
||||||
|
),
|
||||||
pos = point3d(xypos) + unit([0,0,anchor.z],CENTER)*l/2,
|
pos = point3d(xypos) + unit([0,0,anchor.z],CENTER)*l/2,
|
||||||
vec = unit((point3d(xyanch)+UP)/2,UP)
|
vec = unit((point3d(xyanch)+UP*anchor.z)/2,UP)
|
||||||
) [anchor, pos, vec, oang]
|
) [anchor, pos, vec, oang]
|
||||||
) :
|
) :
|
||||||
assert(false, "Unknown attachment geometry type.");
|
assert(false, "Unknown attachment geometry type.");
|
||||||
|
|
|
@ -602,6 +602,50 @@ module octagon(r, d, or, od, ir, id, side, rounding=0, realign=false, align_tip,
|
||||||
regular_ngon(n=8, r=r, d=d, or=or, od=od, ir=ir, id=id, side=side, rounding=rounding, realign=realign, align_tip=align_tip, align_side=align_side, anchor=anchor, spin=spin) children();
|
regular_ngon(n=8, r=r, d=d, or=or, od=od, ir=ir, id=id, side=side, rounding=rounding, realign=realign, align_tip=align_tip, align_side=align_side, anchor=anchor, spin=spin) children();
|
||||||
|
|
||||||
|
|
||||||
|
// Function&Module right_triangle()
|
||||||
|
// Usage: As Module
|
||||||
|
// right_triangle(size, [center], ...);
|
||||||
|
// Usage: With Attachments
|
||||||
|
// right_triangle(size, [center], ...) { attachments }
|
||||||
|
// Usage: As Function
|
||||||
|
// path = right_triangle(size, [center], ...);
|
||||||
|
// Description:
|
||||||
|
// Creates a right triangle with the Hypotenuse in the X+Y+ quadrant.
|
||||||
|
// Arguments:
|
||||||
|
// size = The width and length of the right triangle, given as a scalar or an XY vector.
|
||||||
|
// center = If true, forces `anchor=CENTER`. If false, forces `anchor=[-1,-1]`. Default: undef (use `anchor=`)
|
||||||
|
// ---
|
||||||
|
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
|
||||||
|
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
|
||||||
|
// Example:
|
||||||
|
// right_triangle([40,30]);
|
||||||
|
// Example: With `center=true`
|
||||||
|
// right_triangle([40,30], center=true);
|
||||||
|
// Example: Anchors
|
||||||
|
// right_triangle([40,30])
|
||||||
|
// show_anchors();
|
||||||
|
function right_triangle(size=[1,1], center, anchor, spin=0) =
|
||||||
|
let(
|
||||||
|
size = is_num(size)? [size,size] : size,
|
||||||
|
anchor = get_anchor(anchor, center, [-1,-1], [-1,-1])
|
||||||
|
)
|
||||||
|
assert(is_vector(size,2))
|
||||||
|
let(
|
||||||
|
path = [ [size.x/2,-size.y/2], [-size.x/2,-size.y/2], [-size.x/2,size.y/2] ]
|
||||||
|
) reorient(anchor,spin, two_d=true, size=[size.x,size.y], size2=0, shift=-size.x/2, p=path);
|
||||||
|
|
||||||
|
module right_triangle(size=[1,1], center, anchor, spin=0) {
|
||||||
|
size = is_num(size)? [size,size] : size;
|
||||||
|
anchor = get_anchor(anchor, center, [-1,-1], [-1,-1]);
|
||||||
|
assert(is_vector(size,2));
|
||||||
|
path = right_triangle(size, center=true);
|
||||||
|
attachable(anchor,spin, two_d=true, size=[size.x,size.y], size2=0, shift=-size.x/2) {
|
||||||
|
polygon(path);
|
||||||
|
children();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Function&Module: trapezoid()
|
// Function&Module: trapezoid()
|
||||||
// Usage: As Module
|
// Usage: As Module
|
||||||
// trapezoid(h, w1, w2, [shift=], [rounding=], [chamfer=], ...);
|
// trapezoid(h, w1, w2, [shift=], [rounding=], [chamfer=], ...);
|
||||||
|
|
|
@ -872,13 +872,18 @@ function rect_tube(
|
||||||
) = no_function("rect_tube");
|
) = no_function("rect_tube");
|
||||||
|
|
||||||
|
|
||||||
// Module: right_triangle()
|
// Function&Module: wedge()
|
||||||
//
|
//
|
||||||
// Usage:
|
// Usage: As Module
|
||||||
// right_triangle(size, [center]);
|
// wedge(size, [center], ...);
|
||||||
|
// Usage: With Attachments
|
||||||
|
// wedge(size, [center], ...) { attachments }
|
||||||
|
// Usage: As Function
|
||||||
|
// vnf = wedge(size, [center], ...);
|
||||||
//
|
//
|
||||||
// Description:
|
// Description:
|
||||||
// Creates a 3D right triangular prism with the hypotenuse in the X+Y+ quadrant.
|
// When called as a modulem creates a 3D triangular wedge with the hypotenuse in the X+Z+ quadrant.
|
||||||
|
// When called as a function creates a VNF for a 3D triangular wedge with the hypotenuse in the X+Z+ quadrant.
|
||||||
//
|
//
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// size = [width, thickness, height]
|
// size = [width, thickness, height]
|
||||||
|
@ -889,28 +894,40 @@ function rect_tube(
|
||||||
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
|
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
|
||||||
//
|
//
|
||||||
// Example: Centered
|
// Example: Centered
|
||||||
// right_triangle([60, 40, 10], center=true);
|
// wedge([20, 40, 15], center=true);
|
||||||
// Example: *Non*-Centered
|
// Example: *Non*-Centered
|
||||||
// right_triangle([60, 40, 10]);
|
// wedge([20, 40, 15]);
|
||||||
// Example: Standard Connectors
|
// Example: Standard Connectors
|
||||||
// right_triangle([60, 40, 15]) show_anchors();
|
// wedge([20, 40, 15]) show_anchors();
|
||||||
module right_triangle(size=[1, 1, 1], center, anchor, spin=0, orient=UP)
|
module wedge(size=[1, 1, 1], center, anchor, spin=0, orient=UP)
|
||||||
{
|
{
|
||||||
size = scalar_vec3(size);
|
size = scalar_vec3(size);
|
||||||
anchor = get_anchor(anchor, center, ALLNEG, ALLNEG);
|
anchor = get_anchor(anchor, center, ALLNEG, ALLNEG);
|
||||||
attachable(anchor,spin,orient, size=size) {
|
vnf = wedge(size, center=true);
|
||||||
|
attachable(anchor,spin,orient, size=size, size2=[size.x,0], shift=[0,-size.y/2]) {
|
||||||
if (size.z > 0) {
|
if (size.z > 0) {
|
||||||
linear_extrude(height=size.z, convexity=2, center=true) {
|
vnf_polyhedron(vnf);
|
||||||
polygon([[-size.x/2,-size.y/2], [-size.x/2,size.y/2], [size.x/2,-size.y/2]]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
children();
|
children();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function right_triangle(size=[1,1,1], center, anchor, spin=0, orient=UP) =
|
function wedge(size=[1,1,1], center, anchor, spin=0, orient=UP) =
|
||||||
no_function("right_triangle");
|
let(
|
||||||
|
size = scalar_vec3(size),
|
||||||
|
anchor = get_anchor(anchor, center, ALLNEG, ALLNEG),
|
||||||
|
pts = [
|
||||||
|
[ 1,1,-1], [ 1,-1,-1], [ 1,-1,1],
|
||||||
|
[-1,1,-1], [-1,-1,-1], [-1,-1,1],
|
||||||
|
],
|
||||||
|
faces = [
|
||||||
|
[0,1,2], [3,5,4], [0,3,1], [1,3,4],
|
||||||
|
[1,4,2], [2,4,5], [2,5,3], [0,2,3],
|
||||||
|
],
|
||||||
|
vnf = [scale(size/2,p=pts), faces]
|
||||||
|
)
|
||||||
|
reorient(anchor,spin,orient, size=size, size2=[size.x,0], shift=[0,-size.y/2], p=vnf);
|
||||||
|
|
||||||
|
|
||||||
// Section: Cylinders
|
// Section: Cylinders
|
||||||
|
@ -1529,7 +1546,7 @@ module pie_slice(
|
||||||
// vnf_polyhedron(vnf);
|
// vnf_polyhedron(vnf);
|
||||||
module sphere(r, d, circum=false, style="orig", anchor=CENTER, spin=0, orient=UP) {
|
module sphere(r, d, circum=false, style="orig", anchor=CENTER, spin=0, orient=UP) {
|
||||||
r = get_radius(r=r, d=d, dflt=1);
|
r = get_radius(r=r, d=d, dflt=1);
|
||||||
if (!circum && style=="orig") {
|
if (!circum && style=="orig" && is_num(r)) {
|
||||||
attachable(anchor,spin,orient, r=r) {
|
attachable(anchor,spin,orient, r=r) {
|
||||||
_sphere(r=r);
|
_sphere(r=r);
|
||||||
children();
|
children();
|
||||||
|
|
Loading…
Reference in a new issue