mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2025-01-01 09:49:45 +00:00
mat3_to_mat4() -> affine2d_to_3d() and various trailing space and formatting issues.
This commit is contained in:
parent
e8254cec7d
commit
65b78f90ae
2 changed files with 115 additions and 103 deletions
|
@ -17,9 +17,9 @@
|
|||
function ident(n) = [for (i = [0:1:n-1]) [for (j = [0:1:n-1]) (i==j)?1:0]];
|
||||
|
||||
|
||||
// Function: affine2d_to_affine3d()
|
||||
// Function: affine2d_to_3d()
|
||||
// Description: Takes a 3x3 affine2d matrix and returns its 4x4 affine3d equivalent.
|
||||
function mat3_to_mat4(m) = concat(
|
||||
function affine2d_to_3d(m) = concat(
|
||||
[for (r = [0:2])
|
||||
concat(
|
||||
[for (c = [0:2]) m[r][c]],
|
||||
|
|
76
paths.scad
76
paths.scad
|
@ -525,16 +525,19 @@ module path_spread(path, n, spacing, sp=undef, rotate_children=true, closed=fals
|
|||
is_def(n) && is_def(spacing)? list_range(s=sp, step=spacing, n=n) :
|
||||
is_def(n)? list_range(s=sp, e=length, n=n) :
|
||||
list_range(s=sp, step=spacing, e=length)
|
||||
) :
|
||||
is_def(n) && is_undef(spacing) ? (closed ? let(range=list_range(s=0,e=length, n=n+1)) slice(range,0,-2) :
|
||||
) : is_def(n) && is_undef(spacing)? (
|
||||
closed?
|
||||
let(range=list_range(s=0,e=length, n=n+1)) slice(range,0,-2) :
|
||||
list_range(s=0, e=length, n=n)
|
||||
) :
|
||||
let( n = is_def(n) ? n : floor(length/spacing)+(closed?0:1),
|
||||
) : (
|
||||
let(
|
||||
n = is_def(n)? n : floor(length/spacing)+(closed?0:1),
|
||||
ptlist = list_range(s=0,step=spacing,n=n),
|
||||
listcenter = mean(ptlist)
|
||||
)
|
||||
closed ? sort([for(entry=ptlist) posmod(entry-listcenter,length)]) :
|
||||
[for(entry=ptlist) entry + length/2-listcenter ];
|
||||
) closed?
|
||||
sort([for(entry=ptlist) posmod(entry-listcenter,length)]) :
|
||||
[for(entry=ptlist) entry + length/2-listcenter ]
|
||||
);
|
||||
distOK = min(distances)>=0 && max(distances)<=length;
|
||||
assert(distOK,"Cannot fit all of the copies");
|
||||
cutlist = path_cut(path, distances, closed, direction=true);
|
||||
|
@ -546,10 +549,15 @@ module path_spread(path, n, spacing, sp=undef, rotate_children=true, closed=fals
|
|||
$normal = rotate_children? (planar?[0,1]:[0,0,1]) : cutlist[i][3];
|
||||
translate($pos) {
|
||||
if (rotate_children) {
|
||||
if(planar) rot(from=[0,1],to=cutlist[i][3]) children();
|
||||
else multmatrix(mat3_to_mat4(transpose([cutlist[i][2],cross(cutlist[i][3],cutlist[i][2]), cutlist[i][3]]))) children();
|
||||
if(planar) {
|
||||
rot(from=[0,1],to=cutlist[i][3]) children();
|
||||
} else {
|
||||
multmatrix(affine2d_to_3d(transpose([cutlist[i][2],cross(cutlist[i][3],cutlist[i][2]), cutlist[i][3]])))
|
||||
children();
|
||||
}
|
||||
} else {
|
||||
children();
|
||||
}
|
||||
else children();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -561,11 +569,14 @@ module path_spread(path, n, spacing, sp=undef, rotate_children=true, closed=fals
|
|||
// path_cut(path, dists, [closed], [direction])
|
||||
//
|
||||
// Description:
|
||||
// Cuts a path at a list of distances from the first point in the path. Returns a list of the cut points and indices of the next point in the path after that point.
|
||||
// So for example, a return value entry of [[2,3], 5] means that the cut point was [2,3] and the next point on the path after this point is path[5].
|
||||
// If the path is too short then path_cut returns undef. If you set `direction` to true then `path_cut` will also return the tangent vector to the path
|
||||
// and a normal vector to the path. It tries to find a normal vector that is coplanar to the path near the cut point. If this fails it will return a normal
|
||||
// vector parallel to the xy plane. The output with direction vectors will be `[point, next_index, tangent, normal]`.
|
||||
// Cuts a path at a list of distances from the first point in the path. Returns a list of the cut
|
||||
// points and indices of the next point in the path after that point. So for example, a return
|
||||
// value entry of [[2,3], 5] means that the cut point was [2,3] and the next point on the path after
|
||||
// this point is path[5]. If the path is too short then path_cut returns undef. If you set
|
||||
// `direction` to true then `path_cut` will also return the tangent vector to the path and a normal
|
||||
// vector to the path. It tries to find a normal vector that is coplanar to the path near the cut
|
||||
// point. If this fails it will return a normal vector parallel to the xy plane. The output with
|
||||
// direction vectors will be `[point, next_index, tangent, normal]`.
|
||||
//
|
||||
// Arguments:
|
||||
// path = path to cut
|
||||
|
@ -584,11 +595,10 @@ function path_cut(path, dists, closed=false, direction=false) =
|
|||
assert(long_enough,len(path)<2 ? "Two points needed to define a path" : "Closed path must include three points")
|
||||
!is_list(dists)? path_cut(path, [dists],closed, direction)[0] :
|
||||
let(cuts = _path_cut(path,dists,closed))
|
||||
!direction ? cuts :
|
||||
let( dir = _path_cuts_dir(path, cuts, closed),
|
||||
!direction ? cuts : let(
|
||||
dir = _path_cuts_dir(path, cuts, closed),
|
||||
normals = _path_cuts_normals(path, cuts, dir, closed)
|
||||
)
|
||||
zip(cuts, array_group(dir,1), array_group(normals,1));
|
||||
) zip(cuts, array_group(dir,1), array_group(normals,1));
|
||||
|
||||
// Main recursive path cut function
|
||||
function _path_cut(path, dists, closed=false, pind=0, dtotal=0, dind=0, result=[]) =
|
||||
|
@ -597,40 +607,42 @@ function _path_cut(path, dists, closed=false, pind=0, dtotal=0, dind=0, result=[
|
|||
lastpt = len(result)>0? select(result,-1)[0] : [],
|
||||
dpartial = len(result)==0? 0 : norm(lastpt-path[pind]),
|
||||
nextpoint = dpartial > dists[dind]-dtotal?
|
||||
[lerp(lastpt,path[pind], (dists[dind]-dtotal)/dpartial),pind]
|
||||
:
|
||||
[lerp(lastpt,path[pind], (dists[dind]-dtotal)/dpartial),pind] :
|
||||
_path_cut_single(path, dists[dind]-dtotal-dpartial, closed, pind)
|
||||
)
|
||||
nextpoint == undef ? concat(result, replist(undef,len(dists)-dind)):
|
||||
) is_undef(nextpoint)?
|
||||
concat(result, replist(undef,len(dists)-dind)) :
|
||||
_path_cut(path, dists, closed, nextpoint[1], dists[dind],dind+1, concat(result, [nextpoint]));
|
||||
|
||||
// Search for a single cut point in the path
|
||||
function _path_cut_single(path, dist, closed=false, ind=0, eps=1e-7) =
|
||||
ind>=len(path)? undef :
|
||||
ind==len(path)-1 && !closed? (dist<eps? [path[ind],ind+1] : undef) :
|
||||
let(d = norm(path[ind]-select(path,ind+1)))
|
||||
d > dist ? [lerp(path[ind],select(path,ind+1),dist/d), ind+1] :
|
||||
let(d = norm(path[ind]-select(path,ind+1))) d > dist ?
|
||||
[lerp(path[ind],select(path,ind+1),dist/d), ind+1] :
|
||||
_path_cut_single(path, dist-d,closed, ind+1, eps);
|
||||
|
||||
// Find normal directions to the path, coplanar to local part of the path
|
||||
// Or return a vector parallel to the x-y plane if the above fails
|
||||
function _path_cuts_normals(path, cuts, dirs, closed=false) =
|
||||
[for(i=[0:len(cuts)-1])
|
||||
len(path[0])==2? [-dirs[i].y,dirs[i].x] :
|
||||
len(path[0])==2? [-dirs[i].y, dirs[i].x] : (
|
||||
let(
|
||||
plane = len(path)<3 ? undef :
|
||||
let( start = max(min(cuts[i][1],len(path)-1),2))
|
||||
_path_plane(path, start, start-2)
|
||||
let(start = max(min(cuts[i][1],len(path)-1),2)) _path_plane(path, start, start-2)
|
||||
)
|
||||
plane==undef ? normalize([-dirs[i].y, dirs[i].x,0]) :
|
||||
plane==undef?
|
||||
normalize([-dirs[i].y, dirs[i].x,0]) :
|
||||
normalize(cross(dirs[i],cross(plane[0],plane[1])))
|
||||
)
|
||||
];
|
||||
|
||||
// Scan from the specified point (ind) to find a noncoplanar triple to use
|
||||
// to define the plane of the path.
|
||||
function _path_plane(path, ind, i,closed) =
|
||||
i<(closed?-1:0) ? undef :
|
||||
!collinear(path[ind],path[ind-1], select(path,i)) ? [select(path,i)-path[ind-1],path[ind]-path[ind-1]] : _path_plane(path, ind, i-1);
|
||||
!collinear(path[ind],path[ind-1], select(path,i))?
|
||||
[select(path,i)-path[ind-1],path[ind]-path[ind-1]] :
|
||||
_path_plane(path, ind, i-1);
|
||||
|
||||
// Find the direction of the path at the cut points
|
||||
function _path_cuts_dir(path, cuts, closed=false, eps=1e-2) =
|
||||
|
@ -647,8 +659,8 @@ function _path_cuts_dir(path, cuts, closed=false, eps=1e-2) =
|
|||
(nextind>1 || closed) && approx(cuts[ind][0],path[nextind-1],eps)?
|
||||
normalize(thispath+lastpath) :
|
||||
thispath
|
||||
)
|
||||
nextdir];
|
||||
) nextdir
|
||||
];
|
||||
|
||||
|
||||
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
|
Loading…
Reference in a new issue