From 355418042299b4421c9fa30df8b21cc2d349bf55 Mon Sep 17 00:00:00 2001 From: zeus Date: Fri, 9 Sep 2022 13:22:30 +0200 Subject: [PATCH] added awesome modular multi-hdd-case --- .../Electronics/HardDisk.scad | 148 +++++++++++++++++ .../modular multi-hdd case/Functions/is.scad | 33 ++++ .../Modules/Box/rounded.scad | 137 ++++++++++++++++ .../Modules/Box/tray.scad | 76 +++++++++ .../Modules/Models/SFF/8200.scad | 152 ++++++++++++++++++ .../Modules/Models/SFF/8300.scad | 95 +++++++++++ .../Modules/Models/box.scad | 82 ++++++++++ 7 files changed, 723 insertions(+) create mode 100644 openscad/foreign/modular multi-hdd case/Electronics/HardDisk.scad create mode 100644 openscad/foreign/modular multi-hdd case/Functions/is.scad create mode 100644 openscad/foreign/modular multi-hdd case/Modules/Box/rounded.scad create mode 100644 openscad/foreign/modular multi-hdd case/Modules/Box/tray.scad create mode 100644 openscad/foreign/modular multi-hdd case/Modules/Models/SFF/8200.scad create mode 100644 openscad/foreign/modular multi-hdd case/Modules/Models/SFF/8300.scad create mode 100644 openscad/foreign/modular multi-hdd case/Modules/Models/box.scad diff --git a/openscad/foreign/modular multi-hdd case/Electronics/HardDisk.scad b/openscad/foreign/modular multi-hdd case/Electronics/HardDisk.scad new file mode 100644 index 0000000..4365e00 --- /dev/null +++ b/openscad/foreign/modular multi-hdd case/Electronics/HardDisk.scad @@ -0,0 +1,148 @@ +/** + * Genera un contenedor para almacenar discos duros. + * + * @author Joaquín Fernández + * @url https://gitlab.com/joaquinfq/openscad/blob/master/Electronics/HardDisk.scad + * @license CC-BY-NC-4.0 + * @see https://www.thingiverse.com/thing:3642857 + */ +//--------------------------------------------------------------- +// Variables personalizables +//--------------------------------------------------------------- +count = 4; // Cantidad de discos duros a almacenar. +desktop = false; // Indica si el disco duro es de PC (3.5") o portátil (2.5"). +notch = true; // Indica si se genera el espacio para sacar el disco con el dedo. +padding = 20; // Ancho de la pestaña a usar como separador entre discos. +screws = true; // Indica si se dejan los espacios para los tornillos. +thickness = 2; // Grosor de las paredes del contenedor. +tolerance = 0.9; // Tolerancia a usar en las medidas del disco duro. +model = 5; // Tipo de disco duro (altura estándar): + // 2.5" + // 0: 19.05 + // 1: 17.00 + // 2: 15.00 + // 3: 12.70 + // 4: 10.50 + // 5: 9.50 + // 6: 8.47 + // 7: 7.00 + // 8: 5.00 + // 3.5" + // 0: 42.00 + // 1: 26.10 + // 2: 17.80 +//--------------------------------------------------------------- +use <../Modules/Box/rounded.scad> +use <../Modules/Models/SFF/8200.scad> +use <../Modules/Models/SFF/8300.scad> +//--------------------------------------------------------------- +// Valores calculados. No tocar sin estar seguro. +//--------------------------------------------------------------- +size = desktop + ? sff8300(tolerance = tolerance, type = model) + : sff8200(tolerance = tolerance, type = model); +width = size[desktop ? 3 : 4]; +height = size[1]; +length = size[desktop ? 2 : 6]; +dt = 2 * thickness; +d = (height - dt) * 0.7; +dy = height + thickness; +ty = thickness + count * dy; +epsilon = $preview ? 0.01 : 0; +$fn = $preview ? 60 : 180; + +/** + * Dibuja el separador de los discos. + * + * @param {Float} thickness Grosor del separador. + * @param {Float} radius Radio a usar para redondear el borde. + * @param {Float} width Ancho del espacio a dejar en el separador. + * @param {Float} length Longitud del espacio a dejar en el separador. + */ +module separator(thickness = thickness, radius = 5, width = width - padding, length = length - padding) +{ + _r = radius; + _r2 = _r * _r; + _w = width / 2; + _a1 = _w - _r; + _a2 = _w + _r; + _b = length - _r; + linear_extrude(thickness) + { + polygon( + points = [ + [ _a1, 0 ], + for (_x = [ 0 : 0.1 : _r ]) [ _x + _a1, - sqrt(_r2 - pow(_x, 2)) + _r ], + [ _w, _b ], + for (_x = [ - _r : 0.1 : 0 ]) [ _a2 + _x, sqrt(_r2 - pow(_x, 2)) + _b ], + [ _a2, _b + _r ], + [ _a2, _b + 2 * _r ], + [ - _a2, _b + 2 * _r ], + [ - _a2, _b + _r ], + for (_x = [ _r : -0.1 : 0 ]) [ - _a2 + _x, sqrt(_r2 - pow(_x, 2)) + _b ], + [ - _w, _b ], + for (_x = [ _r : -0.1 : 0 ]) [ - (_x + _a1), - sqrt(_r2 - pow(_x, 2)) + _r ], + [ - _a1, 0 ], + ] + ); + } +} + +//--------------------------------------------------------------- +// Inicio del script. +//--------------------------------------------------------------- +difference() +{ + boxRounded(width + dt, ty, length + thickness, 1.2, thickness); + for (n = [ 0 : count - 1 ]) + { + translate([ - width / 2, n * dy + thickness - ty / 2, - (length + thickness) / 2 + thickness ]) + { + if (desktop) + { + sff8300Model(length + 5, screws ? dt : 0, slot = 5, tolerance = tolerance, type = model); + } + else + { + sff8200Model(length + 5, screws ? dt : 0, slot = 5, tolerance = tolerance, type = model); + } + if (notch) + { + hull() + { + for (_x = [ d + thickness, width - (d + thickness) ]) + { + translate([ _x, height / 2, - thickness / 2 ]) + { + cylinder(h = 2 * dt, d = d, center = true); + } + } + } + } + if (n) + { + if (padding) + { + translate([ width / 2, dt / 4, padding - dt ]) + { + rotate([ 90, 0, 0 ]) + { + separator(dt); + } + } + } + else + { + translate([ width / 2, - epsilon, length / 2 ]) + { + cube([ width, dt + 2 * epsilon, length ], center = true); + } + } + } + } + } + translate([ 0, 0, (length + thickness) / 2 - dt / 2 + 0.01 ]) + { + cube([ width, count * height, dt ], center = true); + } +} diff --git a/openscad/foreign/modular multi-hdd case/Functions/is.scad b/openscad/foreign/modular multi-hdd case/Functions/is.scad new file mode 100644 index 0000000..10c2ae3 --- /dev/null +++ b/openscad/foreign/modular multi-hdd case/Functions/is.scad @@ -0,0 +1,33 @@ +/** + * Diversas funciones para detectar el tipo de datos de un valor. + * + * @author Joaquín Fernández + * @license CC-BY-NC-4.0 + * @url https://gitlab.com/joaquinfq/openscad/blob/master/Functions/is.scad + */ +/** + * Verifica si el valor es un array + * + * @param value Valor a verificar. + * + * @return `true` si el valor es un array. + */ +function isArray(x) = len(x) != undef && !isString(x); + +/** + * Verifica si el valor es un booleano + * + * @param value Valor a verificar. + * + * @return `true` si el valor es un booleano. + */ +function isBool(x) = !isString(x) && (str(x) == "true" || str(x) == "false"); + +/** + * Verifica si el valor es un texto + * + * @param value Valor a verificar. + * + * @return `true` si el valor es un texto. + */ +function isString(x) = x != undef && len(x) != undef && len(str(x,x)) == len(x) * 2; diff --git a/openscad/foreign/modular multi-hdd case/Modules/Box/rounded.scad b/openscad/foreign/modular multi-hdd case/Modules/Box/rounded.scad new file mode 100644 index 0000000..167ee50 --- /dev/null +++ b/openscad/foreign/modular multi-hdd case/Modules/Box/rounded.scad @@ -0,0 +1,137 @@ +/** + * Módulos para dibujar cajas con bordes redondeados. + * + * @author Joaquín Fernández + * @url https://gitlab.com/joaquinfq/openscad/blob/master/Modules/Box/rounded.scad + * @license CC-BY-NC-4.0 + */ +//---------------------------------------------------------- + use <../../Functions/is.scad> + //---------------------------------------------------------- +/** + * Genera las coordenadas para dibujar un rectángulo con las esquinas redondeadas. + * Cada esquina puede tener un radio diferente. + * + * @param {Float} width Ancho del rectángulo. + * @param {Float} height Alto del rectángulo. + * @param {Float[]} radius Radios a usar para redondear cada esquina. + */ +function boxRoundedRect(width, height, radius = [ 1, 1, 1, 1 ]) = let( + _r = radius[0] == undef + ? [ radius, radius, radius, radius ] + : radius + ) + [ + [ + [ 0, height - _r[0] ], + [ _r[0], height - _r[0] ], + [ _r[0], height ], + [ width - _r[1], height ], + [ width - _r[1], height - _r[1] ], + [ width , height - _r[1] ], + [ width , _r[2] ], + [ width - _r[2], _r[2] ], + [ width - _r[2], 0 ], + [ _r[3], 0 ], + [ _r[3], _r[3] ], + [ 0, _r[3] ] + ], + [ + [ _r[0], height - _r[0] ], + [ width - _r[1], height - _r[1] ], + [ width - _r[2], _r[2] ], + [ _r[3], _r[3] ] + ] + ]; +//---------------------------------------------------------- +/** + * Dibuja un bloque con los bordes XY redondeados. + * + * @param {Float} width Ancho del bloque (eje X). + * @param {Float} height Largo del bloque (eje Y). + * @param {Float} length Alto del bloque (eje Z). + * @param {Float|Float[]} radius Radios del borde de cada esquina. + */ +module boxRounded(width, height, length, radius = [ 1, 1, 1, 1 ]) +{ + if (radius) + { + translate([ - width / 2, - height / 2, - length / 2 ]) + { + linear_extrude(length) + { + boxRounded2d(width, height, radius); + } + } + } + else + { + cube([ width, height, length ], center = true); + } +} +//---------------------------------------------------------- +/** + * Dibuja un bloque con los bordes XY redondeados. + * + * @param {Float} width Ancho del bloque (eje X). + * @param {Float} height Largo del bloque (eje Y). + * @param {Float|Float[]} radius Radios del borde de cada esquina. + */ +module boxRounded2d(width, height, radius = [ 1, 1, 1, 1 ]) +{ + // Si se pasa un número, lo convertimos a un array. + _radius = isArray(radius) + ? radius + : [ radius, radius, radius, radius ]; + _data = boxRoundedRect(width, height, _radius); + polygon(points = _data[0]); + for (_index = [ 0 : 3 ]) + { + if (_radius[_index] > 0) + { + translate(_data[1][_index]) + { + circle(r = _radius[_index]); + } + } + } +} +//---------------------------------------------------------- +/** + * Dibuja un bloque con todos los bordes redondeados. + * + * @param width Ancho del bloque (eje X). + * @param height Largo del bloque (eje Y). + * @param length Alto del bloque (eje Z). + * @param radius Radio del borde. + */ +module boxRounded3d(width, height, length, radius = 1) +{ + if (radius > 0) + { + hull() + { + for (z = [ -1, 1 ]) + { + for (y = [ -1, 1 ]) + { + for (x = [ -1, 1 ]) + { + translate([ + x * (width / 2 - radius), + y * (height / 2 - radius), + z * (length / 2 - radius) + ]) + { + sphere(r = radius, center = true); + } + } + } + } + } + } + else + { + cube([ width, height, length ], center = true); + } +} diff --git a/openscad/foreign/modular multi-hdd case/Modules/Box/tray.scad b/openscad/foreign/modular multi-hdd case/Modules/Box/tray.scad new file mode 100644 index 0000000..d4e0557 --- /dev/null +++ b/openscad/foreign/modular multi-hdd case/Modules/Box/tray.scad @@ -0,0 +1,76 @@ +/** + * Genera una bandeja para insertar un modelo. + * + * @author Joaquín Fernández + * @url https://gitlab.com/joaquinfq/openscad/blob/master/Modules/Box/tray.scad + * @license CC-BY-NC-4.0 + */ +//---------------------------------------------------------- +/** + * Permite dibujar una bandeja y decidir cuáles caras eliminar. + * + * Los lados de la bandeja se enumeran de la siguiente manera (con respecto al plano XZ): + * + * - a : Parte trasera. + * - b : Parte inferior. + * - l : Parte izquierda. + * - r : Parte derecha. + * - t : Parte superior. + * + * @param {Float} width Anchura de la bandeja a generar (eje X). + * @param {Float} height Altura de la bandeja a generar (eje Y). + * @param {Float} length Longitud de la bandeja a generar (eje Z). + * @param {Float} thickness Grosor de las paredes de la bandeja. + * @param {Boolean} sides Lados de la bandeja a omitir. + */ +module boxTray(width, height, length, thickness = 5, sides = []) +{ + _t = 2 * thickness; + difference() + { + cube([ width + _t, height + _t, length + thickness ]); + translate([ thickness, thickness, 0 ]) + { + if ($children) + { + children(); + } + else + { + cube([ width, height, length ]); + } + } + for (_s = sides) + { + if (_s == "a") + { + translate([ 0, 0, length ]) + { + cube([ width + _t, height + _t, _t ]); + } + } + else if (_s == "b") + { + cube([ width + _t, thickness, length + _t ]); + } + else if (_s == "l") + { + translate([ width + thickness, 0, 0 ]) + { + cube([ thickness, height + _t, length + _t ]); + } + } + else if (_s == "r") + { + cube([ thickness, height + _t, length + _t ]); + } + else if (_s == "t") + { + translate([ 0, height + thickness, 0 ]) + { + cube([ width + _t, thickness, length + _t ]); + } + } + } + } +} diff --git a/openscad/foreign/modular multi-hdd case/Modules/Models/SFF/8200.scad b/openscad/foreign/modular multi-hdd case/Modules/Models/SFF/8200.scad new file mode 100644 index 0000000..a1b2c77 --- /dev/null +++ b/openscad/foreign/modular multi-hdd case/Modules/Models/SFF/8200.scad @@ -0,0 +1,152 @@ +/** + * Modelos y variables según la especificación SFF-8200. + * + * @author Joaquín Fernández + * @url https://gitlab.com/joaquinfq/openscad/blob/master/Modules/Models/SFF/8200.scad + * @license CC-BY-NC-4.0 + * + * @see SFF-8200 2.5" Form Factor Drives + */ +//---------------------------------------------------------- +use <../../Box/tray.scad> +use <../box.scad> +//---------------------------------------------------------- +/** + * Devuelve las especificaciones de las medidas según SFF-8200. + * + * @param {Float} tolerance Tolerancia a usar para ajustar las medidas. + * @param {Integer} type Tipo de unidad (0: pequeña, 1: mediana, 2: grande). + * + * @return {Float[]} + */ +function sff8200(tolerance = 0, type = 0) = [ + 3.00, // Diámetro del tornillo + ( + type == 0 + ? 19.05 + : type == 1 + ? 17.00 + : type == 2 + ? 15.00 + : type == 3 + ? 12.70 + : type == 4 + ? 10.50 + : type == 5 + ? 9.50 + : type == 6 + ? 8.47 + : type == 7 + ? 7.00 + : 5.00 + ) + tolerance, + 0.00, + 0.50, + 69.85 + tolerance, + 0.25, + 100.45 + tolerance, + undef, + undef, + undef, + 100.20 + tolerance, // #10 + 100.50 + tolerance, + 110.20 + tolerance, + undef, + undef, + undef, + undef, + undef, + undef, + undef, + undef, // #20 + undef, + undef, + 3.00 + tolerance / 2, + 34.93, + 38.10, + undef, + 0.50, + 4.07 + tolerance / 2, + 61.72, + 34.93, // #30 + 38.10, + undef, + 0.50, + undef, + undef, + undef, + 8.00, + 3.00, + undef, + undef, // #40 + 2.50, + undef, + undef, + undef, + undef, + undef, + undef, + undef, + undef, + 14.00 + tolerance / 2, // #50 + 90.60 + tolerance / 2, + 14.00 + tolerance / 2, + 90.60 + tolerance / 2 +]; +//---------------------------------------------------------- +/** + * Dibuja un modelo de una unidad de 3.5" según la especificación SFF-8200. + * + * Este modelo permite extraer el volumen posteriormente para crear una ranura + * como las usadas en las cajas de PCs. + * + * @param {Float} length Longitud de la unidad a generar. + * @param {Float} thickness Grosor del bloque donde se insertará el modelo. + * @param {Float} screw Diámetro del tornillo a usar. + * @param {Float} slot Longitud de la ranura donde se insertarán los tornillos. + * @param {Float} tolerance Valor a usar para ajustar las medidas estándar. + * @param {Integer} type Tipo de unidad (0: pequeña, 1: mediana, 2: grande). + */ +module sff8200Model(length = 0, thickness = 5, screw = 0, slot = 15, tolerance = 0.3, type = 0) +{ + _A = sff8200(tolerance, type); + modelBox( + _A[4], + _A[1], + length ? length : _A[6], + thickness, + screw ? screw : _A[0], + slot, + [ + [ _A[23], _A[6] - _A[52] ], + [ _A[23], _A[6] - _A[53] ] + ], + [ + [ _A[28], _A[6] - _A[50] ], + [ _A[28], _A[6] - _A[51] ], + [ _A[4] - _A[28], _A[6] - _A[50] ], + [ _A[4] - _A[28], _A[6] - _A[51] ] + ] + ); +} +//---------------------------------------------------------- +/** + * Dibuja una bandeja que puede insertarse en una ranura donde va una unidad de 3.5". + * + * @param {Float} length Longitud de la unidad a generar. + * @param {Float} thickness Grosor del bloque donde se insertará el modelo. + * @param {Float} screw Diámetro del tornillo a usar. + * @param {Float} slot Longitud de la ranura donde se insertarán los tornillos. + * @param {Float} tolerance Valor a usar para ajustar las medidas estándar. + * @param {Boolean} sides Lados a eliminar de la bandeja. + * @param {Integer} type Define la altura según el tipo de unidad (0: más grande, 8: más pequeña). + */ +module sff8200Tray(length = 0, thickness = 5, screw = 0, slot = 15, tolerance = 0.3, sides = [ "a", "t" ], type = 0) +{ + _A = sff8200(tolerance, type); + boxTray(_A[4], _A[1], length ? length : _A[6], thickness, sides) + { + sff8200Model(length, thickness, screw ? screw : _A[0], slot, tolerance, type); + } +} +//sff8200Tray(); \ No newline at end of file diff --git a/openscad/foreign/modular multi-hdd case/Modules/Models/SFF/8300.scad b/openscad/foreign/modular multi-hdd case/Modules/Models/SFF/8300.scad new file mode 100644 index 0000000..3f50736 --- /dev/null +++ b/openscad/foreign/modular multi-hdd case/Modules/Models/SFF/8300.scad @@ -0,0 +1,95 @@ +/** + * Modelos y variables según la especificación SFF-8300. + * + * @author Joaquín Fernández + * @url https://gitlab.com/joaquinfq/openscad/blob/master/Modules/Models/SFF/8300.scad + * @license CC-BY-NC-4.0 + * + * @see SFF-8300 3.5" Form Factor Drives + */ +//---------------------------------------------------------- +use <../../Box/tray.scad> +use <../box.scad> +//---------------------------------------------------------- +/** + * Devuelve las especificaciones de las medidas según SFF-8300. + * + * @param {Float} tolerance Tolerancia a usar para ajustar las medidas. + * @param {Integer} type Tipo de unidad (0: pequeña, 1: mediana, 2: grande). + * + * @return {Float[]} + */ +function sff8300(tolerance = 0, type = 1) = [ + 3.00, // Diámetro del tornillo + type == 0 ? 42.00 : (type == 1 ? 26.10 : 17.80) + tolerance, + 147.00 + tolerance, + 101.60 + tolerance, + 95.25 + tolerance, + 3.18, + 44.45 + tolerance / 2, + 41.28 + tolerance / 2, + 28.50 + tolerance / 2, + 101.60 + tolerance / 2, + 6.35 + tolerance / 2, + 0.25, + 0.50, + 76.20 + tolerance / 2 +]; +//---------------------------------------------------------- +/** + * Dibuja un modelo de una unidad de 3.5" según la especificación SFF-8300. + * + * Este modelo permite extraer el volumen posteriormente para crear una ranura + * como las usadas en las cajas de PCs. + * + * @param {Float} length Longitud de la unidad a generar. + * @param {Float} thickness Grosor del bloque donde se insertará el modelo. + * @param {Float} screw Diámetro del tornillo a usar. + * @param {Float} slot Longitud de la ranura donde se insertarán los tornillos. + * @param {Float} tolerance Valor a usar para ajustar las medidas estándar. + * @param {Integer} type Tipo de unidad (0: pequeña, 1: mediana, 2: grande). + */ +module sff8300Model(length = 0, thickness = 5, screw = 0, slot = 15, tolerance = 0.3, type = 0) +{ + _A = sff8300(tolerance, type); + modelBox( + _A[3], + _A[1], + length ? length : _A[2], + thickness, + screw ? screw : _A[0], + slot, + [ + [ _A[10], _A[2] - _A[8] ], + [ _A[10], _A[2] - _A[8] - _A[9] ] + ], + [ + [ _A[5], _A[2] - _A[7] ], + [ _A[5], _A[2] - _A[7] - _A[6] ], + [ _A[5], _A[2] - _A[7] - _A[13] ], + [ _A[3] - _A[5], _A[2] - _A[7] ], + [ _A[3] - _A[5], _A[2] - _A[7] - _A[6] ], + [ _A[3] - _A[5], _A[2] - _A[7] - _A[13] ] + ] + ); +} +//---------------------------------------------------------- +/** + * Dibuja una bandeja que puede insertarse en una ranura donde va una unidad de 3.5". + * + * @param {Float} length Longitud de la unidad a generar. + * @param {Float} thickness Grosor del bloque donde se insertará el modelo. + * @param {Float} screw Diámetro del tornillo a usar. + * @param {Float} slot Longitud de la ranura donde se insertarán los tornillos. + * @param {Float} tolerance Valor a usar para ajustar las medidas estándar. + * @param {Boolean} sides Lados a eliminar de la bandeja. + * @param {Integer} type Define la altura según el tipo de unidad (0: grande, 1: mediana, 2: pequeña). + */ +module sff8300Tray(length = 0, thickness = 5, screw = 0, slot = 15, tolerance = 0.3, sides = [ "a", "t" ], type = 1) +{ + _A = sff8300(tolerance, type); + boxTray(_A[3], _A[1], length ? length : _A[2], thickness, sides) + { + sff8300Model(length, thickness, screw ? screw : _A[0], slot, tolerance, type); + } +} diff --git a/openscad/foreign/modular multi-hdd case/Modules/Models/box.scad b/openscad/foreign/modular multi-hdd case/Modules/Models/box.scad new file mode 100644 index 0000000..146ef33 --- /dev/null +++ b/openscad/foreign/modular multi-hdd case/Modules/Models/box.scad @@ -0,0 +1,82 @@ +/** + * Modelo que dibuja una caja que puede tener tornillos y ranuras y que + * puede usarse como un negativo sobre otra caja y obtener la diferencia. + * + * @author Joaquín Fernández + * @url https://gitlab.com/joaquinfq/openscad/blob/master/Modules/Models/box.scad + * @license CC-BY-NC-4.0 + * + * @param {Float} width Anchura del modelo a generar. + * @param {Float} height Altura del modelo a generar. + * @param {Float} length Longitud del modelo a generar. + * @param {Float} thickness Grosor del bloque donde se insertará el modelo. + * @param {Float} screw Diámetro del tornillo a usar. + * @param {Float} slot Longitud de la ranura donde se insertarán los tornillos. + * @param {Float} tolerance Valor a usar para ajustar las medidas estándar. + * @param {Float[]} side Coordenadas de los agujeros laterales. + * @param {Float[]} bottom Coordenadas de los agujeros inferiores. + */ +module modelBox(width, height, length, thickness, screw = 0, slot = 0, side = [], bottom = []) +{ + cube([ width, height, length ]); + // Agujeros laterales + for (_side = side) + { + if (slot) + { + hull() + { + for (_n = [ - slot / 2, slot / 2 ]) + { + translate([ width / 2, _side[0], _side[1] + _n ]) + { + rotate([ 0, 90, 0 ]) + { + cylinder(d = screw, h = width + thickness * 2, center = true); + } + } + } + } + } + else + { + translate([ width / 2, _side[0], _side[1] ]) + { + rotate([ 0, 90, 0 ]) + { + cylinder(d = screw, h = width + thickness * 2, center = true); + } + } + } + } + // Agujeros inferiores + for (_bottom = bottom) + { + if (slot) + { + hull() + { + for (_n = [ - slot / 2, slot / 2 ]) + { + translate([ width - _bottom[0], 0, _bottom[1] + _n ]) + { + rotate([ 90, 0, 0 ]) + { + cylinder(d = screw, h = thickness); + } + } + } + } + } + else + { + translate([ width - _bottom[0], 0, _bottom[1] ]) + { + rotate([ 90, 0, 0 ]) + { + cylinder(d = screw, h = thickness); + } + } + } + } +}