mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2024-12-28 15:59:45 +00:00
change skin to use different algorithm for "incremental" that is
supposed to be more accurate.
This commit is contained in:
parent
d6fe226fca
commit
3c8e76f65d
1 changed files with 51 additions and 20 deletions
71
skin.scad
71
skin.scad
|
@ -1832,13 +1832,14 @@ function path_sweep(shape, path, method="incremental", normal, closed, twist=0,
|
|||
spathfrac = scale_by_length ? path_length_fractions(path, closed) : [for(i=[0:1:len(path)]) i / (len(path)-(closed?0:1))],
|
||||
L = len(path),
|
||||
unscaled_transform_list =
|
||||
method=="incremental" ?
|
||||
method=="old_incremental" ?
|
||||
let(rotations =
|
||||
[for( i = 0,
|
||||
ynormal = normal - (normal * tangents[0])*tangents[0],
|
||||
rotation = frame_map(y=ynormal, z=tangents[0])
|
||||
;
|
||||
i < len(tangents) + (closed?1:0) ;
|
||||
i < len(tangents) + (closed?1:0)
|
||||
;
|
||||
rotation = i<len(tangents)-1+(closed?1:0)? rot(from=tangents[i],to=tangents[(i+1)%L])*rotation : undef,
|
||||
i=i+1
|
||||
)
|
||||
|
@ -1864,6 +1865,49 @@ function path_sweep(shape, path, method="incremental", normal, closed, twist=0,
|
|||
adjusted_final = !closed ? undef :
|
||||
translate(path[0]) * rotations[0] * zrot(-correction_twist+correction_twist%(360/symmetry)-twist)
|
||||
) [for(i=idx(path)) translate(path[i]) * rotations[i] * zrot((twistfix-twist)*tpathfrac[i]), if(closed) adjusted_final]
|
||||
: method=="incremental" ? // Implements Rotation Minimizing Frame from "Computation of Rotation Minimizing Frames"
|
||||
// by Wenping Yang, Bert Büttler, Dayue Zheng, Yang Liu, 2008
|
||||
// http://doi.acm.org/10.1145/1330511.1330513
|
||||
let(rotations = // https://www.microsoft.com/en-us/research/wp-content/uploads/2016/12/Computation-of-rotation-minimizing-frames.pdf
|
||||
[for( i = 0,
|
||||
ynormal = normal - (normal * tangents[0])*tangents[0],
|
||||
rotation = frame_map(y=ynormal, z=tangents[0]),
|
||||
r=ynormal
|
||||
;
|
||||
i < len(tangents) + (closed?1:0)
|
||||
;
|
||||
v1 = path[(i+1)%L]-path[i%L],
|
||||
c1 = v1*v1,
|
||||
rL = r - 2*(v1*r)/c1 * v1,
|
||||
tL = tangents[i%L] - 2*(v1*tangents[i%L])/c1 * v1,
|
||||
v2 = tangents[(i+1)%L]-tL,
|
||||
c2 = v2*v2,
|
||||
r = rL - (2/c2)*(v2*rL)*v2,
|
||||
rotation = i<len(tangents)-1+(closed?1:0)? frame_map(y=r,z=tangents[(i+1)%L]) : undef,
|
||||
i=i+1
|
||||
)
|
||||
rotation],
|
||||
// The mismatch is the inverse of the last transform times the first one for the closed case, or the inverse of the
|
||||
// desired final transform times the realized final transform in the open case. Note that when closed==true the last transform
|
||||
// is a actually looped around and applies to the first point position, so if we got back exactly where we started
|
||||
// then it will be the identity, but we might have accumulated some twist which will show up as a rotation around the
|
||||
// X axis. Similarly, in the closed==false case the desired and actual transformations can only differ in the twist,
|
||||
// so we can need to calculate the twist angle so we can apply a correction, which we distribute uniformly over the whole path.
|
||||
reference_rot = closed ? rotations[0] :
|
||||
is_undef(last_normal) ? last(rotations) :
|
||||
let(
|
||||
last_tangent = last(tangents),
|
||||
lastynormal = last_normal - (last_normal * last_tangent) * last_tangent
|
||||
)
|
||||
frame_map(y=lastynormal, z=last_tangent),
|
||||
mismatch = transpose(last(rotations)) * reference_rot,
|
||||
correction_twist = atan2(mismatch[1][0], mismatch[0][0]),
|
||||
// Spread out this extra twist over the whole sweep so that it doesn't occur
|
||||
// abruptly as an artifact at the last step.
|
||||
twistfix = correction_twist%(360/symmetry),
|
||||
adjusted_final = !closed ? undef :
|
||||
translate(path[0]) * rotations[0] * zrot(-correction_twist+correction_twist%(360/symmetry)-twist)
|
||||
) [for(i=idx(path)) translate(path[i]) * rotations[i] * zrot((twistfix-twist)*tpathfrac[i]), if(closed) adjusted_final]
|
||||
: method=="manual" ?
|
||||
[for(i=[0:L-(closed?0:1)]) let(
|
||||
ynormal = relaxed ? normals[i%L] : normals[i%L] - (normals[i%L] * tangents[i%L])*tangents[i%L],
|
||||
|
@ -1873,21 +1917,6 @@ function path_sweep(shape, path, method="incremental", normal, closed, twist=0,
|
|||
assert(approx(ynormal*znormal,0),str("Supplied normal is parallel to the path tangent at point ",i))
|
||||
translate(path[i%L])*rotation*zrot(-twist*tpathfrac[i])
|
||||
]
|
||||
: method=="cross"?
|
||||
let(
|
||||
crossnormal_mid = [for(i=[(closed?0:1):L-(closed?1:2)])
|
||||
let(v= cross( select(path,i+1)-path[i], path[i]-select(path,i-1)),
|
||||
f=assert(norm(v)>EPSILON)
|
||||
)
|
||||
v
|
||||
],
|
||||
crossnormal = closed ? crossnormal_mid : [crossnormal_mid[0], each crossnormal_mid, last(crossnormal_mid)]
|
||||
)
|
||||
[for(i=[0:L-(closed?0:1)]) let(
|
||||
rotation = frame_map(x=crossnormal[i%L], z=tangents[i%L])
|
||||
)
|
||||
translate(path[i%L])*rotation*zrot(-twist*tpathfrac[i])
|
||||
]
|
||||
: method=="natural" ? // map x axis of shape to the path normal, which points in direction of curvature
|
||||
let (pathnormal = path_normals(path, tangents, closed))
|
||||
assert(all_defined(pathnormal),"Natural normal vanishes on your curve, select a different method")
|
||||
|
@ -3129,6 +3158,8 @@ function associate_vertices(polygons, split, curpoly=0) =
|
|||
// );
|
||||
|
||||
|
||||
function _tex_fn_default() = 16;
|
||||
|
||||
__vnf_no_n_mesg=" texture is a VNF so it does not accept n. Set sample rate for VNF textures using the tex_samples parameter to cyl(), linear_sweep() or rotate_sweep().";
|
||||
|
||||
function texture(tex, n, border, gap, roughness, inset) =
|
||||
|
@ -3622,7 +3653,7 @@ function _textured_linear_sweep(
|
|||
let(
|
||||
caps = is_bool(caps) ? [caps,caps] : caps,
|
||||
regions = is_path(region,2)? [[region]] : region_parts(region),
|
||||
tex = is_string(texture)? texture(texture) : texture,
|
||||
tex = is_string(texture)? texture(texture,$fn=_tex_fn_default()) : texture,
|
||||
dummy = assert(is_undef(samples) || is_vnf(tex), "You gave the tex_samples argument with a heightfield texture, which is not permitted. Use the n= argument to texture() instead"),
|
||||
dummy2=is_bool(rot)?echo("boolean value for tex_rot is deprecated. Use a numerical angle, one of 0, 90, 180, or 270.")0:0,
|
||||
texture = !rot? tex :
|
||||
|
@ -3870,7 +3901,7 @@ function _textured_revolution(
|
|||
counts, samples,
|
||||
style="min_edge", atype="intersect",
|
||||
anchor=CENTER, spin=0, orient=UP
|
||||
) =
|
||||
) =
|
||||
assert(angle>0 && angle<=360)
|
||||
assert(is_path(shape,[2]) || is_region(shape))
|
||||
assert(is_undef(samples) || is_int(samples))
|
||||
|
@ -3897,7 +3928,7 @@ function _textured_revolution(
|
|||
)
|
||||
assert(closed || is_path(shape,2))
|
||||
let(
|
||||
tex = is_string(texture)? texture(texture) : texture,
|
||||
tex = is_string(texture)? texture(texture,$fn=_tex_fn_default()) : texture,
|
||||
dummy = assert(is_undef(samples) || is_vnf(tex), "You gave the tex_samples argument with a heightfield texture, which is not permitted. Use the n= argument to texture() instead"),
|
||||
dummy2=is_bool(rot)?echo("boolean value for tex_rot is deprecated. Use a numerical angle, one of 0, 90, 180, or 270.")0:0,
|
||||
texture = !rot? tex :
|
||||
|
|
Loading…
Reference in a new issue