mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2025-01-04 03:09:45 +00:00
Merge pull request #233 from RonaldoCMP/master
Minor changes in arrays.scad and math.scad
This commit is contained in:
commit
a7ac480e28
4 changed files with 74 additions and 33 deletions
26
arrays.scad
26
arrays.scad
|
@ -1287,6 +1287,10 @@ function array_dim(v, depth=undef) =
|
|||
|
||||
// Function: transpose()
|
||||
// Description: Returns the transposition of the given array.
|
||||
// When reverse=true, the transposition is done in respect to the secondary diagonal, that is:
|
||||
// .
|
||||
// reverse(transpose(reverse(arr))) == transpose(arr, reverse=true)
|
||||
// By default, reverse=false.
|
||||
// Example:
|
||||
// arr = [
|
||||
// ["a", "b", "c"],
|
||||
|
@ -1313,14 +1317,30 @@ function array_dim(v, depth=undef) =
|
|||
// // ["c", "f"],
|
||||
// // ]
|
||||
// Example:
|
||||
// arr = [
|
||||
// ["a", "b", "c"],
|
||||
// ["d", "e", "f"],
|
||||
// ["g", "h", "i"]
|
||||
// ];
|
||||
// t = transpose(arr, reverse=true);
|
||||
// // Returns:
|
||||
// // [
|
||||
// // ["i", "f", "c"],
|
||||
// // ["h", "e", "b"],
|
||||
// // ["g", "d", "a"]
|
||||
// // ]
|
||||
// Example:
|
||||
// transpose([3,4,5]); // Returns: [3,4,5]
|
||||
function transpose(arr) =
|
||||
function transpose(arr, reverse=false) =
|
||||
assert( is_list(arr) && len(arr)>0, "The array is not a vector neither a matrix." )
|
||||
is_list(arr[0])
|
||||
? let( l0 = len(arr[0]) )
|
||||
assert([for(a=arr) if(!is_list(a) || len(a)!=l0) 1 ]==[], "The array is not a vector neither a matrix." )
|
||||
[for (i=[0:1:l0-1])
|
||||
[ for (j=[0:1:len(arr)-1]) arr[j][i] ] ]
|
||||
reverse
|
||||
? [for (i=[0:1:l0-1])
|
||||
[ for (j=[0:1:len(arr)-1]) arr[len(arr)-1-j][l0-1-i] ] ]
|
||||
: [for (i=[0:1:l0-1])
|
||||
[ for (j=[0:1:len(arr)-1]) arr[j][i] ] ]
|
||||
: assert( is_vector(arr), "The array is not a vector neither a matrix." )
|
||||
arr;
|
||||
|
||||
|
|
25
math.scad
25
math.scad
|
@ -698,9 +698,8 @@ function linear_solve(A,b) =
|
|||
zeros != [] ? [] :
|
||||
m<n
|
||||
// avoiding input validation in back_substitute
|
||||
? let( n = len(R),
|
||||
Rt = [for(i=[0:n-1]) [for(j=[0:n-1]) R[n-1-j][n-1-i]]] )
|
||||
Q*reverse(_back_substitute(Rt,reverse(b)))
|
||||
? let( n = len(R) )
|
||||
Q*reverse(_back_substitute(transpose(R, reverse=true), reverse(b)))
|
||||
: _back_substitute(R, transpose(Q)*b);
|
||||
|
||||
// Function: matrix_inverse()
|
||||
|
@ -728,13 +727,14 @@ function qr_factor(A) =
|
|||
n = len(A[0])
|
||||
)
|
||||
let(
|
||||
qr =_qr_factor(A, column=0, m = m, n=n, Q=ident(m)),
|
||||
Rzero = [
|
||||
for(i=[0:m-1]) [
|
||||
for(j=[0:n-1])
|
||||
i>j ? 0 : qr[1][i][j]
|
||||
qr =_qr_factor(A, Q=ident(m), column=0, m = m, n=n),
|
||||
Rzero =
|
||||
let( R = qr[1] )
|
||||
[ for(i=[0:m-1]) [
|
||||
let( ri = R[i] )
|
||||
for(j=[0:n-1]) i>j ? 0 : ri[j]
|
||||
]
|
||||
]
|
||||
]
|
||||
) [qr[0],Rzero];
|
||||
|
||||
function _qr_factor(A,Q, column, m, n) =
|
||||
|
@ -763,13 +763,12 @@ function back_substitute(R, b, transpose = false) =
|
|||
let(n=len(R))
|
||||
assert(is_vector(b,n) || is_matrix(b,n),str("R and b are not compatible in back_substitute ",n, len(b)))
|
||||
transpose
|
||||
? reverse(_back_substitute([for(i=[0:n-1]) [for(j=[0:n-1]) R[n-1-j][n-1-i]]],
|
||||
reverse(b)))
|
||||
? reverse(_back_substitute(transpose(R, reverse=true), reverse(b)))
|
||||
: _back_substitute(R,b);
|
||||
|
||||
function _back_substitute(R, b, x=[]) =
|
||||
let(n=len(R))
|
||||
len(x) == n ? x
|
||||
let(n=len(R))
|
||||
len(x) == n ? x
|
||||
: let(ind = n - len(x) - 1)
|
||||
R[ind][ind] == 0 ? []
|
||||
: let(
|
||||
|
|
55
paths.scad
55
paths.scad
|
@ -43,10 +43,12 @@ include <triangulation.scad>
|
|||
// dim = list of allowed dimensions of the vectors in the path. Default: [2,3]
|
||||
// fast = set to true for fast check that only looks at first entry. Default: false
|
||||
function is_path(list, dim=[2,3], fast=false) =
|
||||
fast? is_list(list) && is_vector(list[0]) :
|
||||
is_list(list) && is_list(list[0]) && len(list)>1 &&
|
||||
(is_undef(dim) || in_list(len(list[0]), force_list(dim))) &&
|
||||
is_list_of(list, repeat(0,len(list[0])));
|
||||
fast
|
||||
? is_list(list) && is_vector(list[0])
|
||||
: is_matrix(list)
|
||||
&& len(list)>1
|
||||
&& len(list[0])>0
|
||||
&& (is_undef(dim) || in_list(len(list[0]), force_list(dim)));
|
||||
|
||||
|
||||
// Function: is_closed_path()
|
||||
|
@ -105,32 +107,51 @@ function path_subselect(path, s1, u1, s2, u2, closed=false) =
|
|||
|
||||
// Function: simplify_path()
|
||||
// Description:
|
||||
// Takes a path and removes unnecessary collinear points.
|
||||
// Takes a path and removes unnecessary subsequent collinear points.
|
||||
// Usage:
|
||||
// simplify_path(path, [eps])
|
||||
// Arguments:
|
||||
// path = A list of 2D path points.
|
||||
// path = A list of path points of any dimension.
|
||||
// eps = Largest positional variance allowed. Default: `EPSILON` (1-e9)
|
||||
function simplify_path(path, eps=EPSILON) =
|
||||
len(path)<=2? path : let(
|
||||
indices = concat([0], [for (i=[1:1:len(path)-2]) if (!collinear_indexed(path, i-1, i, i+1, eps=eps)) i], [len(path)-1])
|
||||
) [for (i = indices) path[i]];
|
||||
assert( is_path(path), "Invalid path." )
|
||||
assert( is_undef(eps) || (is_finite(eps) && (eps>=0) ), "Invalid tolerance." )
|
||||
len(path)<=2 ? path
|
||||
: let(
|
||||
indices = [ 0,
|
||||
for (i=[1:1:len(path)-2])
|
||||
if (!collinear(path[i-1],path[i],path[i+1], eps=eps)) i,
|
||||
len(path)-1
|
||||
]
|
||||
)
|
||||
[for (i = indices) path[i] ];
|
||||
|
||||
|
||||
// Function: simplify_path_indexed()
|
||||
// Description:
|
||||
// Takes a list of points, and a path as a list of indices into `points`,
|
||||
// and removes all path points that are unecessarily collinear.
|
||||
// Takes a list of points, and a list of indices into `points`,
|
||||
// and removes from the list all indices of subsequent indexed points that are unecessarily collinear.
|
||||
// Returns the list of the remained indices.
|
||||
// Usage:
|
||||
// simplify_path_indexed(path, eps)
|
||||
// simplify_path_indexed(points,indices, eps)
|
||||
// Arguments:
|
||||
// points = A list of points.
|
||||
// path = A list of indices into `points` that forms a path.
|
||||
// indices = A list of indices into `points` that forms a path.
|
||||
// eps = Largest angle variance allowed. Default: EPSILON (1-e9) degrees.
|
||||
function simplify_path_indexed(points, path, eps=EPSILON) =
|
||||
len(path)<=2? path : let(
|
||||
indices = concat([0], [for (i=[1:1:len(path)-2]) if (!collinear_indexed(points, path[i-1], path[i], path[i+1], eps=eps)) i], [len(path)-1])
|
||||
) [for (i = indices) path[i]];
|
||||
function simplify_path_indexed(points, indices, eps=EPSILON) =
|
||||
len(indices)<=2? indices
|
||||
: let(
|
||||
indices = concat( indices[0],
|
||||
[for (i=[1:1:len(indices)-2])
|
||||
let(
|
||||
i1 = indices[i-1],
|
||||
i2 = indices[i],
|
||||
i3 = indices[i+1]
|
||||
)
|
||||
if (!collinear(points[i1],points[i2],points[i3], eps=eps)) indices[i]],
|
||||
indices[len(indices)-1] )
|
||||
)
|
||||
indices;
|
||||
|
||||
|
||||
// Function: path_length()
|
||||
|
|
|
@ -480,6 +480,7 @@ test_array_dim();
|
|||
module test_transpose() {
|
||||
assert(transpose([[1,2,3],[4,5,6],[7,8,9]]) == [[1,4,7],[2,5,8],[3,6,9]]);
|
||||
assert(transpose([[1,2,3],[4,5,6]]) == [[1,4],[2,5],[3,6]]);
|
||||
assert(transpose([[1,2,3],[4,5,6]],reverse=true) == [[6,3], [5,2], [4,1]]);
|
||||
assert(transpose([3,4,5]) == [3,4,5]);
|
||||
}
|
||||
test_transpose();
|
||||
|
|
Loading…
Reference in a new issue