mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2025-01-30 08:19:36 +00:00
Speed improvement "icosa2" for spheroid
This commit is contained in:
parent
a268793cce
commit
f9dd6e7235
1 changed files with 38 additions and 3 deletions
|
@ -1617,8 +1617,8 @@ function sphere(r, d, circum=false, style="orig", anchor=CENTER, spin=0, orient=
|
|||
// - `style="orig"` constructs a sphere the same way that the OpenSCAD `sphere()` built-in does.
|
||||
// - `style="aligned"` constructs a sphere where, if `$fn` is a multiple of 4, it has vertices at all axis maxima and minima. ie: its bounding box is exactly the sphere diameter in length on all three axes. This is the default.
|
||||
// - `style="stagger"` forms a sphere where all faces are triangular, but the top and bottom poles have thinner triangles.
|
||||
// - `style="octa"` forms a sphere by subdividing an octahedron (8-sided platonic solid). This makes more uniform faces over the entirety of the sphere, and guarantees the bounding box is the sphere diameter in size on all axes. The effective `$fn` value is quantized to a multiple of 4, though. This is used in constructing rounded corners for various other shapes.
|
||||
// - `style="icosa"` forms a sphere by subdividing an icosahedron (20-sided platonic solid). This makes even more uniform faces over the entirety of the sphere. The effective `$fn` value is quantized to a multiple of 5, though.
|
||||
// - `style="octa"` forms a sphere by subdividing an octahedron (8-sided platonic solid). This makes more uniform faces over the entirety of the sphere, and guarantees the bounding box is the sphere diameter in size on all axes. The effective `$fn` value is quantized to a multiple of 4. This is used in constructing rounded corners for various other shapes.
|
||||
// - `style="icosa"` forms a sphere by subdividing an icosahedron (20-sided platonic solid). This makes even more uniform faces over the entirety of the sphere. The effective `$fn` value is quantized to a multiple of 5.
|
||||
// Arguments:
|
||||
// r = Radius of the spheroid.
|
||||
// style = The style of the spheroid's construction. One of "orig", "aligned", "stagger", "octa", or "icosa". Default: "aligned"
|
||||
|
@ -1680,6 +1680,12 @@ module spheroid(r, style="aligned", d, circum=false, anchor=CENTER, spin=0, orie
|
|||
}
|
||||
|
||||
|
||||
// p is a list of 3 points defining a triangle in any dimension. N is the number of extra points
|
||||
// to add, so output triangle has N+2 points on each side.
|
||||
function _subsample_triangle(p,N) =
|
||||
[for(i=[0:N+1]) [for (j=[0:N+1-i]) unit(lerp(p[0],p[1],i/(N+1)) + (p[2]-p[0])*j/(N+1))]];
|
||||
|
||||
|
||||
function spheroid(r, style="aligned", d, circum=false, anchor=CENTER, spin=0, orient=UP) =
|
||||
let(
|
||||
r = get_radius(r=r, d=d, dflt=1),
|
||||
|
@ -1688,7 +1694,36 @@ function spheroid(r, style="aligned", d, circum=false, anchor=CENTER, spin=0, or
|
|||
octa_steps = round(max(4,hsides)/4),
|
||||
icosa_steps = round(max(5,hsides)/5),
|
||||
rr = circum? (r / cos(90/vsides) / cos(180/hsides)) : r,
|
||||
stagger = style=="stagger",
|
||||
stagger = style=="stagger"
|
||||
)
|
||||
style=="icosa2" ? // subdivide faces of an icosahedron and project them onto a sphere
|
||||
let(
|
||||
N = icosa_steps-1,
|
||||
// construct an icosahedron
|
||||
icovert=[ for(i=[-1,1], j=[-1,1]) each [[0,i,j*PHI], [i,j*PHI,0], [j*PHI,0,i]]],
|
||||
icoface = hull(icovert),
|
||||
// Subsample face 0 of the icosahedron
|
||||
face0 = select(icovert,icoface[0]),
|
||||
sampled = rr * _subsample_triangle(face0,N),
|
||||
dir0 = mean(face0),
|
||||
point0 = face0[0]-dir0,
|
||||
// Make a rotated copy of the subsampled triangle on each icosahedral face
|
||||
tri_list = [sampled,
|
||||
for(i=[1:1:len(icoface)-1])
|
||||
let(face = select(icovert,icoface[i]))
|
||||
apply(frame_map(z=mean(face),x=face[0]-mean(face))
|
||||
*frame_map(z=dir0,x=point0,reverse=true),
|
||||
sampled)],
|
||||
// faces for the first triangle group
|
||||
faces = vnf_tri_array(tri_list[0])[1],
|
||||
size = repeat((N+2)*(N+3)/2,3),
|
||||
// Expand to full face list
|
||||
fullfaces = [for(i=idx(tri_list)) each [for(f=faces) f+i*size]],
|
||||
fullvert = flatten(flatten(tri_list)) // eliminate triangle structure
|
||||
)
|
||||
[reorient(anchor,spin,orient, r=r, p=fullvert), fullfaces]
|
||||
:
|
||||
let(
|
||||
verts = style=="orig"? [
|
||||
for (i=[0:1:vsides-1]) let(phi = (i+0.5)*180/(vsides))
|
||||
for (j=[0:1:hsides-1]) let(theta = j*360/hsides)
|
||||
|
|
Loading…
Reference in a new issue