Merge pull request #776 from adrianVmariano/master

sphere fixes and tests
This commit is contained in:
Revar Desmera 2022-02-04 19:57:49 -08:00 committed by GitHub
commit a1809feefe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 43 additions and 22 deletions

View file

@ -1655,10 +1655,10 @@ function sphere(r, d, circum=false, style="orig", anchor=CENTER, spin=0, orient=
// - `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. 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. This makes even more uniform faces over the whole sphere. The effective `$fn` value is quantized to a multiple of 5.
// - `style="icosa"` forms a sphere by subdividing an icosahedron. This makes even more uniform faces over the whole sphere. The effective `$fn` value is quantized to a multiple of 5. This sphere has a guaranteed bounding box when `$fn` is a multiple of 10.
// .
// By default the object spheroid() produces is a polyhedron whose vertices all lie on the requested sphere. This means
// it is an inscribed sphere, which sits inside the requested sphere.
// the approximating polyhedron is inscribed in the sphere.
// The `circum` argument requests a circumscribing sphere, where the true sphere is
// inside and tangent to all the faces of the approximating polyhedron. To produce
// a circumscribing polyhedron, we use the dual polyhedron of the basic form. The dual of a polyhedron is
@ -1667,13 +1667,19 @@ function sphere(r, d, circum=false, style="orig", anchor=CENTER, spin=0, orient=
// these styles then the polyhedron will look the same as the default inscribing form. But for the other
// styles, the duals are completely different from their parents, and from each other. Generation of the circumscribed versions (duals)
// for "octa" and "icosa" is fast if you use the module form but can be very slow (several minutes) if you use the functional
// form and choose a large $fn value.
// form and choose a large $fn value.
// .
// With style="align", the circumscribed sphere has its maximum radius on the X and Y axes
// but is undersized on the Z axis. With style="octa" the circumscribed sphere has faces at each axis, so
// the radius on the axes is equal to the specified radius, which is the *minimum* radius of the circumscribed sphere.
// The same thing is true for style="icosa" when $fn is a multiple of 10. This would enable you to create spherical
// holes with guaranteed on-axis dimensions.
// Arguments:
// r = Radius of the spheroid.
// style = The style of the spheroid's construction. One of "orig", "aligned", "stagger", "octa", or "icosa". Default: "aligned"
// ---
// d = Diameter of the spheroid.
// circum = If true, the spheroid is produced in a style where it circumscribes the sphere of the requested size. Otherwise inscribes. Note that for some styles, the circumscribed sphere looks different than the inscribed sphere. Default: false (inscribes)
// circum = If true, the approximate sphere circumscribes the true sphere of the requested size. Otherwise inscribes. Note that for some styles, the circumscribed sphere looks different than the inscribed sphere. Default: false (inscribes)
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
@ -1819,7 +1825,7 @@ function spheroid(r, style="aligned", d, circum=false, anchor=CENTER, spin=0, or
*frame_map(z=dir0,x=point0,reverse=true),
sampled)],
// faces for the first triangle group
faces = vnf_tri_array(tri_list[0])[1],
faces = vnf_tri_array(tri_list[0],reverse=true)[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]],
@ -1871,7 +1877,7 @@ function spheroid(r, style="aligned", d, circum=false, anchor=CENTER, spin=0, or
: assert(in_list(style,["orig","aligned","stagger","octa","icosa"])),
lv = len(verts),
faces = circum && style=="stagger" ?
let(ptcount=2*hsides,ff=echo(verts))
let(ptcount=2*hsides)
[
[for(i=[ptcount-2:-2:0]) i],
for(j=[0:hsides-1])

View file

@ -26,13 +26,7 @@ test_cylinder();
module test_sphere() {
$fn=6;
assert_approx(sphere(r=40), [[[20,0,34.6410161514],[10,17.3205080757,34.6410161514],[-10,17.3205080757,34.6410161514],[-20,0,34.6410161514],[-10,-17.3205080757,34.6410161514],[10,-17.3205080757,34.6410161514],[40,0,0],[20,34.6410161514,0],[-20,34.6410161514,0],[-40,0,0],[-20,-34.6410161514,0],[20,-34.6410161514,0],[20,0,-34.6410161514],[10,17.3205080757,-34.6410161514],[-10,17.3205080757,-34.6410161514],[-20,0,-34.6410161514],[-10,-17.3205080757,-34.6410161514],[10,-17.3205080757,-34.6410161514]],[[5,4,3,2,1,0],[12,13,14,15,16,17],[6,0,1],[6,1,7],[7,1,2],[7,2,8],[8,2,3],[8,3,9],[9,3,4],[9,4,10],[10,4,5],[10,5,11],[11,5,0],[11,0,6],[12,6,7],[12,7,13],[13,7,8],[13,8,14],[14,8,9],[14,9,15],[15,9,10],[15,10,16],[16,10,11],[16,11,17],[17,11,6],[17,6,12]]]);
assert_approx(sphere(r=40,style="orig"), [[[20,0,34.6410161514],[10,17.3205080757,34.6410161514],[-10,17.3205080757,34.6410161514],[-20,0,34.6410161514],[-10,-17.3205080757,34.6410161514],[10,-17.3205080757,34.6410161514],[40,0,0],[20,34.6410161514,0],[-20,34.6410161514,0],[-40,0,0],[-20,-34.6410161514,0],[20,-34.6410161514,0],[20,0,-34.6410161514],[10,17.3205080757,-34.6410161514],[-10,17.3205080757,-34.6410161514],[-20,0,-34.6410161514],[-10,-17.3205080757,-34.6410161514],[10,-17.3205080757,-34.6410161514]],[[5,4,3,2,1,0],[12,13,14,15,16,17],[6,0,1],[6,1,7],[7,1,2],[7,2,8],[8,2,3],[8,3,9],[9,3,4],[9,4,10],[10,4,5],[10,5,11],[11,5,0],[11,0,6],[12,6,7],[12,7,13],[13,7,8],[13,8,14],[14,8,9],[14,9,15],[15,9,10],[15,10,16],[16,10,11],[16,11,17],[17,11,6],[17,6,12]]]);
assert_approx(sphere(r=40,style="aligned"), [[[0,0,40],[34.6410161514,0,20],[17.3205080757,30,20],[-17.3205080757,30,20],[-34.6410161514,0,20],[-17.3205080757,-30,20],[17.3205080757,-30,20],[34.6410161514,0,-20],[17.3205080757,30,-20],[-17.3205080757,30,-20],[-34.6410161514,0,-20],[-17.3205080757,-30,-20],[17.3205080757,-30,-20],[0,0,-40]],[[1,0,2],[13,7,8],[2,0,3],[13,8,9],[3,0,4],[13,9,10],[4,0,5],[13,10,11],[5,0,6],[13,11,12],[6,0,1],[13,12,7],[1,2,8],[1,8,7],[2,3,9],[2,9,8],[3,4,10],[3,10,9],[4,5,11],[4,11,10],[5,6,12],[5,12,11],[6,1,7],[6,7,12]]]);
assert_approx(sphere(r=40,style="stagger"), [[[0,0,40],[30,17.3205080757,20],[0,34.6410161514,20],[-30,17.3205080757,20],[-30,-17.3205080757,20],[0,-34.6410161514,20],[30,-17.3205080757,20],[34.6410161514,0,-20],[17.3205080757,30,-20],[-17.3205080757,30,-20],[-34.6410161514,0,-20],[-17.3205080757,-30,-20],[17.3205080757,-30,-20],[0,0,-40]],[[1,0,2],[13,7,8],[2,0,3],[13,8,9],[3,0,4],[13,9,10],[4,0,5],[13,10,11],[5,0,6],[13,11,12],[6,0,1],[13,12,7],[1,2,8],[1,8,7],[2,3,9],[2,9,8],[3,4,10],[3,10,9],[4,5,11],[4,11,10],[5,6,12],[5,12,11],[6,1,7],[6,7,12]]]);
assert_approx(sphere(r=40,style="octa"), [[[0,0,40],[28.2842712475,0,28.2842712475],[0,28.2842712475,28.2842712475],[-28.2842712475,0,28.2842712475],[0,-28.2842712475,28.2842712475],[40,0,0],[28.2842712475,28.2842712475,0],[0,40,0],[-28.2842712475,28.2842712475,0],[-40,0,0],[-28.2842712475,-28.2842712475,0],[0,-40,0],[28.2842712475,-28.2842712475,0],[28.2842712475,0,-28.2842712475],[0,28.2842712475,-28.2842712475],[-28.2842712475,0,-28.2842712475],[0,-28.2842712475,-28.2842712475],[0,0,-40]],[[0,2,1],[0,3,2],[0,4,3],[0,1,4],[17,15,16],[17,14,15],[17,13,14],[17,16,13],[1,6,5],[1,2,6],[13,5,6],[13,6,14],[2,7,6],[14,6,7],[2,8,7],[2,3,8],[14,7,8],[14,8,15],[3,9,8],[15,8,9],[3,10,9],[3,4,10],[15,9,10],[15,10,16],[4,11,10],[16,10,11],[4,12,11],[4,1,12],[16,11,12],[16,12,13],[1,5,12],[13,12,5]]]);
assert_approx(sphere(r=40,style="icosa"),[[[0,21.0292444848,34.0260323341],[34.0260323341,0,21.0292444848],[21.0292444848,34.0260323341,0],[21.0292444848,34.0260323341,3.5527136788e-15],[34.0260323341,-3.5527136788e-15,21.0292444848],[34.0260323341,-1.7763568394e-15,-21.0292444848],[34.0260323341,-3.5527136788e-15,-21.0292444848],[34.0260323341,-8.881784197e-15,21.0292444848],[21.0292444848,-34.0260323341,0],[21.0292444848,-34.0260323341,5.3290705182e-15],[34.0260323341,-5.3290705182e-15,21.0292444848],[5.3290705182e-15,-21.0292444848,34.0260323341],[3.5527136788e-15,-21.0292444848,34.0260323341],[34.0260323341,3.5527136788e-15,21.0292444848],[3.5527136788e-15,21.0292444848,34.0260323341],[-21.0292444848,34.0260323341,-3.5527136788e-15],[21.0292444848,34.0260323341,-8.881784197e-15],[0,21.0292444848,-34.0260323341],[5.3290705182e-15,21.0292444848,-34.0260323341],[21.0292444848,34.0260323341,-5.3290705182e-15],[34.0260323341,5.3290705182e-15,-21.0292444848],[3.5527136788e-15,21.0292444848,34.0260323341],[21.0292444848,34.0260323341,-3.5527136788e-15],[-21.0292444848,34.0260323341,-1.7763568394e-15],[-34.0260323341,3.5527136788e-15,-21.0292444848],[-34.0260323341,8.881784197e-15,21.0292444848],[-21.0292444848,34.0260323341,0],[-21.0292444848,34.0260323341,5.3290705182e-15],[-34.0260323341,5.3290705182e-15,21.0292444848],[-5.3290705182e-15,21.0292444848,34.0260323341],[-3.5527136788e-15,21.0292444848,34.0260323341],[-34.0260323341,-3.5527136788e-15,21.0292444848],[-3.5527136788e-15,-21.0292444848,34.0260323341],[-5.39089693932e-15,-21.0292444848,34.0260323341],[-34.0260323341,-9.16854539271e-15,21.0292444848],[-21.0292444848,-34.0260323341,6.83383025096e-15],[-21.0292444848,-34.0260323341,3.5527136788e-15],[-34.0260323341,3.5527136788e-15,21.0292444848],[-34.0260323341,1.7763568394e-15,-21.0292444848],[34.0260323341,-5.39089693932e-15,-21.0292444848],[21.0292444848,-34.0260323341,-9.16854539271e-15],[6.83383025096e-15,-21.0292444848,-34.0260323341],[3.5527136788e-15,-21.0292444848,-34.0260323341],[21.0292444848,-34.0260323341,3.5527136788e-15],[-21.0292444848,-34.0260323341,1.7763568394e-15],[-21.0292444848,-34.0260323341,3.5527136788e-15],[21.0292444848,-34.0260323341,8.881784197e-15],[0,-21.0292444848,34.0260323341],[3.5527136788e-15,-21.0292444848,-34.0260323341],[8.881784197e-15,21.0292444848,-34.0260323341],[34.0260323341,0,-21.0292444848],[-34.0260323341,3.5527136788e-15,-21.0292444848],[3.5527136788e-15,21.0292444848,-34.0260323341],[1.7763568394e-15,-21.0292444848,-34.0260323341],[-21.0292444848,34.0260323341,-5.39089693932e-15],[-9.16854539271e-15,21.0292444848,-34.0260323341],[-34.0260323341,6.83383025096e-15,-21.0292444848],[-34.0260323341,-5.3290705182e-15,-21.0292444848],[-5.3290705182e-15,-21.0292444848,-34.0260323341],[-21.0292444848,-34.0260323341,-5.3290705182e-15]],[[0,1,2],[3,4,5],[6,7,8],[9,10,11],[12,13,14],[15,16,17],[18,19,20],[21,22,23],[24,25,26],[27,28,29],[30,31,32],[33,34,35],[36,37,38],[39,40,41],[42,43,44],[45,46,47],[48,49,50],[51,52,53],[54,55,56],[57,58,59]]]);
// Since this is just a passthrough to sphereoid, no tests needed
}
test_sphere();
@ -61,16 +55,37 @@ module test_prismoid() {
test_prismoid();
module sphere_OK(style)
{
R=10;
vnf_in = spheroid(r=R, style=style, circum=false, $fn=32);
vnf_out = spheroid(r=R, style=style, circum=true, $fn=32);
true_vol = 4/3*PI*R^3;
vol_error_in = vnf_volume(vnf_in)/true_vol-1;
vol_error_out = vnf_volume(vnf_out)/true_vol-1;
for (v=vnf_in[0]) assert(approx(norm(v),R),str("Point not on sphere for style ",style));
for (face=vnf_out[1])
assert(approx(R,norm(plane_closest_point(plane_from_points(select(vnf_out[0],face)), [0,0,0]))),
str("face not tangent for style ",style));
assert(abs(vol_error_in)<.023 && vol_error_in<0, str("Volume rel error of sphere style ",style," for circum=false is ",vol_error_in));
assert(abs(vol_error_out)<.013 && vol_error_out>0, str("Volume rel error of sphere style ",style," for circum=true is ",vol_error_out));
}
module test_spheroid() {
$fn=6;
assert_approx(spheroid(r=50),[[[0,0,50],[43.3012701892,0,25],[21.6506350946,37.5,25],[-21.6506350946,37.5,25],[-43.3012701892,0,25],[-21.6506350946,-37.5,25],[21.6506350946,-37.5,25],[43.3012701892,0,-25],[21.6506350946,37.5,-25],[-21.6506350946,37.5,-25],[-43.3012701892,0,-25],[-21.6506350946,-37.5,-25],[21.6506350946,-37.5,-25],[0,0,-50]],[[1,0,2],[13,7,8],[2,0,3],[13,8,9],[3,0,4],[13,9,10],[4,0,5],[13,10,11],[5,0,6],[13,11,12],[6,0,1],[13,12,7],[1,2,8],[1,8,7],[2,3,9],[2,9,8],[3,4,10],[3,10,9],[4,5,11],[4,11,10],[5,6,12],[5,12,11],[6,1,7],[6,7,12]]]);
assert_approx(spheroid(d=100),[[[0,0,50],[43.3012701892,0,25],[21.6506350946,37.5,25],[-21.6506350946,37.5,25],[-43.3012701892,0,25],[-21.6506350946,-37.5,25],[21.6506350946,-37.5,25],[43.3012701892,0,-25],[21.6506350946,37.5,-25],[-21.6506350946,37.5,-25],[-43.3012701892,0,-25],[-21.6506350946,-37.5,-25],[21.6506350946,-37.5,-25],[0,0,-50]],[[1,0,2],[13,7,8],[2,0,3],[13,8,9],[3,0,4],[13,9,10],[4,0,5],[13,10,11],[5,0,6],[13,11,12],[6,0,1],[13,12,7],[1,2,8],[1,8,7],[2,3,9],[2,9,8],[3,4,10],[3,10,9],[4,5,11],[4,11,10],[5,6,12],[5,12,11],[6,1,7],[6,7,12]]]);
assert_approx(spheroid(r=50,circum=true), [[[0,0,57.735026919],[28.8675134595,50,28.8675134595],[-28.8675134595,50,28.8675134595],[-57.735026919,-3.5527136788e-15,28.8675134595],[-28.8675134595,-50,28.8675134595],[28.8675134595,-50,28.8675134595],[57.735026919,3.5527136788e-15,28.8675134595],[28.8675134595,50,-28.8675134595],[-28.8675134595,50,-28.8675134595],[-57.735026919,-3.5527136788e-15,-28.8675134595],[-28.8675134595,-50,-28.8675134595],[28.8675134595,-50,-28.8675134595],[57.735026919,3.5527136788e-15,-28.8675134595],[0,0,-57.735026919]],[[1,0,2],[13,7,8],[2,0,3],[13,8,9],[3,0,4],[13,9,10],[4,0,5],[13,10,11],[5,0,6],[13,11,12],[6,0,1],[13,12,7],[1,2,8],[1,8,7],[2,3,9],[2,9,8],[3,4,10],[3,10,9],[4,5,11],[4,11,10],[5,6,12],[5,12,11],[6,1,7],[6,7,12]]]);
assert_approx(spheroid(r=50,style="orig"),[[[25,0,43.3012701892],[12.5,21.6506350946,43.3012701892],[-12.5,21.6506350946,43.3012701892],[-25,0,43.3012701892],[-12.5,-21.6506350946,43.3012701892],[12.5,-21.6506350946,43.3012701892],[50,0,0],[25,43.3012701892,0],[-25,43.3012701892,0],[-50,0,0],[-25,-43.3012701892,0],[25,-43.3012701892,0],[25,0,-43.3012701892],[12.5,21.6506350946,-43.3012701892],[-12.5,21.6506350946,-43.3012701892],[-25,0,-43.3012701892],[-12.5,-21.6506350946,-43.3012701892],[12.5,-21.6506350946,-43.3012701892]],[[5,4,3,2,1,0],[12,13,14,15,16,17],[6,0,1],[6,1,7],[7,1,2],[7,2,8],[8,2,3],[8,3,9],[9,3,4],[9,4,10],[10,4,5],[10,5,11],[11,5,0],[11,0,6],[12,6,7],[12,7,13],[13,7,8],[13,8,14],[14,8,9],[14,9,15],[15,9,10],[15,10,16],[16,10,11],[16,11,17],[17,11,6],[17,6,12]]]);
assert_approx(spheroid(r=50,style="aligned"),[[[0,0,50],[43.3012701892,0,25],[21.6506350946,37.5,25],[-21.6506350946,37.5,25],[-43.3012701892,0,25],[-21.6506350946,-37.5,25],[21.6506350946,-37.5,25],[43.3012701892,0,-25],[21.6506350946,37.5,-25],[-21.6506350946,37.5,-25],[-43.3012701892,0,-25],[-21.6506350946,-37.5,-25],[21.6506350946,-37.5,-25],[0,0,-50]],[[1,0,2],[13,7,8],[2,0,3],[13,8,9],[3,0,4],[13,9,10],[4,0,5],[13,10,11],[5,0,6],[13,11,12],[6,0,1],[13,12,7],[1,2,8],[1,8,7],[2,3,9],[2,9,8],[3,4,10],[3,10,9],[4,5,11],[4,11,10],[5,6,12],[5,12,11],[6,1,7],[6,7,12]]]);
assert_approx(spheroid(r=50,style="stagger"),[[[0,0,50],[37.5,21.6506350946,25],[0,43.3012701892,25],[-37.5,21.6506350946,25],[-37.5,-21.6506350946,25],[0,-43.3012701892,25],[37.5,-21.6506350946,25],[43.3012701892,0,-25],[21.6506350946,37.5,-25],[-21.6506350946,37.5,-25],[-43.3012701892,0,-25],[-21.6506350946,-37.5,-25],[21.6506350946,-37.5,-25],[0,0,-50]],[[1,0,2],[13,7,8],[2,0,3],[13,8,9],[3,0,4],[13,9,10],[4,0,5],[13,10,11],[5,0,6],[13,11,12],[6,0,1],[13,12,7],[1,2,8],[1,8,7],[2,3,9],[2,9,8],[3,4,10],[3,10,9],[4,5,11],[4,11,10],[5,6,12],[5,12,11],[6,1,7],[6,7,12]]]);
assert_approx(spheroid(r=50,style="octa"),[[[0,0,50],[35.3553390593,0,35.3553390593],[0,35.3553390593,35.3553390593],[-35.3553390593,0,35.3553390593],[0,-35.3553390593,35.3553390593],[50,0,0],[35.3553390593,35.3553390593,0],[0,50,0],[-35.3553390593,35.3553390593,0],[-50,0,0],[-35.3553390593,-35.3553390593,0],[0,-50,0],[35.3553390593,-35.3553390593,0],[35.3553390593,0,-35.3553390593],[0,35.3553390593,-35.3553390593],[-35.3553390593,0,-35.3553390593],[0,-35.3553390593,-35.3553390593],[0,0,-50]],[[0,2,1],[0,3,2],[0,4,3],[0,1,4],[17,15,16],[17,14,15],[17,13,14],[17,16,13],[1,6,5],[1,2,6],[13,5,6],[13,6,14],[2,7,6],[14,6,7],[2,8,7],[2,3,8],[14,7,8],[14,8,15],[3,9,8],[15,8,9],[3,10,9],[3,4,10],[15,9,10],[15,10,16],[4,11,10],[16,10,11],[4,12,11],[4,1,12],[16,11,12],[16,12,13],[1,5,12],[13,12,5]]]);
assert_approx(spheroid(r=50,style="icosa"),[[[0,26.286555606,42.5325404176],[42.5325404176,0,26.286555606],[26.286555606,42.5325404176,0],[26.286555606,42.5325404176,3.5527136788e-15],[42.5325404176,-7.1054273576e-15,26.286555606],[42.5325404176,-1.7763568394e-15,-26.286555606],[42.5325404176,-3.5527136788e-15,-26.286555606],[42.5325404176,-1.24344978758e-14,26.286555606],[26.286555606,-42.5325404176,0],[26.286555606,-42.5325404176,5.3290705182e-15],[42.5325404176,-7.1054273576e-15,26.286555606],[5.3290705182e-15,-26.286555606,42.5325404176],[5.3290705182e-15,-26.286555606,42.5325404176],[42.5325404176,7.1054273576e-15,26.286555606],[3.5527136788e-15,26.286555606,42.5325404176],[-26.286555606,42.5325404176,-3.5527136788e-15],[26.286555606,42.5325404176,-1.24344978758e-14],[0,26.286555606,-42.5325404176],[5.3290705182e-15,26.286555606,-42.5325404176],[26.286555606,42.5325404176,-7.1054273576e-15],[42.5325404176,5.3290705182e-15,-26.286555606],[3.5527136788e-15,26.286555606,42.5325404176],[26.286555606,42.5325404176,-7.1054273576e-15],[-26.286555606,42.5325404176,-1.7763568394e-15],[-42.5325404176,3.5527136788e-15,-26.286555606],[-42.5325404176,1.24344978758e-14,26.286555606],[-26.286555606,42.5325404176,0],[-26.286555606,42.5325404176,5.3290705182e-15],[-42.5325404176,7.1054273576e-15,26.286555606],[-5.3290705182e-15,26.286555606,42.5325404176],[-5.3290705182e-15,26.286555606,42.5325404176],[-42.5325404176,-7.1054273576e-15,26.286555606],[-3.5527136788e-15,-26.286555606,42.5325404176],[-6.73862117414e-15,-26.286555606,42.5325404176],[-42.5325404176,-1.14606817409e-14,26.286555606],[-26.286555606,-42.5325404176,8.5422878137e-15],[-26.286555606,-42.5325404176,3.5527136788e-15],[-42.5325404176,7.1054273576e-15,26.286555606],[-42.5325404176,1.7763568394e-15,-26.286555606],[42.5325404176,-6.73862117414e-15,-26.286555606],[26.286555606,-42.5325404176,-1.14606817409e-14],[8.5422878137e-15,-26.286555606,-42.5325404176],[3.5527136788e-15,-26.286555606,-42.5325404176],[26.286555606,-42.5325404176,7.1054273576e-15],[-26.286555606,-42.5325404176,1.7763568394e-15],[-26.286555606,-42.5325404176,3.5527136788e-15],[26.286555606,-42.5325404176,1.24344978758e-14],[0,-26.286555606,42.5325404176],[3.5527136788e-15,-26.286555606,-42.5325404176],[1.24344978758e-14,26.286555606,-42.5325404176],[42.5325404176,0,-26.286555606],[-42.5325404176,3.5527136788e-15,-26.286555606],[7.1054273576e-15,26.286555606,-42.5325404176],[1.7763568394e-15,-26.286555606,-42.5325404176],[-26.286555606,42.5325404176,-6.73862117414e-15],[-1.14606817409e-14,26.286555606,-42.5325404176],[-42.5325404176,8.5422878137e-15,-26.286555606],[-42.5325404176,-5.3290705182e-15,-26.286555606],[-7.1054273576e-15,-26.286555606,-42.5325404176],[-26.286555606,-42.5325404176,-5.3290705182e-15]],[[0,1,2],[3,4,5],[6,7,8],[9,10,11],[12,13,14],[15,16,17],[18,19,20],[21,22,23],[24,25,26],[27,28,29],[30,31,32],[33,34,35],[36,37,38],[39,40,41],[42,43,44],[45,46,47],[48,49,50],[51,52,53],[54,55,56],[57,58,59]]]);
styles=["orig","aligned","stagger","octa","icosa"];
for (s=styles)
sphere_OK(s);
R=10;
for (s=["aligned","octa","icosa"]){
vnf_in = spheroid(r=R, style=s, circum=false,$fn=20);
assert_approx(pointlist_bounds(vnf_in[0]), R*[[-1,-1,-1],[1,1,1]],str("Alignment failed for style ",s));
}
/* // No outsphere seems to meet the alignment criterion
vnf_out = spheroid(r=R, style="icosa", circum=true, $fn=25);
maxR = max([for(v=vnf_out[0]) norm(v)]);
assert_approx(pointlist_bounds(vnf_out[0]), maxR*[[-1,-1,-1],[1,1,1]]);
*/
}
test_spheroid();