revamp extruded region attachables and apply to linear_sweep.

This commit is contained in:
Adrian Mariano
2021-11-17 13:38:07 -05:00
parent 2bfb4e39e7
commit 475129fd95
5 changed files with 40 additions and 79 deletions

View File

@@ -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.");