Make linear_sweep center in z direction with center option by adding

"zcenter" named anchor.
This commit is contained in:
Adrian Mariano 2021-10-21 11:31:32 -04:00
parent 6de156528b
commit d5ce3615cf
2 changed files with 22 additions and 19 deletions

View file

@ -1117,7 +1117,7 @@ function reorient(
two_d=false,
axis=UP,
p=undef
) =
) =
assert(is_undef(anchor) || is_vector(anchor) || is_string(anchor), str("Got: ",anchor))
assert(is_undef(spin) || is_vector(spin,3) || is_num(spin), str("Got: ",spin))
assert(is_undef(orient) || is_vector(orient,3), str("Got: ",orient))
@ -1526,19 +1526,19 @@ function _get_cp(geom) =
// anchor = Vector or named anchor string.
// geom = The geometry description of the shape.
function _find_anchor(anchor, geom) =
let(
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)? (
is_string(anchor)? (
anchor=="origin"? [anchor, CENTER, UP, 0]
: let(found = search([anchor], anchors, num_returns_per_match=1)[0])
: let(ff=echo(ss=anchors),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))
let(anchor = point3d(anchor))
anchor==CENTER? [anchor, cp, UP, 0] :

View file

@ -390,14 +390,16 @@ function region_parts(region) =
// If called as a module, creates a polyhedron that is the linear extrusion of the given 2D region or path.
// If called as a function, returns a VNF that can be used to generate a polyhedron of the linear extrusion
// of the given 2D region or path. The benefit of using this, over using `linear_extrude region(rgn)` is
// that you can use `anchor`, `spin`, `orient` and attachments with it. You can set `cp` to "mean", "centroid"
// or "box" to get different centerpoint computations, or you can give a custom vector centerpoint.
// Also, you can make more refined
// that it supports `anchor`, `spin`, `orient` and attachments. You can also make more refined
// twisted extrusions by using `maxseg` to subsample flat faces.
// Note that the center option centers vertically using the named anchor "zcenter" whereas
// `anchor=CENTER` centers the entire shape relative to
// the shape's centroid, or other centerpoint you specify. The centerpoint can be "centroid", "mean", "box" or
// a custom point location.
// Arguments:
// region = The 2D [Region](regions.scad) or path that is to be extruded.
// height = The height to extrude the region. Default: 1
// center = If true, the created polyhedron will be vertically centered. If false, it will be extruded upwards from the origin. Default: `false`
// center = If true, the created polyhedron will be vertically centered. If false, it will be extruded upwards from the XY plane. Default: `false`
// slices = The number of slices to divide the shape into along the Z axis, to allow refinement of detail, especially when working with a twist. Default: `twist/5`
// maxseg = If given, then any long segments of the region will be subdivided to be shorter than this length. This can refine twisting flat faces a lot. Default: `undef` (no subsampling)
// twist = The number of degrees to rotate the shape clockwise around the Z axis, as it rises from bottom to top. Default: 0
@ -406,7 +408,7 @@ function region_parts(region) =
// 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
// cp = Centerpoint for determining intersection anchors or centering the shape. Determintes the base of the anchor vector. Default: "centroid"
// 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`
// Example: Extruding a Compound Region.
@ -430,17 +432,18 @@ 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, anchor, spin=0, orient=UP, cp="centroid") {
module linear_sweep(region, height=1, center, twist=0, scale=1, slices, maxseg, style="default", convexity, anchor_isect=false, anchor, spin=0, orient=UP, cp="centroid", anchor="origin") {
region = force_region(region);
dummy=assert(is_region(region),"Input is not a region");
anchor = get_anchor(anchor, center, "origin", "origin");
anchor = center ? "zcenter" : anchor;
anchors = [named_anchor("zcenter", [0,0,height/2], UP)];
vnf = linear_sweep(
region, height=height,
twist=twist, scale=scale,
slices=slices, maxseg=maxseg,
style=style
);
attachable(anchor,spin,orient, cp=cp, vnf=vnf, extent=!anchor_isect) {
attachable(anchor,spin,orient, cp=cp, vnf=vnf, extent=!anchor_isect, anchors=anchors) {
vnf_polyhedron(vnf, convexity=convexity);
children();
}
@ -454,9 +457,9 @@ function linear_sweep(region, height=1, center, twist=0, scale=1, slices,
)
assert(is_region(region), "Input is not a region")
let(
anchor = get_anchor(anchor,center,"origin","origin"),
anchor = center ? "zcenter" : anchor,
anchors = [named_anchor("zcenter", [0,0,height/2], UP)],
regions = region_parts(region),
// cp = mean(pointlist_bounds(flatten(region))),
slices = default(slices, floor(twist/5+1)),
step = twist/slices,
hstep = height/slices,
@ -486,14 +489,14 @@ function linear_sweep(region, height=1, center, twist=0, scale=1, slices,
for (i=[0:1:slices]) let(
sc = lerp(1, scale, i/slices),
ang = i * step,
h = i * hstep - height/2
h = i * hstep //- height/2
) scale([sc,sc,1], p=rot(ang, p=path3d(path,h)))
]
) vnf_vertex_array(verts, caps=false, col_wrap=true, style=style),
for (rgn = regions) vnf_from_region(rgn, down(height/2), reverse=true),
for (rgn = trgns) vnf_from_region(rgn, up(height/2), reverse=false)
for (rgn = regions) vnf_from_region(rgn, ident(4), reverse=true),
for (rgn = trgns) vnf_from_region(rgn, up(height), reverse=false)
])
) reorient(anchor,spin,orient, cp=cp, vnf=vnf, extent=!anchor_isect, p=vnf);
) reorient(anchor,spin,orient, cp=cp, vnf=vnf, extent=!anchor_isect, p=vnf, anchors=anchors);