mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2024-12-29 00:09:41 +00:00
revamp extruded region attachables and apply to linear_sweep.
This commit is contained in:
parent
2bfb4e39e7
commit
475129fd95
5 changed files with 40 additions and 79 deletions
102
attachments.scad
102
attachments.scad
|
@ -1515,10 +1515,10 @@ function _attach_transform(anchor, spin, orient, geom, p) =
|
|||
|
||||
|
||||
function _get_cp(geom) =
|
||||
|
||||
let(cp=select(geom,-3))
|
||||
is_vector(cp) ? cp
|
||||
: let(
|
||||
f=echo(type=geom[0]),
|
||||
type = in_list(geom[0],["vnf_extent","vnf_isect"]) ? "vnf"
|
||||
: in_list(geom[0],["rgn_extent","rgn_isect"]) ? "path"
|
||||
: in_list(geom[0],["xrgn_extent","xrgn_isect"]) ? "xpath"
|
||||
|
@ -1549,20 +1549,22 @@ function _get_cp(geom) =
|
|||
// anchor = Vector or named anchor string.
|
||||
// geom = The geometry description of the shape.
|
||||
function _find_anchor(anchor, geom) =
|
||||
is_string(anchor)? (
|
||||
anchor=="origin"? [anchor, CENTER, UP, 0]
|
||||
: let(
|
||||
anchors = last(geom),
|
||||
found = search([anchor], anchors, num_returns_per_match=1)[0]
|
||||
)
|
||||
assert(found!=[], str("Unknown anchor: ",anchor))
|
||||
anchors[found]
|
||||
) :
|
||||
let(
|
||||
cp = _get_cp(geom),
|
||||
offset_raw = select(geom,-2),
|
||||
offset = [for (i=[0:2]) anchor[i]==0? 0 : offset_raw[i]], // prevents bad centering.
|
||||
anchors = last(geom),
|
||||
type = geom[0]
|
||||
)
|
||||
is_string(anchor)? (
|
||||
anchor=="origin"? [anchor, CENTER, UP, 0]
|
||||
: let(found = search([anchor], anchors, num_returns_per_match=1)[0])
|
||||
assert(found!=[], str("Unknown anchor: ",anchor))
|
||||
anchors[found]
|
||||
) :
|
||||
assert(is_vector(anchor),str("anchor=",anchor))
|
||||
assert(is_vector(anchor),str("Invalid anchor: anchor=",anchor))
|
||||
let(anchor = point3d(anchor))
|
||||
anchor==CENTER? [anchor, cp, UP, 0] :
|
||||
let(
|
||||
|
@ -1725,8 +1727,7 @@ function _find_anchor(anchor, geom) =
|
|||
) : type == "rgn_isect"? ( //region
|
||||
assert(anchor.z==0, "The Z component of an anchor for a 2D shape must be 0.")
|
||||
let(
|
||||
rgn_raw = move(-point2d(cp), p=geom[1]),
|
||||
rgn = is_region(rgn_raw)? rgn_raw : [rgn_raw],
|
||||
rgn = force_region(move(-point2d(cp), p=geom[1])),
|
||||
anchor = point2d(anchor),
|
||||
isects = [
|
||||
for (path=rgn, t=triplet(path,true)) let(
|
||||
|
@ -1753,68 +1754,27 @@ function _find_anchor(anchor, geom) =
|
|||
let(
|
||||
rgn = force_region(geom[1]),
|
||||
anchor = point2d(anchor),
|
||||
m = rot(from=anchor, to=RIGHT) * move(-[cp.x, cp.y, 0]),
|
||||
rpts = apply(m, flatten(rgn)),
|
||||
rpts = rot(from=anchor, to=RIGHT, p=flatten(rgn)),
|
||||
maxx = max(column(rpts,0)),
|
||||
idxs = [for (i = idx(rpts)) if (approx(rpts[i].x, maxx)) i],
|
||||
miny = min([for (i=idxs) rpts[i].y]),
|
||||
maxy = max([for (i=idxs) rpts[i].y]),
|
||||
midy = (miny+maxy)/2,
|
||||
pos = point2d(cp) + rot(from=RIGHT, to=anchor, p=[maxx,midy])
|
||||
) [anchor, pos, anchor, 0]
|
||||
) : type == "xrgn_isect"? ( //region
|
||||
assert(in_list(anchor.z,[-1,0,1]), "The Z component of an anchor for an extruded 2D shape must be -1, 0, or 1.")
|
||||
let(
|
||||
rgn_raw = move(-point2d(cp), p=geom[1]),
|
||||
l = geom[2],
|
||||
rgn = is_region(rgn_raw)? rgn_raw : [rgn_raw],
|
||||
anchor = point3d(anchor),
|
||||
xyanch = point2d(anchor)
|
||||
) approx(xyanch,[0,0])? [anchor, [0,0,anchor.z*l/2], unit(anchor,UP), 0] :
|
||||
let(
|
||||
isects = [
|
||||
for (path=rgn, t=triplet(path,true)) let(
|
||||
seg1 = [t[0],t[1]],
|
||||
seg2 = [t[1],t[2]],
|
||||
isect = line_intersection([[0,0],xyanch], seg1, RAY, SEGMENT),
|
||||
n = is_undef(isect)? [0,1] :
|
||||
!approx(isect, t[1])? line_normal(seg1) :
|
||||
unit((line_normal(seg1)+line_normal(seg2))/2,[0,1]),
|
||||
n2 = vector_angle(xyanch,n)>90? -n : n
|
||||
)
|
||||
if(!is_undef(isect) && !approx(isect,t[0]))
|
||||
[norm(isect), isect, n2]
|
||||
],
|
||||
maxidx = max_index(column(isects,0)),
|
||||
isect = isects[maxidx],
|
||||
pos = point3d(cp) + point3d(isect[1]) + unit([0,0,anchor.z],CENTER)*l/2,
|
||||
xyvec = unit(isect[2],[0,1]),
|
||||
vec = unit((point3d(xyvec)+UP*anchor.z)/2,UP),
|
||||
oang = approx(xyvec, [0,0])? 0 : atan2(xyvec.y, xyvec.x) + 90
|
||||
) [anchor, pos, vec, oang]
|
||||
) : type == "xrgn_extent"? ( //region
|
||||
assert(in_list(anchor.z,[-1,0,1]), "The Z component of an anchor for an extruded 2D shape must be -1, 0, or 1.")
|
||||
let(
|
||||
rgn = force_region(geom[1]),
|
||||
l = geom[2],
|
||||
anchor = point3d(anchor),
|
||||
xyanch = point2d(anchor),
|
||||
m = (
|
||||
approx(xyanch,[0,0])? [[1,0,0],[0,1,0],[0,0,1]] :
|
||||
rot(from=xyanch, to=RIGHT, planar=true)
|
||||
) * move(-[cp.x, cp.y]),
|
||||
rpts = apply(m, flatten(rgn)),
|
||||
maxx = max(column(rpts,0)),
|
||||
idxs = [for (i = idx(rpts)) if (approx(rpts[i].x, maxx)) i],
|
||||
ys = [for (i=idxs) rpts[i].y],
|
||||
ys = [for (pt=rpts) if (approx(pt.x, maxx)) pt.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,
|
||||
vec = unit((point3d(xyanch)+UP*anchor.z)/2,UP)
|
||||
) [anchor, pos, vec, oang]
|
||||
pos = rot(from=RIGHT, to=anchor, p=[maxx,midy])
|
||||
) [anchor, pos, unit(anchor), 0]
|
||||
) : type=="xrgn_extent" || type=="xrgn_isect" ? ( // extruded region
|
||||
assert(in_list(anchor.z,[-1,0,1]), "The Z component of an anchor for an extruded 2D shape must be -1, 0, or 1.")
|
||||
let(
|
||||
anchor_xy = point2d(anchor),
|
||||
L = geom[2]
|
||||
)
|
||||
approx(anchor_xy,[0,0]) ? [anchor, up(anchor.z*L/2,cp), anchor, oang] :
|
||||
let(
|
||||
newgeom = list_set(geom, [0,len(geom)-3], [substr(geom[0],1), point2d(cp)]),
|
||||
result2d = _find_anchor(anchor_xy, newgeom),
|
||||
pos = point3d(result2d[1], cp.z+anchor.z*L/2),
|
||||
vec = unit(point3d(result2d[2], anchor.z),UP),
|
||||
oang = atan2(vec.y,vec.x) + 90
|
||||
)
|
||||
[anchor, pos, vec, oang]
|
||||
) :
|
||||
assert(false, "Unknown attachment geometry type.");
|
||||
|
||||
|
|
|
@ -612,7 +612,7 @@ function region_parts(region) =
|
|||
// style = The style to use when triangulating the surface of the object. Valid values are `"default"`, `"alt"`, or `"quincunx"`.
|
||||
// convexity = Max number of surfaces any single ray could pass through. Module use only.
|
||||
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `"origin"`
|
||||
// anchor_isect = If true, anchoring it performed by finding where the anchor vector intersects the swept shape. Default: false
|
||||
// atype = Set to "hull" or "intersect" to select anchor type. Default: "hull"
|
||||
// cp = Centerpoint for determining intersection anchors or centering the shape. Determintes the base of the anchor vector. Can be "centroid", "mean", "box" or a 3D point. Default: "centroid"
|
||||
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
|
||||
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
|
||||
|
@ -637,7 +637,8 @@ function region_parts(region) =
|
|||
// mrgn = union(rgn1,rgn2);
|
||||
// orgn = difference(mrgn,rgn3);
|
||||
// linear_sweep(orgn,height=20,convexity=16) show_anchors();
|
||||
module linear_sweep(region, height=1, center, twist=0, scale=1, slices, maxseg, style="default", convexity, anchor_isect=false, spin=0, orient=UP, cp="centroid", anchor="origin", atype="hull") {
|
||||
module linear_sweep(region, height=1, center, twist=0, scale=1, slices, maxseg, style="default", convexity,
|
||||
spin=0, orient=UP, cp="centroid", anchor="origin", atype="hull") {
|
||||
region = force_region(region);
|
||||
dummy=assert(is_region(region),"Input is not a region");
|
||||
anchor = center ? "zcenter" : anchor;
|
||||
|
|
|
@ -154,7 +154,7 @@
|
|||
// spin = Rotate this many degrees around Z axis after anchor. Default: 0
|
||||
// orient = Vector to rotate top towards after spin
|
||||
// atype = Select "hull" or "intersect anchor types. Default: "hull"
|
||||
// cp = set centerpoint for anchor computation. Default: "centroid"
|
||||
// cp = Centerpoint for determining "intersect" anchors or centering the shape. Determintes the base of the anchor vector. Can be "centroid", "mean", "box" or a 3D point. Default: "centroid"
|
||||
// style = vnf_vertex_array style. Default: "min_edge"
|
||||
// Example:
|
||||
// skin([octagon(4), circle($fn=70,r=2)], z=[0,3], slices=10);
|
||||
|
@ -570,7 +570,7 @@ function skin(profiles, slices, refine=1, method="direct", sampling, caps, close
|
|||
// spin = Rotate this many degrees around Z axis after anchor. Default: 0
|
||||
// orient = Vector to rotate top towards after spin
|
||||
// atype = Select "hull" or "intersect" anchor types. Default: "hull"
|
||||
// cp = set centerpoint for anchor computation. Default: "centroid"
|
||||
// cp = Centerpoint for determining "intersect" anchors or centering the shape. Determintes the base of the anchor vector. Can be "centroid", "mean", "box" or a 3D point. Default: "centroid"
|
||||
// Example(2D): We'll use this shape in several examples
|
||||
// ushape = [[-10, 0],[-10, 10],[ -7, 10],[ -7, 2],[ 7, 2],[ 7, 7],[ 10, 7],[ 10, 0]];
|
||||
// polygon(ushape);
|
||||
|
@ -949,7 +949,7 @@ function path_sweep(shape, path, method="incremental", normal, closed=false, twi
|
|||
// spin = Rotate this many degrees around Z axis after anchor. Default: 0
|
||||
// orient = Vector to rotate top towards after spin
|
||||
// atype = Select "hull" or "intersect" anchor types. Default: "hull"
|
||||
// cp = set centerpoint for anchor computation. Default: "centroid"
|
||||
// cp = Centerpoint for determining "intersect" anchors or centering the shape. Determintes the base of the anchor vector. Can be "centroid", "mean", "box" or a 3D point. Default: "centroid"
|
||||
// Example: Sine wave example with self-intersections at each peak. This would fail with path_sweep().
|
||||
// sinewave = [for(i=[-30:10:360*2+30]) [i/40,3*sin(i)]];
|
||||
// path_sweep2d(circle(r=3,$fn=15), sinewave);
|
||||
|
@ -1073,7 +1073,7 @@ function _ofs_face_edge(face,firstlen,second=false) =
|
|||
// spin = Rotate this many degrees around Z axis after anchor. Default: 0
|
||||
// orient = Vector to rotate top towards after spin (module only)
|
||||
// atype = Select "hull" or "intersect" anchor types. Default: "hull"
|
||||
// cp = set centerpoint for anchor computation. Default: "centroid"
|
||||
// cp = Centerpoint for determining "intersect" anchors or centering the shape. Determintes the base of the anchor vector. Can be "centroid", "mean", "box" or a 3D point. Default: "centroid"
|
||||
// Example: This is the "sweep-drop" example from list-comprehension-demos.
|
||||
// function drop(t) = 100 * 0.5 * (1 - cos(180 * t)) * sin(180 * t) + 1;
|
||||
// function path(t) = [0, 0, 80 + 80 * cos(180 * t)];
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
// Arguments:
|
||||
// str = string to operate on
|
||||
// pos = starting index of substring, or vector of first and last position. Default: 0
|
||||
// len = length of substring, or omit it to get the rest of the string. If len is less than zero the emptry string is returned.
|
||||
// len = length of substring, or omit it to get the rest of the string. If len is zero or less then the emptry string is returned.
|
||||
// Example:
|
||||
// substr("abcdefg",3,3); // Returns "def"
|
||||
// substr("abcdefg",2); // Returns "cdefg"
|
||||
|
|
2
vnf.scad
2
vnf.scad
|
@ -783,7 +783,7 @@ function _slice_3dpolygons(polys, dir, cuts) =
|
|||
// vnf = A VNF structure, or list of VNF structures.
|
||||
// convexity = Max number of times a line could intersect a wall of the shape.
|
||||
// extent = If true, calculate anchors by extents, rather than intersection. Default: true.
|
||||
// cp = Centerpoint of VNF to use for anchoring when `extent` is false. Default: `[0, 0, 0]`
|
||||
// cp = Centerpoint for determining intersection anchors or centering the shape. Determintes the base of the anchor vector. Can be "centroid", "mean", "box" or a 3D point. Default: "centroid"
|
||||
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `"origin"`
|
||||
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
|
||||
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
|
||||
|
|
Loading…
Reference in a new issue