/* ******************************************* Objekt Info: Parametrierbare Schaniere ******************************************* Version: 27.09.2022 khf ******************************************* */ //*************** Auswahl ************* enable_male_leaf = 1; // [ 0:Nein, 1:Ja ] enable_female_leaf = 1; // [ 0:Nein, 1:Ja ] enable_fillet = 1; // [ 0:Nein, 1:Ja ] // Schalte diese Option aus, um den Scharnierstift vom weiblichen Blatt wegzulassen. enable_pin = 1; // [ 0:Nein, 1:Ja ] // Deaktiviere diese Option, um einen benutzerdefinierten Stiftdurchmesser festzulegen. Die automatische Pingroesse entspricht der Blattstaerke. enable_auto_pin_size = 1; // [ 0:Nein, 1:Ja ] enable_pin_shaft_counterbore = 0; // [ 0:Nein, 1:Ja ] enable_fasteners = 1; // [ 0:Nein, 1:Ja ] knuckle_gusset_type = 2; // [ 0:None, 1:Linear, 2:Circular, 3:Parabolic ] // Von +180 Grad voll geschlossen, bis -90 Grad voll geoeffnet. Standard = 0 (dh. geoeffnet). throw_angle = 0.0; // [ -90 : 5 : 180 ] // Dreht das Modell um 180 Grad um die z-Achse. flip_model = 1; // [ 0:Nein, 1:Ja ] // Der empfohlene Wert ist 64 oder hoeher. resolution = 128; component_color = "Silver"; //***************************************** //*************** Parameter ************* /* [Scharnierparameter] --------------------------------------------------*/ hinge_width = 45.0; //Groesse!!!!!!!!!!!!!!!! leaf_height = 40.0; // Blatt- und Knoecheldicke. Werte groesser als 3 mm empfohlen. leaf_gauge = 3.0; // Empfohlene Werte zwischen 0,3 und 4,0. Bessere Qualitaet unter 3,0, schwer zu loesen. component_clearance = 0.4; // Die Knoechelanzahl muss eine ungerade Zahl sein, damit der Pin an beiden Enden unterstuetzt wird. knuckle_count = 5; // [3:2:31] // Manuelle Einstellung des Stiftdurchmessers. Hat nur Wirkung, wenn "Enable Auto Pin Size" auf "No" gesetzt ist. pin_diameter = 3.0; parametric_pin_diameter = ( enable_auto_pin_size == 1 ) ? leaf_gauge : pin_diameter; /* [Parameter der Stiftwelle] */ 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 ] /* [Parameter des Verbindungselements] */ // Bei Senkungen kann der Fasenwinkel mit den anderen Parametern eingestellt werden. fstener_head_type = 1; // [ 0:Counterbored, 1:Countersunk ] counter_sink_depth = 2.5; fastener_thread_diameter = 3.5; // Fuege dem Kopfdurchmesser des Verbindungselements 0,5 mm bis 1,0 mm hinzu, um eine Kopffreiheit zu ermoeglichen. fastener_head_diameter = 7.0; fastener_count = 2; // [3:32] fastener_column_count = 2; // [1,2] // Abstand vom Rand des Kopfdurchmessers zu den Raendern der Blaetter. fastener_margin = 1; //************** Programm ************** C_CONSTANT = 0 + 0; C_NONE = C_CONSTANT + 0; C_FEMALE = C_CONSTANT + 0; C_MALE = C_CONSTANT + 1; SCG_OVERLAP = C_CONSTANT + 0.01; C_NEGATIVE = C_CONSTANT + 0; C_POSITIVE = C_CONSTANT + 1; C_CIRCULAR = C_CONSTANT + 0; C_SQUARE = C_CONSTANT + 1; C_HEXAGONAL = C_CONSTANT + 2; 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 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; 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 ); 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 ); 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 ); 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; 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; m_resolution = clip ( resolution, C_MIN_TESSELLATION, C_MAX_TESSELLATION ); m_component_color = component_color; C_DEBUG_ENABLED = false; 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 ); } 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 ( 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; gender_angle = ( gender == C_FEMALE ) ? 0 : 180; rotate ( [ 0, 0, gender_angle ] ) { color ( m_component_color ) difference () { workpiece_leaf_knuckle_pin ( gender ); if ( m_fasteners_enabled ) { tool_cutter_fastener_set ( m_fastener_count, m_fastener_column_count, 0 ); } 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 ); } 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 ( gender ) { d = m_parametric_pin_diameter; c = m_component_clearance; e = SCG_OVERLAP; if ( gender == C_FEMALE ) { if ( m_pin_enabled ) { union () { dc = d - c/2.0; workpiece_leaf_knuckle ( C_FEMALE ); pin ( dc, m_leaf_height - e ); } } else { difference () { dc = d + c/2.0; workpiece_leaf_knuckle ( C_FEMALE ); pin ( dc, m_leaf_height + e ); } } } else { difference () { dc = d + c/2.0; workpiece_leaf_knuckle ( C_MALE ); pin ( dc, m_leaf_height + e ); } } } 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 ( gender ) { 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; difference () { difference () { 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 ); } } } tool_cutter_knuckle_array ( gender = gender, fill_component_clearance = true, size = 2.0*m_leaf_gauge + m_component_clearance ); } 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 ( w, l, h, r ) { translate ( [ 0, 0, -h ] ) { union () { if ( m_leaf_fillet_enabled ) { cube ( [ w-r, l, h] ); translate ( [ 0, r, 0 ] ) cube ( [ w, l-2*r, h] ); translate ( [ w - r, r, 0 ] ) cylinder ( r = r, h = h ); translate ( [ w - r, l-r, 0 ] ) cylinder ( r = r, h = h ); } else { cube ( [ w, l, h] ); } } } } module workpiece_gusset_array ( gender, curve, scg_type, fill_component_clearance ) { cutting_block_size = m_leaf_gauge + m_knuckle_gusset_width; leaf_height = ( scg_type == C_NEGATIVE ) ? m_leaf_height + SCG_OVERLAP : m_leaf_height; xt = cutting_block_size/2.0; yt = 0.0; zt = 0.0; difference () { workpiece_gusset ( width = m_knuckle_gusset_width, height = leaf_height, knuckle_radus = m_leaf_gauge, curve = curve, scg_type = scg_type ); translate ( [ xt, yt, zt ] ) tool_cutter_knuckle_array ( gender = gender, fill_component_clearance = !fill_component_clearance, size = cutting_block_size ); } } 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 ( width, height, knuckle_radus, scg_type ) { CENTER = true; DEBUG_ENABLED = true; w = width; h = height; r = knuckle_radus; s = w + r; g = m_leaf_gauge; c = SCG_OVERLAP; x = r*r/s; y = sqrt ( r*r - x*x ); a = y/( x - s ); b = -a*s; wp_xd = 0; wp_yd = 0; wp_zd = -g + c; wp_w = s; wp_g = g + y - c; wp_h = h; 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; 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 ( width, height, knuckle_radus, scg_type ) { CENTER = true; w = width; g = knuckle_radus; c = SCG_OVERLAP; r = ( 2.0*g*w + w*w ) / ( 2.0*g ); h = ( g*r ) / sqrt ( g*g + 2.0*g*w + r*r + w*w ); x = h*( g + w ) / r; ctxd = g + w; ctyd = c; ctzd = r; ctt = height + 2.0*x; wpw = g + w -x; wph = h + c; wpxd = x; wpyd = 0.0; wpzd = 0.0 - c; wpt = height; xr = 90.0; yr = 0.0; zr = 0.0; xs = 1.0; ys = -1.0; zs = ( scg_type == C_POSITIVE ) ? 1.0 : -1.0; 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 ( width, height, knuckle_radus, scg_type ) { CENTER = true; DEBUG_ENABLED = true; RESOLUTION = m_resolution / C_MIN_TESSELLATION; w = width; h = height; r = knuckle_radus; s = w + r; g = m_leaf_gauge; c = SCG_OVERLAP; i = sqrt ( 8.0*r*r + s*s ); x = ( i - s )/2.0; y = sqrt ( r*r - x*x ); an = root4 ( 2.0 ) * root4 ( s*( i - s ) - 2.0*r*r ); ad = sqrt ( s*( 5.0*s - 3.0*i ) + 4.0*r*r ); a = an / ad; wp_xd = 0; wp_yd = 0; wp_zd = -g + c; wp_w = s; wp_g = g + y - c; wp_h = h; 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; 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 ) parabolic_conic_section ( a, s, 0, s, RESOLUTION ); } } } module tool_cutter_fastener ( z_offset, ) { id = m_fastener_thread_diameter; od = m_fastener_head_diameter; t = m_fstener_head_type; d = m_counter_sink_depth; z0 = z_offset - m_leaf_gauge; z1 = z_offset - m_counter_sink_depth; h0 = m_leaf_gauge; h1 = m_counter_sink_depth; c = SCG_OVERLAP; union () { translate ( [ 0, 0, z0 - c ] ) { cylinder ( d = id, h = h0 + 2.0*c ); } union () { translate ( [ 0, 0, z1 ] ) { if ( t == 0 ) { d_top = od; d_bottom = od; h = h1 + c; cylinder ( d2 = d_top, d1 = d_bottom, h = h ); } if ( t == 1 ) { d_top = od + c; d_bottom = id; h = h1 + c; cylinder ( d2 = d_top, d1 = d_bottom, h = h ); } } translate ( [ 0, 0, c ] ) { cylinder ( d = od, h = m_leaf_gauge ); } } } } module tool_cutter_fastener_set ( fastener_count, fastener_column_count, z_offset ) { 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; col0 = 0; col1 = m_leaf_width - m_fastener_head_diameter/2 - m_fastener_margin - xo; 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; 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 ); } } if ( fastener_column_count == 2 ) { for ( col = [ 0 : 1 ] ) { 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 ); } } 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 ( string, size ) { 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 ( gender, fill_component_clearance, size ) { n = m_knuckle_count; h = m_leaf_height; c = m_component_clearance; e = SCG_OVERLAP; k = ( h + c )/n - c; s = ( fill_component_clearance ) ? k + 2.0*c : k; o = ( fill_component_clearance ) ? c : 0.0; a = 0; b = ( gender == C_MALE ) ? n/2 : n/2-1; g = ( gender == C_MALE ) ? 0.0 : k + c; for ( i = [ a : b ] ) { ki = g + 2.0*i*(k + c ) - h/2.0 - o; xt = -size/2.0; yt = ki; zt = -size/2.0; cube_x = size; cube_y = s; cube_z = 2.0*size; color ( "red" ) translate ( [ xt, yt, zt ] ) cube ( [ cube_x, cube_y, cube_z ] ); } } module tool_cutter_pin_shaft_counterbore ( diameter_top, depth_top, shape_top, diameter_bottom, depth_bottom, shape_bottom ) { TOP_COUNTER_BORE_ENABLED = true; BOTTOM_COUNTER_BORE_ENABLED = true; d0 = diameter_bottom; d1 = diameter_top; h0 = depth_bottom + SCG_OVERLAP; h1 = depth_top + SCG_OVERLAP; s = 6; a = 360.0/(2.0*s); x0 = d0/2.0; y0 = x0*tan ( a ); r0 = sqrt ( x0*x0 + y0*y0 ); x1 = d1/2.0; y1 = x1*tan ( a ); r1 = sqrt ( x1*x1 + y1*y1 ); xd = 0.0; yd0 = ( h0 - m_leaf_height )/2.0 - SCG_OVERLAP; yd1 = -( h1 - m_leaf_height )/2.0 + SCG_OVERLAP; zd = 0.0; rx = 90.0; ry = ( s%2 == 0 ) ? a+90 : -a/2.0; rz = 0.0; 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 ); } } 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 ( a, x, y, domain, resolution ) { t = 0.0; n = resolution; i = 0; d = domain; v = []; points = parabolic_vector ( a, t, n, i, d, v ); translate ( [ x, y, 0 ] ) polygon ( points ); } module triangle ( v ) { polygon ( points = v ); } module rectangle ( w, h, center ) { scale ( [ w, h ] ) square ( size = 1.0, center = center ); } function root4 ( x ) = ( x >= 0 ) ? sqrt ( sqrt ( x ) ) : 0; function clip ( x, x_min, x_max ) = ( x < x_min ) ? x_min : ( x > x_max ) ? x_max : x; function parabolic_vector ( a, x, n, i, d, v ) = ( i > 2.0*d*n ? concat ( v, [] ) : parabolic_vector ( a, x, n, i + 1, d, concat ( v, [ [ i/n - d, a*a*(i/n - d)*(i/n - d) ] ] ) ) );