diff --git a/attachments.scad b/attachments.scad index 9e5b88b..77f58c9 100644 --- a/attachments.scad +++ b/attachments.scad @@ -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] : diff --git a/regions.scad b/regions.scad index 0124e10..2084efe 100644 --- a/regions.scad +++ b/regions.scad @@ -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);