// ============================================ // PORTA-UTENSÍLIOS DE BANHEIRO // ============================================ // Formato: Copo quadrado/retangular com bordas arredondadas (Squircle) // Textura: Linhas verticais nas laterais // Drenagem: Grade opcional no fundo // Divisões: Divisórias internas configuráveis // ============================================ // PARÂMETROS CONFIGURÁVEIS // ============================================ // Dimensões principais (mm) largura = 80; // Largura (X) profundidade = 80; // Profundidade (Y) altura = 100; // Altura (Z) espessura_parede = 2; // Espessura da parede // Arredondamento das bordas (estilo Squircle) raio_arredondamento = 20; // Quanto maior, mais arredondado (recomendado: 15-30) // Grade de drenagem no fundo com_grade_drenagem = true; // true = com grade, false = fundo sólido largura_linha_fundo = 1; // Largura das linhas do fundo (mesmo das laterais) espacamento_linhas_fundo = 4; // Espaçamento entre linhas no fundo // Textura lateral (linhas verticais) com_textura = true; // true = com textura, false = liso largura_linha = 1.5; // Largura das linhas da textura espacamento_linhas = 4; // Espaçamento entre linhas profundidade_textura = 0.8; // Profundidade das ranhuras // Borda superior arredondada com_borda_superior = true; // true = com borda, false = sem borda raio_borda_superior = 2; // Raio do arredondamento da borda // Divisões internas com_divisoes = true; // true = com divisões, false = sem divisões num_divisoes_x = 1; // Número de divisões no eixo X (0 = nenhuma) num_divisoes_y = 1; // Número de divisões no eixo Y (0 = nenhuma) posicao_divisao_x = 50; // Posição da divisão X em % (0-100) posicao_divisao_y = 50; // Posição da divisão Y em % (0-100) espessura_divisao = 1.5; // Espessura das divisões internas // Qualidade de renderização $fn = 100; // Aumentar para melhor qualidade (60-100) // ============================================ // MÓDULOS PRINCIPAIS // ============================================ // Módulo principal module porta_utensilios() { difference() { union() { // Corpo externo (Squircle) squircle_3d(largura, profundidade, altura, raio_arredondamento); // Borda superior arredondada if (com_borda_superior) { borda_superior(); } } // Cavidade interna translate([0, 0, espessura_parede]) squircle_3d( largura - 2*espessura_parede, profundidade - 2*espessura_parede, altura, raio_arredondamento - espessura_parede ); // Aplicar textura nas laterais if (com_textura) { textura_vertical(); } // Grade de drenagem no fundo (ranhuras) if (com_grade_drenagem) { grade_drenagem(); } } // Adicionar divisões internas if (com_divisoes) { divisoes_internas(); } } // Cria um "Squircle" 3D (quadrado/retângulo com bordas super arredondadas) module squircle_3d(w, d, h, r) { hull() { // Cantos arredondados for (x = [-1, 1]) { for (y = [-1, 1]) { translate([x * (w/2 - r), y * (d/2 - r), 0]) cylinder(h=h, r=r); } } } } // Borda superior arredondada module borda_superior() { altura_borda = raio_borda_superior * 2; translate([0, 0, altura - altura_borda]) { difference() { // Corpo da borda com topo arredondado hull() { // Base da borda squircle_3d(largura, profundidade, 0.1, raio_arredondamento); // Topo arredondado (ligeiramente menor para criar o arredondamento) translate([0, 0, altura_borda - raio_borda_superior]) squircle_3d( largura - raio_borda_superior, profundidade - raio_borda_superior, raio_borda_superior, raio_arredondamento - raio_borda_superior/2 ); } // Cavidade interna translate([0, 0, -0.1]) squircle_3d( largura - 2*espessura_parede, profundidade - 2*espessura_parede, altura_borda + 0.2, raio_arredondamento - espessura_parede ); } } } // Textura vertical nas laterais (linhas alternadas) module textura_vertical() { altura_textura = altura - espessura_parede - (com_borda_superior ? raio_borda_superior * 2 : 0); raio_linha = largura_linha / 2; num_linhas_x = floor(largura / espacamento_linhas); num_linhas_y = floor(profundidade / espacamento_linhas); // Linhas nas laterais X (frente e trás) for (i = [0:num_linhas_x]) { x_pos = -largura/2 + i * espacamento_linhas; // Frente translate([x_pos, -profundidade/2 + profundidade_textura/2, espessura_parede]) cylinder(h=altura_textura, r=raio_linha, $fn=20); // Trás translate([x_pos, profundidade/2 - profundidade_textura/2, espessura_parede]) cylinder(h=altura_textura, r=raio_linha, $fn=20); } // Linhas nas laterais Y (esquerda e direita) for (i = [0:num_linhas_y]) { y_pos = -profundidade/2 + i * espacamento_linhas; // Esquerda translate([-largura/2 + profundidade_textura/2, y_pos, espessura_parede]) cylinder(h=altura_textura, r=raio_linha, $fn=20); // Direita translate([largura/2 - profundidade_textura/2, y_pos, espessura_parede]) cylinder(h=altura_textura, r=raio_linha, $fn=20); } // Linhas nos cantos arredondados (4 cantos) num_linhas_canto = floor((PI * raio_arredondamento / 2) / espacamento_linhas); for (canto_x = [-1, 1]) { for (canto_y = [-1, 1]) { centro_x = canto_x * (largura/2 - raio_arredondamento); centro_y = canto_y * (profundidade/2 - raio_arredondamento); angulo_inicio = atan2(canto_y, canto_x) - 45; for (i = [0:num_linhas_canto]) { angulo = angulo_inicio + (90 * i / num_linhas_canto); raio_canto = raio_arredondamento - profundidade_textura/2; x_pos = centro_x + raio_canto * cos(angulo); y_pos = centro_y + raio_canto * sin(angulo); translate([x_pos, y_pos, espessura_parede]) cylinder(h=altura_textura, r=raio_linha, $fn=20); } } } } // Grade de drenagem no fundo (ranhuras que permitem escoar água) module grade_drenagem() { dim_interna_x = largura - 2*espessura_parede; dim_interna_y = profundidade - 2*espessura_parede; // Usar intersection para garantir que as linhas não ultrapassem a borda intersection() { // Limite da área interna translate([0, 0, -1]) squircle_3d( dim_interna_x - 1, dim_interna_y - 1, espessura_parede + 3, raio_arredondamento - espessura_parede - 0.5 ); // Canais de drenagem paralelos union() { num_canais = floor(dim_interna_x / espacamento_linhas_fundo); for (i = [1:num_canais-1]) { x_pos = -dim_interna_x/2 + i * espacamento_linhas_fundo; // Canal (cubo que remove material do fundo) translate([x_pos - largura_linha_fundo/2, 0, espessura_parede/2]) cube([largura_linha_fundo, dim_interna_y + 10, espessura_parede + 1], center=true); } } } } // Divisões internas module divisoes_internas() { dim_interna_x = largura - 2*espessura_parede; dim_interna_y = profundidade - 2*espessura_parede; altura_divisao = altura - espessura_parede; // Divisões no eixo X if (num_divisoes_x > 0) { for (i = [1:num_divisoes_x]) { pos_x = -dim_interna_x/2 + (dim_interna_x * posicao_divisao_x / 100) * i / num_divisoes_x; translate([pos_x, 0, espessura_parede + altura_divisao/2]) cube([ espessura_divisao, dim_interna_y, altura_divisao ], center=true); } } // Divisões no eixo Y if (num_divisoes_y > 0) { for (i = [1:num_divisoes_y]) { pos_y = -dim_interna_y/2 + (dim_interna_y * posicao_divisao_y / 100) * i / num_divisoes_y; translate([0, pos_y, espessura_parede + altura_divisao/2]) cube([ dim_interna_x, espessura_divisao, altura_divisao ], center=true); } } } // ============================================ // RENDERIZAÇÃO // ============================================ porta_utensilios();