diff --git a/attachments.scad b/attachments.scad index 755d4cf..7ddbe2b 100644 --- a/attachments.scad +++ b/attachments.scad @@ -3180,12 +3180,12 @@ function attach_geom( assert(is_list(anchors)) assert(is_bool(two_d)) assert(is_vector(axis)) + let( + over_f = is_undef(override) ? function(anchor) [undef,undef,undef] + : is_func(override) ? override + : function(anchor) _local_struct_val(override,anchor) + ) !is_undef(size)? ( - let( - over_f = is_undef(override) ? function(anchor) [undef,undef,undef] - : is_func(override) ? override - : function(anchor) _local_struct_val(override,anchor) - ) two_d? ( let( size2 = default(size2, size.x), @@ -3208,8 +3208,8 @@ function attach_geom( ) : !is_undef(vnf)? ( assert(is_vnf(vnf)) assert(two_d == false) - extent? ["vnf_extent", vnf, cp, offset, anchors] : - ["vnf_isect", vnf, cp, offset, anchors] + extent? ["vnf_extent", vnf, over_f, cp, offset, anchors] + : ["vnf_isect", vnf, over_f, cp, offset, anchors] ) : !is_undef(region)? ( assert(is_region(region),2) let( l = default(l, h) ) @@ -3467,32 +3467,32 @@ function _attach_transform(anchor, spin, orient, geom, p) = spin = default(spin, 0), orient = default(orient, UP), two_d = _attach_geom_2d(geom), - m = ($attach_to != undef)? ( // $attach_to is the attachment point on this object - let( // which will attach to the parent - anch = _find_anchor($attach_to, geom), - // if $anchor_override is set it defines the object position anchor (but note not direction or spin). - // Otherwise we use the provided anchor for the object. - pos = is_undef($anchor_override) ? anch[1] - : _find_anchor(_make_anchor_legal($anchor_override,geom),geom)[1] - ) - two_d? - assert(is_num(spin)) - /*affine3d_zrot(spin) * */ - rot(to=FWD, from=point3d(anch[2])) - * affine3d_translate(point3d(-pos)) - : - let( - ang = vector_angle(anch[2], DOWN), // anch[2] is the anchor direction vector - axis = vector_axis(anch[2], DOWN), - ang2 = (anch[2]==UP || anch[2]==DOWN)? 0 : 180-anch[3], - axis2 = rot(p=axis,[0,0,ang2]) - ) - affine3d_rot_by_axis(axis2,ang) - * (is_num(spin)? affine3d_zrot(ang2+spin) - : affine3d_zrot(spin.z) * affine3d_yrot(spin.y) * affine3d_xrot(spin.x) - * affine3d_zrot(ang2)) - * affine3d_translate(point3d(-pos)) - ) : ( + m = ($attach_to != undef) ? // $attach_to is the attachment point on this object + ( // which will attach to the parent + let( + anch = _find_anchor($attach_to, geom), + // if $anchor_override is set it defines the object position anchor (but note not direction or spin). + // Otherwise we use the provided anchor for the object. + pos = is_undef($anchor_override) ? anch[1] + : _find_anchor(_make_anchor_legal($anchor_override,geom),geom)[1] + ) + two_d? + assert(is_num(spin)) + affine3d_zrot(spin) + * rot(to=FWD, from=point3d(anch[2])) + * affine3d_translate(point3d(-pos)) + : + let( + spinT = is_num(spin) ? affine3d_zrot(-anch[3]-spin) + : affine3d_zrot(-spin.z) * affine3d_yrot(-spin.y) * affine3d_xrot(-spin.x) + * affine3d_zrot(-anch[3]) + ) + affine3d_yrot(180) + * spinT + * rot(from=anch[2],to=UP) + * affine3d_translate(point3d(-pos)) + ) + : let( anchor = is_undef($attach_alignment) ? anchor : two_d? _make_anchor_legal(zrot(-spin,$attach_alignment),geom) @@ -3503,7 +3503,6 @@ function _attach_transform(anchor, spin, orient, geom, p) = assert(is_num(spin)) affine3d_zrot(spin) * affine3d_translate(point3d(-pos)) : - assert(is_num(spin) || is_vector(spin,3)) let( axis = vector_axis(UP,orient), // Returns BACK if orient is UP ang = vector_angle(UP,orient) @@ -3512,7 +3511,6 @@ function _attach_transform(anchor, spin, orient, geom, p) = * ( is_num(spin)? affine3d_zrot(spin) : affine3d_zrot(spin.z) * affine3d_yrot(spin.y) * affine3d_xrot(spin.x)) * affine3d_translate(point3d(-pos)) - ) ) is_undef(p)? m : is_vnf(p) && p==EMPTY_VNF? p @@ -3681,8 +3679,11 @@ function _find_anchor(anchor, geom) = vec = unit(v_mul(r,anchor),UP) ) [anchor, pos, vec, oang] ) : type == "vnf_isect"? ( //vnf - let( vnf=geom[1] ) - approx(anchor,CTR)? [anchor, cp, UP, 0] : // CENTER anchors anchor on cp, "origin" anchors on [0,0] + let( + vnf=geom[1], + override = geom[2](anchor) + ) // CENTER anchors anchor on cp, "origin" anchors on [0,0] + approx(anchor,CTR)? [anchor, default(override[0],cp),default(override[1],UP),default(override[2], 0)] : vnf==EMPTY_VNF? [anchor, [0,0,0], unit(anchor), 0] : let( eps = 1/2048, @@ -3729,10 +3730,13 @@ function _find_anchor(anchor, geom) = n = unit(sum(unorms)), oang = approx(point2d(n), [0,0])? 0 : atan2(n.y, n.x) + 90 ) - [anchor, pos, n, oang] + [anchor, default(override[0],pos),default(override[1], n),default(override[2], oang)] ) : type == "vnf_extent"? ( //vnf - let( vnf=geom[1] ) - approx(anchor,CTR)? [anchor, cp, UP, 0] : // CENTER anchors anchor on cp, "origin" anchors on [0,0] + let( + vnf=geom[1], + override = geom[2](anchor) + ) // CENTER anchors anchor on cp, "origin" anchors on [0,0] + approx(anchor,CTR)? [anchor, default(override[0],cp),default(override[1],UP),default(override[2], 0)] : vnf==EMPTY_VNF? [anchor, [0,0,0], unit(anchor,UP), 0] : let( rpts = apply(rot(from=anchor, to=RIGHT) * move(point3d(-cp)), vnf[0]), @@ -3741,7 +3745,7 @@ function _find_anchor(anchor, geom) = avep = sum(select(rpts,idxs))/len(idxs), mpt = approx(point2d(anchor),[0,0])? [maxx,0,0] : avep, pos = point3d(cp) + rot(from=RIGHT, to=anchor, p=mpt) - ) [anchor, pos, anchor, oang] + ) [anchor, default(override[0],pos),default(override[1],anchor),default(override[2],oang)] ) : type == "trapezoid"? ( //size, size2, shift, override let(all_comps_good = [for (c=anchor) if (c!=sign(c)) 1]==[]) assert(all_comps_good, "All components of an anchor for a rectangle/trapezoid must be -1, 0, or 1") diff --git a/shapes3d.scad b/shapes3d.scad index d94408a..7f2d5a7 100644 --- a/shapes3d.scad +++ b/shapes3d.scad @@ -873,12 +873,12 @@ function octahedron(size=1, anchor=CENTER, spin=0, orient=UP) = // different `$fn` than the number of prism faces, you can apply texture to the flat faces without forcing a high facet count, // anchors are located on the true object instead of the ideal cylinder and you can anchor to the edges and faces. // Named Anchors: -// "edge0", "edge1", etc. = Center of each side edge -// "face0", "face1", etc. = Center of each side face -// "topedge0", "topedge1", etc = Center of each top edge, pointing in direction of associated side face -// "botedge0", "botedge1", etc = Center of each bottom edge, pointing in direction of associated side face -// "topcorner0", "topcorner1", etc = Top corner, pointing in direction of associated edge anchor -// "botcorner0", "botcorner1", etc = Bottom corner, pointing in direction of associated edge anchor +// "edge0", "edge1", etc. = Center of each side edge, spin pointing up along the edge +// "face0", "face1", etc. = Center of each side face, spin pointing up +// "topedge0", "topedge1", etc = Center of each top edge, pointing in direction of associated side face, spin up +// "botedge0", "botedge1", etc = Center of each bottom edge, pointing in direction of associated side face, spin up +// "topcorner0", "topcorner1", etc = Top corner, pointing in direction of associated edge anchor, spin up along associated edge +// "botcorner0", "botcorner1", etc = Bottom corner, pointing in direction of associated edge anchor, spin up along associated edge // Arguments: // l / h / length / height = Length of prism // r = Outer radius of prism. @@ -1162,7 +1162,8 @@ function regular_prism(n, Mface = skmat*zrot(-(i+1/2)*360/n), faceedge = faces[i][1], facenormal = faces[i][0], - facespin = _compute_spin(facenormal, faceedge), + //facespin = _compute_spin(facenormal, faceedge), // spin along centerline of face instea of pointing up---seems to be wrong choice + facespin = _compute_spin(facenormal, UP), edgenormal = unit(vector_bisect(facenormal,select(faces,i-1)[0])), Medge = skmat*zrot(-i*360/n), edge = faces[i][2], @@ -1179,7 +1180,9 @@ function regular_prism(n, ], override = approx(shift,[0,0]) ? undef : [[UP, [point3d(shift,height/2), UP]]] ) - [reorient(anchor,spin,orient, vnf=ovnf, p=ovnf,anchors=anchors, override=override),anchors,override]; + [reorient(anchor,spin,orient, vnf=ovnf, p=ovnf,anchors=anchors, override=override),anchors,override]; + + // Module: rect_tube() diff --git a/vnf.scad b/vnf.scad index 5b9106f..3656df8 100644 --- a/vnf.scad +++ b/vnf.scad @@ -1055,7 +1055,7 @@ function _slice_3dpolygons(polys, dir, cuts) = // Arguments: // vnf = A VNF structure, or list of VNF structures. // convexity = Max number of times a line could intersect a wall of the shape. -// 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" +// cp = Centerpoint for determining intersection anchors or centering the shape. Determines 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#subsection-anchor). Default: `"origin"` // spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0` // orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`