mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2024-12-29 00:09:41 +00:00
Fixed bugs in hull_points, added seeds to tests, added seed parm to shuffle()
This commit is contained in:
parent
e10a70fc98
commit
a495528398
5 changed files with 42 additions and 35 deletions
11
arrays.scad
11
arrays.scad
|
@ -672,15 +672,20 @@ function _valid_idx(idx,imin,imax) =
|
|||
|
||||
|
||||
// Function: shuffle()
|
||||
// Usage:
|
||||
// shuffled = shuffle(list,[seed])
|
||||
// Description:
|
||||
// Shuffles the input list into random order.
|
||||
// If given a string, shuffles the characters within the string.
|
||||
function shuffle(list) =
|
||||
// If you give a numeric seed value then the permutation
|
||||
// will be repeatable.
|
||||
function shuffle(list,seed) =
|
||||
assert(is_list(list)||is_string(list), "Invalid input." )
|
||||
is_string(list)? str_join(shuffle([for (x = list) x])) :
|
||||
is_string(list)? str_join(shuffle([for (x = list) x],seed=seed)) :
|
||||
len(list)<=1 ? list :
|
||||
let (
|
||||
rval = rands(0,1,len(list)),
|
||||
rval = is_num(seed) ? rands(0,1,len(list),seed_value=seed)
|
||||
: rands(0,1,len(list)),
|
||||
left = [for (i=[0:len(list)-1]) if (rval[i]< 0.5) list[i]],
|
||||
right = [for (i=[0:len(list)-1]) if (rval[i]>=0.5) list[i]]
|
||||
)
|
||||
|
|
43
hull.scad
43
hull.scad
|
@ -41,10 +41,10 @@ function hull(points) =
|
|||
// If given a list of 2D points, creates a 2D convex hull polygon that encloses all those points.
|
||||
// If given a list of 3D points, creates a 3D polyhedron that encloses all the points. This should
|
||||
// handle about 4000 points in slow mode. If `fast` is set to true, this should be able to handle
|
||||
// far more.
|
||||
// far more. When fast mode is off, 3d hulls that lie in a plane will produce a single face of a polyhedron, which can be viewed in preview but will not render.
|
||||
// Arguments:
|
||||
// points = The list of points to form a hull around.
|
||||
// fast = If true, uses a faster cheat that may handle more points, but also may emit warnings that can stop your script if you have "Halt on first warning" enabled. Default: false
|
||||
// fast = If true for 3d case, uses a faster cheat that may handle more points, but also may emit warnings that can stop your script if you have "Halt on first warning" enabled. Ignored for the 2d case. Default: false
|
||||
// Example(2D):
|
||||
// pts = [[-10,-10], [0,10], [10,10], [12,-10]];
|
||||
// hull_points(pts);
|
||||
|
@ -52,27 +52,26 @@ function hull(points) =
|
|||
// pts = [for (phi = [30:60:150], theta = [0:60:359]) spherical_to_xyz(10, theta, phi)];
|
||||
// hull_points(pts);
|
||||
module hull_points(points, fast=false) {
|
||||
if (points) {
|
||||
assert(is_list(points[0]));
|
||||
if (fast) {
|
||||
if (len(points[0]) == 2) {
|
||||
hull() polygon(points=points);
|
||||
} else {
|
||||
extra = len(points)%3;
|
||||
faces = concat(
|
||||
[[for(i=[0:1:extra+2])i]],
|
||||
[for(i=[extra+3:3:len(points)-3])[i,i+1,i+2]]
|
||||
);
|
||||
hull() polyhedron(points=points, faces=faces);
|
||||
}
|
||||
} else {
|
||||
perim = hull(points);
|
||||
if (is_num(perim[0])) {
|
||||
polygon(points=points, paths=[perim]);
|
||||
} else {
|
||||
polyhedron(points=points, faces=perim);
|
||||
}
|
||||
assert(is_path(points))
|
||||
assert(len(points)>=3, "Point list must contain 3 points")
|
||||
if (len(points[0])==2)
|
||||
hull() polygon(points=points);
|
||||
else {
|
||||
if (fast) {
|
||||
extra = len(points)%3;
|
||||
faces = [
|
||||
[for(i=[0:1:extra+2])i], // If vertex count not divisible by 3, combine extras with first 3
|
||||
for(i=[extra+3:3:len(points)-3])[i,i+1,i+2]
|
||||
];
|
||||
hull() polyhedron(points=points, faces=faces);
|
||||
} else {
|
||||
faces = hull(points);
|
||||
if (is_num(faces[0])){
|
||||
if (len(faces)<=2) echo("Hull contains only two points");
|
||||
else polyhedron(points=points, faces=[faces]);
|
||||
}
|
||||
else polyhedron(points=points, faces=faces);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -268,13 +268,16 @@ test_enumerate();
|
|||
|
||||
module test_shuffle() {
|
||||
nums1 = [for (i=list_range(100)) i];
|
||||
nums2 = shuffle(nums1);
|
||||
nums3 = shuffle(nums2);
|
||||
assert(len(nums2)==len(nums1));
|
||||
assert(len(nums3)==len(nums2));
|
||||
nums2 = shuffle(nums1,33);
|
||||
nums3 = shuffle(nums2,99);
|
||||
assert(sort(nums2)==nums1);
|
||||
assert(sort(nums3)==nums1);
|
||||
assert(nums1!=nums2);
|
||||
assert(nums2!=nums3);
|
||||
assert(nums1!=nums3);
|
||||
str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
shufstr = shuffle(str,12);
|
||||
assert(shufstr != str && sort(shufstr)==str);
|
||||
}
|
||||
test_shuffle();
|
||||
|
||||
|
|
|
@ -112,8 +112,8 @@ function info_str(list,i=0,string=chr(10)) =
|
|||
|
||||
|
||||
module test_closest_point_on_plane(){
|
||||
plane = rands(-5,5,4)+[10,0,0,0];
|
||||
point = rands(-1,1,3);
|
||||
plane = rands(-5,5,4,seed=175)+[10,0,0,0];
|
||||
point = rands(-1,1,3,seed=477);
|
||||
point2 = closest_point_on_plane(plane,point);
|
||||
assert_approx(norm(point-point2), abs(distance_from_plane(plane,point)));
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ module test_closest_point_on_plane(){
|
|||
|
||||
|
||||
module test_normalize_plane(){
|
||||
plane = rands(-5,5,4)+[10,0,0,0];
|
||||
plane = rands(-5,5,4,seed=333)+[10,0,0,0];
|
||||
plane2 = normalize_plane(plane);
|
||||
assert_approx(norm(point3d(plane2)),1);
|
||||
assert_approx(plane*plane2[3],plane2*plane[3]);
|
||||
|
@ -129,7 +129,7 @@ module test_normalize_plane(){
|
|||
*test_normalize_plane();
|
||||
|
||||
module test_plane_line_intersection(){
|
||||
line = [rands(-1,1,3),rands(-1,1,3)+[2,0,0]];
|
||||
line = [rands(-1,1,3,seed=74),rands(-1,1,3,seed=99)+[2,0,0]];
|
||||
plane1 = plane_from_normal(line[1]-line[0],2*line[0]-line[1]); // plane disjoint from segment
|
||||
plane2 = plane_from_normal(line[1]-line[0],(line[0]+line[1])/2); // through middle point of line
|
||||
plane3 = plane3pt(line[1],line[0], rands(-1,1,3)+[0,3,0]); // containing line
|
||||
|
|
|
@ -238,7 +238,7 @@ test_approx();
|
|||
|
||||
|
||||
module test_min_index() {
|
||||
vals = rands(-100,100,100);
|
||||
vals = rands(-100,100,100,seed=75);
|
||||
minval = min(vals);
|
||||
minidx = min_index(vals);
|
||||
assert_equal(vals[minidx], minval);
|
||||
|
@ -254,7 +254,7 @@ test_min_index();
|
|||
|
||||
|
||||
module test_max_index() {
|
||||
vals = rands(-100,100,100);
|
||||
vals = rands(-100,100,100,seed=97);
|
||||
maxval = max(vals);
|
||||
maxidx = max_index(vals);
|
||||
assert_equal(vals[maxidx], maxval);
|
||||
|
|
Loading…
Reference in a new issue