add scale argument to path_sweep()

This commit is contained in:
Adrian Mariano 2022-10-13 19:00:45 -04:00
parent af36385835
commit a994011f4d

View file

@ -1215,6 +1215,7 @@ module spiral_sweep(poly, h, r, turns=1, higbee, center, r1, r2, d, d1, d2, higb
// normal = normal vector for initializing the incremental method, or for setting normals with method="manual". Default: UP if the path makes an angle lower than 45 degrees to the xy plane, BACK otherwise.
// closed = path is a closed loop. Default: false
// twist = amount of twist to add in degrees. For closed sweeps must be a multiple of 360/symmetry. Default: 0
// scale = Amount to scale the profiles. If you give a scalar the scale starts at 1 and ends at your specified value. You can also give a vector of values, one for each path point. Default: 1 (no scaling)
// symmetry = symmetry of the shape when closed=true. Allows the shape to join with a 360/symmetry rotation instead of a full 360 rotation. Default: 1
// last_normal = normal to last point in the path for the "incremental" method. Constrains the orientation of the last cross section if you supply it.
// uniform = if set to false then compute tangents using the uniform=false argument, which may give better results when your path is non-uniformly sampled. This argument is passed to {{path_tangents()}}. Default: true
@ -1498,12 +1499,12 @@ module spiral_sweep(poly, h, r, turns=1, higbee, center, r1, r2, d, d1, d2, higb
// method="manual", normal=UP);
// }
module path_sweep(shape, path, method="incremental", normal, closed, twist=0, twist_by_length=true,
module path_sweep(shape, path, method="incremental", normal, closed, twist=0, twist_by_length=true, scale=1,
symmetry=1, last_normal, tangent, uniform=true, relaxed=false, caps, style="min_edge", convexity=10,
anchor="origin",cp="centroid",spin=0, orient=UP, atype="hull",profiles=false,width=1)
{
dummy = assert(is_region(shape) || is_path(shape,2), "shape must be a 2D path or region");
vnf = path_sweep(shape, path, method, normal, closed, twist, twist_by_length,
vnf = path_sweep(shape, path, method, normal, closed, twist, twist_by_length, scale,
symmetry, last_normal, tangent, uniform, relaxed, caps, style);
if (profiles){
@ -1523,10 +1524,10 @@ module path_sweep(shape, path, method="incremental", normal, closed, twist=0, tw
}
function path_sweep(shape, path, method="incremental", normal, closed, twist=0, twist_by_length=true,
function path_sweep(shape, path, method="incremental", normal, closed, twist=0, twist_by_length=true, scale=1,
symmetry=1, last_normal, tangent, uniform=true, relaxed=false, caps, style="min_edge", transforms=false,
anchor="origin",cp="centroid",spin=0, orient=UP, atype="hull") =
is_1region(path) ? path_sweep(shape=shape,path=path[0], method=method, normal=normal, closed=default(closed,true),
is_1region(path) ? path_sweep(shape=shape,path=path[0], method=method, normal=normal, closed=default(closed,true), scale=scale,
twist=twist, twist_by_length=twist_by_length, symmetry=symmetry, last_normal=last_normal,
tangent=tangent, uniform=uniform, relaxed=relaxed, caps=caps, style=style, transforms=transforms,
anchor=anchor, cp=cp, spin=spin, orient=orient, atype=atype) :
@ -1555,7 +1556,10 @@ function path_sweep(shape, path, method="incremental", normal, closed, twist=0,
assert(!closed || !caps, "Cannot make closed shape with caps")
assert(is_undef(normal) || (is_vector(normal) && len(normal)==3) || (is_path(normal) && len(normal)==len(path) && len(normal[0])==3), "Invalid normal specified")
assert(is_undef(tangent) || (is_path(tangent) && len(tangent)==len(path) && len(tangent[0])==3), "Invalid tangent specified")
assert(is_num(scale) || is_vector(scale,len(path)), str("Incompatible or invalid scale: must be a scalar or vector of length ",len(path)))
let(
scale = is_num(scale) ? lerpn(1,scale,len(path)) : scale,
scale_list = [for(s=scale) scale(s),if (closed) scale(scale[0])],
tangents = is_undef(tangent) ? path_tangents(path,uniform=uniform,closed=closed) : [for(t=tangent) unit(t)],
normal = is_path(normal) ? [for(n=normal) unit(n)] :
is_def(normal) ? unit(normal) :
@ -1563,7 +1567,7 @@ function path_sweep(shape, path, method="incremental", normal, closed, twist=0,
normals = is_path(normal) ? normal : repeat(normal,len(path)),
pathfrac = twist_by_length ? path_length_fractions(path, closed) : [for(i=[0:1:len(path)]) i / (len(path)-(closed?0:1))],
L = len(path),
transform_list =
unscaled_transform_list =
method=="incremental" ?
let(rotations =
[for( i = 0,
@ -1595,36 +1599,37 @@ function path_sweep(shape, path, method="incremental", normal, closed, twist=0,
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)*pathfrac[i]), if(closed) adjusted_final] :
method=="manual" ?
) [for(i=idx(path)) translate(path[i]) * rotations[i] * zrot((twistfix-twist)*pathfrac[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],
znormal = relaxed ? tangents[i%L] - (normals[i%L] * tangents[i%L])*normals[i%L] : tangents[i%L],
rotation = frame_map(y=ynormal, z=znormal)
)
assert(approx(ynormal*znormal,0),str("Supplied normal is parallel to the path tangent at point ",i))
translate(path[i%L])*rotation*zrot(-twist*pathfrac[i]),
] :
method=="natural" ? // map x axis of shape to the path normal, which points in direction of curvature
translate(path[i%L])*rotation*zrot(-twist*pathfrac[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")
let( testnormals = [for(i=[0:len(pathnormal)-1-(closed?1:2)]) pathnormal[i]*select(pathnormal,i+2)],
a=[for(i=idx(testnormals)) testnormals[i]<.5 ? echo(str("Big change at index ",i," pn=",pathnormal[i]," pn2= ",select(pathnormal,i+2))):0],
dummy = min(testnormals) < .5 ? echo("WARNING: ***** Abrupt change in normal direction. Consider a different method *****") :0
dummy = min(testnormals) < .5 ? echo("WARNING: ***** Abrupt change in normal direction. Consider a different method in path_sweep() *****") :0
)
[for(i=[0:L-(closed?0:1)]) let(
rotation = frame_map(x=pathnormal[i%L], z=tangents[i%L])
)
translate(path[i%L])*rotation*zrot(-twist*pathfrac[i])
] :
assert(false,"Unknown method or no method given")[], // unknown method
]
: assert(false,"Unknown method or no method given"), // unknown method
transform_list = v_mul(unscaled_transform_list, scale_list),
ends_match = !closed ? true
: let( rshape = is_path(shape) ? [path3d(shape)]
: [for(s=shape) path3d(s)]
)
are_regions_equal(apply(transform_list[0], rshape),
apply(transform_list[L], rshape)),
dummy = ends_match ? 0 : echo("WARNING: ***** The points do not match when closing the model *****")
dummy = ends_match ? 0 : echo("WARNING: ***** The points do not match when closing the model in path_sweep() *****")
)
transforms ? transform_list
: sweep(is_path(shape)?clockwise_polygon(shape):shape, transform_list, closed=false, caps=fullcaps,style=style,