From b0b483a17277213ea0b8d5dda322386a1500d70c Mon Sep 17 00:00:00 2001 From: Arthur Moore Date: Sat, 9 Mar 2024 23:14:18 -0500 Subject: [PATCH] Use a more advanced chamfer algorithm for stacking_lip Removes the need for "h_lip" within that function. Significantly reduces the number of operations. Which is helpful when importing to FreeCAD. Future Work: * Convert chamfer calculations to functions. * Use those functions to replace "h_lip" with a calculated value. * Genericize chamfer code to a module. --- gridfinity-rebuilt-utility.scad | 79 ++++++++++++++------------ gridfinity-stacking-lip-constants.scad | 47 +++++++++++++++ standard.scad | 18 ------ 3 files changed, 89 insertions(+), 55 deletions(-) create mode 100644 gridfinity-stacking-lip-constants.scad diff --git a/gridfinity-rebuilt-utility.scad b/gridfinity-rebuilt-utility.scad index a39dd1f..442be98 100644 --- a/gridfinity-rebuilt-utility.scad +++ b/gridfinity-rebuilt-utility.scad @@ -5,6 +5,7 @@ */ include +include // ===== User Modules ===== // @@ -361,49 +362,53 @@ module refined_hole() { } /** - * @brief Stacking lip based on https://gridfinity.xyz/specification/ - * @details Also includes a support base. + * @brief Stacking lip with a chamfered top. + * @details Based on https://gridfinity.xyz/specification/ + * Also includes a support base. */ -module stacking_lip() { - // Technique: Descriptive constant names are useful, but can be unweildy. - // Use abbreviations if they are going to be re-used repeatedly in a small piece of code. - inner_slope = stacking_lip_inner_slope_height_mm; - wall_height = stacking_lip_wall_height_mm; +module stacking_lip_chamfered() { + // Replace 2D edge with a radius. + // Method used: tangent, tangent, radius algorithm + // See: https://math.stackexchange.com/questions/797828/calculate-center-of-circle-tangent-to-two-lines-in-space + before_chamfer = stacking_lip_points[2]; + to_chamfer = stacking_lip_points[3]; // tip, Point to Chamfer + after_chamfer = stacking_lip_points[4]; - support_wall = stacking_lip_support_wall_height_mm; - s_total = stacking_lip_support_height_mm; + chamfer_vectors = [ + to_chamfer - before_chamfer, + after_chamfer - to_chamfer, + ]; - polygon([ - [0, 0], // Inner tip - [inner_slope, inner_slope], // Go out 45 degrees - [inner_slope, inner_slope+wall_height], // Vertical increase - [stacking_lip_depth, stacking_lip_height], // Go out 45 degrees - [stacking_lip_depth, -s_total], // Down to support bottom - [0, -support_wall], // Up and in - [0, 0] // Close the shape. Tehcnically not needed. - ]); -} + to_chamfer_angle = 180 + + atan2( + cross(chamfer_vectors[0], chamfer_vectors[1]), + chamfer_vectors[0] * chamfer_vectors[1] + ); + half_angle = to_chamfer_angle / 2; -/** - * @brief Stacking lip with a rounded top. - */ -module stacking_lip_rounded_top() { - radius_center_y = h_lip - r_f1; + // Distance from tip to the center point of the circle. + distance_from_edge = r_f1 / sin(half_angle); + + // Circle's center point + chamfer_center_vector = [ + distance_from_edge * sin(half_angle), + distance_from_edge * cos(half_angle) + ]; + chamfer_center_point = to_chamfer - chamfer_center_vector; + + // Exact point edges intersect the circle + intersection_distance = distance_from_edge * cos(half_angle); union() { - // Create rounded top - intersection() { - translate([0, radius_center_y, 0]) - square([stacking_lip_depth, stacking_lip_height]); - offset(r = r_f1) - offset(delta = -r_f1) - stacking_lip(); - } - // Remove pointed top + // Rounded top chamfer + translate(concat(chamfer_center_point, [0])) + circle(r = r_f1); + + // Stacking lip with cutout for circle to fit in difference(){ - stacking_lip(); - translate([0, radius_center_y, 0]) - square([stacking_lip_depth*2, stacking_lip_height*2]); + polygon(stacking_lip_points); + translate([to_chamfer.x, to_chamfer.y, 0]) + circle(r = intersection_distance); } } } @@ -416,7 +421,7 @@ module profile_wall(height_mm) { assert(is_num(height_mm)) translate([1.4, 0, 0]){ translate([0, height_mm, 0]) - stacking_lip_rounded_top(); + stacking_lip_chamfered(); translate([stacking_lip_depth-d_wall/2, 0, 0]) square([d_wall/2, height_mm]); } diff --git a/gridfinity-stacking-lip-constants.scad b/gridfinity-stacking-lip-constants.scad new file mode 100644 index 0000000..9ef598d --- /dev/null +++ b/gridfinity-stacking-lip-constants.scad @@ -0,0 +1,47 @@ +/** + * @file gridfinity-stacking-lip-constants.scad + * @brief Constants which define the stacking lip. + * @copyright MIT License, Arthur Moore 2024. + * See LICENSE for more information. + */ + + include + +//Based on https://gridfinity.xyz/specification/ +stacking_lip_inner_slope_height_mm = 0.7; +stacking_lip_wall_height_mm = 1.8; +stacking_lip_outer_slope_height_mm = 1.9; + +stacking_lip_depth = + stacking_lip_inner_slope_height_mm + + stacking_lip_outer_slope_height_mm; +stacking_lip_height = + stacking_lip_inner_slope_height_mm + + stacking_lip_wall_height_mm + + stacking_lip_outer_slope_height_mm; + +// Extracted from `profile_wall_sub_sub`. +stacking_lip_support_wall_height_mm = 1.2; +stacking_lip_support_height_mm = + stacking_lip_support_wall_height_mm + d_wall2; + + + +// Technique: Descriptive constant names are useful, but can be unweildy. +// Use abbreviations if they are going to be re-used repeatedly in a small piece of code. +// Python style _ to indicate this is an internal variable. +_slishmm = stacking_lip_inner_slope_height_mm; + +/** + * @brief Points used to make a stacking lip polygon. + * @details Also includes a support base. + */ +stacking_lip_points = [ + [0, 0], // Inner tip + [_slishmm, _slishmm], // Go out 45 degrees + [_slishmm, _slishmm + stacking_lip_wall_height_mm], // Vertical increase + [stacking_lip_depth, stacking_lip_height], // Go out 45 degrees + [stacking_lip_depth, -stacking_lip_support_height_mm], // Down to support bottom + [0, -stacking_lip_support_wall_height_mm], // Up and in + [0, 0] // Close the shape. Tehcnically not needed. +]; diff --git a/standard.scad b/standard.scad index 354aa00..c3f4a92 100644 --- a/standard.scad +++ b/standard.scad @@ -55,24 +55,6 @@ h_lip = 3.548; d_wall2 = r_base-r_c1-d_clear*sqrt(2); d_magic = -2*d_clear-2*d_wall+d_div; -// Stacking Lip -// Based on https://gridfinity.xyz/specification/ -stacking_lip_inner_slope_height_mm = 0.7; -stacking_lip_wall_height_mm = 1.8; -stacking_lip_outer_slope_height_mm = 1.9; -stacking_lip_depth = - stacking_lip_inner_slope_height_mm + - stacking_lip_outer_slope_height_mm; -stacking_lip_height = - stacking_lip_inner_slope_height_mm + - stacking_lip_wall_height_mm + - stacking_lip_outer_slope_height_mm; - -// Extracted from `profile_wall_sub_sub`. -stacking_lip_support_wall_height_mm = 1.2; -stacking_lip_support_height_mm = - stacking_lip_support_wall_height_mm + d_wall2; - // Baseplate constants