// Meissner Tetrahedron (solid of constant width) - common vertex variant // ceptimus 2018-01-13 width = 50; // width of the object to be printed $fn = 50; // higher numbers give smoother object but (much) longer render times // vertices and edge length of Reuleaux Tetrahedron from Wikipedia v1 = [sqrt(8/9), 0, -1/3]; v2 = [-sqrt(2/9), sqrt(2/3), -1/3]; v3 = [-sqrt(2/9), -sqrt(2/3), -1/3]; v4 = [0, 0, 1]; a = sqrt(8/3); // edge length given by above vertices k = width / a; // scaling constant to generate desired width from standard vertices alpha = atan(2 * sqrt(2)) / 2; // half 'dihedral angle' (amount the three edges up to the apex lean inwards from the vertical) difference() { reuleauxTetrahedron(); for (angle = [0 : 120 : 240]) rotate([0, 0, angle]) translate(v1 * k) rotate([0, -alpha, 0]) translate([0, 0, -1]) wedge(); } color([1, 0, 0]) for (angle = [0 : 120 : 240]) rotate([0, 0, angle]) translate(v1 * k) rotate([0, -alpha, 0]) spindle(); module reuleauxTetrahedron() { intersection() { translate(v1 * k) sphere(r = width); translate(v2 * k) sphere(r = width); translate(v3 * k) sphere(r = width); translate(v4 * k) rotate([90, 0, 0]) // use similar part of sphere for bottom face as other faces - OpenSCAD renders the parts of 'spheres' near the 'poles' differently sphere(r = width); } } module wedge() { // used to subtract three sharp edges of Reuleaux Tetrahedron prior to adding the rounded 'spindle' edges hull() { rotate([0, 0, -alpha]) // 5 is just an empirical 'big enough' figure so that the wedge includes the Reuleaux Tetrahedron edge when placed appropriately cube([width/5, 0.001, width + 2]); rotate([0, 0, alpha]) translate([0, -0.001, 0]) cube([width/5, 0.001, width + 2]); } } // rotate the curve produced where the Reuleaux Tetrahedron surface intersects with the (extended) underlying tetrahedron face // this produces the correct spindle shape for rounding off three edges of the Reuleaux Tetrahedron to produce the Meissner Tetrahedron module spindle() { translate([0, 0, width/2]) rotate_extrude() intersection() { // 6 is just an empirical 'big enough' figure so that the arc is contained within the rectangle translate([-width / 6, -sqrt(2/3) * k, 0]) square([width / 6, width]); translate([(sqrt(2/9) + sqrt(8/9)) * k, 0, 0]) circle(r = width); } }