3D/Home Objects/customizable_cable_duct.scad

275 lines
No EOL
6.9 KiB
OpenSCAD

/*
* Parametric cable duct with cover
* ========================================
*
* Create your own custom cable duct with desired dimensions and matching top cover.
*
* Created by Thomas Hessling <mail@dream-dimensions.de>.
* License: Creative Commons - Attribution - Non-Commercial - Share Alike
*
* https://www.dream-dimensions.de
* https://www.thingiverse.com/thing:3775502
*
* Version: 1.1 (2019-08-03)
*
* ChangeLog:
* ## v1.1 (2019-08-03)
* ### Added
* - Add some custom text to your duct's cover
* - Option to create a cover with the same width as the duct, for narrow places
*
* ## v1.0 (2019-07-28)
* - model creation works, first print successful.
*/
/*
* Define the cable duct's final dimensions.
* All values are millimetres.
*/
/* [General settings] */
// Cable duct overall length
cd_length = 300;
// Cable duct width
cd_width = 50;
// Cable duct height
cd_height = 80;
// Number of fins
cd_fins = 20;
// Fin width
cd_fin_width = 5;
// Shell thickness (should be a multiple of your nozzle diameter)
cd_shell =2;
// Force equal cover width - no overlap
cd_cover_equalwidth = 1; // [0:false, 1:true]
// Which part to create? Duct, cover or both.
part = "duct"; // [duct:Cable duct,cover:Duct top cover,both:Both parts]
/* [Mounting feature settings] */
// Mounting feature height
mf_length = 2;
// Mounting feature angle
mf_angle = 45;
// Mounting feature depth
mf_depth = 0.8;
// Mounting feature offset from top
mf_top_offset = 0.6;
// Tolerance between cover and duct
mf_top_tolerance = 0.15;
/* [Cover text] */
// Show the text?
text_enable = 1; // [0:false, 1:true]
// The text
text_string = "thing:3775502";
// Engraving depth, should be a multiple of layer height
text_depth = 0.6;
// Scaling relative to duct width
text_scale = 0.5;
// The font to use
text_font = "DejaVu Sans";
/* [Hidden] */
// the color
col = [0.3,0.5,0.85];
// safety offset for boolean operations, prevents spurious surfaces
s = 0.01;
cd_fin_spacing = (cd_length - cd_fin_width) / cd_fins;
cd_slit_width = cd_fin_spacing - cd_fin_width;
// Create the part
render()
print_part();
/*
Create the part based on the part-variable: duct, cover or both
*/
module print_part()
{
if (part == "duct") {
create_duct();
} else if (part == "cover") {
create_cover();
} else if (part == "both") {
create_duct();
create_cover();
}
}
/*
Create each children and a mirrored version of it along the given axis.
*/
module create_and_mirror(axis)
{
for (i=[0:$children-1]) {
children(i);
mirror(axis) children(i);
}
}
/*
Generates a trapezoidal profile that serves as a mounting feature for a cover.
*/
module clip_profile(forCover)
{
// Make the the angle is properly defined and does not lead to geometry errors
assert(mf_angle > 0, "The angle must be greater than 0 deg.");
assert(mf_angle <= 90, "The angle cannot be greater than 90 deg.");
assert(mf_depth*tan(90-mf_angle)*2 <= mf_length,
"The mounting feature length is too small. Increase length or the angle.");
polyp = [[0,0],
[0,-mf_length],
[mf_depth,-mf_length+mf_depth*tan(90-mf_angle)],
[mf_depth,-mf_depth*tan(90-mf_angle)]];
polygon(polyp);
}
/*
Cut profile for the interior of the rectangle, taking into account the mounting feature.
*/
module inner_duct_profile()
{
cd_hwidth = cd_width/2;
depth_factor = cd_cover_equalwidth ? 2 : 1;
polygon([[cd_hwidth-depth_factor*mf_depth-cd_shell, cd_height+s],
[cd_hwidth-depth_factor*mf_depth-cd_shell, cd_height-mf_length-mf_top_offset],
[cd_hwidth-cd_shell, cd_height-mf_length-mf_top_offset-depth_factor*mf_depth*tan(45)],
[cd_hwidth-cd_shell, cd_shell],
[0, cd_shell],
[0, cd_height+s]]);
}
/*
The duct's cross-sectional profile, used in an extrusion.
*/
module create_duct_profile()
{
/*
Basic shape: rectangle
Subtract the mounting features from it, and also the interior bulk.
This then serves as an extrusion profile.
*/
difference() {
difference() {
difference() {
scale([cd_width, cd_height])
translate([-0.5, 0])
square(1, center=false);
if (cd_cover_equalwidth)
{
union() {
create_and_mirror([1, 0]) {
translate([-cd_width/2-s+cd_shell+mf_top_tolerance, cd_height-mf_top_offset])
clip_profile();
translate([-cd_width/2, cd_height-mf_top_offset])
polygon([[0,mf_top_offset],
[cd_shell+mf_top_tolerance, mf_top_offset],
[cd_shell+mf_top_tolerance, -mf_length],
[cd_shell+mf_top_tolerance*(1-cos(mf_angle)), -mf_length-mf_top_tolerance*cos(mf_angle)],
[0, -mf_length-mf_top_tolerance*cos(mf_angle)]]);
}
}
} else {
union() {
create_and_mirror([1,0]) {
translate([-cd_width/2-s, cd_height-mf_top_offset])
clip_profile();
}
}
}
}
}
union() {
create_and_mirror([1,0]) {
inner_duct_profile();
}
}
}
}
/*
Create the cover profile to be extruded.
*/
module create_cover_profile()
{
union() {
xoffset = cd_cover_equalwidth ? cd_shell+mf_top_tolerance : 0;
create_and_mirror([1,0]) {
translate([cd_width/2+mf_top_tolerance-xoffset, cd_height-mf_top_offset, 0])
mirror([1, 0])
clip_profile(1);
}
polygon([[cd_width/2+mf_top_tolerance-xoffset, cd_height-mf_top_offset-mf_length],
[cd_width/2+mf_top_tolerance-xoffset, cd_height+mf_top_tolerance],
[-cd_width/2-mf_top_tolerance+xoffset, cd_height+mf_top_tolerance],
[-cd_width/2-mf_top_tolerance+xoffset, cd_height-mf_top_offset-mf_length],
[-cd_width/2-mf_top_tolerance-cd_shell+xoffset, cd_height-mf_top_offset-mf_length],
[-cd_width/2-mf_top_tolerance-cd_shell+xoffset, cd_height+mf_top_tolerance+cd_shell],
[cd_width/2+mf_top_tolerance+cd_shell-xoffset, cd_height+mf_top_tolerance+cd_shell],
[cd_width/2+mf_top_tolerance+cd_shell-xoffset, cd_height-mf_top_offset-mf_length],
]);
}
}
/*
Extrude the duct's cross-section profile, cut boxes in regular distance to create the
"fins" and cut holes in the bottom to save material.
*/
module create_duct()
{
color(col)
rotate(90, [1, 0, 0])
difference() {
linear_extrude(height=cd_length, center=false)
create_duct_profile();
union() {
for (i = [0:cd_fins-1]) {
translate([-cd_width/2-1, 3*cd_shell, i*cd_fin_spacing+cd_fin_width])
cube([cd_width+2, cd_height+1, cd_fin_spacing-cd_fin_width]);
}
}
}
}
/*
Create a cover for the duct.
*/
module create_cover()
{
color(col)
difference() {
translate([2*cd_width, 0, cd_height+mf_top_tolerance+cd_shell])
rotate(180, [0, 1, 0])
rotate(90, [1, 0, 0])
linear_extrude(height=cd_length, center=false)
create_cover_profile();
if (text_enable) {
translate([2*cd_width, -cd_length/2, -s+0.6])
rotate(90, [0, 0, -1])
rotate(180, [1, 0, 0])
linear_extrude(height=text_depth, center=false)
text(text_string, cd_width*text_scale, text_font, valign="center", halign="center", $fn=32);
}
}
}