mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2025-01-30 08:19:36 +00:00
search_vectors update
This commit is contained in:
parent
9a0f18ed44
commit
922e2da952
2 changed files with 24 additions and 14 deletions
|
@ -178,7 +178,7 @@ test_vector_search();
|
||||||
module test_vector_search_tree(){
|
module test_vector_search_tree(){
|
||||||
points1 = [ [0,1,2], [1,2,3], [2,3,4] ];
|
points1 = [ [0,1,2], [1,2,3], [2,3,4] ];
|
||||||
tree1 = vector_search_tree(points1);
|
tree1 = vector_search_tree(points1);
|
||||||
assert(tree1 == [ points1, [[0,1,2]] ]);
|
assert(tree1 == points1);
|
||||||
points2 = [for(i=[0:9], j=[0:9], k=[1:5]) [i,j,k] ];
|
points2 = [for(i=[0:9], j=[0:9], k=[1:5]) [i,j,k] ];
|
||||||
tree2 = vector_search_tree(points2);
|
tree2 = vector_search_tree(points2);
|
||||||
assert(tree2[0]==points2);
|
assert(tree2[0]==points2);
|
||||||
|
|
36
vectors.scad
36
vectors.scad
|
@ -171,8 +171,8 @@ function pointlist_bounds(pts) =
|
||||||
// v5 = unit([0,0,0],[1,2,3]); // Returns: [1,2,3]
|
// v5 = unit([0,0,0],[1,2,3]); // Returns: [1,2,3]
|
||||||
// v6 = unit([0,0,0]); // Asserts an error.
|
// v6 = unit([0,0,0]); // Asserts an error.
|
||||||
function unit(v, error=[[["ASSERT"]]]) =
|
function unit(v, error=[[["ASSERT"]]]) =
|
||||||
assert(is_vector(v), str("Expected a vector. Got: ",v))
|
assert(is_vector(v), "Invalid vector")
|
||||||
norm(v)<EPSILON? (error==[[["ASSERT"]]]? assert(norm(v)>=EPSILON,"Tried to normalize a zero vector") : error) :
|
norm(v)<EPSILON? (error==[[["ASSERT"]]]? assert(norm(v)>=EPSILON,"Cannot normalize a zero vector") : error) :
|
||||||
v/norm(v);
|
v/norm(v);
|
||||||
|
|
||||||
|
|
||||||
|
@ -313,8 +313,10 @@ function furthest_point(pt, points) =
|
||||||
// When `target` is a large list of points, a search tree is constructed to
|
// When `target` is a large list of points, a search tree is constructed to
|
||||||
// speed up the search with an order around O(log n) per query point.
|
// speed up the search with an order around O(log n) per query point.
|
||||||
// For small point lists, a direct search is done dispensing a tree construction.
|
// For small point lists, a direct search is done dispensing a tree construction.
|
||||||
// Alternatively, `target` may be a search tree built with `vector_tree_search()`.
|
// Alternatively, `target` may be a search tree built with `vector_search_tree()`.
|
||||||
// In that case, that tree is parsed looking for matches.
|
// In that case, that tree is parsed looking for matches.
|
||||||
|
// An empty list of query points will return a empty output list.
|
||||||
|
// An empty list of target points will return a output list with an empty list for each query point.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// query = list of points to find matches for.
|
// query = list of points to find matches for.
|
||||||
// r = the search radius.
|
// r = the search radius.
|
||||||
|
@ -351,6 +353,8 @@ function furthest_point(pt, points) =
|
||||||
// color("red") move_copies(select(points, search_2[i])) circle(r=.08);
|
// color("red") move_copies(select(points, search_2[i])) circle(r=.08);
|
||||||
// }
|
// }
|
||||||
function vector_search(query, r, target) =
|
function vector_search(query, r, target) =
|
||||||
|
query==[] ? [] :
|
||||||
|
is_list(query) && target==[] ? is_vector(query) ? [] : [for(q=query) [] ] :
|
||||||
assert( is_finite(r) && r>=0,
|
assert( is_finite(r) && r>=0,
|
||||||
"The query radius should be a positive number." )
|
"The query radius should be a positive number." )
|
||||||
let(
|
let(
|
||||||
|
@ -365,13 +369,12 @@ function vector_search(query, r, target) =
|
||||||
"The target should be a list of points or a search tree compatible with the query." )
|
"The target should be a list of points or a search tree compatible with the query." )
|
||||||
let(
|
let(
|
||||||
dim = tgpts ? len(target[0]) : len(target[0][0]),
|
dim = tgpts ? len(target[0]) : len(target[0][0]),
|
||||||
simple = is_vector(query, dim),
|
simple = is_vector(query, dim)
|
||||||
mult = !simple && is_matrix(query,undef,dim)
|
)
|
||||||
)
|
assert( simple || is_matrix(query,undef,dim),
|
||||||
assert( simple || mult,
|
|
||||||
"The query points should be a list of points compatible with the target point list.")
|
"The query points should be a list of points compatible with the target point list.")
|
||||||
tgpts
|
tgpts
|
||||||
? len(target)<200
|
? len(target)<=400
|
||||||
? simple ? [for(i=idx(target)) if(norm(target[i]-query)<r) i ] :
|
? simple ? [for(i=idx(target)) if(norm(target[i]-query)<r) i ] :
|
||||||
[for(q=query) [for(i=idx(target)) if(norm(target[i]-q)<r) i ] ]
|
[for(q=query) [for(i=idx(target)) if(norm(target[i]-q)<r) i ] ]
|
||||||
: let( tree = _bt_tree(target, count(len(target)), leafsize=25) )
|
: let( tree = _bt_tree(target, count(len(target)), leafsize=25) )
|
||||||
|
@ -382,7 +385,7 @@ function vector_search(query, r, target) =
|
||||||
|
|
||||||
|
|
||||||
//Ball tree search
|
//Ball tree search
|
||||||
function _bt_search(query, r, points, tree) = //echo(tree)
|
function _bt_search(query, r, points, tree) =
|
||||||
assert( is_list(tree)
|
assert( is_list(tree)
|
||||||
&& ( ( len(tree)==1 && is_list(tree[0]) )
|
&& ( ( len(tree)==1 && is_list(tree[0]) )
|
||||||
|| ( len(tree)==4 && is_num(tree[0]) && is_num(tree[1]) ) ),
|
|| ( len(tree)==4 && is_num(tree[0]) && is_num(tree[1]) ) ),
|
||||||
|
@ -413,25 +416,32 @@ function _bt_search(query, r, points, tree) = //echo(tree)
|
||||||
// for high data dimensions. This data structure is useful when you will be
|
// for high data dimensions. This data structure is useful when you will be
|
||||||
// performing many searches of the same data, so that the cost of constructing
|
// performing many searches of the same data, so that the cost of constructing
|
||||||
// the tree is justified. (See https://en.wikipedia.org/wiki/Ball_tree)
|
// the tree is justified. (See https://en.wikipedia.org/wiki/Ball_tree)
|
||||||
|
// For a small lists of points, the search with a tree may be more expensive
|
||||||
|
// than direct comparisons. The argument `treemin` sets the minimum length of
|
||||||
|
// point set for which a tree search will be done by `vector_search`.
|
||||||
|
// For an empty list of points it returns an empty list.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// points = list of points to store in the search tree.
|
// points = list of points to store in the search tree.
|
||||||
// leafsize = the size of the tree leaves. Default: 25
|
// leafsize = the size of the tree leaves. Default: 25
|
||||||
|
// treemin = the minimum size of the point list for which a tree search is done. Default: 400
|
||||||
// Example: A set of four queries to find points within 1 unit of the query. The circles show the search region and all have radius 1.
|
// Example: A set of four queries to find points within 1 unit of the query. The circles show the search region and all have radius 1.
|
||||||
// $fn=32;
|
// $fn=32;
|
||||||
// k = 2000;
|
// k = 2000;
|
||||||
// points = array_group(rands(0,10,k*2,seed=13333),2);
|
// points = random_points(k, scale=10, dim=2,seed=13333);
|
||||||
// queries = [for(i=[3,7],j=[3,7]) [i,j]];
|
// queries = [for(i=[3,7],j=[3,7]) [i,j]];
|
||||||
// search_tree = vector_search_tree(points);
|
// search_tree = vector_search_tree(points);
|
||||||
// search_ind = vector_tree_search(search_tree, queries, 1);
|
// search_ind = vector_search(queries,1,search_tree);
|
||||||
// move_copies(points) circle(r=.08);
|
// move_copies(points) circle(r=.08);
|
||||||
// for(i=idx(queries)){
|
// for(i=idx(queries)){
|
||||||
// color("blue") stroke(move(queries[i],circle(r=1)), closed=true, width=.08);
|
// color("blue") stroke(move(queries[i],circle(r=1)), closed=true, width=.08);
|
||||||
// color("red") move_copies(select(points, search_ind[i])) circle(r=.08); }
|
// color("red") move_copies(select(points, search_ind[i])) circle(r=.08);
|
||||||
// }
|
// }
|
||||||
function vector_search_tree(points, leafsize=25) =
|
function vector_search_tree(points, leafsize=25, treemin=400) =
|
||||||
|
points==[] ? [] :
|
||||||
assert( is_matrix(points), "The input list entries should be points." )
|
assert( is_matrix(points), "The input list entries should be points." )
|
||||||
assert( is_int(leafsize) && leafsize>=1,
|
assert( is_int(leafsize) && leafsize>=1,
|
||||||
"The tree leaf size should be an integer greater than zero.")
|
"The tree leaf size should be an integer greater than zero.")
|
||||||
|
len(points)<treemin ? points :
|
||||||
[ points, _bt_tree(points, count(len(points)), leafsize) ];
|
[ points, _bt_tree(points, count(len(points)), leafsize) ];
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue