mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2025-01-06 12:19:47 +00:00
Merge pull request #144 from adrianVmariano/master
Misc tweaks/bug fixes
This commit is contained in:
commit
e61960cfee
6 changed files with 64 additions and 27 deletions
26
common.scad
26
common.scad
|
@ -81,6 +81,11 @@ function is_integer(n) = is_num(n) && n == round(n);
|
||||||
function is_nan(x) = (x!=x);
|
function is_nan(x) = (x!=x);
|
||||||
|
|
||||||
|
|
||||||
|
// Function: is_range()
|
||||||
|
// Description:
|
||||||
|
// Returns true if its argument is a range
|
||||||
|
function is_range(x) = is_num(x[0]) && !is_list(x);
|
||||||
|
|
||||||
// Function: is_list_of()
|
// Function: is_list_of()
|
||||||
// Usage:
|
// Usage:
|
||||||
// is_list_of(list, pattern)
|
// is_list_of(list, pattern)
|
||||||
|
@ -157,6 +162,25 @@ function first_defined(v,recursive=false,_i=0) =
|
||||||
)? first_defined(v,recursive=recursive,_i=_i+1) : v[_i];
|
)? first_defined(v,recursive=recursive,_i=_i+1) : v[_i];
|
||||||
|
|
||||||
|
|
||||||
|
// Function: one_defined()
|
||||||
|
// Usage:
|
||||||
|
// one_defined(vars, names, [required])
|
||||||
|
// Description:
|
||||||
|
// Examines the input list `vars` and returns the entry which is not `undef`. If more
|
||||||
|
// than one entry is `undef` then issues an assertion specifying "Must define exactly one of" followed
|
||||||
|
// by the defined items from the `names` parameter. If `required` is set to false then it is OK if all of the
|
||||||
|
// entries of `vars` are undefined, and in this case, `undef` is returned.
|
||||||
|
// Example:
|
||||||
|
// length = one_defined([length,L,l], ["length","L","l"]);
|
||||||
|
function one_defined(vars, names, required=true) =
|
||||||
|
assert(len(vars)==len(names))
|
||||||
|
let (
|
||||||
|
ok = num_defined(vars)==1 || (!required && num_defined(vars)==0)
|
||||||
|
)
|
||||||
|
assert(ok,str("Must define ",required?"exactly":"at most"," one of ",[for(i=[0:len(vars)]) if (is_def(vars[i])) names[i]]))
|
||||||
|
first_defined(vars);
|
||||||
|
|
||||||
|
|
||||||
// Function: num_defined()
|
// Function: num_defined()
|
||||||
// Description: Counts how many items in list `v` are not `undef`.
|
// Description: Counts how many items in list `v` are not `undef`.
|
||||||
function num_defined(v,_i=0,_cnt=0) = _i>=len(v)? _cnt : num_defined(v,_i+1,_cnt+(is_undef(v[_i])? 0 : 1));
|
function num_defined(v,_i=0,_cnt=0) = _i>=len(v)? _cnt : num_defined(v,_i+1,_cnt+(is_undef(v[_i])? 0 : 1));
|
||||||
|
@ -180,6 +204,8 @@ function any_defined(v,recursive=false) = first_defined(v,recursive=recursive) !
|
||||||
function all_defined(v,recursive=false) = max([for (x=v) is_undef(x)||(recursive&&is_list(x)&&!all_defined(x))? 1 : 0])==0;
|
function all_defined(v,recursive=false) = max([for (x=v) is_undef(x)||(recursive&&is_list(x)&&!all_defined(x))? 1 : 0])==0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Section: Argument Helpers
|
// Section: Argument Helpers
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -100,6 +100,7 @@ function path4d(points, fill=0) =
|
||||||
result + repeat(addition, len(result));
|
result + repeat(addition, len(result));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Section: Coordinate Systems
|
// Section: Coordinate Systems
|
||||||
|
|
||||||
// Function: polar_to_xy()
|
// Function: polar_to_xy()
|
||||||
|
@ -174,7 +175,7 @@ function project_plane(point, a, b, c) =
|
||||||
v = unit(c-a),
|
v = unit(c-a),
|
||||||
n = unit(cross(u,v)),
|
n = unit(cross(u,v)),
|
||||||
w = unit(cross(n,u)),
|
w = unit(cross(n,u)),
|
||||||
relpoint = is_vector(point)? (point-a) : move(-a,p=point)
|
relpoint = apply(move(-a),point)
|
||||||
) relpoint * transpose([w,u]);
|
) relpoint * transpose([w,u]);
|
||||||
|
|
||||||
|
|
||||||
|
@ -205,7 +206,7 @@ function lift_plane(point, a, b, c) =
|
||||||
n = unit(cross(u,v)),
|
n = unit(cross(u,v)),
|
||||||
w = unit(cross(n,u)),
|
w = unit(cross(n,u)),
|
||||||
remapped = point*[w,u]
|
remapped = point*[w,u]
|
||||||
) is_vector(remapped)? (a+remapped) : move(a,p=remapped);
|
) apply(move(a),remapped);
|
||||||
|
|
||||||
|
|
||||||
// Function: cylindrical_to_xyz()
|
// Function: cylindrical_to_xyz()
|
||||||
|
|
11
math.scad
11
math.scad
|
@ -26,11 +26,14 @@ NAN = acos(2); // The value `nan`, useful for comparisons.
|
||||||
// Usage:
|
// Usage:
|
||||||
// sqr(x);
|
// sqr(x);
|
||||||
// Description:
|
// Description:
|
||||||
// Returns the square of the given number.
|
// Returns the square of the given number or entries in list
|
||||||
// Examples:
|
// Examples:
|
||||||
// sqr(3); // Returns: 9
|
// sqr(3); // Returns: 9
|
||||||
// sqr(-4); // Returns: 16
|
// sqr(-4); // Returns: 16
|
||||||
function sqr(x) = x*x;
|
// sqr([3,4]); // Returns: [9,16]
|
||||||
|
// sqr([[1,2],[3,4]]); // Returns [[1,4],[9,16]]
|
||||||
|
// sqr([[1,2],3]); // Returns [[1,4],9]
|
||||||
|
function sqr(x) = is_list(x) ? [for(val=x) sqr(val)] : x*x;
|
||||||
|
|
||||||
|
|
||||||
// Function: log2()
|
// Function: log2()
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
include <BOSL2/hull.scad>
|
include <hull.scad>
|
||||||
|
|
||||||
|
|
||||||
// CommonCode:
|
// CommonCode:
|
||||||
|
@ -320,14 +320,14 @@ module regular_polyhedron(
|
||||||
in_radius = entry[5];
|
in_radius = entry[5];
|
||||||
if (draw){
|
if (draw){
|
||||||
if (rounding==0)
|
if (rounding==0)
|
||||||
polyhedron(move(p=scaled_points, translation), faces = face_triangles);
|
polyhedron(move(translation, p=scaled_points), faces = face_triangles);
|
||||||
else {
|
else {
|
||||||
fn = segs(rounding);
|
fn = segs(rounding);
|
||||||
rounding = rounding/cos(180/fn);
|
rounding = rounding/cos(180/fn);
|
||||||
adjusted_scale = 1 - rounding / in_radius;
|
adjusted_scale = 1 - rounding / in_radius;
|
||||||
minkowski(){
|
minkowski(){
|
||||||
sphere(r=rounding, $fn=fn);
|
sphere(r=rounding, $fn=fn);
|
||||||
polyhedron(move(p=adjusted_scale*scaled_points,translation), faces = face_triangles);
|
polyhedron(move(translation,p=adjusted_scale*scaled_points), faces = face_triangles);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -335,13 +335,13 @@ module regular_polyhedron(
|
||||||
maxrange = repeat ? len(faces)-1 : $children-1;
|
maxrange = repeat ? len(faces)-1 : $children-1;
|
||||||
for(i=[0:1:maxrange]) {
|
for(i=[0:1:maxrange]) {
|
||||||
// Would like to orient so an edge (longest edge?) is parallel to x axis
|
// Would like to orient so an edge (longest edge?) is parallel to x axis
|
||||||
facepts = move(p=select(scaled_points, faces[i]), translation);
|
facepts = move(translation, p=select(scaled_points, faces[i]));
|
||||||
center = mean(facepts);
|
center = mean(facepts);
|
||||||
rotatedface = rot(p=move(p=facepts,-center), from=face_normals[i], to=[0,0,1]);
|
rotatedface = rot(from=face_normals[i], to=[0,0,1], p=move(-center, p=facepts));
|
||||||
clockwise = sortidx([for(pt=rotatedface) -atan2(pt.y,pt.x)]);
|
clockwise = sortidx([for(pt=rotatedface) -atan2(pt.y,pt.x)]);
|
||||||
$face = rotate_children?
|
$face = rotate_children?
|
||||||
path2d(select(rotatedface,clockwise)) :
|
path2d(select(rotatedface,clockwise)) :
|
||||||
select(move(p=facepts,-center), clockwise);
|
select(move(-center,p=facepts), clockwise);
|
||||||
$faceindex = i;
|
$faceindex = i;
|
||||||
$center = -translation-center;
|
$center = -translation-center;
|
||||||
translate(center)
|
translate(center)
|
||||||
|
@ -549,6 +549,7 @@ _stellated_polyhedra_ = [
|
||||||
// Calculate characteristics of regular polyhedra or the selection set for regular_polyhedron().
|
// Calculate characteristics of regular polyhedra or the selection set for regular_polyhedron().
|
||||||
// Invoke with the same arguments used by regular_polyhedron() and use the `info` argument to
|
// Invoke with the same arguments used by regular_polyhedron() and use the `info` argument to
|
||||||
// request the desired return value. Set `info` to:
|
// request the desired return value. Set `info` to:
|
||||||
|
// * `"vnf"`: vnf for the selected polyhedron
|
||||||
// * `"vertices"`: vertex list for the selected polyhedron
|
// * `"vertices"`: vertex list for the selected polyhedron
|
||||||
// * `"faces"`: list of faces for the selected polyhedron, where each entry on the list is a list of point index values to be used with the vertex list
|
// * `"faces"`: list of faces for the selected polyhedron, where each entry on the list is a list of point index values to be used with the vertex list
|
||||||
// * `"face normals"`: list of normal vectors for each face
|
// * `"face normals"`: list of normal vectors for each face
|
||||||
|
@ -688,8 +689,16 @@ function regular_polyhedron_info(
|
||||||
face_normals = rot(p=faces_normals_vertices[1], from=down_direction, to=[0,0,-1]),
|
face_normals = rot(p=faces_normals_vertices[1], from=down_direction, to=[0,0,-1]),
|
||||||
side_length = scalefactor * entry[edgelen]
|
side_length = scalefactor * entry[edgelen]
|
||||||
)
|
)
|
||||||
info == "fullentry" ? [scaled_points, translation,stellate ? faces : face_triangles, faces, face_normals, side_length*entry[in_radius]] :
|
info == "fullentry" ? [
|
||||||
info == "vertices" ? move(p=scaled_points,translation) :
|
scaled_points,
|
||||||
|
translation,
|
||||||
|
stellate ? faces : face_triangles,
|
||||||
|
faces,
|
||||||
|
face_normals,
|
||||||
|
side_length*entry[in_radius]
|
||||||
|
] :
|
||||||
|
info == "vnf" ? [move(translation,p=scaled_points), stellate ? faces : face_triangles] :
|
||||||
|
info == "vertices" ? move(translation,p=scaled_points) :
|
||||||
info == "faces" ? faces :
|
info == "faces" ? faces :
|
||||||
info == "face normals" ? face_normals :
|
info == "face normals" ? face_normals :
|
||||||
info == "in_radius" ? side_length * entry[in_radius] :
|
info == "in_radius" ? side_length * entry[in_radius] :
|
||||||
|
@ -766,7 +775,7 @@ function _facenormal(pts, face) = unit(cross(pts[face[2]]-pts[face[0]], pts[face
|
||||||
|
|
||||||
function _full_faces(pts,faces) =
|
function _full_faces(pts,faces) =
|
||||||
let(
|
let(
|
||||||
normals = [for(face=faces) vquant(_facenormal(pts,face),1e-12)],
|
normals = [for(face=faces) quant(_facenormal(pts,face),1e-12)],
|
||||||
groups = _unique_groups(normals),
|
groups = _unique_groups(normals),
|
||||||
faces = [for(entry=groups) unique(flatten(select(faces, entry)))],
|
faces = [for(entry=groups) unique(flatten(select(faces, entry)))],
|
||||||
facenormals = [for(entry=groups) normals[entry[0]]]
|
facenormals = [for(entry=groups) normals[entry[0]]]
|
||||||
|
|
|
@ -95,13 +95,6 @@ function vdiv(v1, v2) = [for (i = [0:1:len(v1)-1]) v1[i]/v2[i]];
|
||||||
function vabs(v) = [for (x=v) abs(x)];
|
function vabs(v) = [for (x=v) abs(x)];
|
||||||
|
|
||||||
|
|
||||||
// Function: vsqr()
|
|
||||||
// Usage:
|
|
||||||
// x = vsqr(v);
|
|
||||||
// Description:
|
|
||||||
// Returns a vector where each value in the original given vector is squared.
|
|
||||||
function vsqr(v) = [for(i=v) i*i];
|
|
||||||
|
|
||||||
|
|
||||||
// Function: unit()
|
// Function: unit()
|
||||||
// Description:
|
// Description:
|
||||||
|
|
15
vnf.scad
15
vnf.scad
|
@ -349,7 +349,9 @@ module vnf_polyhedron(vnf, convexity=2) {
|
||||||
// Usage:
|
// Usage:
|
||||||
// vol = vnf_volume(vnf);
|
// vol = vnf_volume(vnf);
|
||||||
// Description:
|
// Description:
|
||||||
// Returns the volume enclosed by the given manifold VNF. May return a negative value if faces are reversed.
|
// Returns the volume enclosed by the given manifold VNF. The VNF must describe a valid polyhedron with consistent face direction and
|
||||||
|
// no holes; otherwise the results are undefined. Returns a positive volume if face direction is clockwise and a negative volume
|
||||||
|
// if face direction is counter-clockwise.
|
||||||
function vnf_volume(vnf) =
|
function vnf_volume(vnf) =
|
||||||
let(vnf = vnf_triangulate(vnf))
|
let(vnf = vnf_triangulate(vnf))
|
||||||
sum([
|
sum([
|
||||||
|
@ -364,7 +366,10 @@ function vnf_volume(vnf) =
|
||||||
// Usage:
|
// Usage:
|
||||||
// vol = vnf_centroid(vnf);
|
// vol = vnf_centroid(vnf);
|
||||||
// Description:
|
// Description:
|
||||||
// Returns the centroid of the given manifold VNF.
|
// Returns the centroid of the given manifold VNF. The VNF must describe a valid polyhedron with consistent face direction and
|
||||||
|
// no holes; otherwise the results are undefined.
|
||||||
|
|
||||||
|
// Algorithm from: https://wwwf.imperial.ac.uk/~rn/centroid.pdf
|
||||||
function vnf_centroid(vnf) =
|
function vnf_centroid(vnf) =
|
||||||
let(
|
let(
|
||||||
vnf = vnf_triangulate(vnf),
|
vnf = vnf_triangulate(vnf),
|
||||||
|
@ -376,9 +381,9 @@ function vnf_centroid(vnf) =
|
||||||
) [
|
) [
|
||||||
face[0] * n,
|
face[0] * n,
|
||||||
vmul(n,
|
vmul(n,
|
||||||
vsqr(face[0] + face[1]) +
|
sqr(face[0] + face[1]) +
|
||||||
vsqr(face[0] + face[2]) +
|
sqr(face[0] + face[2]) +
|
||||||
vsqr(face[1] + face[2])
|
sqr(face[1] + face[2])
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
])
|
])
|
||||||
|
|
Loading…
Reference in a new issue