/** * @file gridfinity-rebuilt-holes.scad * @brief Functions to create different types of holes in an object. */ include /** * @brief Wave generation function for wrapping a circle. * @param t An angle of the circle. Between 0 and 360 degrees. * @param count The number of **full** waves in a 360 degree circle. * @param range **Half** the difference between minimum and maximum values. * @param vertical_offset A simple offset. * @details * If plotted on an x/y graph this produces a standard sin wave. * Range only seems weird because it describes half a wave. * Mapped by doing [sin(t), cost(t)] * wave_function(...). * When wrapping a circle: * Final Outer radius is (wave_vertical_offset + wave_range). * Final Inner radius is (wave_vertical_offset - wave_range). */ function wave_function(t, count, range, vertical_offset) = (sin(t * count) * range) + vertical_offset; /** * @brief A circle with crush ribs to give a tighter press fit. * @details Extrude and use as a negative modifier. * Idea based on Slant3D's video at 5:20 https://youtu.be/Bd7Yyn61XWQ?t=320 * Implementaiton is completely different. * Important: Lower ribs numbers just result in a deformed circle. * @param outer_radius Final outer radius. * @param inner_radius Final inner radius. * @param ribs Number of crush ribs the circle has. **/ module ribbed_circle(outer_radius, inner_radius, ribs) { assert(outer_radius > 0, "outer_radius must be positive"); assert(inner_radius > 0, "inner_radius must be positive"); assert(ribs > 0, "ribs must be positive"); assert(outer_radius > inner_radius, "outer_radius must be larger than inner_radius"); wave_range = (outer_radius - inner_radius) / 2; wave_vertical_offset = inner_radius + wave_range; // Circe with a wave wrapped around it wrapped_circle = [ for (i = [0:360]) [sin(i), cos(i)] * wave_function(i, ribs, wave_range, wave_vertical_offset) ]; polygon(wrapped_circle); } /** * @brief A cylinder with crush ribs to give a tighter press fit. * @details To be used as the negative for a hole. * @see ribbed_circle * @param outer_radius Outer Radius of the crush ribs. * @param inner_radius Inner Radius of the crush ribs. * @param height Cylinder's height. * @param ribs Number of crush ribs. */ module hole_crush_ribs(outer_radius, inner_radius, height, ribs) { assert(height > 0, "height must be positive"); linear_extrude(height) ribbed_circle( outer_radius, inner_radius, ribs ); } /** * @brief A single magnet and screw hole. * @param screw_radius Radius of the screw hole. * @param magnet_radius Radius of the magnet hole. * @param screw_depth Depth of the screw hole. * @param magnet_depth Depth of the magnet hole. * @details This is the negative designed to be cut out of the base. */ module magnet_and_screw_hole(screw_radius, magnet_radius, screw_depth, magnet_depth) { union() { cylinder(h = magnet_depth, r=magnet_radius); cylinder(h = screw_depth, r = screw_radius); } } /** * @brief A single magnet and screw hole, designed to be printed without supports. * @see https://www.youtube.com/watch?v=W8FbHTcB05w * @param screw_radius Radius of the screw hole. * @param magnet_radius Radius of the magnet hole. * @param screw_depth Depth of the screw hole. * @param magnet_depth Depth of the magnet hole. * @details This is the negative designed to be cut out of the base. */ module magnet_and_screw_hole_printable(screw_radius, magnet_radius, screw_depth, magnet_depth) { difference() { magnet_and_screw_hole(screw_radius, magnet_radius, screw_depth, magnet_depth + h_slit); translate([-1.5*magnet_radius, screw_radius+0.1, magnet_depth]) cube([magnet_radius*3, magnet_radius*3, 10]); // Equivalent to copy_mirror([0,1,0]) mirror([0,1,0]) translate([-1.5*magnet_radius, screw_radius+0.1, magnet_depth]) cube([magnet_radius*3, magnet_radius*3, 10]); } } /** * @brief A single magnet/screw hole. To be cut out of the base. * @pram style_hole Determines the type of hole that will be generated. Style 4 handled elsewhere! * @param o Offset * @details * Just calls the appropriate function with an offset from the constants. * - 0: No holes. Does nothing. * - 1: Magnet holes only * - 2: Magnet and screw holes - no printable slit. * - 3: Magnet and screw holes - printable slit. * - 4: Gridfinity Refined hole - no glue needed. Not handled here! * - 5: Magnet hole with crush ribs. */ module block_base_hole(style_hole, o=0) { assert(style_hole >= 0 && style_hole <= 5, "Unhandled Hole Style"); assert(style_hole != 4, "Gridfinity Refined holes are handled by refined_hole()"); screw_radius = SCREW_HOLE_RADIUS - (o/2); magnet_radius = MAGNET_HOLE_RADIUS - (o/2); magnet_inner_radius = MAGNET_HOLE_CRUSH_RIB_INNER_RADIUS - (o/2); screw_depth = h_base-o; magnet_depth = MAGNET_HOLE_DEPTH - o; if (style_hole == 1) { cylinder(h = magnet_depth, r=magnet_radius); } if (style_hole == 2) { magnet_and_screw_hole(screw_radius, magnet_radius, screw_depth, magnet_depth); } if (style_hole==3) { magnet_and_screw_hole_printable(screw_radius, magnet_radius, screw_depth, magnet_depth); } if (style_hole == 5) { hole_crush_ribs(magnet_radius, magnet_inner_radius, magnet_depth, MAGNET_HOLE_CRUSH_RIB_COUNT); } }