diff --git a/beziers.scad b/beziers.scad index e417aec..c57281e 100644 --- a/beziers.scad +++ b/beziers.scad @@ -1642,8 +1642,136 @@ function bezier_sheet(patch, delta, splinesteps=16, style="default", thickness=u ) del[0]=0) ), "\nInvalid tolerance.") - len(path)<=2 ? path : let(path = deduplicate(path, closed=closed)) + len(path)<=2 ? path : [ if(!closed) path[0], for(triple=triplet(path,wrap=closed)) @@ -167,6 +167,47 @@ function path_merge_collinear(path, closed, eps=_EPSILON) = ]; + +// Function: path_merge_collinear_indexed() +// Synopsis: Removes unnecessary collinear points from a path specified as an index list into a list +// SynTags: Path +// Topics: Paths, Regions +// Description: +// Given a {{path}} and a list of indices, removes unnecessary sequential collinear points found in `path[indices]` and returns +// the list of indices corresponding to the simplified path. When `closed=true` either of the path +// endpoints may be removed. If you don't provide `indices` then the default is the consecutive index +// list `[0,...,len(list)-1]`. This is useful if you need to remove collinear points from list A and then +// remove corresponding points from list B. +// Usage: +// path_merge_collinear(path, [eps]) +// Arguments: +// path = A path of any dimension or a 1-region +// indices = Index list that indexes into `path`. Default: `count(path)` +// closed = treat as closed polygon. Default: false for lists, true for 1-regions +// eps = Largest positional variance allowed. Default: 1e-9 +function path_merge_collinear_indexed(path, indices, closed, eps=_EPSILON) = + is_1region(path) ? path_merge_collinear_indexed(path[0], indices, default(closed,true), eps) : + let( + closed=default(closed,false), + indices=default(indices,count(path)) + ) + assert(is_bool(closed)) + assert( is_path(path), "\nInvalid path in path_merge_collinear.") + assert( is_undef(eps) || (is_finite(eps) && (eps>=0) ), "\nInvalid tolerance.") + assert( is_vector(indices), "\nindices must be a list of indices values") + assert( min(indices)>=0, "\nIndices list has negative entry") + assert( max(indices)0, "\nsymmetry must be a positive integer.") let(path = force_path(path)) - assert(is_path(path,[2,3]), "\ninput path is not a 2D or 3D path.") + assert(is_path(path,[2,3]), "\nInput path is not a 2D or 3D path.") + assert(len(path)==len(deduplicate(path)),"\nInput path contains duplicate points (consider using deduplicate)") assert(!closed || !approx(path[0],last(path)), "\nClosed path includes start point at the end.") assert((is_region(shape) || is_path(shape,2)) || (transforms && !(closed && method=="incremental")),"\nshape must be a 2d path or region.") let(