Adds sweep and new version of path_sweep to skin.scad, which probably

needs a name change.  Adds apply(), apply_list() and
affine_frame_map() to affine.scad.  Adds derivative calcluation to
math.scad.  Adds path_tangent, path_normal, path_curvature and
path_torsion functions.  Adds path_length_fraction().
Fixed bug in reindex_polygon where it randomly reverses a 3d path (due
to clockwise check that is bogus in 3d) and put a check in
polygon_is_clockwise to trap this case.
This commit is contained in:
Adrian Mariano
2020-02-27 17:32:03 -05:00
parent 25fe326d2a
commit f8fc8cb544
5 changed files with 705 additions and 47 deletions

View File

@@ -379,4 +379,66 @@ function affine3d_apply(pts, affines) =
// Function: apply()
// Usage: apply(transform, points)
// Description:
// Applies the specified transformation matrix to a point list (or single point). Both inputs can be 2d or 3d, and it is also allowed
// to supply 3d transformations with 2d data as long as the the only action on the z coordinate is a simple scaling.
// Examples:
// transformed = apply(xrot(45), path3d(circle(r=3))); // Rotates 3d circle data around x axis
// transformed = apply(rot(45), circle(r=3)); // Rotates 2d circle data by 45 deg
// transformed = apply(rot(45)*right(4)*scale(3), circle(r=3)); // Scales, translates and rotates 2d circle data
function apply(transform,points) =
is_vector(points) ? apply(transform, [points])[0] :
let(
tdim = len(transform[0])-1,
datadim = len(points[0])
)
tdim == 3 && datadim == 3 ? [for(p=points) point3d(transform*concat(p,[1]))] :
tdim == 2 && datadim == 2 ? [for(p=points) point2d(transform*concat(p,[1]))] :
tdim == 3 && datadim == 2 ?
assert(is_2d_transform(transform),str("Transforms is 3d but points are 2d"))
[for(p=points) point2d(transform*concat(p,[0,1]))] :
assert(false,str("Unsupported combination: transform with dimension ",tdim,", data of dimension ",datadim));
// Function: apply_list()
// Usage: apply_list(points, transform_list)
// Description:
// Transforms the specified point list (or single point) using a list of transformation matrices. Transformations on
// the list are applied in the order they appear in the list (as in right multiplication of matrices). Both inputs can be
// 2d or 3d, and it is also allowed to supply 3d transformations with 2d data as long as the the only action on the z coordinate
// is a simple scaling. All transformations on `transform_list` must have the same dimension: you cannot mix 2d and 3d transformations
// even when acting on 2d data.
// Examples:
// transformed = apply_list(path3d(circle(r=3)),[xrot(45)]); // Rotates 3d circle data around x axis
// transformed = apply_list(circle(r=3), [scale(3), right(4), rot(45)]); // Scales, then translates, and then rotates 2d circle data
function apply_list(points,transform_list) =
is_vector(points) ? apply_list([points],transform_list)[0] :
let(
tdims = array_dim(transform_list),
datadim = len(points[0])
)
assert(len(tdims)==3 || tdims[1]!=tdims[2], "Invalid transformation list")
let( tdim = tdims[1]-1 )
tdim==2 && datadim == 2 ? apply(affine2d_chain(transform_list), points) :
tdim==3 && datadim == 3 ? apply(affine3d_chain(transform_list), points) :
tdim==3 && datadim == 2 ?
let(
badlist = [for(i=idx(transform_list)) if (!is_2d_transform(transform_list[i])) i]
)
assert(badlist==[],str("Transforms with indices ",badlist," are 3d but points are 2d"))
apply(affine3d_chain(transform_list), points) :
assert(false,str("Unsupported combination: transform with dimension ",tdim,", data of dimension ",datadim));
// Function: is_2d_transform()
// Usage: is_2d_transform(t)
// Description: Checks if the input is a 3d transform that does not act on the z coordinate, except
// possibly for a simple scaling of z. Note that an input which is only a zscale returns false.
function is_2d_transform(t) = // z-parameters are zero, except we allow t[2][2]!=1 so scale() works
t[2][0]==0 && t[2][1]==0 && t[2][3]==0 && t[0][2] == 0 && t[1][2]==0 &&
(t[2][2]==1 || !(t[0][0]==1 && t[0][1]==0 && t[1][0]==0 && t[1][1]==1)); // But rule out zscale()
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap