Last active
August 30, 2021 20:17
-
-
Save hbast/c7fb6fbf37a436089bc172856d8f375e to your computer and use it in GitHub Desktop.
parametric butt hinge with slotted holes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // Title: Parametric Butt Hinge | |
| // Version: 3.8 | |
| // Release Date: 2021-05-08 (ISO 8601) | |
| // Author: Rohin Gosling | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // | |
| // Description: | |
| // | |
| // - Parametric butt hinge, designed to be printed in one step. | |
| // | |
| // - While the entire working hinge may be printed in one step, it is also possible to disabled the internal fused pin, and leave a shaft | |
| // which may be used in the case where an external pin is desired. | |
| // | |
| // Release Notes: | |
| // | |
| // - Version 3.8 | |
| // * Corrected the title comment at the top of the file from to refernce the correct project title, "Parametric Butt Hinge". | |
| // * Previous versions had the title comment, "Parametric Caged Bearing". This was an old copy and paste error that made it | |
| // all the way through to version 3.7. Fixed now. | |
| // | |
| // - Version 3.7 | |
| // * Added a comment for the "knuckle_count" parameter, to notify users to always set an odd knuckle count in order to ensure that the unified | |
| // pin is supported by male knuckles on both ends. An even number of knuckles will leave one end of the unified pin unsupported by a male knuckle. | |
| // * Added a constraint to the "knuckle_count" parameter, to force an odd knuckle count. Even knuckle counts are now incemented to next odd number. | |
| // Example: | |
| // - A knuckle count of 4, will be incremented to 5. | |
| // - A knuckle count of 10 will, with be incremented to 11 | |
| // | |
| // - Version 3.6 | |
| // * Removed extended ASCII characters to make the source code compatible with the UTF-8 encoding required by the Thingiverse Customizer. | |
| // | |
| // - Version 3.5 | |
| // * For hexagonal counterbores, the hexagonal cut has been rotated 90 degrees, to reduce the need for support material. | |
| // The overhang angle for hexagonal counterbore is 60 degrees. | |
| // | |
| // - Version 3.4 | |
| // * Added support for linear and parabolic gusset curves. | |
| // * Factored out all SCG (Solid Constructive Geometry) overlap constants, and consolidated them into one global constant, "SCG_OVERLAP". | |
| // | |
| // - Version 3.3 | |
| // * Placed pin shaft parameters into their own parameter group in the Thingiverse Customizer. | |
| // | |
| // - Version 3.2 | |
| // * Added support for independently configurable top and bottom pin shaft counterbores. | |
| // * Added an assembly option to flip the model about the z-axis. | |
| // Usefull for viewing the top and bottom pin shaft counterbores. | |
| // * Configured the hinge throw angle Thingiverse Customizer parameter step size, to 5 degrees. | |
| // | |
| // - Version 3.1 | |
| // * Added a counterbore feature for the pin shaft. | |
| // - While this feature may be enabled for one piece hinges that have the fused pin enabled, it is primarily designed for use with two | |
| // piece configurations that have their pin disabled. For instance, when the hinge is to be assembled using an external pin. | |
| // - In the case where a hinge is to be assembled using an external pin, it may be desired to have a pin shaft counterbore, where the end | |
| // caps of the knuckle joint array are counterbored, in order to allow the pin or bolt heads of the pin shaft, to be set flush with the | |
| // top and bottom edges of the hinge leaves. | |
| // - To accommodate both hexagonal and square bolt heads and nuts, the counterbore may be set to any one of circular, square or hexagonal. | |
| // * Added private text feature. | |
| // - A public parameter for the Thingiverse Customizer has not been added yet, however, users may set the 'text_enabled' local variable | |
| // in the 'leaf' module to 'true', which will enable a single row of inscribed text on each leaf. | |
| // - By default this feature will only work when exactly 4 fastener holes have been selected via the 'fastener_count' parameter, simply | |
| // because there is a nice open space available between the fastener holes for placing text, when 4 fastener holes are chosen. | |
| // - Text for the male and female leaves may be specified independently. | |
| // | |
| // - Version 3.0 | |
| // * Added a parameter to disable the hinge pin, for when users would like to assemble with an external pin. | |
| // * Changed the main Thingiverse Customizer parameter group name from "Hinge Options", to "Assembly Options". | |
| // * Added a parameter to set the hinge throw angle. | |
| // Users can now set the throw angle, either for analysis and visualisation purposes, or for when the hinge is to be printed vertically | |
| // standing up on edge, in which case a throw angle of 120 degrees may be used to help keep the hinge stable on the build plate. | |
| // * Corrected spelling errors in the comments. | |
| // | |
| // - Version 2.9 | |
| // * Added support for parabolic knuckle gussets to strengthen the knuckle joints. | |
| // Knuckle gussets may now be toggled on and off with the 'enable_knuckle_gusset' parameter. | |
| // | |
| // - Version 2.8 | |
| // * Added the parameter, 'fastener_column_count', to enable single column fastener arrangements, that can be used for | |
| // piano hinge style fastener arrangements. | |
| // | |
| // - Version 2.7 | |
| // * Rewrote the knuckle cutter module using mode generic math, that enables more parametizable control over knuckle joint | |
| // dimensions and configuration. | |
| // | |
| // - Version 2.6 | |
| // * Added support for countersunk fastener holes. Now users can select either counterbore or countersunk. | |
| // dimensions and configuration. | |
| // * Started tracking release updates. | |
| // | |
| // - Version 1.0 - 2.5 | |
| // * N/A - Release updates not tracked. | |
| // | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // Constants: | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // System constants. | |
| C_CONSTANT = 0 + 0; // Used to hide constant values from Thingiverse. Add to other constants to hide them as well. | |
| C_NONE = C_CONSTANT + 0; | |
| // Leaf gender. | |
| C_FEMALE = C_CONSTANT + 0; | |
| C_MALE = C_CONSTANT + 1; | |
| // SCG constants. | |
| SCG_OVERLAP = C_CONSTANT + 0.01; // Used for overlapping Boolean operations in order to avoid Boolean edge artefacts. | |
| C_NEGATIVE = C_CONSTANT + 0; // Used for subtractive Boolean tools. | |
| C_POSITIVE = C_CONSTANT + 1; // Used for additive Boolean tools. | |
| // Bolt head shapes. | |
| C_CIRCULAR = C_CONSTANT + 0; | |
| C_SQUARE = C_CONSTANT + 1; | |
| C_HEXAGONAL = C_CONSTANT + 2; | |
| // Curve Type | |
| C_FUNCTION_LINEAR = C_CONSTANT + 1; // y = ax + b | |
| C_FUNCTION_CIRCULAR = C_CONSTANT + 2; // r2 = x2 + y2 | |
| C_FUNCTION_PARABOLIC = C_CONSTANT + 3; // y = a2(x - j)2 + k ...Vertex form. | |
| // Minimum and maximum constraints. | |
| C_MIN_HINGE_WIDTH = C_CONSTANT + 1.0; | |
| C_MIN_HINGE_HEIGHT = C_CONSTANT + 1.0; | |
| C_MIN_LEAF_GAUGE = C_CONSTANT + 1.0; | |
| C_MIN_COMPONENT_CLEARENCE = C_CONSTANT + 0.1; | |
| C_MAX_COMPONENT_CLEARENCE = C_CONSTANT + 1.0; | |
| C_MIN_KNUCKLE_COUNT = C_CONSTANT + 3; | |
| C_MAX_KNUCKLE_COUNT = C_CONSTANT + 15; | |
| C_MIN_KNUCKLE_GUSSET_WIDTH = C_CONSTANT + 1.0; | |
| C_MIN_FASTENER_MARGIN = C_CONSTANT + 1.0; | |
| C_MIN_PIN_DIAMETER = C_CONSTANT + 1.0; | |
| C_MIN_COUNTER_SINK_DEPTH_STOP = C_CONSTANT + 1.0; | |
| C_MIN_FASTENER_THREAD_DIAMETER = C_CONSTANT + 0.0; | |
| C_MIN_FASTENER_COUNT = C_CONSTANT + 3; | |
| C_MIN_FASTENER_COLUMN_COUNT = C_CONSTANT + 1; | |
| C_MAX_FASTENER_COLUMN_COUNT = C_CONSTANT + 2; | |
| C_MIN_TESSELLATION = C_CONSTANT + 32; | |
| C_MAX_TESSELLATION = C_CONSTANT + 256; | |
| C_MIN_THROW_ANGLE = C_CONSTANT + -90; | |
| C_MAX_THROW_ANGLE = C_CONSTANT + 180; | |
| C_DEFAULT_THROW_ANGLE = C_CONSTANT + 0; | |
| C_MIN_PIN_SHAFT_COUNTERBORE_DIAMETER = C_CONSTANT + 0.1; | |
| C_MIN_PIN_SHAFT_COUNTERBORE_WALL_THICKNESS = C_CONSTANT + 0.3; | |
| C_MIN_PIN_SHAFT_COUNTERBORE_DEPTH = C_CONSTANT + 0.0; | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // Thingiverse Parameters. | |
| // | |
| // - These parameters are used to integrate with the Thingiverse Customizer, and should only be used by the | |
| // class member variables specified in the "Model parameters" section below. | |
| // | |
| // - These Thingiverse Parameters should never be accessed from inside any module. We do this to enforce | |
| // principles of object orientation. | |
| // | |
| // - By separating concerns between variables exposed to Thingiverse vs. variables used internally by the | |
| // SCAD model (class), we are better able to manage the ordering and grouping of variables exposed to | |
| // Thingiverse, vs. the ordering of variables used internally by the model. | |
| // | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| /* [Assembly Options] */ | |
| enable_male_leaf = 1; // [ 0:No, 1:Yes ] | |
| enable_female_leaf = 1; // [ 0:No, 1:Yes ] | |
| enable_fillet = 1; // [ 0:No, 1:Yes ] | |
| // Turn this off to omit the hinge pin from the female leaf. | |
| enable_pin = 1; // [ 0:No, 1:Yes ] | |
| // Turn this off to set a custom pin diameter. Auto pin size is equal to the leaf gauge. | |
| enable_auto_pin_size = 1; // [ 0:No, 1:Yes ] | |
| enable_pin_shaft_counterbore = 0; // [ 0:No, 1:Yes ] | |
| enable_fasteners = 1; // [ 0:No, 1:Yes ] | |
| knuckle_gusset_type = 0; // [ 0:None, 1:Linear, 2:Circular, 3:Parabolic ] | |
| // From +180 degrees fully closed, to -90 degrees fully opened. Default = 0 (ie. Opened flat). | |
| throw_angle = 0.0; // [ -90 : 5 : 180 ] | |
| // Rotates the model 180 degrees about the z-axis. | |
| flip_model = 0; // [ 0:No, 1:Yes ] | |
| // Recommended value is 64 or greater. | |
| resolution = 128; | |
| component_color = "Silver"; | |
| /* [Hinge Parameters] */ | |
| hinge_width = 65.0; | |
| leaf_height = 60.0; | |
| // Leaf and knuckle thickness. Values greater than 3mm recommended. | |
| leaf_gauge = 5.0; | |
| // Recomended values between 0.3 and 4.0. Better quality below 3.0, tough to loosen. | |
| component_clearance = 0.4; | |
| // Knuckle count must be an odd number, so that the pin is supported on both ends. | |
| knuckle_count = 7; // [3:2:31] | |
| // Manual pin diameter setting. Only has effect, if "Enable Auto Pin Size" is set to "No". | |
| pin_diameter = 3.0; | |
| parametric_pin_diameter = ( enable_auto_pin_size == 1 ) ? leaf_gauge : pin_diameter; | |
| /* [Pin Shaft Parameters] */ | |
| top_pin_shaft_counterbore_diameter = 6.5; | |
| top_pin_shaft_counterbore_depth = 2.5; | |
| top_pin_shaft_counterbore_shape = 0; // [ 0:Circular, 1:Square, 2:Hexagonal ] | |
| bottom_pin_shaft_counterbore_diameter = 6.0; | |
| bottom_pin_shaft_counterbore_depth = 2.5; | |
| bottom_pin_shaft_counterbore_shape = 2; // [ 0:Circular, 1:Square, 2:Hexagonal ] | |
| /* [Fastener Parameters] */ | |
| // For countersunk, the chamfer angle may be adjusted using the other parameters. | |
| fstener_head_type = 0; // [ 0:Counterbored, 1:Countersunk ] | |
| counter_sink_depth = 2.5; | |
| fastener_thread_diameter = 3.5; | |
| // Add 0.5mm to 1.0mm to the fastener head diameter, to allow for head clearance. | |
| fastener_head_diameter = 7.0; | |
| fastener_count = 6; // [3:32] | |
| fastener_column_count = 2; // [1,2] | |
| fastener_slotted = false; // [true,false] | |
| // Determining how the center hole should be inserted. | |
| fastener_slotted_middle = 0; // [0:middle, 1:inner, 2:outer, 3:slotted] | |
| // Distance from the edge of the head diameter, to the edges of the leaves. | |
| fastener_margin = 3; | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // Model parameters and geometric constraints. (Class member variables). | |
| // | |
| // - If we treat an OpenSCAD file as though it is an object oriented class, then we can prefix global variables | |
| // with "m_", to denote class membership. | |
| // - As an alternative to "m_", we could also use "this_" as a standard. However, "m_" is shorter and faster to type. | |
| // - Another advantage of this convention, is that we can arrange parameters meant for display in Thingiverse, in | |
| // an order that makes sense to the user, while arranging the member versions of the parameters in an order | |
| // that better accommodates constraint computation. | |
| // | |
| // - Once we have defined global variables as member variables of a class, in this case the class represented | |
| // by the SCAD file, then we are free to better manage global vs local scope of class member | |
| // variables, vs. local module (method) variables. | |
| // | |
| // - Thingiverse only integrates constant literal values. So as long as we reference other parameters or | |
| // initialize variables as expressions, then none of these will appear in the Thingiverse customizer. | |
| // | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // Assembly Options. | |
| m_male_leaf_enabled = ( enable_male_leaf == 1 ) ? true : false; | |
| m_female_leaf_enabled = ( enable_female_leaf == 1 ) ? true : false; | |
| m_leaf_fillet_enabled = ( enable_fillet == 1 ) ? true : false; | |
| m_pin_enabled = ( enable_pin == 1 ) ? true : false; | |
| m_pin_auto_size_enabled = ( enable_auto_pin_size == 1 ) ? true : false; | |
| m_pin_shaft_counterbore_enabled = ( enable_pin_shaft_counterbore == 1 ) ? true : false; | |
| m_fasteners_enabled = ( enable_fasteners == 1 ) ? true : false; | |
| m_knuckle_gusset_type = knuckle_gusset_type; | |
| m_flip_model = ( flip_model == 1 ) ? true : false; | |
| m_throw_angle = clip ( throw_angle, C_MIN_THROW_ANGLE, C_MAX_THROW_ANGLE ); | |
| // Leaf Parameters. | |
| m_hinge_width = ( hinge_width <= C_MIN_HINGE_WIDTH ) ? C_MIN_HINGE_WIDTH : hinge_width; | |
| m_leaf_width = m_hinge_width / 2.0; | |
| m_leaf_height = ( leaf_height <= C_MIN_HINGE_HEIGHT ) ? C_MIN_HINGE_HEIGHT : leaf_height; | |
| m_leaf_gauge = clip ( leaf_gauge, C_MIN_LEAF_GAUGE, m_leaf_width/2.0 ); | |
| // Mechanical Properties. | |
| m_component_clearance = clip ( component_clearance, C_MIN_COMPONENT_CLEARENCE, C_MAX_COMPONENT_CLEARENCE ); | |
| m_knuckle_outer_radius = m_leaf_gauge * 2.0; | |
| m_knuckle_count = clip ( 1 + 2 * floor ( knuckle_count / 2 ), C_MIN_KNUCKLE_COUNT, C_MAX_KNUCKLE_COUNT ); | |
| m_fastener_margin = clip ( fastener_margin, C_MIN_FASTENER_MARGIN, ( m_leaf_width - m_leaf_gauge - fastener_head_diameter )/2.0 ); | |
| m_knuckle_gusset_width = clip ( m_fastener_margin, C_MIN_KNUCKLE_GUSSET_WIDTH, m_leaf_width - m_leaf_gauge - m_component_clearance ); | |
| // Pin Parameters. | |
| m_pin_diameter = clip ( pin_diameter, C_MIN_PIN_DIAMETER, 2.0*m_leaf_gauge - C_MIN_PIN_DIAMETER ); | |
| m_parametric_pin_diameter = ( m_pin_auto_size_enabled == true ) ? m_leaf_gauge : m_pin_diameter; | |
| m_top_pin_shaft_counterbore_diameter = clip ( top_pin_shaft_counterbore_diameter, C_MIN_PIN_SHAFT_COUNTERBORE_DIAMETER, 2.0*m_leaf_gauge - C_MIN_PIN_SHAFT_COUNTERBORE_WALL_THICKNESS ); | |
| m_top_pin_shaft_counterbore_depth = clip ( top_pin_shaft_counterbore_depth, C_MIN_PIN_SHAFT_COUNTERBORE_DEPTH, 0.66*( m_leaf_height / ( m_knuckle_count + m_component_clearance )) ); | |
| m_top_pin_shaft_counterbore_shape = top_pin_shaft_counterbore_shape; | |
| m_bottom_pin_shaft_counterbore_diameter = clip ( bottom_pin_shaft_counterbore_diameter, C_MIN_PIN_SHAFT_COUNTERBORE_DIAMETER, 2.0*m_leaf_gauge - C_MIN_PIN_SHAFT_COUNTERBORE_WALL_THICKNESS ); | |
| m_bottom_pin_shaft_counterbore_depth = clip ( bottom_pin_shaft_counterbore_depth, C_MIN_PIN_SHAFT_COUNTERBORE_DEPTH, 0.8*( m_leaf_height / m_knuckle_count) ); | |
| m_bottom_pin_shaft_counterbore_shape = bottom_pin_shaft_counterbore_shape; | |
| // Fastener parameters. | |
| m_fstener_head_type = fstener_head_type; | |
| m_counter_sink_depth = clip ( counter_sink_depth, 0.0, m_leaf_gauge - C_MIN_COUNTER_SINK_DEPTH_STOP ); | |
| m_fastener_head_diameter = clip ( fastener_head_diameter, fastener_thread_diameter, m_leaf_width - m_leaf_gauge - m_component_clearance - 2.0*m_fastener_margin ); | |
| m_fastener_thread_diameter = clip ( fastener_thread_diameter, C_MIN_FASTENER_THREAD_DIAMETER, m_fastener_head_diameter ); | |
| m_fastener_column_count = clip ( fastener_column_count, C_MIN_FASTENER_COLUMN_COUNT, C_MAX_FASTENER_COLUMN_COUNT ); | |
| m_fastener_count = clip ( fastener_count, C_MIN_FASTENER_COUNT, m_fastener_column_count*( m_leaf_height - 2.0*m_fastener_margin )/(m_fastener_head_diameter + m_component_clearance)); | |
| m_leaf_fillet_radius = m_fastener_head_diameter / 2.0 + m_fastener_margin; | |
| // Model parameters. | |
| m_resolution = clip ( resolution, C_MIN_TESSELLATION, C_MAX_TESSELLATION ); | |
| m_component_color = component_color; | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // DEBUG: Console Output. | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| C_DEBUG_ENABLED = true; | |
| if ( C_DEBUG_ENABLED ) | |
| { | |
| echo ( m_hinge_width = m_hinge_width ); | |
| echo ( m_leaf_width = m_leaf_width ); | |
| echo ( absolute_leaf_width = m_leaf_width - m_leaf_gauge ); | |
| echo ( m_leaf_height = m_leaf_height ); | |
| echo ( m_leaf_gauge = m_leaf_gauge ); | |
| echo ( m_component_clearance = m_component_clearance ); | |
| echo ( m_knuckle_outer_radius = m_knuckle_outer_radius ); | |
| echo ( m_knuckle_count = m_knuckle_count ); | |
| echo ( m_knuckle_gusset_width = m_knuckle_gusset_width ); | |
| echo ( m_leaf_fillet_radius = m_leaf_fillet_radius ); | |
| echo ( m_fastener_margin = m_fastener_margin ); | |
| echo ( m_pin_diameter = m_pin_diameter ); | |
| echo ( m_parametric_pin_diameter = m_parametric_pin_diameter ); | |
| echo ( absolute_pin_diameter = m_parametric_pin_diameter - m_component_clearance / 2.0 ); | |
| echo ( m_pin_shaft_counterbore_diameter = m_pin_shaft_counterbore_diameter ); | |
| echo ( m_pin_shaft_counterbore_depth = m_pin_shaft_counterbore_depth ); | |
| } | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // Module: Main | |
| // Module Type: Model | |
| // | |
| // Description: | |
| // | |
| // - Program entry point. | |
| // | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| main(); | |
| module main () | |
| { | |
| // Initialize model resolution. | |
| $fn = m_resolution; | |
| // Generate hinge assembly. | |
| rotate ( [ 0.0, 0.0, ( m_flip_model ) ? 180.0 : 0.0 ] ) | |
| { | |
| if ( m_female_leaf_enabled ) rotate ( [ 0.0, -m_throw_angle, 0.0 ] ) leaf ( C_FEMALE ); | |
| if ( m_male_leaf_enabled ) leaf ( C_MALE ); | |
| } | |
| } | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // Module: leaf. | |
| // Module Type: Component. | |
| // | |
| // Description: | |
| // | |
| // - Creates a hinge leaf component, whose gender may be selected through the gender argument. | |
| // | |
| // - Note: | |
| // The text option is not made public to the Thingiverse Customizer at this time. | |
| // However, you can add and configure text here in the code. | |
| // | |
| // Parameters: | |
| // | |
| // - gender: | |
| // The gender (male, female), of the leaf. The female leaf holds the pin. | |
| // | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| module leaf ( gender ) | |
| { | |
| // Text configuration. | |
| text_enabled = false; | |
| text_string_female = "0.4"; | |
| text_string_male = "RG"; | |
| text_female_font_size = 8; | |
| text_male_font_size = 8; | |
| // Compute the gender angle. | |
| // - 0 degrees for female, and 180 degrees for male. | |
| // - In other words, we leave the female leaf un-rotated, but we rotate the male leaf 180 degrees, to place it at an | |
| // opposing orientation to the female. | |
| gender_angle = ( gender == C_FEMALE ) ? 0 : 180; | |
| // Create leaves. | |
| rotate ( [ 0, 0, gender_angle ] ) | |
| { | |
| color ( m_component_color ) | |
| difference () | |
| { | |
| // Cut pin hole. | |
| workpiece_leaf_knuckle_pin ( gender ); | |
| // Cut fstener holes. | |
| if ( m_fasteners_enabled ) | |
| { | |
| tool_cutter_fastener_set ( m_fastener_count, m_fastener_column_count, 0 ); | |
| } | |
| // Cut pin shaft counterbore into female leaf. | |
| if ( m_pin_shaft_counterbore_enabled && gender == C_FEMALE ) | |
| { | |
| tool_cutter_pin_shaft_counterbore | |
| ( | |
| diameter_top = m_top_pin_shaft_counterbore_diameter, | |
| depth_top = m_top_pin_shaft_counterbore_depth, | |
| shape_top = m_top_pin_shaft_counterbore_shape, | |
| diameter_bottom = m_bottom_pin_shaft_counterbore_diameter, | |
| depth_bottom = m_bottom_pin_shaft_counterbore_depth, | |
| shape_bottom = m_bottom_pin_shaft_counterbore_shape | |
| ); | |
| } | |
| // Cut text. | |
| // - We will only cut text into the leaves, if we are using exactly 4 fasteners per leaf. | |
| // - All other leaf counts will not leave enough space for the text to fit easily. So we only add text, if we are using 4 fasteners. | |
| if ( text_enabled && m_fastener_count == 4 ) | |
| { | |
| if ( gender == C_FEMALE ) tool_cutter_text ( text_string_female, text_female_font_size ); | |
| if ( gender == C_MALE ) tool_cutter_text ( text_string_male, text_male_font_size ); | |
| } | |
| } | |
| } | |
| } | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // Module: workpiece_leaf_knuckle_pin | |
| // Module Type: Workpiece. | |
| // | |
| // Description: | |
| // | |
| // - This module creates the workpiece used to construct either a male or female leaves. | |
| // | |
| // Parameters: | |
| // | |
| // - gender: | |
| // The gender (male, female), of the leaf. The female leaf holds the pin. | |
| // | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| module workpiece_leaf_knuckle_pin ( gender ) | |
| { | |
| // Initialize local variables. | |
| d = m_parametric_pin_diameter; | |
| c = m_component_clearance; | |
| e = SCG_OVERLAP; | |
| // Combine pin with leaf and knuckle. | |
| if ( gender == C_FEMALE ) | |
| { | |
| if ( m_pin_enabled ) | |
| { | |
| // Fuse the pin to the female leaf by default. | |
| union () | |
| { | |
| dc = d - c/2.0; | |
| workpiece_leaf_knuckle ( C_FEMALE ); | |
| pin ( dc, m_leaf_height - e ); | |
| } | |
| } | |
| else | |
| { | |
| // Cut a hole for an external pin if selected by the user. | |
| difference () | |
| { | |
| dc = d + c/2.0; | |
| workpiece_leaf_knuckle ( C_FEMALE ); | |
| pin ( dc, m_leaf_height + e ); | |
| } | |
| } | |
| } | |
| else | |
| { | |
| // Cut a hole for the pin to pass throug in the male leaf. | |
| difference () | |
| { | |
| dc = d + c/2.0; | |
| workpiece_leaf_knuckle ( C_MALE ); | |
| pin ( dc, m_leaf_height + e ); | |
| } | |
| } | |
| } | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // Module: pin | |
| // Module Type: Component. | |
| // | |
| // Description: | |
| // | |
| // - Hinge pin component. | |
| // | |
| // Parameters: | |
| // | |
| // - diameter: | |
| // Diameter of the cylinder used to create the pin. | |
| // | |
| // - length: | |
| // Length of the cylinder used to create the pin. | |
| // | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| module pin ( diameter, length ) | |
| { | |
| rotate ( [ 90, 0, 0 ] ) | |
| { | |
| // Initialize pin dimensions. | |
| tx = 0; | |
| ty = 0; | |
| tz = -length/2; | |
| // Create pin. | |
| translate ( [ tx, ty, tz ] ) | |
| { | |
| cylinder ( d = diameter, h = length ); | |
| } | |
| } | |
| } | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // Module: workpiece_leaf_knuckle | |
| // Module Type: Workpiece. | |
| // | |
| // Description: | |
| // | |
| // - Workpiece used to cut away knuckle structures. | |
| // | |
| // Parameters: | |
| // | |
| // - gender: | |
| // The gender (male, female), of the leaf. The female leaf holds the pin. | |
| // | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| module workpiece_leaf_knuckle ( gender ) | |
| { | |
| // Initialize local variables. | |
| gender_flipped = ( gender == C_MALE ) ? C_FEMALE : C_MALE; | |
| w = m_leaf_width; | |
| l = m_leaf_height; | |
| h = m_leaf_gauge; | |
| r = m_leaf_fillet_radius; | |
| d = m_knuckle_outer_radius; | |
| // Create workpiece. | |
| difference () | |
| { | |
| difference () | |
| { | |
| // leaf and knuckle work piece. | |
| translate ( [ 0, -l/2, 0 ] ) | |
| { | |
| union () | |
| { | |
| // Leaf. | |
| workpiece_leaf ( w, l, h, r ); | |
| // Knuckle. | |
| rotate ( [ -90, 0, 0 ] ) cylinder ( d = d, h = l ); | |
| // Gusset array. | |
| if ( m_knuckle_gusset_type != C_NONE ) | |
| { | |
| translate ( [ 0, l/2, 0 ] ) | |
| workpiece_gusset_array | |
| ( | |
| gender = gender, | |
| curve = m_knuckle_gusset_type, | |
| scg_type = C_POSITIVE, | |
| fill_component_clearance = false | |
| ); | |
| } | |
| } | |
| } | |
| // Cut knuckle gaps. | |
| tool_cutter_knuckle_array | |
| ( | |
| gender = gender, | |
| fill_component_clearance = true, | |
| size = 2.0*m_leaf_gauge + m_component_clearance | |
| ); | |
| } | |
| // Cut opposing gusset groves. | |
| if ( m_knuckle_gusset_type != C_NONE ) | |
| { | |
| workpiece_gusset_array | |
| ( | |
| gender = gender_flipped, | |
| curve = m_knuckle_gusset_type, | |
| scg_type = C_NEGATIVE, | |
| fill_component_clearance = true | |
| ); | |
| } | |
| } | |
| } | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // Module: workpiece_leaf | |
| // Module Type: Workpiece. | |
| // | |
| // Description: | |
| // | |
| // - Workpiece used to cut away leaf structures. | |
| // | |
| // Parameters: | |
| // | |
| // - w: | |
| // Width of a single leaf. | |
| // | |
| // - l: | |
| // Length of the leaf. | |
| // | |
| // - h: | |
| // Height of the leaf. | |
| // | |
| // - r: | |
| // Radius of the hinge knuckle. | |
| // | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| module workpiece_leaf ( w, l, h, r ) | |
| { | |
| translate ( [ 0, 0, -h ] ) | |
| { | |
| union () | |
| { | |
| if ( m_leaf_fillet_enabled ) | |
| { | |
| // Leaf. | |
| cube ( [ w-r, l, h] ); | |
| translate ( [ 0, r, 0 ] ) cube ( [ w, l-2*r, h] ); | |
| // Fillet corcers. | |
| translate ( [ w - r, r, 0 ] ) cylinder ( r = r, h = h ); | |
| translate ( [ w - r, l-r, 0 ] ) cylinder ( r = r, h = h ); | |
| } | |
| else | |
| { | |
| // Leaf. | |
| cube ( [ w, l, h] ); | |
| } | |
| } | |
| } | |
| } | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // Module: workpiece_gusset_array | |
| // Module Type: Workpiece. | |
| // | |
| // Description: | |
| // | |
| // - Create an array of cutting blocks. Mostly used to cut gusset workpiece into individual gusset positives or negatives. | |
| // | |
| // Parameters: | |
| // | |
| // - gender: | |
| // Specifies the number of knuckle joints based on hinge leaf gender. | |
| // | |
| // - scg_type: | |
| // Solid Constructive Geometry type. | |
| // If C_POSITIVE, then add to the base work piece. | |
| // If C_NAGATIVE, then subtract from the base workpiece. | |
| // | |
| // - fill_component_clearance: | |
| // If true, then create wide cutting blocks that fill in the component clearance. | |
| // If false, then create narrow cutting blocks that leave space for the component clearance. | |
| // | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| module workpiece_gusset_array ( gender, curve, scg_type, fill_component_clearance ) | |
| { | |
| // Compute cutting block size. | |
| cutting_block_size = m_leaf_gauge + m_knuckle_gusset_width; | |
| leaf_height = ( scg_type == C_NEGATIVE ) ? m_leaf_height + SCG_OVERLAP : m_leaf_height; | |
| // Compute cutting block translation. | |
| xt = cutting_block_size/2.0; | |
| yt = 0.0; | |
| zt = 0.0; | |
| // Create gusset array. | |
| difference () | |
| { | |
| // Create a solid cylindrical gusset cylinder. | |
| workpiece_gusset | |
| ( | |
| width = m_knuckle_gusset_width, | |
| height = leaf_height, | |
| knuckle_radus = m_leaf_gauge, | |
| curve = curve, | |
| scg_type = scg_type | |
| ); | |
| // Use the knuckle array cutter tool, to cut knuckle gaps into the gusset to match the dimensions of the knuckles. | |
| translate ( [ xt, yt, zt ] ) | |
| tool_cutter_knuckle_array | |
| ( | |
| gender = gender, | |
| fill_component_clearance = !fill_component_clearance, | |
| size = cutting_block_size | |
| ); | |
| } | |
| } | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // Module: workpiece_gusset | |
| // Module Type: Workpiece | |
| // | |
| // Description: | |
| // | |
| // - Knuckle gusset used to strengthen the knuckle joints. | |
| // | |
| // Parameters: | |
| // | |
| // - width | |
| // The length of the gusset, as measured from the edge of the knuckle. | |
| // We name it "width", in order to maintain dimension naming consistency with the rest of the hinge dimensions. | |
| // | |
| // - height | |
| // The thickness of the gusset. | |
| // We name this "height", in order to maintain dimension naming consistency with the rest of the hinge dimensions. | |
| // | |
| // - knuckle_radus | |
| // Outer radius of the knuckles. This is also the same value as the leaf gauge. | |
| // | |
| // - curve | |
| // The mathematical function used to describe the shape of the gusset. | |
| // - Linear | |
| // - Parabolic | |
| // - Circular | |
| // | |
| // - scg_type | |
| // Solid Constructive Geometry (SCG) mode. | |
| // - If set to 0 or C_NEGATVE, to create the version of the component used for cutting away from the leaves. | |
| // - If set to 1 or C_POSITIVE, to create the version of the component used for adding to the leaves and knuckles. | |
| // | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| module workpiece_gusset ( width, height, knuckle_radus, curve, scg_type ) | |
| { | |
| if ( curve == C_FUNCTION_LINEAR ) workpiece_gusset_linear ( width, height, knuckle_radus, scg_type ); | |
| else if ( curve == C_FUNCTION_CIRCULAR ) workpiece_gusset_circular ( width, height, knuckle_radus, scg_type ); | |
| else if ( curve == C_FUNCTION_PARABOLIC ) workpiece_gusset_parabolic ( width, height, knuckle_radus, scg_type ); | |
| } | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // Module: workpiece_gusset_linear | |
| // Module Type: Workpiece | |
| // | |
| // Description: | |
| // | |
| // - Linear knuckle gusset, called by workpiece_gusset. | |
| // | |
| // Parameters: | |
| // | |
| // - width | |
| // The length of the gusset, as measured from the edge of the knuckle. | |
| // We name it "width", in order to maintain dimension naming consistency with the rest of the hinge dimensions. | |
| // | |
| // - height | |
| // The thickness of the gusset. | |
| // We name this "height", in order to maintain dimension naming consistency with the rest of the hinge dimensions. | |
| // | |
| // - knuckle_radus | |
| // Outer radius of the knuckles. This is also the same value as the leaf gauge. | |
| // | |
| // - scg_type | |
| // Solid Constructive Geometry (SCG) mode. | |
| // - If set to 0 or C_NEGATVE, to create the version of the component used for cutting away from the leaves. | |
| // - If set to 1 or C_POSITIVE, to create the version of the component used for adding to the leaves and knuckles. | |
| // | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| module workpiece_gusset_linear ( width, height, knuckle_radus, scg_type ) | |
| { | |
| CENTER = true; | |
| DEBUG_ENABLED = true; | |
| // Initialize input values. | |
| w = width; // Gusset width. | |
| h = height; // Hinge leaf height. | |
| r = knuckle_radus; // Knuckle radius is equal to the leaf gauge. | |
| s = w + r; // Cartesian position of the point where the gusset curve merges with the leaf. | |
| g = m_leaf_gauge; // Leafe gauge. | |
| c = SCG_OVERLAP; // Amount to overlap unions in order to prevent Boolean anomalies. | |
| // Compute gusset tangent curve. | |
| x = r*r/s; | |
| y = sqrt ( r*r - x*x ); | |
| a = y/( x - s ); | |
| b = -a*s; | |
| // Compute work piece translation and dimensions. | |
| wp_xd = 0; // Work piece origin x. | |
| wp_yd = 0; // Work piece origin y. | |
| wp_zd = -g + c; // Work piece origin z. | |
| wp_w = s; // Work piece width (x axis length). | |
| wp_g = g + y - c; // Work piece gauge (y access length. i.e. thickness). | |
| wp_h = h; // Work piece height (y axis length). | |
| // Compute cutting tool translation and dimensions. | |
| ct_xd = 0; | |
| ct_yd = 0; | |
| ct_zd = 0; | |
| ct_w0 = x; | |
| ct_w1 = s; | |
| ct_g0 = y; | |
| ct_g1 = 0; | |
| ct_h = h + 2*c; | |
| // Compute and configure orientation. | |
| test_yd = 0; | |
| zs = ( scg_type == C_POSITIVE ) ? 1.0 : -1.0; | |
| scale ( [ 1.0, -1.0, zs ] ) | |
| difference() | |
| { | |
| translate ( [ wp_xd, wp_yd + test_yd, wp_zd ] ) rotate ( [ 90, 0, 0 ] ) | |
| { | |
| linear_extrude ( height = wp_h, center = CENTER ) rectangle ( w = wp_w, h = wp_g ); | |
| } | |
| translate ( [ ct_xd, ct_yd + test_yd, ct_zd ] ) rotate ( [ 90, 0, 0 ] ) | |
| { | |
| linear_extrude ( height = ct_h, center = CENTER ) triangle ( [ [ ct_w0, ct_g0 ],[ ct_w1+c, ct_g0+c ],[ ct_w1, ct_g1 ] ] ); | |
| } | |
| } | |
| } | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // Module: workpiece_gusset_circular | |
| // Module Type: Workpiece | |
| // | |
| // Description: | |
| // | |
| // - Linear knuckle gusset, called by workpiece_gusset. | |
| // | |
| // Parameters: | |
| // | |
| // - width | |
| // The length of the gusset, as measured from the edge of the knuckle. | |
| // We name it "width", in order to maintain dimension naming consistency with the rest of the hinge dimensions. | |
| // | |
| // - height | |
| // The thickness of the gusset. | |
| // We name this "height", in order to maintain dimension naming consistency with the rest of the hinge dimensions. | |
| // | |
| // - knuckle_radus | |
| // Outer radius of the knuckles. This is also the same value as the leaf gauge. | |
| // | |
| // - scg_type | |
| // Solid Constructive Geometry (SCG) mode. | |
| // - If set to 0 or C_NEGATVE, to create the version of the component used for cutting away from the leaves. | |
| // - If set to 1 or C_POSITIVE, to create the version of the component used for adding to the leaves and knuckles. | |
| // | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| module workpiece_gusset_circular ( width, height, knuckle_radus, scg_type ) | |
| { | |
| CENTER = true; | |
| // Initialize input values. | |
| w = width; // Gusset width. | |
| g = knuckle_radus; // Knuckle radius is equal to the leaf gauge. | |
| c = SCG_OVERLAP; // Amount to overlap unions in order to prevent Boolean anomalies. | |
| // Compute gusset radius. The radius of the circle, that is tangential to the knuckle cylinder. | |
| r = ( 2.0*g*w + w*w ) / ( 2.0*g ); | |
| // Compute gusset height. The point of intersection between the knuckle cylinder and the gusset cutter. | |
| h = ( g*r ) / sqrt ( g*g + 2.0*g*w + r*r + w*w ); | |
| // Compute intersection point between knuckle and gusset cutting tool, using gusset height. | |
| // The coordinate of the intersection point are, p(x,h), where h is the vertical value of the coordinate. | |
| x = h*( g + w ) / r; | |
| // Compute gusset cutting tool translation. | |
| ctxd = g + w; | |
| ctyd = c; | |
| ctzd = r; | |
| ctt = height + 2.0*x; | |
| // Compute gusset work piece translation and dimensions. | |
| wpw = g + w -x; | |
| wph = h + c; | |
| wpxd = x; | |
| wpyd = 0.0; | |
| wpzd = 0.0 - c; | |
| wpt = height; | |
| // Initialize cutting plane and component scaling. | |
| xr = 90.0; | |
| yr = 0.0; | |
| zr = 0.0; | |
| xs = 1.0; | |
| ys = -1.0; | |
| zs = ( scg_type == C_POSITIVE ) ? 1.0 : -1.0; | |
| // Generate gusset. | |
| color ( "silver" ) | |
| scale ( [ xs, ys, zs ] ) | |
| difference () | |
| { | |
| translate ( [ wpxd, wpyd, wpzd ] ) rotate ( [ xr, yr, zr ] ) linear_extrude ( height = wpt, center = CENTER ) rectangle ( w = wpw, h = wph ); | |
| translate ( [ ctxd, ctyd, ctzd ] ) rotate ( [ xr, yr, zr ] ) linear_extrude ( height = ctt, center = CENTER ) circle ( r = r ); | |
| } | |
| } | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // Module: workpiece_gusset_parabolic | |
| // Module Type: Workpiece | |
| // | |
| // Description: | |
| // | |
| // - Parabolic knuckle gusset, called by workpiece_gusset. | |
| // | |
| // Parameters: | |
| // | |
| // - width | |
| // The length of the gusset, as measured from the edge of the knuckle. | |
| // We name it "width", in order to maintain dimension naming consistency with the rest of the hinge dimensions. | |
| // | |
| // - height | |
| // The thickness of the gusset. | |
| // We name this "height", in order to maintain dimension naming consistency with the rest of the hinge dimensions. | |
| // | |
| // - knuckle_radus | |
| // Outer radius of the knuckles. This is also the same value as the leaf gauge. | |
| // | |
| // - scg_type | |
| // Solid Constructive Geometry (SCG) mode. | |
| // - If set to 0 or C_NEGATVE, to create the version of the component used for cutting away from the leaves. | |
| // - If set to 1 or C_POSITIVE, to create the version of the component used for adding to the leaves and knuckles. | |
| // | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| module workpiece_gusset_parabolic ( width, height, knuckle_radus, scg_type ) | |
| { | |
| CENTER = true; | |
| DEBUG_ENABLED = true; | |
| RESOLUTION = m_resolution / C_MIN_TESSELLATION; | |
| // Initialize input values. | |
| w = width; // Gusset width. | |
| h = height; // Hinge leaf height. | |
| r = knuckle_radus; // Knuckle radius is equal to the leaf gauge. | |
| s = w + r; // Cartesian position of the point where the gusset curve merges with the leaf. | |
| g = m_leaf_gauge; // Leafe gauge. | |
| c = SCG_OVERLAP; // Amount to overlap unions in order to prevent Boolean anomalies. | |
| // Compute parabolic point of contact with the knuckle cylinder. | |
| i = sqrt ( 8.0*r*r + s*s ); // Common root. | |
| x = ( i - s )/2.0; // x intercept. | |
| y = sqrt ( r*r - x*x ); // y intercept. | |
| // Compute coefficient 'a' of vertex form parabola. | |
| // y = a2(x-s)2 | |
| an = root4 ( 2.0 ) * root4 ( s*( i - s ) - 2.0*r*r ); // Numerator. | |
| ad = sqrt ( s*( 5.0*s - 3.0*i ) + 4.0*r*r ); // Denominator. | |
| a = an / ad; // Coefficient 'a' of, y = a2(x-s)2 | |
| // Compute work piece translation and dimensions. | |
| wp_xd = 0; // Work piece origin x. | |
| wp_yd = 0; // Work piece origin y. | |
| wp_zd = -g + c; // Work piece origin z. | |
| wp_w = s; // Work piece width (x axis length). | |
| wp_g = g + y - c; // Work piece gauge (y access length. i.e. thickness). | |
| wp_h = h; // Work piece height (y axis length). | |
| // Compute cutting tool translation and dimensions. | |
| ct_xd = 0; | |
| ct_yd = 0; | |
| ct_zd = 0; | |
| ct_w0 = x; | |
| ct_w1 = s; | |
| ct_g0 = y; | |
| ct_g1 = 0; | |
| ct_h = h + 2*c; | |
| // Compute positive or negative tool orientation. We flip the tool by using a negative unit scale. | |
| test_yd = 0; | |
| zs = ( scg_type == C_POSITIVE ) ? 1.0 : -1.0; | |
| scale ( [ 1.0, -1.0, zs ] ) | |
| // Create gusset work piece. | |
| difference() | |
| { | |
| // Work piece. | |
| translate ( [ wp_xd, wp_yd + test_yd, wp_zd ] ) rotate ( [ 90, 0, 0 ] ) | |
| { | |
| linear_extrude ( height = wp_h, center = CENTER ) rectangle ( w = wp_w, h = wp_g ); | |
| } | |
| // Parabolic cutting tool. | |
| translate ( [ ct_xd, ct_yd + test_yd, ct_zd ] ) rotate ( [ 90, 0, 0 ] ) | |
| { | |
| linear_extrude ( height = ct_h, center = CENTER ) parabolic_conic_section ( a, s, 0, s, RESOLUTION ); | |
| } | |
| } | |
| } | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // Module: tool_cutter_fastener | |
| // Module Type: Cutting Tool. | |
| // | |
| // Description: | |
| // | |
| // - Cutting tool used to cut fastener holes into leaf workpiece. | |
| // | |
| // Parameters: | |
| // | |
| // - z_offset: | |
| // Depth of the cut. | |
| // | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| module tool_cutter_fastener ( z_offset, ) | |
| { | |
| // Create cutting tool. | |
| union () | |
| { | |
| // Thread | |
| tool_cutter_thread ( z_offset ); | |
| // Head. | |
| tool_cutter_head ( z_offset ); | |
| } | |
| } | |
| module tool_cutter_head ( z_offset, ) | |
| { | |
| // Initialize local variables. | |
| id = m_fastener_thread_diameter; // Inner diameter. | |
| od = m_fastener_head_diameter; // Outer diameter. | |
| t = m_fstener_head_type; // 0 = Fillister (Pan head), 1 = flat countersunk. | |
| d = m_counter_sink_depth; // Depth of head counter sink. | |
| z0 = z_offset - m_leaf_gauge; // Vertical position of head. | |
| z1 = z_offset - m_counter_sink_depth; // Vertical position of thread. | |
| h0 = m_leaf_gauge; // Height of head. | |
| h1 = m_counter_sink_depth; // Height of thread. | |
| c = SCG_OVERLAP; | |
| // Create cutting tool. | |
| union () | |
| { | |
| // Fastener head. | |
| translate ( [ 0, 0, z1 ] ) | |
| { | |
| // Fillister (Pan head). | |
| if ( t == 0 ) | |
| { | |
| d_top = od; | |
| d_bottom = od; | |
| h = h1 + c; | |
| cylinder ( d2 = d_top, d1 = d_bottom, h = h ); | |
| } | |
| // Flat countersunk. | |
| if ( t == 1 ) | |
| { | |
| d_top = od + c; | |
| d_bottom = id; | |
| h = h1 + c; | |
| cylinder ( d2 = d_top, d1 = d_bottom, h = h ); | |
| } | |
| } | |
| // Cutting tool extention. | |
| translate ( [ 0, 0, c ] ) | |
| { | |
| cylinder ( d = od, h = m_leaf_gauge ); | |
| } | |
| } | |
| } | |
| module tool_cutter_thread ( z_offset, ) | |
| { | |
| // Initialize local variables. | |
| id = m_fastener_thread_diameter; // Inner diameter. | |
| od = m_fastener_head_diameter; // Outer diameter. | |
| t = m_fstener_head_type; // 0 = Fillister (Pan head), 1 = flat countersunk. | |
| d = m_counter_sink_depth; // Depth of head counter sink. | |
| z0 = z_offset - m_leaf_gauge; // Vertical position of head. | |
| z1 = z_offset - m_counter_sink_depth; // Vertical position of thread. | |
| h0 = m_leaf_gauge; // Height of head. | |
| h1 = m_counter_sink_depth; // Height of thread. | |
| c = SCG_OVERLAP; | |
| // Create cutting tool. | |
| union () | |
| { | |
| // Thread | |
| translate ( [ 0, 0, z0 - c ] ) | |
| { | |
| cylinder ( d = id, h = h0 + 2.0*c ); | |
| } | |
| } | |
| } | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // Module: tool_cutter_fastener_set | |
| // Module Type: Cutting Tool. | |
| // | |
| // Description: | |
| // | |
| // - Cutting tool used to cut fastener holes into leaf workpiece. | |
| // | |
| // Parameters: | |
| // | |
| // - fastener_count: | |
| // Number of fastener holes to be cut into a single leaf. | |
| // The total number of fastener holes on the whole hinge, will be twice the value of fastener_count. | |
| // i.e. 'fastener_count' holes, on each leaf. | |
| // | |
| // - fastener_column_count: | |
| // Number of fastener column per leaf. This value can be either 1, or 2. | |
| // | |
| // - z_offset: | |
| // Depth of the cut. | |
| // | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| module tool_cutter_fastener_set ( fastener_count, fastener_column_count, z_offset ) | |
| { | |
| // Relative origin. | |
| xo = m_leaf_gauge + m_component_clearance/2 + m_fastener_head_diameter/2 + m_fastener_margin; | |
| yo = -m_leaf_height/2 + m_fastener_head_diameter/2 + m_fastener_margin; | |
| // Column offsets. | |
| col0 = 0; | |
| col1 = m_leaf_width - m_fastener_head_diameter/2 - m_fastener_margin - xo; | |
| // Loop configuration. | |
| even = ( fastener_count % 2 ) ? false : true; | |
| n1 = fastener_count - 1; | |
| n2 = round ( fastener_count / 2 ) - 1; | |
| k1 = ( m_leaf_height - m_fastener_head_diameter - 2*m_fastener_margin ) / n1; | |
| k2 = ( m_leaf_height - m_fastener_head_diameter - 2*m_fastener_margin ) / n2; | |
| // Generate fastener cutting tool. | |
| if ( fastener_slotted == true ) | |
| { | |
| // slotted holes | |
| for ( row = [ 0 : n1 ] ) | |
| { | |
| if ((row == 0) || (row == n1)) | |
| { | |
| t1x = xo + col0; | |
| t1y = yo + row * k1; | |
| t1z = 0; | |
| t2x = xo + col1; | |
| t2y = yo + row * k1; | |
| t2z = 0; | |
| hull() | |
| { | |
| translate([t1x,t1y,t1z]) tool_cutter_head ( z_offset ); | |
| translate([t2x,t2y,t2z]) tool_cutter_head ( z_offset ); | |
| } | |
| hull() | |
| { | |
| translate([t1x,t1y,t1z]) tool_cutter_thread ( z_offset ); | |
| translate([t2x,t2y,t2z]) tool_cutter_thread ( z_offset ); | |
| } | |
| } | |
| else | |
| { | |
| // [0:middle, 1:inner, 2:outer, 3:slotted] | |
| if ( fastener_slotted_middle == 0 ) | |
| { | |
| cx = ( col0 + col1 ) / 2.0; | |
| tx = xo + cx; | |
| ty = yo + row * k1; | |
| tz = 0; | |
| translate([tx,ty,tz]) tool_cutter_fastener ( z_offset ); | |
| } | |
| else if ( fastener_slotted_middle == 1 ) | |
| { | |
| cx = col0; | |
| tx = xo + cx; | |
| ty = yo + row * k1; | |
| tz = 0; | |
| translate([tx,ty,tz]) tool_cutter_fastener ( z_offset ); | |
| } | |
| else if ( fastener_slotted_middle == 2 ) | |
| { | |
| cx = col1; | |
| tx = xo + cx; | |
| ty = yo + row * k1; | |
| tz = 0; | |
| translate([tx,ty,tz]) tool_cutter_fastener ( z_offset ); | |
| } | |
| else if ( fastener_slotted_middle == 3 ) | |
| { | |
| t1x = xo + col0; | |
| t1y = yo + row * k1; | |
| t1z = 0; | |
| t2x = xo + col1; | |
| t2y = yo + row * k1; | |
| t2z = 0; | |
| hull() | |
| { | |
| translate([t1x,t1y,t1z]) tool_cutter_head ( z_offset ); | |
| translate([t2x,t2y,t2z]) tool_cutter_head ( z_offset ); | |
| } | |
| hull() | |
| { | |
| translate([t1x,t1y,t1z]) tool_cutter_thread ( z_offset ); | |
| translate([t2x,t2y,t2z]) tool_cutter_thread ( z_offset ); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| else { | |
| // One column of fastener holes, if we have selected one fastener hole column. | |
| if ( fastener_column_count == 1 ) | |
| { | |
| for ( row = [ 0 : n1 ] ) | |
| { | |
| cx = ( col0 + col1 ) / 2.0; | |
| tx = xo + cx; | |
| ty = yo + row * k1; | |
| tz = 0; | |
| translate ( [ tx, ty, tz ] ) tool_cutter_fastener ( z_offset ); | |
| } | |
| } | |
| // Two columns of fastener holes, if we have selected two fastener hole column. | |
| if ( fastener_column_count == 2 ) | |
| { | |
| for ( col = [ 0 : 1 ] ) | |
| { | |
| // Column 0, offset translation when we have an odd number of fasteners. | |
| if ( col == 0 ) | |
| { | |
| m = ( even ) ? 0 : 1; | |
| for ( row = [ 0 : n2 - m ] ) | |
| { | |
| cx = ( col == 0 ) ? col0 : col1; | |
| tx = xo + cx; | |
| ty = ( even ) ? yo + row * k2 : yo + row * k2 + k2/2; | |
| tz = 0; | |
| translate ( [ tx, ty, tz ] ) tool_cutter_fastener ( z_offset ); | |
| } | |
| } | |
| // Column 1. | |
| if ( col == 1 ) | |
| { | |
| for ( row = [ 0 : n2 ] ) | |
| { | |
| cx = ( col == 0 ) ? col0 : col1; | |
| tx = xo + cx; | |
| ty = yo + row * k2; | |
| tz = 0; | |
| translate ( [ tx, ty, tz ] ) tool_cutter_fastener ( z_offset ); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // Module: tool_cutter_text. | |
| // Module Type: Tool cutter. | |
| // | |
| // Description: | |
| // | |
| // - Inscribes a string of text onto a surface. | |
| // | |
| // Parameters: | |
| // | |
| // - string: | |
| // The string of text we would like to inscribes. | |
| // | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| module tool_cutter_text ( string, size ) | |
| { | |
| // create text cutter. | |
| font = "Ariel:style=Bold"; | |
| height = 0.15*6.0; | |
| xd = 20.0; | |
| yd = 0.0; | |
| zd = height; | |
| translate ( [ xd, yd, -zd ] ) | |
| { | |
| rotate ( [ 0.0, 0.0, -90.0 ] ) | |
| { | |
| linear_extrude ( height = height + SCG_OVERLAP ) | |
| { | |
| text ( string, font = font, size = size, valign = "center", halign = "center" ); | |
| } | |
| } | |
| } | |
| } | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // Module: tool_cutter_knuckle_array | |
| // Module Type: Cutting tool. | |
| // | |
| // Description: | |
| // | |
| // - Create an array of cutting blocks. Mostly used to cut gusset workpiece into individual gusset positives or negatives. | |
| // | |
| // Parameters: | |
| // | |
| // - gender: | |
| // Specifies the number of knuckle joints based on hinge leaf gender. | |
| // | |
| // - fill_component_clearance: | |
| // If true, then create wide cutting blocks that fill in the component clearance. | |
| // If false, then create narrow cutting blocks that leave space for the component clearance. | |
| // | |
| // - size: | |
| // Specifies the dimension used for the x and z axes. | |
| // | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| module tool_cutter_knuckle_array ( gender, fill_component_clearance, size ) | |
| { | |
| // Initialize local variables. | |
| n = m_knuckle_count; | |
| h = m_leaf_height; | |
| c = m_component_clearance; | |
| e = SCG_OVERLAP; | |
| // Compute knuckle width and segment width. | |
| k = ( h + c )/n - c; | |
| s = ( fill_component_clearance ) ? k + 2.0*c : k; | |
| // Compute segment offset. | |
| o = ( fill_component_clearance ) ? c : 0.0; | |
| // Generate block array. | |
| a = 0; | |
| b = ( gender == C_MALE ) ? n/2 : n/2-1; | |
| g = ( gender == C_MALE ) ? 0.0 : k + c; | |
| for ( i = [ a : b ] ) | |
| { | |
| // Compute translation index. | |
| ki = g + 2.0*i*(k + c ) - h/2.0 - o; | |
| // Initialize translation. | |
| xt = -size/2.0; | |
| yt = ki; | |
| zt = -size/2.0; | |
| // Initialize cutting block dimensions. | |
| cube_x = size; | |
| cube_y = s; | |
| cube_z = 2.0*size; | |
| // Create cutting block. | |
| color ( "red" ) | |
| translate ( [ xt, yt, zt ] ) | |
| cube ( [ cube_x, cube_y, cube_z ] ); | |
| } | |
| } | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // Module: tool_cutter_pin_shaft_counterbore | |
| // Module Type: Cutting tool. | |
| // | |
| // Description: | |
| // | |
| // - Cuts a counterbore into the endcaps of the pin shaft. | |
| // - If the model is being printed in its default orientation, open and flat on the build plate, then support material may be required | |
| // for the counterbore. | |
| // | |
| // Parameters: | |
| // | |
| // - diameter: | |
| // Specifies the diameter of the counterbore. | |
| // For square and hexagonal counterbore shapes, the diameter refers to the inscribed circle of those shapes. | |
| // | |
| // - depth: | |
| // Specifies the depth of the cut. | |
| // | |
| // - shape: | |
| // The shame of the counterbore. | |
| // - Circular | |
| // - Square | |
| // - Hexagonal | |
| // | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| module tool_cutter_pin_shaft_counterbore ( diameter_top, depth_top, shape_top, diameter_bottom, depth_bottom, shape_bottom ) | |
| { | |
| // Local constants. | |
| TOP_COUNTER_BORE_ENABLED = true; | |
| BOTTOM_COUNTER_BORE_ENABLED = true; | |
| // Initialize local variables. | |
| d0 = diameter_bottom; | |
| d1 = diameter_top; | |
| h0 = depth_bottom + SCG_OVERLAP; | |
| h1 = depth_top + SCG_OVERLAP; | |
| // Compute diameter of polygon, inscribed by a circle of radius d/2. | |
| s = 6; // Polygon sides. | |
| a = 360.0/(2.0*s); // Half the angle between each point of the polygon. | |
| x0 = d0/2.0; // Bottom: Run of the right angle triangle who hypotenuse is equal to half the radius of our new circle. | |
| y0 = x0*tan ( a ); // Bottom: Rise of the right angle triangle who hypotenuse is equal to half the radius of our new circle. | |
| r0 = sqrt ( x0*x0 + y0*y0 ); // Bottom: Hypotenuse of the right angle triangle who hypotenuse is equal to half the radius of our new circle. | |
| x1 = d1/2.0; // Top: Run of the right angle triangle who hypotenuse is equal to half the radius of our new circle. | |
| y1 = x1*tan ( a ); // Top: Rise of the right angle triangle who hypotenuse is equal to half the radius of our new circle. | |
| r1 = sqrt ( x1*x1 + y1*y1 ); // Top: Hypotenuse of the right angle triangle who hypotenuse is equal to half the radius of our new circle. | |
| // Compute cutting tool translation. | |
| xd = 0.0; | |
| yd0 = ( h0 - m_leaf_height )/2.0 - SCG_OVERLAP; | |
| yd1 = -( h1 - m_leaf_height )/2.0 + SCG_OVERLAP; | |
| zd = 0.0; | |
| // Compute polygon rotation angle. | |
| rx = 90.0; | |
| ry = ( s%2 == 0 ) ? a+90 : -a/2.0; | |
| rz = 0.0; | |
| // Create top counterbore cutting tool. | |
| if ( BOTTOM_COUNTER_BORE_ENABLED ) | |
| { | |
| color ( "red" ) | |
| if ( shape_bottom == C_CIRCULAR ) | |
| { | |
| translate ( [ xd, yd0, zd ] ) rotate ( [ rx, ry, rz ] ) cylinder ( h = h0, r = d0/2.0, center = true ); | |
| } | |
| else if ( shape_bottom == C_SQUARE ) | |
| { | |
| translate ( [ xd, yd0, zd ] ) cube ( [ diameter_bottom, h0, diameter_bottom ], center = true ); | |
| } | |
| else if ( shape_bottom == C_HEXAGONAL ) | |
| { | |
| translate ( [ xd, yd0, zd ] ) rotate ( [ rx, ry+90, rz ] ) cylinder ( h = h0, r = r0, center = true, $fn = s ); | |
| } | |
| } | |
| // Create bottom counterbore cutting tool. | |
| if ( TOP_COUNTER_BORE_ENABLED ) | |
| { | |
| color ( "red" ) | |
| if ( shape_top == C_CIRCULAR ) | |
| { | |
| translate ( [ xd, yd1, zd ] ) rotate ( [ rx, ry, rz ] ) cylinder ( h = h1, r = d1/2.0, center = true ); | |
| } | |
| else if ( shape_top == C_SQUARE ) | |
| { | |
| translate ( [ xd, yd1, zd ] ) cube ( [ diameter_top, h1, diameter_top ], center = true ); | |
| } | |
| else if ( shape_top == C_HEXAGONAL ) | |
| { | |
| translate ( [ xd, yd1, zd ] ) rotate ( [ rx, ry, rz ] ) cylinder ( h = h1, r = r1, center = true, $fn = s ); | |
| } | |
| } | |
| } | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // Module: parabolic_conic_section. | |
| // Module Type: 2D Shape. | |
| // | |
| // Description: | |
| // | |
| // - Creates a parabolic conic section object. | |
| // | |
| // Parameters: | |
| // | |
| // - radius: | |
| // Radius of the cylinder sector. | |
| // | |
| // - a: | |
| // Coefficient of the vertex form parabola, y = a2(x-b)2. | |
| // | |
| // - x: | |
| // x Coordinate of parabola turning point. | |
| // Note: | |
| // For the sake of simplifying the actual parabolic function used in the recursive | |
| // function "parabolic_vector", we use a call to "translate" to set the vertex, rather than the parabolic function its self. | |
| // | |
| // - y: | |
| // y Coordinate of parabola turning point. | |
| // Note: | |
| // For the sake of simplifying the actual parabolic function used in the recursive | |
| // function "parabolic_vector", we use a call to "translate" to set the vertex, rather than the parabolic function its self. | |
| // | |
| // - domain: | |
| // The input domain x, over which to compute the parabolic function. | |
| // | |
| // - resolution: | |
| // The input domain step size, is used to control the resolution of the shape. | |
| // | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| module parabolic_conic_section ( a, x, y, domain, resolution ) | |
| { | |
| // Generate 2D geometry | |
| t = 0.0; | |
| n = resolution; | |
| i = 0; | |
| d = domain; | |
| v = []; | |
| points = parabolic_vector ( a, t, n, i, d, v ); | |
| // Generate 3D object. | |
| translate ( [ x, y, 0 ] ) | |
| polygon ( points ); | |
| } | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // Module: triangle. | |
| // Module Type: 2D Shape. | |
| // | |
| // Description: | |
| // | |
| // - Creates a 2D triangle from three vertices. | |
| // | |
| // Parameters: | |
| // | |
| // - x0, x1, x2 | |
| // x coordinates of vertices 0 through 2. | |
| // | |
| // - y0, y1, y2 | |
| // y coordinates of vertices 0 through 2. | |
| // | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| module triangle ( v ) | |
| { | |
| polygon ( points = v ); | |
| } | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // Module: Rectangle. | |
| // Module Type: 2D Shape. | |
| // | |
| // Description: | |
| // | |
| // - Creates a 2D rectangle. | |
| // | |
| // Parameters: | |
| // | |
| // - w | |
| // Rectangle width. | |
| // | |
| // - h | |
| // Rectangle height. | |
| // | |
| // - center | |
| // Center the rectangle about the origin (0,0,0) if true, else place the rectangle in the positive quadrant. | |
| // | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| module rectangle ( w, h, center ) | |
| { | |
| scale ( [ w, h ] ) square ( size = 1.0, center = center ); | |
| } | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // Function: root4 | |
| // | |
| // Description: | |
| // | |
| // - Compute the 4th root of x. | |
| // | |
| // Return Value: | |
| // | |
| // - Return the 4th root of x. | |
| // | |
| // Parameters: | |
| // | |
| // - x | |
| // Input value. | |
| // | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| function root4 ( x ) = ( x >= 0 ) ? sqrt ( sqrt ( x ) ) : 0; | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // Function: Clip | |
| // | |
| // Description: | |
| // | |
| // - Clips an input value, to a minimum and maximum value. | |
| // | |
| // x_min <= x <= x_max | |
| // | |
| // Parameters: | |
| // | |
| // - x | |
| // Input value. | |
| // | |
| // - x_min | |
| // Minimal value constraint. Any x less than x_min, is set to x_min. | |
| // | |
| // - x_max | |
| // Maximum value constraint. Any x greater than x_max, is set to x_max. | |
| // | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| function clip ( x, x_min, x_max ) = ( x < x_min ) ? x_min : ( x > x_max ) ? x_max : x; | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // Function: Generate a parabolic vector point array. | |
| // | |
| // Description: | |
| // | |
| // - Recursive function to generate an array of 2D points on a parabolic curve. | |
| // | |
| // - The parabolic vertex form is used. | |
| // | |
| // y = a2(x-b)2 | |
| // | |
| // Where, | |
| // | |
| // a is the horizontal scale of the parabola. | |
| // (b,c) is the Cartesian position of the turning point. | |
| // | |
| // | |
| // Parameters: | |
| // | |
| // - a | |
| // Horizontal scale of the parabola. | |
| // | |
| // - x | |
| // Horizontal input domain. | |
| // | |
| // - n | |
| // Tessellation factor. Number of points to compute for each half of the parabola object, with both halves sharing the turning point. | |
| // For example: | |
| // - A tessellation factor of 1, will compute 3 points in total. Two for each half, with one out of the two on each half being the | |
| // Shared turning point. | |
| // - A tessellation factor of 2, with compute 5 points in total, 3 for each half with a shared turning point. | |
| // | |
| // - i | |
| // Point index. Initialize to zero. | |
| // | |
| // - d | |
| // Input domain. The x range over which to compute the function. | |
| // -d <= x <= d | |
| // | |
| // - v | |
| // Vector that will be populated with geometry points. Initialize to empty vector, []. | |
| // | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| function parabolic_vector ( a, x, n, i, d, v ) = | |
| ( | |
| i > 2.0*d*n | |
| // Recursive terminating condition: | |
| // Return an empty vector. | |
| ? concat ( v, [] ) | |
| // Recursive general condition: | |
| // Compute the next point on the parabolic path. | |
| // x = i/n - 1 | |
| // y = a2(i/n - 1)2 | |
| : parabolic_vector ( a, x, n, i + 1, d, concat ( v, [ [ i/n - d, a*a*(i/n - d)*(i/n - d) ] ] ) ) | |
| ); | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // Function: funtion_name | |
| // | |
| // Description: | |
| // | |
| // - Function description. | |
| // | |
| // Return Value: | |
| // | |
| // - Description of return value. | |
| // | |
| // Parameters: | |
| // | |
| // - x | |
| // Argument x description. | |
| // | |
| // - y | |
| // Argument y description. | |
| // | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
| // Module: module_name | |
| // Module Type: [ 2D Shape, Profile, Tool, Workpiece, Component ] | |
| // Description: | |
| // | |
| // - Module description. | |
| // | |
| // Parameters: | |
| // | |
| // - x | |
| // Argument x description. | |
| // | |
| // - y | |
| // Argument y description. | |
| // | |
| // -------------------------------------+---------------------------------------+---------------------------------------+--------------------------------------- | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment