234 lines
9.2 KiB
OpenSCAD
234 lines
9.2 KiB
OpenSCAD
//
|
|
// NopSCADlib Copyright Chris Palmer 2020
|
|
// nop.head@gmail.com
|
|
// hydraraptor.blogspot.com
|
|
//
|
|
// This file is part of NopSCADlib.
|
|
//
|
|
// NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
|
|
// GNU General Public License as published by the Free Software Foundation, either version 3 of
|
|
// the License, or (at your option) any later version.
|
|
//
|
|
// NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
|
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
// See the GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License along with NopSCADlib.
|
|
// If not, see <https://www.gnu.org/licenses/>.
|
|
//
|
|
|
|
//
|
|
//! A fully parametric 3D printed case that can be customised with cutouts and additions specified by children.
|
|
//!
|
|
//! The walls can be made wavy, which possibly reduces warping when printing and looks nice, however if holes need to be made
|
|
//! in the sides you can't print a wavy bridge. Any holes need to be surrounded by a 45° chamfer to make the bridges straight.
|
|
//! See the mounting points for the feet in the first example.
|
|
//!
|
|
//! It can also have printed feet on the base with the screws doubling up to hold the base on.
|
|
//
|
|
include <../core.scad>
|
|
use <../vitamins/insert.scad>
|
|
use <foot.scad>
|
|
|
|
function pbox(name, wall, top_t, base_t, radius, size, foot = false, screw = false, ridges = [0, 0]) //! Construct a printed box property list
|
|
= concat([name, wall, top_t, base_t, foot, screw, radius, ridges], size);
|
|
|
|
function pbox_name(type) = type[0]; //! Name to allow more than one box in a project
|
|
function pbox_wall(type) = type[1]; //! Wall thickness
|
|
function pbox_top(type) = type[2]; //! Top thickness
|
|
function pbox_base(type) = type[3]; //! Base thickness, can be zero for no base
|
|
function pbox_foot(type) = type[4]; //! Printed foot, can be false to suppress feet
|
|
function pbox_base_screw(type) = type[5]; //! Screw type if no feet
|
|
function pbox_radius(type) = type[6]; //! Internal corner radius
|
|
function pbox_ridges(type) = type[7]; //! Ridge wavelength and amplitude
|
|
function pbox_width(type) = type[8]; //! Internal width
|
|
function pbox_depth(type) = type[9]; //! Internal depth
|
|
function pbox_height(type) = type[10]; //! Internal height
|
|
|
|
base_outset = 1; // How much the base overlaps the inner dimensions
|
|
base_overlap = 2; // The width of ledge the base sits on
|
|
height_overlap = 1; // How far the edges sit below the base
|
|
|
|
function pbox_inclusion(type) = pbox_base(type) ? base_overlap - base_outset : 0; //! How far the ledge for the base extends inwards
|
|
|
|
function pbox_total_height(type) = //! Total height including base overlap
|
|
let(base = pbox_base(type),
|
|
foot = pbox_foot(type),
|
|
washer = pbox_washer(type),
|
|
screw = pbox_screw(type))
|
|
pbox_height(type) + pbox_top(type) + base + (base ? height_overlap : 0) + (foot || !base ? 0 : washer_thickness(washer) + screw_head_height(screw));
|
|
|
|
function pbox_screw(type) = //! Foot screw if got feet else base_screw
|
|
let(foot = pbox_foot(type)) foot ? foot_screw(foot) : pbox_base_screw(type);
|
|
|
|
function pbox_insert(type) = screw_insert(pbox_screw(type)); //! The insert for the base screws
|
|
function pbox_washer(type) = screw_washer(pbox_screw(type)); //! The washer for the base screws
|
|
|
|
function pbox_screw_length(type, panel_thickness = 0) = //! Length of the base screw
|
|
let(foot = pbox_foot(type), screw = pbox_screw(type))
|
|
screw_length(screw, pbox_base(type) + (foot ? foot_thickness(foot) : panel_thickness), 1, true);
|
|
|
|
function pbox_mid_offset(type) = pbox_ridges(type).y + pbox_wall(type) / 2; // Offset to wall midpoint
|
|
|
|
function pbox_screw_inset(type) = //! How far the base screws are inset
|
|
let(foot = pbox_foot(type),
|
|
r = foot ? foot_diameter(foot) / 2 : pbox_base(type) ? washer_radius(pbox_washer(type)) : insert_hole_radius(pbox_insert(type)),
|
|
R = pbox_radius(type)
|
|
) max(r, R - (R - r) / sqrt(2));
|
|
|
|
module pbox_screw_positions(type) { //! Place children at base screw positions
|
|
foot = pbox_foot(type);
|
|
inset = pbox_screw_inset(type);
|
|
for(x = [-1, 1], y = [-1, 1])
|
|
translate([x * (pbox_width(type) / 2 - inset), y * (pbox_depth(type) / 2 - inset)])
|
|
rotate((y > 0 ? -x * 45 : -x * 135) + 90)
|
|
children();
|
|
}
|
|
|
|
module pbox_mid_shape(type) {
|
|
ridges = pbox_ridges(type);
|
|
offset = ridges.y + pbox_wall(type) / 2;
|
|
rad = pbox_radius(type) + offset;
|
|
w = pbox_width(type) + 2 * offset;
|
|
d = pbox_depth(type) + 2 * offset;
|
|
|
|
module waves(length) {
|
|
l = length - 2 * rad;
|
|
|
|
waves = round(l / ridges.x);
|
|
points = 16;
|
|
translate([-l / 2, ridges.y / 2])
|
|
polygon(concat([[0, -10]], [for(i = [0 : waves * points], a = 360 * i / points) [i * l / waves / points, -cos(a) * ridges.y / 2] ], [[l, -10]]));
|
|
}
|
|
|
|
difference() {
|
|
rounded_square([w, d], rad, center = true);
|
|
|
|
if(ridges.y)
|
|
for(side = [-1, 1]) {
|
|
translate([0, side * d / 2])
|
|
rotate(90 + side * 90)
|
|
waves(w);
|
|
|
|
translate([side * w / 2, 0])
|
|
rotate(side * 90)
|
|
waves(d);
|
|
}
|
|
}
|
|
}
|
|
|
|
module pbox_inner_shape(type) {
|
|
rad = pbox_radius(type);
|
|
w = pbox_width(type);
|
|
d = pbox_depth(type);
|
|
|
|
rounded_square([w, d], rad, center = true);
|
|
}
|
|
|
|
module pbox_outer_shape(type) //! 2D outer shape of the box
|
|
offset(pbox_wall(type) / 2) pbox_mid_shape(type);
|
|
|
|
module pbox_base(type) { //! Generate the STL for the base
|
|
stl(str(pbox_name(type),"_base"));
|
|
t = pbox_base(type);
|
|
difference() {
|
|
union() {
|
|
linear_extrude(t)
|
|
offset(base_outset - 0.2)
|
|
pbox_inner_shape(type);
|
|
|
|
if($children > 0)
|
|
children(0);
|
|
}
|
|
pbox_screw_positions(type)
|
|
poly_cylinder(r = screw_clearance_radius(pbox_screw(type)), h = 2 * t + eps, center = true);
|
|
|
|
if($children > 1)
|
|
children(1);
|
|
}
|
|
}
|
|
|
|
module pbox(type) { //! Generate the STL for the main case
|
|
stl(pbox_name(type));
|
|
|
|
height = pbox_height(type);
|
|
total_height = pbox_total_height(type);
|
|
top_thickness = pbox_top(type);
|
|
wall = pbox_wall(type);
|
|
ledge_outset = pbox_ridges(type).y;
|
|
ledge_inset = base_outset - base_overlap;
|
|
ledge_h = pbox_base(type) ? (ledge_outset - ledge_inset) * 2 : 0;
|
|
|
|
difference() {
|
|
union() {
|
|
linear_extrude(total_height)
|
|
pbox_outer_shape(type);
|
|
|
|
if($children > 2)
|
|
children(2);
|
|
}
|
|
difference() {
|
|
translate_z(top_thickness)
|
|
union() {
|
|
linear_extrude(height + eps)
|
|
offset(-wall / 2) pbox_mid_shape(type);
|
|
|
|
translate_z(height) // Recess for the base
|
|
linear_extrude(total_height - height)
|
|
offset(base_outset)
|
|
pbox_inner_shape(type);
|
|
}
|
|
// Ledge to support the lid
|
|
if(ledge_h)
|
|
translate_z(top_thickness + height - ledge_h)
|
|
difference() {
|
|
rounded_rectangle([pbox_width(type) + 2 * outset, pbox_depth(type) + 2 * outset, ledge_h], 1, center = false);
|
|
|
|
hull() {
|
|
linear_extrude(ledge_h + eps)
|
|
offset(ledge_inset)
|
|
pbox_inner_shape(type);
|
|
|
|
linear_extrude(eps)
|
|
offset(ledge_outset)
|
|
pbox_inner_shape(type);
|
|
}
|
|
pbox_screw_positions(type)
|
|
insert_hole(pbox_insert(type));
|
|
}
|
|
|
|
// Corner lugs for inserts
|
|
outset = wall + pbox_ridges(type).y;
|
|
or = pbox_radius(type) + outset;
|
|
inset = pbox_screw_inset(type) + outset;
|
|
br = insert_boss_radius(pbox_insert(type), wall);
|
|
ext = sqrt(2) * inset - or * (sqrt(2) - 1) - br;
|
|
translate_z(height + top_thickness)
|
|
pbox_screw_positions(type)
|
|
insert_lug(pbox_insert(type), wall, counter_bore = 0, extension = ext, corner_r = or);
|
|
|
|
if($children > 0)
|
|
children(0);
|
|
}
|
|
if($children > 1)
|
|
children(1);
|
|
}
|
|
}
|
|
|
|
module pbox_inserts(type) //! Place the inserts for the base screws
|
|
translate_z(pbox_height(type) + pbox_top(type))
|
|
pbox_screw_positions(type)
|
|
insert(pbox_insert(type));
|
|
|
|
module pbox_base_screws(type, thickness = 0) //! Place the screws and feet
|
|
translate_z(pbox_height(type) + pbox_top(type) + pbox_base(type))
|
|
pbox_screw_positions(type) {
|
|
foot = pbox_foot(type);
|
|
if(foot)
|
|
stl_colour(pp4_colour)
|
|
foot(foot);
|
|
|
|
translate_z(foot ? foot_thickness(foot) : thickness)
|
|
screw_and_washer(pbox_screw(type), pbox_screw_length(type, thickness));
|
|
}
|