Added source code
This commit is contained in:
parent
d80facf2ca
commit
34a9b0e87b
|
@ -0,0 +1,8 @@
|
||||||
|
*_canute.bat
|
||||||
|
Thumbs.db
|
||||||
|
__pycache__
|
||||||
|
*.pyc
|
||||||
|
tests/bom/
|
||||||
|
tests/deps/
|
||||||
|
*.log
|
||||||
|
*.html
|
|
@ -0,0 +1,471 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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 box made from routed or laser cut sheet sheets and printed profiles and bezels. It can be arbitrarily large
|
||||||
|
//! compared to the 3D printed parts because they can be cut into interlocking sections and solvent welded
|
||||||
|
//! together. The box panels can be customised to have holes and parts mounted on them by overriding the
|
||||||
|
//! definitions of `box_base()`, `box_front()`, etc.
|
||||||
|
//!
|
||||||
|
//! `box.scad` should be ```use```d and `box_assembly.scad` ```include```d.
|
||||||
|
//!
|
||||||
|
//! A box is defined with a list that specifies the inside dimensions, top, bottom and side sheet materials, the
|
||||||
|
//! screw type and printed part wall thickness. This diagram shows how the various dimensions are labelled:
|
||||||
|
//! ![](docs/box.png)
|
||||||
|
//!
|
||||||
|
//! Normally the side sheets are the same type but they can be overridden individually as long as the substitute has the same thickness.
|
||||||
|
//
|
||||||
|
include <core.scad>
|
||||||
|
use <vitamins/sheet.scad>
|
||||||
|
use <vitamins/screw.scad>
|
||||||
|
use <vitamins/washer.scad>
|
||||||
|
|
||||||
|
include <vitamins/inserts.scad>
|
||||||
|
use <utils/quadrant.scad>
|
||||||
|
|
||||||
|
bezel_clearance = 0.2;
|
||||||
|
sheet_end_clearance = 1;
|
||||||
|
sheet_slot_clearance = 0.2;
|
||||||
|
|
||||||
|
function box_screw(type) = type[0]; //! Screw type to be used at the corners
|
||||||
|
function box_wall(type) = type[1]; //! Wall thickness of 3D parts
|
||||||
|
function box_sheets(type) = type[2]; //! Sheet type used for the sides
|
||||||
|
function box_top_sheet(type) = type[3]; //! Sheet type for the top
|
||||||
|
function box_base_sheet(type)= type[4]; //! Sheet type for the bottom
|
||||||
|
function box_feet(type) = type[5]; //! True to enable feet on the bottom bezel
|
||||||
|
function box_width(type) = type[6]; //! Internal width
|
||||||
|
function box_depth(type) = type[7]; //! Internal depth
|
||||||
|
function box_height(type) = type[8]; //! Internal height
|
||||||
|
|
||||||
|
function box_bezel_clearance(type) = bezel_clearance;
|
||||||
|
|
||||||
|
function box_corner_gap(type) = 3; //! Gap between box_sheets at the corners to connect inside and outside profiles
|
||||||
|
function box_profile_overlap(type) = 3 + sheet_end_clearance / 2;
|
||||||
|
|
||||||
|
function box_washer(type) = screw_washer(box_screw(type));
|
||||||
|
function box_insert(type) = screw_insert(box_screw(type));
|
||||||
|
|
||||||
|
function box_hole_inset(type) = washer_radius(box_washer(type)) + 1;
|
||||||
|
function box_insert_r(type) = insert_hole_radius(box_insert(type));
|
||||||
|
function box_insert_l(type) = insert_length(box_insert(type));
|
||||||
|
function box_boss_r(type) = ceil(corrected_radius(box_insert_r(type)) + box_wall(type));
|
||||||
|
|
||||||
|
function box_sheet_slot(type) = sheet_thickness(box_sheets(type)) + sheet_slot_clearance; // add some clearance
|
||||||
|
function box_corner_overlap(type) = box_wall(type);
|
||||||
|
|
||||||
|
function box_corner_rad(type) = box_sheet_slot(type) - sheet_slot_clearance / 2 + box_corner_gap(type) + box_corner_overlap(type);
|
||||||
|
function box_sheet_r(type) = box_corner_rad(type) - box_sheet_slot(type) - box_corner_overlap(type);
|
||||||
|
|
||||||
|
function box_screw_length(type, top) = screw_longer_than(2 * washer_thickness(box_washer(type))
|
||||||
|
+ sheet_thickness(top ? box_top_sheet(type) : box_base_sheet(type))
|
||||||
|
+ box_corner_gap(type) + box_profile_overlap(type) + box_insert_l(type) - 1);
|
||||||
|
|
||||||
|
function box_wall_clearance(type) = box_sheet_slot(type) / 2 - sheet_thickness(box_sheets(type)) / 2;
|
||||||
|
function box_margin(type) = box_profile_overlap(type) + box_corner_gap(type); //! How much the bezel intrudes on the specified height
|
||||||
|
function box_intrusion(type) = box_hole_inset(type) + box_boss_r(type); //! Corner profile intrusion
|
||||||
|
function sheet_reduction(type) = 2 * box_corner_gap(type) + sheet_end_clearance;
|
||||||
|
function box_outset(type) = box_sheet_slot(type) + box_wall(type) - sheet_slot_clearance / 2; //! How much the bezel expands the specified internal size
|
||||||
|
function box_inset(type) = box_wall(type) + sheet_slot_clearance / 2; //! How much the bezel intrudes on the specified width and length, away from the corners
|
||||||
|
function box_bezel_height(type, bottom) = //! Bezel height for top or bottom
|
||||||
|
let(t1 = sheet_thickness(box_base_sheet(type)), t2 = sheet_thickness(box_top_sheet(type)))
|
||||||
|
box_corner_rad(type) + box_profile_overlap(type) + (bottom ? max(t1, t2) : t2) - sheet_thickness(box_sheets(type));
|
||||||
|
|
||||||
|
grill_hole = 5;
|
||||||
|
grill_gap = 1.9;
|
||||||
|
module grill(width, height, r = 1000, poly = false, h = 0) { //! A staggered array of 5mm holes to make grills in sheets. Can be constrained to be circular. Set ```poly``` ```true``` for printing, ```false``` for milling.
|
||||||
|
nx = floor(width / (grill_hole + grill_gap));
|
||||||
|
xpitch = width / nx;
|
||||||
|
ny = floor(height / ((grill_hole + grill_gap) * cos(30)));
|
||||||
|
ypitch = height / ny;
|
||||||
|
|
||||||
|
extrude_if(h)
|
||||||
|
for(y = [0 : ny - 1], x = [0 : nx - 1 - (y % 2)]) {
|
||||||
|
x = -width / 2 + (x + 0.5 + (y % 2) / 2) * xpitch;
|
||||||
|
y = -height / 2 + (y + 0.5) * ypitch;
|
||||||
|
if(sqrt(sqr(x) + sqr(y)) + grill_hole / 2 <= r)
|
||||||
|
translate([x, y])
|
||||||
|
if(poly)
|
||||||
|
poly_circle(r = grill_hole / 2);
|
||||||
|
else
|
||||||
|
circle(d = grill_hole);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module box_corner_profile_2D(type) { //! The 2D shape of the corner profile.
|
||||||
|
t = box_sheet_slot(type);
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
quadrant(box_hole_inset(type) + box_boss_r(type), box_boss_r(type)); // inside corner
|
||||||
|
|
||||||
|
translate([box_corner_gap(type) + box_profile_overlap(type), box_corner_gap(type) + box_profile_overlap(type)])
|
||||||
|
rotate(180)
|
||||||
|
quadrant(box_profile_overlap(type) + box_corner_rad(type), box_corner_rad(type)); // outside corner
|
||||||
|
}
|
||||||
|
translate([box_corner_gap(type), -t + sheet_slot_clearance / 2])
|
||||||
|
square([100, t]);
|
||||||
|
|
||||||
|
translate([-t + sheet_slot_clearance / 2, box_corner_gap(type)])
|
||||||
|
square([t, 100]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module box_corner_profile(type) { //! Generates the corner profile STL for 3D printing.
|
||||||
|
stl("box_corner_profile");
|
||||||
|
|
||||||
|
length = box_height(type) - 2 * box_margin(type);
|
||||||
|
difference() {
|
||||||
|
linear_extrude(height = length, center = true, convexity = 5)
|
||||||
|
box_corner_profile_2D(type);
|
||||||
|
|
||||||
|
for(z = [-1, 1])
|
||||||
|
translate([box_hole_inset(type), box_hole_inset(type), z * length / 2])
|
||||||
|
insert_hole(box_insert(type), 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module box_corner_profile_section(type, section, sections) { //! Generates interlocking sections of the corner profile to allow it to be taller than the printer
|
||||||
|
overlap = 4;
|
||||||
|
length = box_height(type) - 2 * box_margin(type);
|
||||||
|
section_length = round_to_layer((length - overlap) / sections);
|
||||||
|
last_section = section >= sections - 1;
|
||||||
|
h = last_section ? length - (sections - 1) * section_length : section_length;
|
||||||
|
overlap_wall = 2;
|
||||||
|
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
linear_extrude(height = h, convexity = 5)
|
||||||
|
box_corner_profile_2D(type);
|
||||||
|
|
||||||
|
if(!last_section) // male end always at the top
|
||||||
|
translate_z(section_length - 1)
|
||||||
|
for(i = [0 : 1], offset = i * layer_height)
|
||||||
|
linear_extrude(height = overlap + 1 - offset)
|
||||||
|
offset(1 + offset - layer_height)
|
||||||
|
offset(-overlap_wall - 1)
|
||||||
|
box_corner_profile_2D(type);
|
||||||
|
}
|
||||||
|
if(section > 0)
|
||||||
|
translate_z(last_section ? h : 0) { // female at bottom unless last section
|
||||||
|
linear_extrude(height = 2 * (overlap + layer_height), center = true, convexity = 5)
|
||||||
|
offset(-overlap_wall)
|
||||||
|
box_corner_profile_2D(type);
|
||||||
|
|
||||||
|
linear_extrude(height = 2 * layer_height, center = true, convexity = 5)
|
||||||
|
offset(-overlap_wall + layer_height)
|
||||||
|
box_corner_profile_2D(type);
|
||||||
|
}
|
||||||
|
if(!section || last_section) // insert holes always at the bottom
|
||||||
|
translate([box_hole_inset(type), box_hole_inset(type)])
|
||||||
|
insert_hole(box_insert(type), 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module box_corner_quadrants(type, width, depth)
|
||||||
|
for(corner = [0:3]) {
|
||||||
|
x = [-1,1,1,-1][corner];
|
||||||
|
y = [-1,-1,1,1][corner];
|
||||||
|
|
||||||
|
translate([x * width / 2, y * depth / 2, 0])
|
||||||
|
rotate(corner * 90)
|
||||||
|
quadrant(box_intrusion(type), box_boss_r(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
module box_bezel(type, bottom) { //! Generates top and bottom bezel STLs
|
||||||
|
stl(bottom ? "bottom_bezel" : "top_bezel");
|
||||||
|
feet = bottom && box_feet(type);
|
||||||
|
t = box_sheet_slot(type);
|
||||||
|
outset = box_outset(type);
|
||||||
|
inner_r = box_sheet_r(type);
|
||||||
|
foot_height = box_corner_gap(type) + sheet_thickness(box_base_sheet(type)) + washer_thickness(box_washer(type)) + screw_head_height(box_screw(type)) + box_profile_overlap(type) + 2;
|
||||||
|
foot_length = box_corner_rad(type) * 2;
|
||||||
|
height = box_bezel_height(type, bottom);
|
||||||
|
foot_extension = foot_height - height;
|
||||||
|
|
||||||
|
difference() {
|
||||||
|
translate_z(-box_profile_overlap(type)) difference() {
|
||||||
|
rounded_rectangle([box_width(type) + 2 * outset, box_depth(type) + 2 * outset, feet ? foot_height : height], box_corner_rad(type), false);
|
||||||
|
//
|
||||||
|
// Remove edges between the feet
|
||||||
|
//
|
||||||
|
if(feet)
|
||||||
|
hull() {
|
||||||
|
translate_z(height + 0.5)
|
||||||
|
cube([box_width(type) - 2 * foot_length, box_depth(type) + 2 * outset + 1, 1], center = true);
|
||||||
|
|
||||||
|
translate_z(foot_height + 1)
|
||||||
|
cube([box_width(type) - 2 * (foot_length - foot_extension), box_depth(type) + 2 * outset + 1, 1], center = true);
|
||||||
|
}
|
||||||
|
if(feet)
|
||||||
|
hull() {
|
||||||
|
translate_z(height + 0.5)
|
||||||
|
cube([box_width(type) + 2 * outset + 1, box_depth(type) - 2 * foot_length, 1], center = true);
|
||||||
|
|
||||||
|
translate_z(foot_height + 1)
|
||||||
|
cube([box_width(type) + 2 * outset + 1, box_depth(type) - 2 * (foot_length - foot_extension), 1], center = true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// slots for side panels
|
||||||
|
//
|
||||||
|
translate_z(-box_profile_overlap(type))
|
||||||
|
linear_extrude(height = 2 * box_profile_overlap(type), center = true)
|
||||||
|
for(i = [-1, 1]) {
|
||||||
|
translate([i * (box_width(type) / 2 + t / 2 - sheet_slot_clearance / 2), 0])
|
||||||
|
square([t, box_depth(type) - 2 * box_corner_gap(type)], center = true);
|
||||||
|
|
||||||
|
translate([0, i * (box_depth(type) / 2 + t / 2 - sheet_slot_clearance / 2)])
|
||||||
|
square([box_width(type) - 2 * box_corner_gap(type), t], center = true);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// recess for top / bottom panel
|
||||||
|
//
|
||||||
|
translate_z(box_corner_gap(type))
|
||||||
|
rounded_rectangle([box_width(type) + bezel_clearance, box_depth(type) + bezel_clearance, height], inner_r + bezel_clearance / 2, false);
|
||||||
|
//
|
||||||
|
// leave plastic over the corner profiles
|
||||||
|
//
|
||||||
|
translate_z(-box_profile_overlap(type) - 1)
|
||||||
|
linear_extrude(height = box_profile_overlap(type) + box_corner_gap(type) + 2)
|
||||||
|
union() {
|
||||||
|
difference() {
|
||||||
|
square([box_width(type) - 2 * box_inset(type),
|
||||||
|
box_depth(type) - 2 * box_inset(type)], center = true);
|
||||||
|
|
||||||
|
box_corner_quadrants(type, box_width(type), box_depth(type));
|
||||||
|
}
|
||||||
|
box_screw_hole_positions(type)
|
||||||
|
poly_circle(screw_clearance_radius(box_screw(type)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dowel_length = 20;
|
||||||
|
dowel_wall = extrusion_width * 3;
|
||||||
|
dowel_h_wall = layer_height * 6;
|
||||||
|
|
||||||
|
|
||||||
|
module box_bezel_section(type, bottom, rows, cols, x, y) { //! Generates interlocking sections of the bezel to allow it to be bigger than the printer
|
||||||
|
w = (box_width(type) + 2 * box_outset(type)) / cols;
|
||||||
|
h = (box_depth(type) + 2 * box_outset(type)) / rows;
|
||||||
|
bw = box_outset(type) - bezel_clearance / 2;
|
||||||
|
bw2 = box_outset(type) + box_inset(type);
|
||||||
|
|
||||||
|
dw = bw - 2 * dowel_wall;
|
||||||
|
dh = box_bezel_height(type, bottom) - dowel_h_wall;
|
||||||
|
|
||||||
|
dh2 = box_profile_overlap(type) + box_corner_gap(type) - dowel_h_wall;
|
||||||
|
|
||||||
|
end_clearance = 0.5;
|
||||||
|
module male() {
|
||||||
|
rotate([90, 0, 90])
|
||||||
|
linear_extrude(height = dowel_length - 2 * end_clearance, center = true)
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
h = dh - layer_height;
|
||||||
|
h2 = dh2 - layer_height;
|
||||||
|
hull() {
|
||||||
|
translate([bw / 2, h / 2])
|
||||||
|
square([dw - 1, h], center = true);
|
||||||
|
|
||||||
|
translate([bw / 2, (h - 1) / 2])
|
||||||
|
square([dw, h - 1], center = true);
|
||||||
|
}
|
||||||
|
|
||||||
|
hull() {
|
||||||
|
translate([bw2 / 2, h2 / 2])
|
||||||
|
square([bw2 - 2 * dowel_wall - 1, h2], center = true);
|
||||||
|
|
||||||
|
translate([bw2 / 2, (h2 - 1) / 2])
|
||||||
|
square([bw2 - 2 * dowel_wall, h2 - 1], center = true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
translate([bw2 / 2, 0])
|
||||||
|
square([box_sheet_slot(type), 2 * box_profile_overlap(type)], center = true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module female() {
|
||||||
|
union() {
|
||||||
|
translate([0, bw / 2, dh / 2])
|
||||||
|
cube([dowel_length, dw, dh], center = true);
|
||||||
|
|
||||||
|
translate([0, bw2 / 2])
|
||||||
|
cube([dowel_length, bw2 - 2 * dowel_wall, dh2 * 2], center = true);
|
||||||
|
|
||||||
|
hull() {
|
||||||
|
translate([0, bw / 2, dh / 2])
|
||||||
|
cube([2, dw, dh], center = true);
|
||||||
|
|
||||||
|
translate([0, bw / 2, dh / 2])
|
||||||
|
cube([eps, dw + 2 * extrusion_width, dh], center = true);
|
||||||
|
|
||||||
|
}
|
||||||
|
hull() {
|
||||||
|
translate([0, bw2 / 2, dh2 / 2])
|
||||||
|
cube([2, bw2 - 2 * dowel_wall, dh2], center = true);
|
||||||
|
|
||||||
|
translate([0, bw2 / 2, dh2 / 2])
|
||||||
|
cube([eps, bw2 - 2 * dowel_wall + 2 * extrusion_width, dh2], center = true);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module support() {
|
||||||
|
if(!$preview)
|
||||||
|
translate([0, bw / 2 + dw / 2])
|
||||||
|
cube([dowel_length / 2 - 0.25, 2 * extrusion_width + 0.2, dh2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
union() {
|
||||||
|
render() difference() {
|
||||||
|
union() {
|
||||||
|
clip(xmin = 0, xmax = w, ymin = 0, ymax = h)
|
||||||
|
translate([box_width(type) / 2 + box_outset(type) - x * w, box_depth(type) / 2 + box_outset(type) - y * h, box_profile_overlap(type)])
|
||||||
|
box_bezel(type, bottom);
|
||||||
|
|
||||||
|
if(x < cols - 1 && y == 0)
|
||||||
|
translate([w, 0])
|
||||||
|
male();
|
||||||
|
|
||||||
|
if(x > 0 && y == rows - 1)
|
||||||
|
translate([0, h])
|
||||||
|
rotate(180)
|
||||||
|
male();
|
||||||
|
|
||||||
|
if(y < rows - 1 && x == cols - 1)
|
||||||
|
translate([w, h])
|
||||||
|
rotate(90)
|
||||||
|
male();
|
||||||
|
|
||||||
|
if(y > 0 && x == 0)
|
||||||
|
rotate(-90)
|
||||||
|
male();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(x < cols - 1 && y == rows - 1)
|
||||||
|
translate([w, h])
|
||||||
|
rotate(180)
|
||||||
|
female();
|
||||||
|
|
||||||
|
if(x > 0 && y == 0)
|
||||||
|
female();
|
||||||
|
|
||||||
|
if(y < rows - 1 && x == 0)
|
||||||
|
translate([0, h])
|
||||||
|
rotate(-90)
|
||||||
|
female();
|
||||||
|
|
||||||
|
if(y > 0 && x == cols - 1)
|
||||||
|
translate([w, 0])
|
||||||
|
rotate(90)
|
||||||
|
female();
|
||||||
|
}
|
||||||
|
if(x < cols - 1 && y == rows - 1)
|
||||||
|
translate([w, h])
|
||||||
|
rotate(180)
|
||||||
|
support();
|
||||||
|
|
||||||
|
if(x > 0 && y == 0)
|
||||||
|
support();
|
||||||
|
|
||||||
|
if(y < rows - 1 && x == 0)
|
||||||
|
translate([0, h])
|
||||||
|
rotate(-90)
|
||||||
|
support();
|
||||||
|
|
||||||
|
if(y > 0 && x == cols - 1)
|
||||||
|
translate([w, 0])
|
||||||
|
rotate(90)
|
||||||
|
support();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module box_shelf_blank(type) { //! Generates a 2D template for a shelf sheet
|
||||||
|
dxf("box_shelf");
|
||||||
|
|
||||||
|
difference() {
|
||||||
|
sheet_2D(box_sheets(type), box_width(type) - bezel_clearance, box_depth(type) - bezel_clearance, 1);
|
||||||
|
|
||||||
|
offset(bezel_clearance / 2)
|
||||||
|
box_corner_quadrants(type, box_width(type), box_depth(type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module box_screw_hole_positions(type)
|
||||||
|
for(x = [-1, 1], y = [-1, 1])
|
||||||
|
translate([x * (box_width(type) / 2 - box_hole_inset(type)), y * (box_depth(type) / 2 - box_hole_inset(type))])
|
||||||
|
children();
|
||||||
|
|
||||||
|
module box_base_blank(type) { //! Generates a 2D template for the base sheet
|
||||||
|
dxf("box_base");
|
||||||
|
|
||||||
|
difference() {
|
||||||
|
sheet_2D(box_base_sheet(type), box_width(type), box_depth(type), box_sheet_r(type));
|
||||||
|
|
||||||
|
box_screw_hole_positions(type)
|
||||||
|
drill(screw_clearance_radius(box_screw(type)), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module box_top_blank(type) { //! Generates a 2D template for the top sheet
|
||||||
|
dxf("box_top");
|
||||||
|
|
||||||
|
difference() {
|
||||||
|
sheet_2D(box_top_sheet(type), box_width(type), box_depth(type), box_sheet_r(type));
|
||||||
|
|
||||||
|
box_screw_hole_positions(type)
|
||||||
|
drill(screw_clearance_radius(box_screw(type)), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function subst_sheet(type, sheet) =
|
||||||
|
let(s = box_sheets(type))
|
||||||
|
sheet ? assert(sheet_thickness(sheet) == sheet_thickness(s)) sheet : s;
|
||||||
|
|
||||||
|
module box_left_blank(type, sheet = false) { //! Generates a 2D template for the left sheet, ```sheet``` can be set to override the type
|
||||||
|
dxf("box_left");
|
||||||
|
|
||||||
|
sheet_2D(subst_sheet(type, sheet), box_depth(type) - sheet_reduction(type), box_height(type) - sheet_reduction(type), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
module box_right_blank(type, sheet = false) { //! Generates a 2D template for the right sheet, ```sheet``` can be set to override the type
|
||||||
|
dxf("box_right");
|
||||||
|
|
||||||
|
sheet_2D(subst_sheet(type, sheet), box_depth(type) - sheet_reduction(type), box_height(type) - sheet_reduction(type), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
module box_front_blank(type, sheet = false) { //! Generates a 2D template for the front sheet, ```sheet``` can be set to override the type
|
||||||
|
dxf("box_front");
|
||||||
|
|
||||||
|
sheet_2D(subst_sheet(type, sheet), box_width(type) - sheet_reduction(type), box_height(type) - sheet_reduction(type), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
module box_back_blank(type, sheet = false) { //! Generates a 2D template for the back sheet, ```sheet``` can be set to override the type
|
||||||
|
dxf("box_back");
|
||||||
|
|
||||||
|
sheet_2D(subst_sheet(type, sheet), box_width(type) - sheet_reduction(type), box_height(type) - sheet_reduction(type), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
module box_base(type) render_2D_sheet(box_base_sheet(type)) box_base_blank(type); //! Default base, can be overridden to customise
|
||||||
|
module box_top(type) render_2D_sheet(box_top_sheet(type)) box_top_blank(type); //! Default top, can be overridden to customise
|
||||||
|
module box_back(type) render_2D_sheet(box_sheets(type)) box_back_blank(type); //! Default back, can be overridden to customise
|
||||||
|
module box_front(type) render_2D_sheet(box_sheets(type)) box_front_blank(type); //! Default front, can be overridden to customise
|
||||||
|
module box_left(type) render_2D_sheet(box_sheets(type)) box_left_blank(type); //! Default left side, can be overridden to customise
|
||||||
|
module box_right(type) render_2D_sheet(box_sheets(type)) box_right_blank(type); //! Default right side, can be overridden to customise
|
|
@ -0,0 +1,94 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// The assembly is ```include```d so the panel definitions can be overridden to add holes and components.
|
||||||
|
// The _box_module also needs to be wrapped in the file that uses it so it can be called without
|
||||||
|
// parameters to make the assembly views. E.g. module box_assembly() _box_assembly(box);
|
||||||
|
//
|
||||||
|
module _box_assembly(type, top = true, base = true, left = true, right = true, back = true, front = true, bezels = true, corners = 4)
|
||||||
|
assembly("box") {
|
||||||
|
echo("Box:", box_width(type), box_depth(type), box_height(type));
|
||||||
|
|
||||||
|
t = sheet_thickness(box_sheets(type));
|
||||||
|
|
||||||
|
for(corner = [0 : corners - 1]) {
|
||||||
|
x = [-1,1,1,-1][corner];
|
||||||
|
y = [-1,-1,1,1][corner];
|
||||||
|
translate([x * (box_width(type) / 2 + 25 * exploded()), y * (box_depth(type) / 2 + 25 * exploded())])
|
||||||
|
rotate(corner * 90) {
|
||||||
|
color(pp2_colour) render()
|
||||||
|
box_corner_profile(type);
|
||||||
|
|
||||||
|
translate([box_hole_inset(type), box_hole_inset(type)])
|
||||||
|
for(z = [-1, 1])
|
||||||
|
rotate([z * 90 -90, 0, 0])
|
||||||
|
translate_z(box_height(type) / 2 - box_margin(type))
|
||||||
|
insert(box_insert(type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(z = [-1, 1]) {
|
||||||
|
sheet_thickness = sheet_thickness(z > 0 ? box_top_sheet(type) : box_base_sheet(type));
|
||||||
|
|
||||||
|
translate_z(z * (box_height(type) / 2 - box_corner_gap(type) + 50 * exploded()))
|
||||||
|
rotate([z * 90 - 90, 0, 0])
|
||||||
|
if(bezels && (z > 0 ? top : base))
|
||||||
|
color(pp1_colour) render() box_bezel(type, z < 0);
|
||||||
|
|
||||||
|
translate_z(z * (box_height(type) / 2 + sheet_thickness + 50 * exploded()))
|
||||||
|
box_screw_hole_positions(type)
|
||||||
|
rotate([z * 90 -90, 0, 0])
|
||||||
|
explode(50, true)
|
||||||
|
screw_and_washer(box_screw(type), box_screw_length(type, z > 0), true);
|
||||||
|
}
|
||||||
|
for(x = [-1, 1])
|
||||||
|
translate([x * (box_width(type) / 2 + t / 2 + 25 * exploded()), 0])
|
||||||
|
rotate([90, 0, x * 90])
|
||||||
|
if(x > 0) {
|
||||||
|
if(right)
|
||||||
|
box_right(type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(left)
|
||||||
|
box_left(type);
|
||||||
|
|
||||||
|
for(y = [-1, 1])
|
||||||
|
translate([0, y * (box_depth(type) / 2 + t / 2 + 25 * exploded())])
|
||||||
|
rotate([90, 0, y * 90 + 90])
|
||||||
|
if(y < 0) {
|
||||||
|
if(front)
|
||||||
|
box_front(type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(back)
|
||||||
|
box_back(type);
|
||||||
|
|
||||||
|
for(z = [-1, 1]) {
|
||||||
|
sheet_thickness = sheet_thickness(z > 0 ? box_top_sheet(type) : box_base_sheet(type));
|
||||||
|
translate_z(z * (box_height(type) / 2 + sheet_thickness / 2 + eps + 100 * exploded()))
|
||||||
|
if(z > 0) {
|
||||||
|
if(top)
|
||||||
|
box_top(type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(base)
|
||||||
|
box_base(type);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,261 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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 box made from CNC cut panels butted together using printed fixing blocks. Useful for making large
|
||||||
|
//! boxes with minimal 3D printing. More blocks are added as the box gets bigger.
|
||||||
|
//!
|
||||||
|
//! Needs to be ```include```d rather than ```use```d to allow the panel definitions to be overridden to add holes
|
||||||
|
//! and mounted components.
|
||||||
|
//!
|
||||||
|
//! A list specifies the internal dimensions, screw type, top, bottom and side sheet types and the block
|
||||||
|
//! maximum spacing.
|
||||||
|
//!
|
||||||
|
//! Uses [fixing blocks](#fixing_block) and [corner blocks](#corner_block).
|
||||||
|
//
|
||||||
|
|
||||||
|
use <fixing_block.scad>
|
||||||
|
use <corner_block.scad>
|
||||||
|
use <utils/maths.scad>
|
||||||
|
|
||||||
|
function bbox_screw(type) = type[0]; //! Screw type for corner blocks
|
||||||
|
function bbox_sheets(type) = type[1]; //! Sheet type for the sides
|
||||||
|
function bbox_base_sheet(type)= type[2]; //! Sheet type for the base
|
||||||
|
function bbox_top_sheet(type) = type[3]; //! Sheet type for the top
|
||||||
|
function bbox_span(type) = type[4]; //! Maximum span between fixing blocks
|
||||||
|
function bbox_width(type) = type[5]; //! Internal width
|
||||||
|
function bbox_depth(type) = type[6]; //! Internal depth
|
||||||
|
function bbox_height(type) = type[7]; //! Internal height
|
||||||
|
|
||||||
|
module bbox_shelf_blank(type) { //! 2D template for a shelf
|
||||||
|
dxf("bbox_shelf");
|
||||||
|
|
||||||
|
sheet_2D(bbox_sheets(type), bbox_width(type), bbox_depth(type), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function corner_block_positions(type) = let(
|
||||||
|
width = bbox_width(type),
|
||||||
|
depth = bbox_depth(type),
|
||||||
|
height = bbox_height(type)
|
||||||
|
)
|
||||||
|
[for(corner = [0 : 3], z = [-1, 1])
|
||||||
|
let(
|
||||||
|
x = [-1,1,1,-1][corner],
|
||||||
|
y = [-1,-1,1,1][corner]
|
||||||
|
) translate([x * (width / 2), y * (depth / 2), z * height / 2]) *
|
||||||
|
rotate([z > 0 ? 180 : 0, 0, corner * 90 + (z > 0 ? 90 : 0)])
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
module corner_block_positions(type) {
|
||||||
|
bt = sheet_thickness(bbox_base_sheet(type));
|
||||||
|
tt = sheet_thickness(bbox_top_sheet(type));
|
||||||
|
for(p = corner_block_positions(type))
|
||||||
|
let($thickness = transform([0, 0, 0], p).z > 0 ? tt : bt)
|
||||||
|
multmatrix(p)
|
||||||
|
children();
|
||||||
|
}
|
||||||
|
|
||||||
|
function corner_holes(type) = [for(p = corner_block_positions(type), q = corner_block_holes(bbox_screw(type))) p * q];
|
||||||
|
|
||||||
|
function fixing_block_positions(type) = let(
|
||||||
|
width = bbox_width(type),
|
||||||
|
depth = bbox_depth(type),
|
||||||
|
height = bbox_height(type),
|
||||||
|
span = bbox_span(type),
|
||||||
|
wspans = floor(width / span),
|
||||||
|
wspan = width / (wspans + 1),
|
||||||
|
dspans = floor(depth / span),
|
||||||
|
dspan = depth / (dspans + 1),
|
||||||
|
hspans = floor(height / span),
|
||||||
|
hspan = height / (hspans + 1)
|
||||||
|
)
|
||||||
|
[
|
||||||
|
for(i = [0 : 1 : wspans - 1], y = [-1, 1], z = [-1, 1])
|
||||||
|
translate([(i - (wspans - 1) / 2) * wspan, y * depth / 2, z * height / 2]) *
|
||||||
|
rotate([0, z * 90 + 90, y * 90 + 90]),
|
||||||
|
|
||||||
|
for(i = [0 : 1 : dspans - 1], x = [-1, 1], z = [-1, 1])
|
||||||
|
translate([x * width / 2, (i - (dspans - 1) / 2) * dspan, z * height / 2]) *
|
||||||
|
rotate([0, z * 90 + 90, x * 90]),
|
||||||
|
|
||||||
|
for(i = [0 : 1 : hspans - 1], x = [-1, 1], y = [-1, 1])
|
||||||
|
translate([x * width / 2, y * depth / 2, (i - (hspans - 1) / 2) * hspan]) *
|
||||||
|
rotate([y > 0 ? 180 : 0, x * y * 90]),
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
function side_holes(type) = [for(p = fixing_block_positions(type), q = fixing_block_holes(bbox_screw(type))) p * q];
|
||||||
|
|
||||||
|
module fixing_block_positions(type) {
|
||||||
|
t = sheet_thickness(bbox_sheets(type));
|
||||||
|
bt = sheet_thickness(bbox_base_sheet(type));
|
||||||
|
tt = sheet_thickness(bbox_top_sheet(type));
|
||||||
|
h = bbox_height(type) / 2 - 1;
|
||||||
|
for(p = fixing_block_positions(type))
|
||||||
|
let(z = transform([0, 0, 0], p).z, $thickness = z > h ? tt : z < -h ? bt : t)
|
||||||
|
multmatrix(p)
|
||||||
|
children();
|
||||||
|
}
|
||||||
|
|
||||||
|
module drill_holes(type, t)
|
||||||
|
for(list = [corner_holes(type), side_holes(type)], p = list)
|
||||||
|
let(q = t * p)
|
||||||
|
if(abs(transform([0, 0, 0], q).z) < eps)
|
||||||
|
multmatrix(q)
|
||||||
|
drill(screw_clearance_radius(bbox_screw(type)), 0);
|
||||||
|
|
||||||
|
module bbox_base_blank(type) { //! 2D template for the base
|
||||||
|
dxf("bbox_base");
|
||||||
|
|
||||||
|
difference() {
|
||||||
|
sheet_2D(bbox_base_sheet(type), bbox_width(type), bbox_depth(type), 1);
|
||||||
|
|
||||||
|
drill_holes(type, translate(bbox_height(type) / 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module bbox_top_blank(type) { //! 2D template for the top
|
||||||
|
dxf("bbox_top");
|
||||||
|
|
||||||
|
t = sheet_thickness(bbox_sheets(type));
|
||||||
|
|
||||||
|
difference() {
|
||||||
|
translate([0, t / 2])
|
||||||
|
sheet_2D(bbox_top_sheet(type), bbox_width(type) + 2 * t, bbox_depth(type) + t);
|
||||||
|
|
||||||
|
drill_holes(type, translate(-bbox_height(type) / 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module bbox_left_blank(type) { //! 2D template for the left side
|
||||||
|
dxf("bbox_left");
|
||||||
|
|
||||||
|
t = sheet_thickness(bbox_sheets(type));
|
||||||
|
bb = sheet_thickness(bbox_base_sheet(type));
|
||||||
|
|
||||||
|
difference() {
|
||||||
|
translate([-t / 2, -bb / 2])
|
||||||
|
sheet_2D(bbox_sheets(type), bbox_depth(type) + t, bbox_height(type) + bb);
|
||||||
|
|
||||||
|
drill_holes(type, rotate([0, 90, 90]) * translate([bbox_width(type) / 2, 0]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module bbox_right_blank(type) { //! 2D template for the right side
|
||||||
|
dxf("bbox_right");
|
||||||
|
|
||||||
|
t = sheet_thickness(bbox_sheets(type));
|
||||||
|
bb = sheet_thickness(bbox_base_sheet(type));
|
||||||
|
|
||||||
|
difference() {
|
||||||
|
translate([t / 2, -bb / 2])
|
||||||
|
sheet_2D(bbox_sheets(type), bbox_depth(type) + t, bbox_height(type) + bb);
|
||||||
|
|
||||||
|
drill_holes(type, rotate([0, -90, 90]) * translate([-bbox_width(type) / 2, 0]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module bbox_front_blank(type) { //! 2D template for the front
|
||||||
|
dxf("bbox_front");
|
||||||
|
|
||||||
|
t = sheet_thickness(bbox_sheets(type));
|
||||||
|
bb = sheet_thickness(bbox_base_sheet(type));
|
||||||
|
bt = sheet_thickness(bbox_top_sheet(type));
|
||||||
|
|
||||||
|
difference() {
|
||||||
|
translate([0, (bt - bb) / 2])
|
||||||
|
sheet_2D(bbox_sheets(type), bbox_width(type) + 2 * t, bbox_height(type) + bb + bt);
|
||||||
|
|
||||||
|
drill_holes(type, rotate([-90, 0, 0]) * translate([0, bbox_depth(type) / 2]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module bbox_back_blank(type) { //! 2D template for the back
|
||||||
|
dxf("bbox_back");
|
||||||
|
|
||||||
|
bb = sheet_thickness(bbox_base_sheet(type));
|
||||||
|
t = sheet_thickness(bbox_sheets(type));
|
||||||
|
|
||||||
|
difference() {
|
||||||
|
translate([0, -bb / 2])
|
||||||
|
sheet_2D(bbox_sheets(type), bbox_width(type), bbox_height(type) + bb);
|
||||||
|
|
||||||
|
drill_holes(type, rotate([90, 0, 0]) * translate([0, -bbox_depth(type) / 2]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module bbox_base(type) render_2D_sheet(bbox_base_sheet(type)) bbox_base_blank(type); //! Default base, can be overridden to customise
|
||||||
|
module bbox_top(type) render_2D_sheet(bbox_top_sheet(type)) bbox_top_blank(type); //! Default top, can be overridden to customise
|
||||||
|
module bbox_back(type) render_2D_sheet(bbox_sheets(type)) bbox_back_blank(type); //! Default back, can be overridden to customise
|
||||||
|
module bbox_front(type) render_2D_sheet(bbox_sheets(type)) bbox_front_blank(type); //! Default front, can be overridden to customise
|
||||||
|
module bbox_left(type) render_2D_sheet(bbox_sheets(type)) bbox_left_blank(type); //! Default left side, can be overridden to customise
|
||||||
|
module bbox_right(type) render_2D_sheet(bbox_sheets(type)) bbox_right_blank(type); //! Default right side, can be overridden to customise
|
||||||
|
|
||||||
|
module _bbox_assembly(type, top = true, base = true, left = true, right = true, back = true, front = true) //! The box assembly, wrap with a local copy without parameters
|
||||||
|
assembly("bbox") {
|
||||||
|
width = bbox_width(type);
|
||||||
|
depth = bbox_depth(type);
|
||||||
|
height = bbox_height(type);
|
||||||
|
echo("Box:", width, depth, height);
|
||||||
|
|
||||||
|
t = sheet_thickness(bbox_sheets(type));
|
||||||
|
bt = sheet_thickness(bbox_base_sheet(type));
|
||||||
|
tt = sheet_thickness(bbox_top_sheet(type));
|
||||||
|
|
||||||
|
corner_block_positions(type)
|
||||||
|
fastened_corner_block_assembly(t, bbox_screw(type), $thickness);
|
||||||
|
|
||||||
|
fixing_block_positions(type)
|
||||||
|
fastened_fixing_block_assembly(t, bbox_screw(type), thickness2 = $thickness);
|
||||||
|
|
||||||
|
for(x = [-1, 1])
|
||||||
|
translate([x * (width / 2 + t / 2 + eps + 25 * exploded()), 0])
|
||||||
|
rotate([90, 0, x * 90])
|
||||||
|
if(x > 0) {
|
||||||
|
if(right)
|
||||||
|
bbox_right(type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(left)
|
||||||
|
bbox_left(type);
|
||||||
|
|
||||||
|
for(y = [-1, 1])
|
||||||
|
translate([0, y * (depth / 2 + t / 2 + eps + 25 * exploded())])
|
||||||
|
rotate([90, 0, y * 90 + 90])
|
||||||
|
if(y < 0) {
|
||||||
|
if(front)
|
||||||
|
bbox_front(type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(back)
|
||||||
|
bbox_back(type);
|
||||||
|
|
||||||
|
for(z = [-1, 1]) {
|
||||||
|
sheet_thickness = z > 0 ? tt : bt;
|
||||||
|
translate_z(z * (height / 2 + sheet_thickness / 2 + eps + 100 * exploded()))
|
||||||
|
if(z > 0) {
|
||||||
|
if(top)
|
||||||
|
bbox_top(type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(base)
|
||||||
|
bbox_base(type);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,187 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
//! Printed cable grommets for passing cables through panels avoiding sharp edges and in the case
|
||||||
|
//! of conductive panels, an extra layer of insulation.
|
||||||
|
//
|
||||||
|
include <core.scad>
|
||||||
|
use <vitamins/cable_strip.scad>
|
||||||
|
|
||||||
|
base = 1.25;
|
||||||
|
slot_height = round_to_layer(1.27) + layer_height;
|
||||||
|
wall = 1.6;
|
||||||
|
overlap = 1.5;
|
||||||
|
height = base + slot_height + wall + overlap;
|
||||||
|
rad = wall + overlap;
|
||||||
|
clearance = 0.1;
|
||||||
|
|
||||||
|
module ribbon_grommet_hole(ways, h = 50, expand = true) { //! Generate a hole for a ribbon grommet
|
||||||
|
length = ribbon_clamp_slot(ways) + 2 * wall;
|
||||||
|
rad = cnc_bit_r;
|
||||||
|
height = base + slot_height + wall;
|
||||||
|
extrude_if(h)
|
||||||
|
offset(expand ? clearance : 0)
|
||||||
|
hull() {
|
||||||
|
translate([-length / 2, 0])
|
||||||
|
square([length, base]);
|
||||||
|
|
||||||
|
for(end = [-1, 1])
|
||||||
|
translate([end * (length / 2 - rad), height - rad])
|
||||||
|
drill(rad, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module ribbon_grommet(ways, thickness) { //! Generate the STL for a printed ribbon grommet
|
||||||
|
stl(str("ribbon_grommet_", ways, "_", thickness));
|
||||||
|
|
||||||
|
width = 2 * (wall + clearance) + thickness;
|
||||||
|
slot_length = ribbon_clamp_slot(ways);
|
||||||
|
length = slot_length + 2 * wall + 2 * overlap;
|
||||||
|
|
||||||
|
rotate([90, 0, 0])
|
||||||
|
union() {
|
||||||
|
for(side = [-1, 1])
|
||||||
|
translate_z(side * (width - wall) / 2)
|
||||||
|
linear_extrude(height = wall, center = true, convexity = 5)
|
||||||
|
difference() {
|
||||||
|
hull() {
|
||||||
|
translate([-length / 2, 0])
|
||||||
|
square([length, base]);
|
||||||
|
|
||||||
|
for(end = [-1, 1])
|
||||||
|
translate([end * (length / 2 - rad), height - rad])
|
||||||
|
semi_circle(rad);
|
||||||
|
}
|
||||||
|
translate([-slot_length / 2, base])
|
||||||
|
square([slot_length, slot_height]);
|
||||||
|
}
|
||||||
|
|
||||||
|
linear_extrude(height = width -1, center = true)
|
||||||
|
difference() {
|
||||||
|
ribbon_grommet_hole(ways, expand = false, h = 0);
|
||||||
|
|
||||||
|
translate([-slot_length / 2, base])
|
||||||
|
square([slot_length, slot_height]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module round_grommet_top(diameter, thickness, od = undef) { //! Generate the STL for a round grommet top half
|
||||||
|
stl(str("round_grommet_top_", round(diameter * 10), "_", thickness));
|
||||||
|
chamfer = layer_height;
|
||||||
|
h = wall + thickness + wall;
|
||||||
|
r1 = diameter / 2;
|
||||||
|
r2 = od == undef ? corrected_radius(r1) + wall : od / 2;
|
||||||
|
r3 = r2 + overlap;
|
||||||
|
r0 = r1 + 1;
|
||||||
|
union() {
|
||||||
|
rotate_extrude()
|
||||||
|
polygon([
|
||||||
|
[r0, 0],
|
||||||
|
[r3 - chamfer, 0],
|
||||||
|
[r3, chamfer],
|
||||||
|
[r3, wall],
|
||||||
|
[r2, wall],
|
||||||
|
[r2, h - chamfer],
|
||||||
|
[r2 - chamfer, h],
|
||||||
|
[r0, h],
|
||||||
|
]);
|
||||||
|
|
||||||
|
render() difference() {
|
||||||
|
cylinder(r = r0 + eps, h = h);
|
||||||
|
|
||||||
|
poly_cylinder(r = r1, h = 100, center = true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module round_grommet_bottom(diameter, od = undef) { //! Generate the STL for a round grommet bottom half
|
||||||
|
stl(str("round_grommet_bottom_", round(diameter * 10)));
|
||||||
|
chamfer = layer_height;
|
||||||
|
r1 = diameter / 2;
|
||||||
|
r2 = od == undef ? corrected_radius(r1) + wall : od / 2;
|
||||||
|
r3 = r2 + max(overlap, wall + chamfer);
|
||||||
|
rotate_extrude()
|
||||||
|
polygon([
|
||||||
|
[r2, chamfer],
|
||||||
|
[r2 + chamfer, 0],
|
||||||
|
[r3, 0],
|
||||||
|
[r3, wall - chamfer],
|
||||||
|
[r3 - chamfer, wall],
|
||||||
|
[r2, wall],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
module round_grommet_hole(diameter, h = 100) //! Make a hole for a round grommet
|
||||||
|
drill(diameter / 2 + wall + clearance, h);
|
||||||
|
|
||||||
|
module round_grommet_assembly(diameter, thickness, od = undef) {
|
||||||
|
color(pp1_colour)
|
||||||
|
translate_z(wall)
|
||||||
|
vflip()
|
||||||
|
round_grommet_top(diameter, thickness, od);
|
||||||
|
|
||||||
|
color(pp2_colour)
|
||||||
|
translate_z(-thickness)
|
||||||
|
vflip()
|
||||||
|
round_grommet_bottom(diameter, od);
|
||||||
|
}
|
||||||
|
|
||||||
|
module mouse_grommet_hole(r, h = 50, z = undef, expand = wall + clearance) //! Make a hole for a mouse grommet
|
||||||
|
extrude_if(h)
|
||||||
|
hull(){
|
||||||
|
R = r + expand;
|
||||||
|
translate([0, z == undef ? R : z])
|
||||||
|
semi_circle(R);
|
||||||
|
|
||||||
|
translate([-R, 0])
|
||||||
|
square([2 * R, eps]);
|
||||||
|
}
|
||||||
|
|
||||||
|
module mouse_grommet(r, thickness) { //! Make the STL for a mouse grommet
|
||||||
|
stl(str("mouse_grommet_", r * 10, "_", thickness));
|
||||||
|
|
||||||
|
width = 2 * (wall + clearance) + thickness;
|
||||||
|
length = 2 * r + 2 * wall + 2 * overlap;
|
||||||
|
|
||||||
|
rotate([90, 0, 0])
|
||||||
|
union() {
|
||||||
|
for(side = [-1, 1])
|
||||||
|
translate_z(side * (width - wall) / 2)
|
||||||
|
linear_extrude(height = wall, center = true)
|
||||||
|
difference() {
|
||||||
|
mouse_grommet_hole(r + wall + overlap, z = r + wall, h = 0, expand = 0);
|
||||||
|
|
||||||
|
translate([0, wall])
|
||||||
|
mouse_grommet_hole(r, h = 0, expand = 0);
|
||||||
|
}
|
||||||
|
linear_extrude(height = width - 1, center = true)
|
||||||
|
difference() {
|
||||||
|
mouse_grommet_hole(r, h = 0, z = r + wall, expand = wall);
|
||||||
|
|
||||||
|
translate([0, wall])
|
||||||
|
mouse_grommet_hole(r, h = 0, expand = 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module ribbon_grommet_20_3_stl() ribbon_grommet(20, 3);
|
||||||
|
module mouse_grommet_20_3_stl() mouse_grommet(2,3);
|
||||||
|
module mouse_grommet_30_3_stl() mouse_grommet(3,3);
|
|
@ -0,0 +1,63 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
//! Adapts ESP12 module to 0.1" grid. See <https://hydraraptor.blogspot.com/2018/04/esp-12-module-breakout-adaptor.html>.
|
||||||
|
//
|
||||||
|
$extrusion_width = 0.5;
|
||||||
|
|
||||||
|
include <core.scad>
|
||||||
|
|
||||||
|
module ESP12F_carrier_stl() { //! Generate the STL for an ESP12 carrier
|
||||||
|
stl("ESP12F_carrier");
|
||||||
|
pins = 8;
|
||||||
|
pitch1 = 2;
|
||||||
|
pitch2 = 2.54;
|
||||||
|
hole = pitch1 - squeezed_wall;
|
||||||
|
hole2 = pitch2 - 3 * extrusion_width;
|
||||||
|
length1 = (pins - 1) * pitch1 + hole + squeezed_wall * 2;
|
||||||
|
length2 = (pins - 1) * pitch2 + hole + squeezed_wall * 2;
|
||||||
|
height = 3;
|
||||||
|
|
||||||
|
wpitch1 = (pins - 1) * pitch1;
|
||||||
|
wpitch2 = ceil(wpitch1 / 2.54) * 2.54;
|
||||||
|
|
||||||
|
width1 = wpitch1 + hole + squeezed_wall * 2;
|
||||||
|
width2 = wpitch2 + hole2 + squeezed_wall * 2;
|
||||||
|
|
||||||
|
difference() {
|
||||||
|
hull() {
|
||||||
|
translate_z(height - eps / 2)
|
||||||
|
cube([width1, length1, eps], center = true);
|
||||||
|
|
||||||
|
translate_z(eps / 2)
|
||||||
|
cube([width2, length2, eps], center = true);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(side = [-1, 1])
|
||||||
|
for(i = [0 : pins - 1])
|
||||||
|
hull() {
|
||||||
|
translate([side * wpitch1 / 2, i * pitch1 - (pins - 1) * pitch1 / 2, height])
|
||||||
|
cube([hole, hole, eps], center = true);
|
||||||
|
|
||||||
|
translate([side * wpitch2 / 2, i * pitch2 - (pins - 1) * pitch2 / 2])
|
||||||
|
cube([hole2, hole2, eps], center = true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// Include this file to use the library
|
||||||
|
//
|
||||||
|
include <global_defs.scad>
|
||||||
|
//
|
||||||
|
// Global functions and modules
|
||||||
|
//
|
||||||
|
use <utils/core/global.scad>
|
|
@ -0,0 +1,181 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
//! Corner brackets using threaded inserts for fastening three sheets together at right angles.
|
||||||
|
//! Defaults to M3 but other screws sizes can be specified provided they have inserts defined.
|
||||||
|
//!
|
||||||
|
//! See [butt_box](#Butt_box) for an example of usage.
|
||||||
|
//!
|
||||||
|
//! Note that the block with its inserts is defined as a sub assembly, but its fasteners get added to the parent assembly.
|
||||||
|
//
|
||||||
|
include <core.scad>
|
||||||
|
include <vitamins/screws.scad>
|
||||||
|
include <vitamins/inserts.scad>
|
||||||
|
use <utils/rounded_cylinder.scad>
|
||||||
|
use <utils/maths.scad>
|
||||||
|
|
||||||
|
def_screw = M3_cap_screw;
|
||||||
|
wall = 3;
|
||||||
|
overshoot = 2; // how far screw can overshoot the insert
|
||||||
|
|
||||||
|
function corner_block_screw() = def_screw; //! Default screw type
|
||||||
|
|
||||||
|
function corner_block_hole_offset(screw = def_screw) = //! Hole offset from the edge
|
||||||
|
let(insert = screw_insert(screw))
|
||||||
|
insert_length(insert) + max(overshoot + screw_clearance_radius(screw), insert_hole_radius(insert)) + 1;
|
||||||
|
|
||||||
|
function corner_block_width(screw = def_screw) = //! Block width, depth and height
|
||||||
|
corner_block_hole_offset(screw) + insert_outer_d(screw_insert(screw)) / 2 + wall;
|
||||||
|
|
||||||
|
function corner_block_v_hole(screw = def_screw) = let(offset = corner_block_hole_offset(screw)) translate([offset, offset]) * rotate([180, 0, 0]); //! Transform to bottom hole
|
||||||
|
|
||||||
|
function corner_block_h_holes(screw = def_screw) = //! List of transforms to side holes
|
||||||
|
let(offset = corner_block_hole_offset(screw))
|
||||||
|
[translate([offset, 0, offset]) * rotate([90, 0, 0]),
|
||||||
|
translate([0, offset, offset - layer_height]) * rotate([90, 0, -90])];
|
||||||
|
|
||||||
|
function corner_block_holes(screw) = concat([corner_block_v_hole(screw)], corner_block_h_holes(screw)); //! List of transforms to all holes
|
||||||
|
|
||||||
|
module corner_block_v_hole(screw = def_screw) //! Place children at the bottom screw hole
|
||||||
|
multmatrix(corner_block_v_hole(screw))
|
||||||
|
children();
|
||||||
|
|
||||||
|
module corner_block_h_holes(screw = def_screw) //! Place children at the side screw holes
|
||||||
|
for(p = corner_block_h_holes(screw))
|
||||||
|
multmatrix(p)
|
||||||
|
children();
|
||||||
|
|
||||||
|
module corner_block_holes(screw = def_screw) //! Place children at all the holes
|
||||||
|
for(p = corner_block_holes(screw))
|
||||||
|
multmatrix(p)
|
||||||
|
children();
|
||||||
|
|
||||||
|
module corner_block(screw = def_screw, name = false) { //! Generate the STL for a printed corner block
|
||||||
|
stl(name ? name : str("corner_block", "_M", screw_radius(screw) * 20));
|
||||||
|
|
||||||
|
r = 1;
|
||||||
|
cb_width = corner_block_width(screw);
|
||||||
|
cb_height = cb_width;
|
||||||
|
cb_depth = cb_width;
|
||||||
|
insert = screw_insert(screw);
|
||||||
|
corner_rad = insert_outer_d(insert) / 2 + wall;
|
||||||
|
offset = corner_block_hole_offset(screw);
|
||||||
|
difference() {
|
||||||
|
hull() {
|
||||||
|
translate([r, r])
|
||||||
|
rounded_cylinder(r = r, h = cb_height, r2 = r);
|
||||||
|
|
||||||
|
translate([r, cb_depth - r])
|
||||||
|
cylinder(r = r, h = cb_height - corner_rad);
|
||||||
|
|
||||||
|
translate([cb_width - r, r])
|
||||||
|
cylinder(r = r, h = cb_height - corner_rad);
|
||||||
|
|
||||||
|
translate([offset, offset, offset])
|
||||||
|
sphere(corner_rad);
|
||||||
|
|
||||||
|
translate([offset, offset])
|
||||||
|
cylinder(r = corner_rad, h = offset);
|
||||||
|
|
||||||
|
translate([offset, r, offset])
|
||||||
|
rotate([-90, 0, 180])
|
||||||
|
rounded_cylinder(r = corner_rad, h = r, r2 = r);
|
||||||
|
|
||||||
|
translate([r, offset, offset])
|
||||||
|
rotate([0, 90, 180])
|
||||||
|
rounded_cylinder(r = corner_rad, h = r, r2 = r);
|
||||||
|
}
|
||||||
|
corner_block_v_hole(screw)
|
||||||
|
insert_hole(insert, overshoot);
|
||||||
|
|
||||||
|
corner_block_h_holes(screw)
|
||||||
|
insert_hole(insert, overshoot, true);
|
||||||
|
|
||||||
|
children();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module corner_block_assembly(screw = def_screw, name = false) //! The printed block with inserts
|
||||||
|
assembly(str("corner_block_M", 20 * screw_radius(screw))) {
|
||||||
|
insert = screw_insert(screw);
|
||||||
|
|
||||||
|
color(name ? pp2_colour : pp1_colour)
|
||||||
|
render() corner_block(screw, name) children();
|
||||||
|
|
||||||
|
corner_block_h_holes(screw)
|
||||||
|
insert(insert);
|
||||||
|
|
||||||
|
corner_block_v_hole(screw)
|
||||||
|
insert(insert);
|
||||||
|
}
|
||||||
|
|
||||||
|
module fastened_corner_block_assembly(thickness, screw = def_screw, thickness_below = undef, name = false) { //! Printed block with all fasteners
|
||||||
|
washer = screw_washer(screw);
|
||||||
|
insert = screw_insert(screw);
|
||||||
|
screw_length = screw_shorter_than(2 * washer_thickness(washer) + thickness + insert_length(insert) + overshoot);
|
||||||
|
|
||||||
|
corner_block_assembly(screw, name) children();
|
||||||
|
|
||||||
|
corner_block_h_holes(screw)
|
||||||
|
translate_z(thickness)
|
||||||
|
screw_and_washer(screw, screw_length, true);
|
||||||
|
|
||||||
|
thickness2 = thickness_below ? thickness_below : thickness;
|
||||||
|
screw_length2 = screw_shorter_than(2 * washer_thickness(washer) + thickness2 + insert_length(insert) + overshoot);
|
||||||
|
corner_block_v_hole(screw)
|
||||||
|
translate_z(thickness2)
|
||||||
|
screw_and_washer(screw, screw_length2, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
module corner_block_M20_stl() corner_block(M2_cap_screw);
|
||||||
|
module corner_block_M25_stl() corner_block(M2p5_cap_screw);
|
||||||
|
module corner_block_M30_stl() corner_block(M3_cap_screw);
|
||||||
|
module corner_block_M40_stl() corner_block(M4_cap_screw);
|
||||||
|
//
|
||||||
|
//! 1. Lay the blocks out and place an M2 insert in each upward facing hole.
|
||||||
|
//! 1. Push them home with a soldering iron with a conical bit heated to 200°C.
|
||||||
|
//! When removing the iron it helps to twist it a little anti-clockwise to release it from the thread.
|
||||||
|
//! 1. Lay the blocks on each of their other two flat sides and repeat.
|
||||||
|
//
|
||||||
|
module corner_block_M20_assembly() corner_block_assembly(M2_cap_screw);
|
||||||
|
|
||||||
|
//
|
||||||
|
//! 1. Lay the blocks out and place an M2.5 insert in each upward facing hole.
|
||||||
|
//! 1. Push them home with a soldering iron with a conical bit heated to 200°C.
|
||||||
|
//! When removing the iron it helps to twist it a little anti-clockwise to release it from the thread.
|
||||||
|
//! 1. Lay the blocks on each of their other two flat sides and repeat.
|
||||||
|
//
|
||||||
|
module corner_block_M25_assembly() corner_block_assembly(M2p5_cap_screw);
|
||||||
|
|
||||||
|
//
|
||||||
|
//! 1. Lay the blocks out and place an M3 insert in each upward facing hole.
|
||||||
|
//! 1. Push them home with a soldering iron with a conical bit heated to 200°C.
|
||||||
|
//! When removing the iron it helps to twist it a little anti-clockwise to release it from the thread.
|
||||||
|
//! 1. Lay the blocks on each of their other two flat sides and repeat.
|
||||||
|
//
|
||||||
|
module corner_block_M30_assembly() corner_block_assembly(M3_cap_screw);
|
||||||
|
|
||||||
|
//
|
||||||
|
//! 1. Lay the blocks out and place an M4 insert in each upward facing hole.
|
||||||
|
//! 1. Push them home with a soldering iron with a conical bit heated to 200°C.
|
||||||
|
//! When removing the iron it helps to twist it a little anti-clockwise to release it from the thread.
|
||||||
|
//! 1. Lay the blocks on each of their other two flat sides and repeat.
|
||||||
|
//
|
||||||
|
module corner_block_M40_assembly() corner_block_assembly(M4_cap_screw);
|
|
@ -0,0 +1,187 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
//! Door hinges to hang an acrylic sheet door on a 3D printer, default 6mm thick.
|
||||||
|
//!
|
||||||
|
//! The screws are tapped into the acrylic.
|
||||||
|
//! Rubber door [sealing strip](#sealing_strip) is used to make it airtight and a [door_latch](#door_latch) holds it closed.
|
||||||
|
//
|
||||||
|
include <core.scad>
|
||||||
|
include <vitamins/screws.scad>
|
||||||
|
|
||||||
|
width = 18;
|
||||||
|
thickness = 4;
|
||||||
|
rad = 3;
|
||||||
|
dia = 12;
|
||||||
|
|
||||||
|
pin_screw = M3_cap_screw;
|
||||||
|
screw = M3_dome_screw;
|
||||||
|
stat_screw = M4_dome_screw;
|
||||||
|
|
||||||
|
stat_width = 15;
|
||||||
|
stat_length = 34;
|
||||||
|
stat_clearance = 0.75;
|
||||||
|
|
||||||
|
function door_hinge_pin_x() = -dia / 2; //! X offset of the hinge pin
|
||||||
|
function door_hinge_pin_y() = -dia / 2 - stat_clearance; //! Y offset of the hinge pin
|
||||||
|
function door_hinge_screw() = screw; //! Screw type used for hinge pin
|
||||||
|
function door_hinge_stat_screw() = stat_screw; //! Screw use to fasten the stationary part
|
||||||
|
function door_hinge_stat_width() = stat_width; //! Width of the stationary part
|
||||||
|
function door_hinge_stat_length() = stat_length; //! Length of the stationary part
|
||||||
|
|
||||||
|
module door_hinge_hole_positions(dir = 0) { //! Position chidren at the door hole positions
|
||||||
|
hole_pitch = width - 10;
|
||||||
|
|
||||||
|
for(side = [-1, 1])
|
||||||
|
translate([width / 2 + side * hole_pitch / 2, -dir * width / 2 -side * hole_pitch / 2])
|
||||||
|
children();
|
||||||
|
}
|
||||||
|
|
||||||
|
module door_hinge(door_thickness) { //! Generates STL for the moving part of the hinge
|
||||||
|
stl(str("door_hinge_", door_thickness));
|
||||||
|
|
||||||
|
hole_pitch = width - 10;
|
||||||
|
|
||||||
|
union() {
|
||||||
|
rotate([90, 0, 0])
|
||||||
|
linear_extrude(height = width, center = true)
|
||||||
|
difference() {
|
||||||
|
hull() {
|
||||||
|
translate([dia / 2, thickness + door_thickness / 2])
|
||||||
|
intersection() {
|
||||||
|
rotate(180)
|
||||||
|
teardrop(r = dia / 2, h = 0, truncate = false);
|
||||||
|
|
||||||
|
square([dia + 1, 2 * thickness + door_thickness], center = true);
|
||||||
|
}
|
||||||
|
|
||||||
|
square([1, thickness + door_thickness]);
|
||||||
|
}
|
||||||
|
translate([dia / 2, thickness + door_thickness / 2])
|
||||||
|
teardrop(r = screw_clearance_radius(pin_screw), h = 0);
|
||||||
|
}
|
||||||
|
linear_extrude(height = thickness)
|
||||||
|
difference() {
|
||||||
|
hull() {
|
||||||
|
translate([0, -width / 2])
|
||||||
|
square([1, width]);
|
||||||
|
|
||||||
|
for(side = [-1, 1])
|
||||||
|
translate([-width + rad, side * (width / 2 - rad)])
|
||||||
|
circle4n(rad);
|
||||||
|
}
|
||||||
|
rotate(180)
|
||||||
|
vflip()
|
||||||
|
door_hinge_hole_positions()
|
||||||
|
poly_circle(screw_clearance_radius(screw));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module door_hinge_6_stl() door_hinge(6);
|
||||||
|
|
||||||
|
module door_hinge_stat_hole_positions(dir = 0) { //! Position children over the screws holes of the stationary part
|
||||||
|
hole_pitch = dia + (stat_length - dia) / 2;
|
||||||
|
|
||||||
|
for(side = [-1, 1])
|
||||||
|
translate([side * hole_pitch / 2, dir * (stat_width / 2 + washer_thickness(screw_washer(pin_screw))), thickness])
|
||||||
|
children();
|
||||||
|
}
|
||||||
|
|
||||||
|
module door_hinge_stat_stl() { //! Generates the STL for the stationary part
|
||||||
|
stl("door_hinge_stat");
|
||||||
|
|
||||||
|
union() {
|
||||||
|
linear_extrude(height = thickness)
|
||||||
|
difference() {
|
||||||
|
rounded_square([stat_length, stat_width], rad);
|
||||||
|
|
||||||
|
door_hinge_stat_hole_positions()
|
||||||
|
poly_circle(screw_clearance_radius(stat_screw));
|
||||||
|
}
|
||||||
|
|
||||||
|
rotate([90, 0, 0])
|
||||||
|
linear_extrude(height = stat_width, center = true)
|
||||||
|
difference() {
|
||||||
|
hull() {
|
||||||
|
translate([0, dia / 2 + stat_clearance])
|
||||||
|
circle(d = dia);
|
||||||
|
|
||||||
|
translate([0, 0.5])
|
||||||
|
square([dia, 1], center = true);
|
||||||
|
}
|
||||||
|
translate([0, dia / 2 + stat_clearance])
|
||||||
|
teardrop(r = screw_clearance_radius(pin_screw), h = 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module door_hinge_assembly(top, door_thickness = 6) { //! The moving assembly that goes on the door
|
||||||
|
dir = top ? -1 : 1;
|
||||||
|
pin_x = door_hinge_pin_x();
|
||||||
|
pin_y = door_hinge_pin_y();
|
||||||
|
washer = screw_washer(screw);
|
||||||
|
screw_length = screw_shorter_than(thickness + door_thickness + washer_thickness(washer));
|
||||||
|
|
||||||
|
translate([0, pin_y - (thickness + door_thickness / 2), dir * width / 2]) {
|
||||||
|
rotate([90, 0, 180])
|
||||||
|
color("red") door_hinge(door_thickness);
|
||||||
|
|
||||||
|
rotate([90, 0, 0])
|
||||||
|
door_hinge_hole_positions()
|
||||||
|
screw_and_washer(screw, screw_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
translate([pin_x, pin_y, top ? 0 : -washer_thickness(screw_washer(pin_screw))])
|
||||||
|
washer(screw_washer(pin_screw));
|
||||||
|
|
||||||
|
translate([pin_x, pin_y, top ? washer_thickness(screw_washer(pin_screw)) + stat_width : width])
|
||||||
|
screw_and_washer(pin_screw, screw_longer_than(2 * washer_thickness(screw_washer(pin_screw)) + width + stat_width));
|
||||||
|
}
|
||||||
|
|
||||||
|
module door_hinge_static_assembly(top, sheet_thickness = 3) { //! The stationary assembly
|
||||||
|
dir = top ? -1 : 1;
|
||||||
|
pin_x = door_hinge_pin_x();
|
||||||
|
|
||||||
|
stat_washer = screw_washer(stat_screw);
|
||||||
|
stat_nut = screw_nut(stat_screw);
|
||||||
|
stat_screw_length = screw_longer_than(thickness + sheet_thickness + 2 * washer_thickness(stat_washer) + nut_thickness(stat_nut, true));
|
||||||
|
|
||||||
|
translate([pin_x, 0, -dir * (stat_width / 2 + washer_thickness(screw_washer(pin_screw)))])
|
||||||
|
rotate([90, 0, 0]) {
|
||||||
|
color("lime") door_hinge_stat_stl();
|
||||||
|
|
||||||
|
door_hinge_stat_hole_positions() {
|
||||||
|
screw_and_washer(stat_screw, stat_screw_length);
|
||||||
|
translate_z(-thickness - sheet_thickness)
|
||||||
|
vflip()
|
||||||
|
nut_and_washer(stat_nut, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module door_hinge_parts_stl() { //! Generates the STL for both parts of the hinge
|
||||||
|
translate([2, width / 2 + 1])
|
||||||
|
door_hinge_6_stl();
|
||||||
|
|
||||||
|
translate([0, -stat_width / 2 - 1])
|
||||||
|
door_hinge_stat_stl();
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
//! Door latch for 6mm acrylic door for 3D printer. See [door_hinge](#door_hinge).
|
||||||
|
//
|
||||||
|
include <core.scad>
|
||||||
|
use <utils/hanging_hole.scad>
|
||||||
|
include <vitamins/screws.scad>
|
||||||
|
|
||||||
|
length = 35;
|
||||||
|
width = 12;
|
||||||
|
height = 14.25;
|
||||||
|
|
||||||
|
thickness = 5;
|
||||||
|
rad = 3;
|
||||||
|
|
||||||
|
screw = M4_hex_screw;
|
||||||
|
|
||||||
|
function door_latch_screw() = screw; //! The screw used for the axle
|
||||||
|
function door_latch_offset() = width / 2 + 1; //! Offset of the axle from the door edge
|
||||||
|
|
||||||
|
nut_trap_depth = round_to_layer(screw_head_height(screw)) + 4 * layer_height;
|
||||||
|
|
||||||
|
module door_latch_stl() { //! Generates the STL for the printed part
|
||||||
|
stl("door_latch");
|
||||||
|
|
||||||
|
ridge = 4;
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
hull() {
|
||||||
|
rounded_rectangle([length, width, thickness - tan(30) * (width - ridge) / 2], rad, center = false);
|
||||||
|
|
||||||
|
translate_z(thickness / 2)
|
||||||
|
cube([length, ridge, thickness], center = true);
|
||||||
|
}
|
||||||
|
|
||||||
|
cylinder(d = width, h = height);
|
||||||
|
}
|
||||||
|
hanging_hole(nut_trap_depth, screw_clearance_radius(screw))
|
||||||
|
circle(r = nut_trap_radius(screw_nut(screw)), $fn = 6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module door_latch_assembly(sheet_thickness = 3) { //! The assembly for a specified sheet thickess
|
||||||
|
washer = screw_washer(screw);
|
||||||
|
nut = screw_nut(screw);
|
||||||
|
|
||||||
|
screw_length = screw_longer_than(height - nut_trap_depth + sheet_thickness + 2 * washer_thickness(washer) + nut_thickness(nut, true));
|
||||||
|
|
||||||
|
translate([0, -height - washer_thickness(washer)])
|
||||||
|
rotate([-90, 0, 0]) {
|
||||||
|
color("lime") render() door_latch_stl();
|
||||||
|
|
||||||
|
translate_z(nut_trap_depth)
|
||||||
|
vflip()
|
||||||
|
screw(screw, screw_length);
|
||||||
|
|
||||||
|
translate_z(height)
|
||||||
|
washer(washer);
|
||||||
|
|
||||||
|
translate_z(height + sheet_thickness + washer_thickness(washer))
|
||||||
|
nut_and_washer(nut, true);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
|
||||||
|
//
|
||||||
|
//! Pintable fan finger guard to match the specified fan. To be ```include```d, not ```use```d.
|
||||||
|
//!
|
||||||
|
//! The ring spacing as well as the number of spokes can be specified, if zero a gasket is generated instead of a guard.
|
||||||
|
//
|
||||||
|
use <utils/tube.scad>
|
||||||
|
|
||||||
|
function fan_guard_thickness() = 2; //! Default thickness
|
||||||
|
|
||||||
|
function fan_guard_wall() = extrusion_width - layer_height / 2 + nozzle / 2 + extrusion_width / 2;
|
||||||
|
function fan_guard_corner_r(type) = washer_diameter(screw_washer(fan_screw(type))) / 2 + 0.5; //! Corner radius of the guard
|
||||||
|
function fan_guard_width(type) = max(2 * (fan_hole_pitch(type) + fan_guard_corner_r(type)), fan_bore(type) + 4 * fan_guard_wall()); //! Width of the guard
|
||||||
|
|
||||||
|
module fan_guard(type, name = false, thickness = fan_guard_thickness(), spokes = 4, finger_width = 7, grill = false) { //! Generate the STL
|
||||||
|
if(thickness)
|
||||||
|
stl(name ? name : str("fan_guard_", fan_width(type)));
|
||||||
|
hole_pitch = fan_hole_pitch(type);
|
||||||
|
corner_radius = fan_guard_corner_r(type);
|
||||||
|
wall = grill ? 2 : fan_guard_wall();
|
||||||
|
spoke = grill ? 3 : wall;
|
||||||
|
width = fan_guard_width(type);
|
||||||
|
|
||||||
|
hole = fan_aperture(type) / 2;
|
||||||
|
max_ring_pitch = finger_width + wall;
|
||||||
|
inner_ring = max_ring_pitch / 2;
|
||||||
|
gap = hole + wall / 2 - inner_ring;
|
||||||
|
rings = ceil(gap / max_ring_pitch);
|
||||||
|
ring_pitch = gap / rings;
|
||||||
|
spoke_end = grill && fan_aperture(type) > fan_bore(type) ? hole - ring_pitch : hole;
|
||||||
|
spoke_start = grill && rings > 1 ? inner_ring + ring_pitch : inner_ring;
|
||||||
|
rounding = grill ? 1.5 : 0;
|
||||||
|
|
||||||
|
extrude_if(thickness) {
|
||||||
|
difference() {
|
||||||
|
offset(-rounding) offset(rounding) {
|
||||||
|
difference() {
|
||||||
|
rounded_square([width, width], r = width / 2 - hole_pitch);
|
||||||
|
|
||||||
|
fan_holes(type, !grill, !grill, h = 0);
|
||||||
|
}
|
||||||
|
if(spokes) {
|
||||||
|
intersection() {
|
||||||
|
union() {
|
||||||
|
for(i = [(grill ? 1 : 0) : 1 : rings - 1]) {
|
||||||
|
r = inner_ring + i * ring_pitch;
|
||||||
|
|
||||||
|
ring(or = r + wall / 2, ir = r - wall / 2);
|
||||||
|
}
|
||||||
|
for(i = [0 : spokes - 1])
|
||||||
|
rotate(i * 360 / spokes + 45)
|
||||||
|
translate([spoke_start, -spoke / 2])
|
||||||
|
square([spoke_end - spoke_start + eps, spoke]);
|
||||||
|
}
|
||||||
|
square(width - eps, center = true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(grill)
|
||||||
|
fan_hole_positions(type, z = 0)
|
||||||
|
drill(screw_clearance_radius(fan_screw(type)), 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
if(grill)
|
||||||
|
difference() {
|
||||||
|
r = min(inner_ring + ring_pitch, fan_hub(type) / 2);
|
||||||
|
circle(r);
|
||||||
|
|
||||||
|
for(a = [45 : 90 : 360])
|
||||||
|
rotate(a)
|
||||||
|
translate([r / 2, 0])
|
||||||
|
circle(wall);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,170 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
//! Fixing block to mount two sheets at right angles using threaded inserts.
|
||||||
|
//! Defaults to M3 but other screw sizes can be specified provided they have inserts defined.
|
||||||
|
//!
|
||||||
|
//! See [butt_box](#Butt_box) for an example of usage.
|
||||||
|
//!
|
||||||
|
//! Note that the block with its inserts is defined as a sub assembly, but its fasteners get added to the parent assembly.
|
||||||
|
//
|
||||||
|
include <core.scad>
|
||||||
|
include <vitamins/screws.scad>
|
||||||
|
include <vitamins/inserts.scad>
|
||||||
|
use <utils/maths.scad>
|
||||||
|
|
||||||
|
def_screw = M3_cap_screw;
|
||||||
|
wall = 2.5;
|
||||||
|
|
||||||
|
function fixing_block_screw() = def_screw; //! Default screw type
|
||||||
|
function fixing_block_width(screw = def_screw) = 4 * wall + 3 * insert_outer_d(screw_insert(screw)); //! Width given screw size
|
||||||
|
function fixing_block_depth(screw = def_screw) = //! Depth given screw size
|
||||||
|
let(insert = screw_insert(screw))
|
||||||
|
max(insert_length(insert) + wall, insert_outer_d(insert) + 2 * wall);
|
||||||
|
|
||||||
|
function fixing_block_height(screw = def_screw) = fixing_block_depth(screw); //! Height given screw size, same as depth
|
||||||
|
|
||||||
|
function fixing_block_h_hole(screw = def_screw) = translate(fixing_block_depth(screw) / 2) * rotate([90, 0, 0]); //! Returns transform to position the horizontal screw
|
||||||
|
function fixing_block_v_holes(screw = def_screw) = //! Returns a list of transforms to position the vertical screws
|
||||||
|
let(pitch = 2 * insert_outer_d(screw_insert(screw)) + 2 * wall, offset = fixing_block_depth(screw) / 2)
|
||||||
|
[for(end = [-1, 1]) translate([end * pitch / 2, offset]) * rotate([180, 0, 0])];
|
||||||
|
|
||||||
|
function fixing_block_holes(screw) = concat([fixing_block_h_hole(screw)], fixing_block_v_holes(screw)); //! Returns a list of transforms to position all the screws
|
||||||
|
|
||||||
|
module fixing_block_h_hole(screw = def_screw) //! Position children on the horizontal hole
|
||||||
|
multmatrix(fixing_block_h_hole(screw))
|
||||||
|
children();
|
||||||
|
|
||||||
|
module fixing_block_v_holes(screw = def_screw) //! Position children on the vertical holes
|
||||||
|
for(p = fixing_block_v_holes(screw))
|
||||||
|
multmatrix(p)
|
||||||
|
children();
|
||||||
|
|
||||||
|
module fixing_block_holes(screw = def_screw) //! Position children on all the holes
|
||||||
|
for(p = fixing_block_holes(screw))
|
||||||
|
multmatrix(p)
|
||||||
|
children();
|
||||||
|
|
||||||
|
module fixing_block_h_hole_2D(screw = def_screw) //! Position 2D child on the horizontal hole
|
||||||
|
translate([0, fixing_block_depth(screw) / 2])
|
||||||
|
children();
|
||||||
|
|
||||||
|
module fixing_block(screw = def_screw) { //! Generate the STL
|
||||||
|
stl(str("fixing_block_M", screw_radius(screw) * 20));
|
||||||
|
r = 1;
|
||||||
|
insert = screw_insert(screw);
|
||||||
|
corner_rad = insert_outer_d(insert) / 2 + wall;
|
||||||
|
fb_width = fixing_block_width(screw);
|
||||||
|
fb_height = fixing_block_height(screw);
|
||||||
|
fb_depth = fixing_block_depth(screw);
|
||||||
|
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
linear_extrude(height = fb_height, convexity = 5)
|
||||||
|
difference() {
|
||||||
|
hull() {
|
||||||
|
for(side = [-1, 1]) {
|
||||||
|
translate([side * (fb_width / 2 - corner_rad), fb_depth - corner_rad])
|
||||||
|
circle4n(corner_rad);
|
||||||
|
|
||||||
|
translate([side * (fb_width / 2 - r), r])
|
||||||
|
circle4n(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fixing_block_v_holes(screw)
|
||||||
|
poly_circle(screw_clearance_radius(screw));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
translate_z(fb_height)
|
||||||
|
fixing_block_v_holes(screw)
|
||||||
|
insert_hole(insert);
|
||||||
|
|
||||||
|
fixing_block_h_hole(screw)
|
||||||
|
insert_hole(insert, 10, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module fixing_block_assembly(screw = def_screw) pose([55, 180, 25], [0, 4.8, 4.8]) //! Printed part with the inserts inserted
|
||||||
|
assembly(str("fixing_block_M", 20 * screw_radius(screw))) {
|
||||||
|
translate_z(fixing_block_height(screw))
|
||||||
|
rotate([0, 180, 0])
|
||||||
|
color(pp1_colour) render() fixing_block(screw);
|
||||||
|
|
||||||
|
insert = screw_insert(screw);
|
||||||
|
|
||||||
|
fixing_block_v_holes(screw)
|
||||||
|
insert(insert);
|
||||||
|
|
||||||
|
fixing_block_h_hole(screw)
|
||||||
|
insert(insert);
|
||||||
|
}
|
||||||
|
|
||||||
|
module fastened_fixing_block_assembly(thickness, screw = def_screw, screw2 = undef, thickness2 = undef) { //! Assembly with fasteners in place
|
||||||
|
module fb_screw(screw, thickness) {
|
||||||
|
washer = screw_washer(screw);
|
||||||
|
insert = screw_insert(screw);
|
||||||
|
screw_length = screw_longer_than(2 * washer_thickness(washer) + thickness + insert_length(insert));
|
||||||
|
|
||||||
|
translate_z(thickness)
|
||||||
|
screw_and_washer(screw, screw_length, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
no_pose() fixing_block_assembly(screw);
|
||||||
|
|
||||||
|
fixing_block_v_holes(screw)
|
||||||
|
fb_screw(screw, thickness2 ? thickness2 : thickness);
|
||||||
|
|
||||||
|
fixing_block_h_hole(screw)
|
||||||
|
fb_screw(screw2 ? screw2 : screw, thickness);
|
||||||
|
}
|
||||||
|
|
||||||
|
module fixing_block_M20_stl() fixing_block(M2_cap_screw);
|
||||||
|
module fixing_block_M25_stl() fixing_block(M2p5_cap_screw);
|
||||||
|
module fixing_block_M30_stl() fixing_block(M3_cap_screw);
|
||||||
|
module fixing_block_M40_stl() fixing_block(M4_cap_screw);
|
||||||
|
|
||||||
|
//
|
||||||
|
//! 1. Lay the blocks out with the two larger holes facing upwards.
|
||||||
|
//! 1. Place two M2 inserts into the two vertical holes of each block and push them home with a soldering iron with a conical bit heated to 200°C.
|
||||||
|
//! When removing the iron it helps to twist it a little anti-clockwise to release it from the thread.
|
||||||
|
//! 1. Lay the blocks on their backs and insert a third insert the same way.
|
||||||
|
//
|
||||||
|
module fixing_block_M20_assembly() fixing_block_assembly(M2_cap_screw);
|
||||||
|
//
|
||||||
|
//! 1. Lay the blocks out with the two larger holes facing upwards.
|
||||||
|
//! 1. Place two M2.5 inserts into the two vertical holes of each block and push them home with a soldering iron with a conical bit heated to 200°C.
|
||||||
|
//! When removing the iron it helps to twist it a little anti-clockwise to release it from the thread.
|
||||||
|
//! 1. Lay the blocks on their backs and insert a third insert the same way.
|
||||||
|
//
|
||||||
|
module fixing_block_M25_assembly() fixing_block_assembly(M2p5_cap_screw);
|
||||||
|
//
|
||||||
|
//! 1. Lay the blocks out with the two larger holes facing upwards.
|
||||||
|
//! 1. Place two M3 inserts into the two vertical holes of each block and push them home with a soldering iron with a conical bit heated to 200°C.
|
||||||
|
//! When removing the iron it helps to twist it a little anti-clockwise to release it from the thread.
|
||||||
|
//! 1. Lay the blocks on their backs and insert a third insert the same way.
|
||||||
|
//
|
||||||
|
module fixing_block_M30_assembly() fixing_block_assembly(M3_cap_screw);
|
||||||
|
//
|
||||||
|
//! 1. Lay the blocks out with the two larger holes facing upwards.
|
||||||
|
//! 1. Place two M4 inserts into the two vertical holes of each block and push them home with a soldering iron with a conical bit heated to 200°C.
|
||||||
|
//! When removing the iron it helps to twist it a little anti-clockwise to release it from the thread.
|
||||||
|
//! 1. Lay the blocks on their backs and insert a third insert the same way.
|
||||||
|
//
|
||||||
|
module fixing_block_M40_assembly() fixing_block_assembly(M4_cap_screw);
|
|
@ -0,0 +1,151 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
//! Customisable printed rubber feet for equipment cases. The insert variant is better for solid feet because
|
||||||
|
//! inserts don't grip well in rubber.
|
||||||
|
//
|
||||||
|
include <core.scad>
|
||||||
|
include <vitamins/screws.scad>
|
||||||
|
include <vitamins/inserts.scad>
|
||||||
|
|
||||||
|
foot = [25, 12, 3, 2, M4_cap_screw, 10];
|
||||||
|
insert_foot = [20, 10, 0, 2, M3_cap_screw, 10];
|
||||||
|
|
||||||
|
function foot() = foot; //! Default foot used unless a list of parameters is passed
|
||||||
|
function insert_foot() = insert_foot; //! Default foot with insert
|
||||||
|
|
||||||
|
function foot_diameter(type = foot) = type[0]; //! Outside maximum diameter
|
||||||
|
function foot_height(type = foot) = type[1]; //! Total height
|
||||||
|
function foot_thickness(type = foot)= type[2]; //! Thickness under the screw
|
||||||
|
function foot_rad(type = foot) = type[3]; //! Rounded corner radius
|
||||||
|
function foot_screw(type = foot) = type[4]; //! Screw type
|
||||||
|
function foot_slant(type = foot) = type[5]; //! Taper angle
|
||||||
|
|
||||||
|
module foot(type = foot) { //! Generate STL
|
||||||
|
stl("foot");
|
||||||
|
h = foot_height(type);
|
||||||
|
t = foot_thickness(type);
|
||||||
|
r1 = washer_radius(screw_washer(foot_screw(type)));
|
||||||
|
r3 = foot_diameter(type) / 2;
|
||||||
|
r2 = r3 - h * tan(foot_slant(type));
|
||||||
|
r = foot_rad(type);
|
||||||
|
|
||||||
|
union() {
|
||||||
|
rotate_extrude(convexity = 3) {
|
||||||
|
hull() {
|
||||||
|
translate([r1, 0])
|
||||||
|
square([r3 - r1, eps]);
|
||||||
|
|
||||||
|
for(x = [r1 + r, r2 - r])
|
||||||
|
translate([x, h - r])
|
||||||
|
circle4n(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
linear_extrude(height = t)
|
||||||
|
difference() {
|
||||||
|
circle(r1 + eps);
|
||||||
|
|
||||||
|
poly_circle( screw_clearance_radius(foot_screw(type)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module foot_assembly(t = 0, type = foot) { //! Assembly with fasteners in place for specified sheet thickness
|
||||||
|
screw = foot_screw(type);
|
||||||
|
washer = screw_washer(screw);
|
||||||
|
nut = screw_nut(screw);
|
||||||
|
squeeze = 0.5;
|
||||||
|
screw_length = screw_longer_than(foot_thickness(type) + t + 2 * washer_thickness(washer) + nut_thickness(nut, true) - squeeze);
|
||||||
|
|
||||||
|
vflip() explode(15, true) {
|
||||||
|
color(pp4_colour) foot(type);
|
||||||
|
|
||||||
|
if(t)
|
||||||
|
explode(15, true)
|
||||||
|
translate_z(foot_thickness(type))
|
||||||
|
screw_and_washer(screw, screw_length);
|
||||||
|
}
|
||||||
|
if(t)
|
||||||
|
translate_z(t)
|
||||||
|
nut_and_washer(nut, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
module insert_foot(type = insert_foot) { //! Generate STL for foot with insert
|
||||||
|
stl("insert_foot");
|
||||||
|
h = foot_height(type);
|
||||||
|
r3 = foot_diameter(type) / 2;
|
||||||
|
r2 = r3 - h * tan(foot_slant(type));
|
||||||
|
r = foot_rad(type);
|
||||||
|
|
||||||
|
insert = screw_insert(foot_screw(type));
|
||||||
|
h2 = insert_hole_length(insert);
|
||||||
|
r4 = insert_hole_radius(insert);
|
||||||
|
r5 = r4 + 1;
|
||||||
|
union() {
|
||||||
|
rotate_extrude() {
|
||||||
|
union() {
|
||||||
|
hull() {
|
||||||
|
translate([r5, 0]) {
|
||||||
|
square([r3 - r5, eps]);
|
||||||
|
square([eps, h]);
|
||||||
|
}
|
||||||
|
|
||||||
|
translate([r2 - r, h - r])
|
||||||
|
circle4n(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
linear_extrude(height = h2 + eps)
|
||||||
|
difference() {
|
||||||
|
circle(r5 + eps);
|
||||||
|
|
||||||
|
poly_circle(r4);
|
||||||
|
}
|
||||||
|
|
||||||
|
translate_z(h2)
|
||||||
|
cylinder(r = r5 + eps, h = h - h2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
//! Place the insert in the bottom of the foot and push home with a soldering iron with a conical bit heated to 200°C.
|
||||||
|
//
|
||||||
|
module insert_foot_assembly(type = insert_foot) //! Printed part with insert in place
|
||||||
|
assembly("insert_foot") {
|
||||||
|
screw = foot_screw(type);
|
||||||
|
insert = screw_insert(screw);
|
||||||
|
|
||||||
|
vflip()
|
||||||
|
color(pp1_colour) insert_foot(type);
|
||||||
|
|
||||||
|
translate_z(-foot_thickness(type))
|
||||||
|
insert(insert);
|
||||||
|
}
|
||||||
|
|
||||||
|
module fastened_insert_foot_assembly(t = 3, type = insert_foot) { //! Assembly with fasteners in place for specified sheet thickness
|
||||||
|
screw = foot_screw(type);
|
||||||
|
washer = screw_washer(screw);
|
||||||
|
insert = screw_insert(screw);
|
||||||
|
screw_length = screw_shorter_than(insert_length(insert) + t + 2 * washer_thickness(washer));
|
||||||
|
|
||||||
|
explode(-10) insert_foot_assembly(type);
|
||||||
|
|
||||||
|
translate_z(t)
|
||||||
|
screw_and_washer(screw, screw_length, true);
|
||||||
|
}
|
|
@ -0,0 +1,90 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// This file included directly or indirectly in every scad file.
|
||||||
|
//
|
||||||
|
// This scheme allows the following:
|
||||||
|
// bom defaults to 0
|
||||||
|
// Setting $bom on the command line or in the main file before including lib.scad overrides it everywhere.
|
||||||
|
// Setting $bom after including lib overrides bom in the libs but not in the local file.
|
||||||
|
// Setting $_bom in the local file overrides it in the local file but not in the libs.
|
||||||
|
//
|
||||||
|
//function is_undef(x) = x == undef;
|
||||||
|
|
||||||
|
$_bom = is_undef($bom) ? 0 : $bom; // 0 no bom, 1 assemblies and stls, 2 vitamins as well
|
||||||
|
$exploded = is_undef($explode) ? 0 : $explode; // 1 for exploded view
|
||||||
|
layer_height = is_undef($layer_height) ? 0.25 : $layer_height; // layer heigth when printing
|
||||||
|
extrusion_width = is_undef($extrusion_width) ? 0.5 : $extrusion_width; // filament width when printing
|
||||||
|
nozzle = is_undef($nozzle) ? 0.45 : $nozzle; // 3D printer nozzle
|
||||||
|
cnc_bit_r = is_undef($cnc_bit_r) ? 1.2 : $cnc_bit_r; // miniumum tool radius when milling 2D objects
|
||||||
|
pp1_colour = is_undef($pp1_colour) ? "lime" : $pp1_colour; // printed part colour 1
|
||||||
|
pp2_colour = is_undef($pp2_colour) ? "red" : $pp2_colour; // printed part colour 2
|
||||||
|
pp3_colour = is_undef($pp3_colour) ? "blue" : $pp3_colour; // printed part colour 3
|
||||||
|
pp4_colour = is_undef($pp4_colour) ? "darkorange" : $pp4_colour;// printed part colour 4
|
||||||
|
show_rays = is_undef($show_rays) ? false : $show_rays; // show camera sight lines and light direction
|
||||||
|
|
||||||
|
// Minimum wall is about two filaments wide but we extrude it closer to get better bonding
|
||||||
|
squeezed_wall = $preview ? 2 * extrusion_width - layer_height * (1 - PI / 4)
|
||||||
|
: extrusion_width - layer_height / 2 + nozzle / 2 + extrusion_width / 2;
|
||||||
|
|
||||||
|
inf = 1e10; // very big
|
||||||
|
eps = 1/128; // small fudge factor to stop CSG barfing on coincident faces.
|
||||||
|
$fa = 6;
|
||||||
|
$fs = extrusion_width / 2;
|
||||||
|
|
||||||
|
function round_to_layer(z) = ceil(z / layer_height) * layer_height;
|
||||||
|
// Some additional named colors
|
||||||
|
grey20 = [0.2, 0.2, 0.2];
|
||||||
|
grey30 = [0.3, 0.3, 0.3];
|
||||||
|
grey40 = [0.4, 0.4, 0.4];
|
||||||
|
grey50 = [0.5, 0.5, 0.5];
|
||||||
|
grey60 = [0.6, 0.6, 0.6];
|
||||||
|
grey70 = [0.7, 0.7, 0.7];
|
||||||
|
grey80 = [0.8, 0.8, 0.8];
|
||||||
|
grey90 = [0.9, 0.9, 0.9];
|
||||||
|
brass = "gold";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enums
|
||||||
|
*/
|
||||||
|
//
|
||||||
|
// Screws
|
||||||
|
//
|
||||||
|
hs_cap = 0;
|
||||||
|
hs_pan = 1;
|
||||||
|
hs_cs = 2; // counter sunk
|
||||||
|
hs_hex = 3;
|
||||||
|
hs_grub = 4; // pulley set screw
|
||||||
|
hs_cs_cap = 5;
|
||||||
|
hs_dome = 6;
|
||||||
|
//
|
||||||
|
// Hot end descriptions
|
||||||
|
//
|
||||||
|
jhead = 1;
|
||||||
|
e3d = 2;
|
||||||
|
//
|
||||||
|
// Face enumeration
|
||||||
|
//
|
||||||
|
f_bottom = 0;
|
||||||
|
f_top = 1;
|
||||||
|
f_left = 2;
|
||||||
|
f_right = 3;
|
||||||
|
f_front = 4;
|
||||||
|
f_back = 5;
|
|
@ -0,0 +1,103 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
//! Printed handle that can be printed without needing support material due to its truncated teardrop profile.
|
||||||
|
//
|
||||||
|
include <core.scad>
|
||||||
|
include <vitamins/screws.scad>
|
||||||
|
include <vitamins/inserts.scad>
|
||||||
|
|
||||||
|
dia = 18;
|
||||||
|
length = 90; // inside length
|
||||||
|
height = 30; // inside height
|
||||||
|
screw = M4_cap_screw;
|
||||||
|
insert = screw_insert(screw);
|
||||||
|
|
||||||
|
pitch = length + dia;
|
||||||
|
|
||||||
|
function handle_length() = pitch + dia; //! Outside length
|
||||||
|
function handle_width() = dia; //! The width, i.e. diameter
|
||||||
|
function handle_height() = height + dia; //! Total height
|
||||||
|
function handle_screw() = screw; //! The screw type
|
||||||
|
|
||||||
|
module handle_screw_positions() //! Position children at the screw positions
|
||||||
|
for(end = [-1, 1])
|
||||||
|
translate([end * pitch / 2, 0])
|
||||||
|
children();
|
||||||
|
|
||||||
|
module handle_holes(h = 100) //! Drills holes for the screws
|
||||||
|
handle_screw_positions()
|
||||||
|
drill(screw_clearance_radius(screw), h);
|
||||||
|
|
||||||
|
module handle_stl() { //! generate the STL
|
||||||
|
stl("handle");
|
||||||
|
|
||||||
|
module end(end)
|
||||||
|
translate([end * pitch / 2, 0])
|
||||||
|
rotate_extrude()
|
||||||
|
intersection() {
|
||||||
|
rotate(180)
|
||||||
|
teardrop(r = dia / 2, h = 0);
|
||||||
|
|
||||||
|
translate([0, - (dia + 1) / 2])
|
||||||
|
square([dia / 2 + 1, dia + 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
translate_z(dia / 2)
|
||||||
|
union() {
|
||||||
|
hull() {
|
||||||
|
end(-1);
|
||||||
|
|
||||||
|
end(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_screw_positions()
|
||||||
|
render() difference() {
|
||||||
|
h = height + dia / 2;
|
||||||
|
cylinder(d = dia, h = h);
|
||||||
|
|
||||||
|
translate_z(h)
|
||||||
|
insert_hole(insert, 6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
//! Place inserts in the bottom of the posts and push them home with a soldering iron with a conical bit heated to 200°C.
|
||||||
|
//
|
||||||
|
module handle_assembly() pose([225, 0, 150], [0, 0, 14]) //! Printed part with inserts in place
|
||||||
|
assembly("handle") {
|
||||||
|
translate_z(handle_height())
|
||||||
|
color(pp1_colour) vflip() handle_stl();
|
||||||
|
|
||||||
|
handle_screw_positions()
|
||||||
|
vflip()
|
||||||
|
insert(insert);
|
||||||
|
}
|
||||||
|
|
||||||
|
module handle_fastened_assembly(thickness) { //! Assembly with fasteners in place
|
||||||
|
screw_length = screw_longer_than(thickness + insert_length(insert) + 2 * washer_thickness(screw_washer(screw)));
|
||||||
|
|
||||||
|
handle_assembly();
|
||||||
|
|
||||||
|
handle_screw_positions()
|
||||||
|
vflip()
|
||||||
|
translate_z(thickness)
|
||||||
|
screw_and_washer(screw, screw_length, true);
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// Include this file to use the library
|
||||||
|
//
|
||||||
|
include <core.scad>
|
||||||
|
|
||||||
|
include <vitamins/fans.scad>
|
||||||
|
include <vitamins/inserts.scad>
|
||||||
|
include <vitamins/ring_terminals.scad>
|
||||||
|
include <vitamins/rails.scad>
|
||||||
|
include <vitamins/belts.scad>
|
||||||
|
include <vitamins/pulleys.scad>
|
||||||
|
include <vitamins/sheets.scad>
|
||||||
|
include <vitamins/stepper_motors.scad>
|
||||||
|
include <vitamins/components.scad>
|
||||||
|
include <vitamins/hot_ends.scad>
|
||||||
|
include <vitamins/tubings.scad>
|
||||||
|
include <vitamins/zipties.scad>
|
||||||
|
include <vitamins/linear_bearings.scad>
|
||||||
|
include <vitamins/rod.scad>
|
||||||
|
include <vitamins/leadnuts.scad>
|
||||||
|
include <vitamins/bulldogs.scad>
|
||||||
|
include <vitamins/pillars.scad>
|
||||||
|
include <vitamins/psus.scad>
|
||||||
|
include <vitamins/iecs.scad>
|
||||||
|
include <vitamins/rockers.scad>
|
||||||
|
include <vitamins/ssrs.scad>
|
||||||
|
include <vitamins/d_connectors.scad>
|
||||||
|
include <vitamins/buttons.scad>
|
||||||
|
include <vitamins/pcbs.scad>
|
||||||
|
include <vitamins/modules.scad>
|
||||||
|
include <vitamins/displays.scad>
|
||||||
|
include <vitamins/blowers.scad>
|
||||||
|
include <vitamins/leds.scad>
|
||||||
|
include <vitamins/toggles.scad>
|
||||||
|
include <vitamins/transformers.scad>
|
||||||
|
include <vitamins/variacs.scad>
|
||||||
|
include <vitamins/springs.scad>
|
||||||
|
include <vitamins/batteries.scad>
|
||||||
|
include <vitamins/microswitches.scad>
|
||||||
|
include <vitamins/ball_bearings.scad>
|
||||||
|
include <vitamins/light_strips.scad>
|
||||||
|
include <vitamins/spools.scad>
|
||||||
|
include <vitamins/mains_sockets.scad>
|
||||||
|
|
||||||
|
use <vitamins/jack.scad>
|
||||||
|
use <vitamins/meter.scad>
|
||||||
|
use <vitamins/fuseholder.scad>
|
||||||
|
|
||||||
|
use <vitamins/opengrab.scad>
|
||||||
|
use <vitamins/wire.scad>
|
||||||
|
use <vitamins/sealing_strip.scad>
|
||||||
|
use <vitamins/cable_strip.scad>
|
||||||
|
use <vitamins/veroboard.scad>
|
||||||
|
use <vitamins/o_ring.scad>
|
||||||
|
use <vitamins/microview.scad>
|
||||||
|
|
||||||
|
use <utils/maths.scad>
|
||||||
|
use <utils/bezier.scad>
|
||||||
|
use <utils/sweep.scad>
|
||||||
|
use <utils/rounded_cylinder.scad>
|
||||||
|
use <utils/dogbones.scad>
|
||||||
|
use <utils/tube.scad>
|
||||||
|
use <utils/quadrant.scad>
|
||||||
|
use <utils/hanging_hole.scad>
|
||||||
|
use <utils/fillet.scad>
|
||||||
|
use <utils/rounded_polygon.scad>
|
||||||
|
use <utils/layout.scad>
|
||||||
|
use <utils/round.scad>
|
||||||
|
use <utils/offset.scad>
|
||||||
|
use <utils/sector.scad>
|
|
@ -0,0 +1,339 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// This file shows all the parts in the library.
|
||||||
|
//
|
||||||
|
include <lib.scad>
|
||||||
|
|
||||||
|
use <tests/ball_bearings.scad>
|
||||||
|
use <tests/batteries.scad>
|
||||||
|
use <tests/belts.scad>
|
||||||
|
use <tests/blowers.scad>
|
||||||
|
use <tests/bulldogs.scad>
|
||||||
|
use <tests/buttons.scad>
|
||||||
|
use <tests/cable_strips.scad>
|
||||||
|
use <tests/components.scad>
|
||||||
|
use <tests/d_connectors.scad>
|
||||||
|
use <tests/displays.scad>
|
||||||
|
use <tests/fans.scad>
|
||||||
|
use <tests/fuseholder.scad>
|
||||||
|
use <tests/hot_ends.scad>
|
||||||
|
use <tests/iecs.scad>
|
||||||
|
use <tests/inserts.scad>
|
||||||
|
use <tests/jack.scad>
|
||||||
|
use <tests/leadnuts.scad>
|
||||||
|
use <tests/leds.scad>
|
||||||
|
use <tests/light_strips.scad>
|
||||||
|
use <tests/linear_bearings.scad>
|
||||||
|
use <tests/meter.scad>
|
||||||
|
use <tests/microswitches.scad>
|
||||||
|
use <tests/modules.scad>
|
||||||
|
use <tests/nuts.scad>
|
||||||
|
use <tests/o_ring.scad>
|
||||||
|
use <tests/opengrab.scad>
|
||||||
|
use <tests/pcbs.scad>
|
||||||
|
use <tests/pillars.scad>
|
||||||
|
use <tests/psus.scad>
|
||||||
|
use <tests/pulleys.scad>
|
||||||
|
use <tests/rails.scad>
|
||||||
|
use <tests/ring_terminals.scad>
|
||||||
|
use <tests/rockers.scad>
|
||||||
|
use <tests/rod.scad>
|
||||||
|
use <tests/screws.scad>
|
||||||
|
use <tests/sealing_strip.scad>
|
||||||
|
use <tests/sheets.scad>
|
||||||
|
use <tests/spades.scad>
|
||||||
|
use <tests/springs.scad>
|
||||||
|
use <tests/ssrs.scad>
|
||||||
|
use <tests/stepper_motors.scad>
|
||||||
|
use <tests/toggles.scad>
|
||||||
|
use <tests/transformers.scad>
|
||||||
|
use <tests/tubings.scad>
|
||||||
|
use <tests/veroboard.scad>
|
||||||
|
use <tests/washers.scad>
|
||||||
|
use <tests/variacs.scad>
|
||||||
|
use <tests/zipties.scad>
|
||||||
|
|
||||||
|
use <tests/box.scad>
|
||||||
|
use <tests/butt_box.scad>
|
||||||
|
use <tests/cable_grommets.scad>
|
||||||
|
use <tests/carriers.scad>
|
||||||
|
use <tests/corner_block.scad>
|
||||||
|
use <tests/door_hinge.scad>
|
||||||
|
use <tests/door_latch.scad>
|
||||||
|
use <tests/fan_guard.scad>
|
||||||
|
use <tests/fixing_block.scad>
|
||||||
|
use <tests/foot.scad>
|
||||||
|
use <tests/handle.scad>
|
||||||
|
use <tests/ribbon_clamp.scad>
|
||||||
|
use <tests/screw_knob.scad>
|
||||||
|
use <tests/socket_box.scad>
|
||||||
|
use <tests/strap_handle.scad>
|
||||||
|
|
||||||
|
x5 = 800;
|
||||||
|
|
||||||
|
cable_grommets_y = 0;
|
||||||
|
|
||||||
|
translate([x5, cable_grommets_y])
|
||||||
|
cable_grommets();
|
||||||
|
|
||||||
|
translate([x5, cable_grommets_y + 50])
|
||||||
|
feet();
|
||||||
|
|
||||||
|
translate([x5, cable_grommets_y + 75])
|
||||||
|
fixing_blocks();
|
||||||
|
|
||||||
|
translate([x5, cable_grommets_y + 100])
|
||||||
|
corner_blocks();
|
||||||
|
|
||||||
|
translate([x5, cable_grommets_y + 150])
|
||||||
|
ribbon_clamps();
|
||||||
|
|
||||||
|
translate([x5 + 70, cable_grommets_y + 150])
|
||||||
|
screw_knobs();
|
||||||
|
|
||||||
|
translate([x5, cable_grommets_y + 470]) {
|
||||||
|
door_hinges()
|
||||||
|
door_latches();
|
||||||
|
}
|
||||||
|
|
||||||
|
translate([x5, cable_grommets_y + 370])
|
||||||
|
no_explode() socket_boxes();
|
||||||
|
|
||||||
|
translate([x5 + 60, cable_grommets_y + 200])
|
||||||
|
strap_handles();
|
||||||
|
|
||||||
|
translate([x5, cable_grommets_y + 250])
|
||||||
|
handle();
|
||||||
|
|
||||||
|
translate([900, 600])
|
||||||
|
box_test();
|
||||||
|
|
||||||
|
translate([850, 1170])
|
||||||
|
bbox_test();
|
||||||
|
|
||||||
|
x0 = 0;
|
||||||
|
inserts_y = 0;
|
||||||
|
nuts_y = inserts_y + 20;
|
||||||
|
washers_y = nuts_y + 60;
|
||||||
|
screws_y = washers_y + 120;
|
||||||
|
o_rings_y = screws_y + 130;
|
||||||
|
springs_y = o_rings_y + 20;
|
||||||
|
sealing_strip_y = springs_y + 20;
|
||||||
|
tubings_y = sealing_strip_y + 20;
|
||||||
|
pillars_y = tubings_y + 20;
|
||||||
|
leadnuts_y = pillars_y + 40;
|
||||||
|
pulleys_y = leadnuts_y +40;
|
||||||
|
hot_ends_y = pulleys_y + 60;
|
||||||
|
linear_bearings_y = hot_ends_y + 50;
|
||||||
|
sheets_y = linear_bearings_y + 50;
|
||||||
|
pcbs_y = sheets_y + 40;
|
||||||
|
displays_y = pcbs_y + 150;
|
||||||
|
fans_y = displays_y + 100;
|
||||||
|
transformers_y = fans_y + 120;
|
||||||
|
psus_y = transformers_y + 190;
|
||||||
|
|
||||||
|
translate([x0 + 20, inserts_y])
|
||||||
|
inserts();
|
||||||
|
|
||||||
|
translate([x0, inserts_y])
|
||||||
|
ring_terminals();
|
||||||
|
|
||||||
|
translate([x0, nuts_y])
|
||||||
|
nuts();
|
||||||
|
|
||||||
|
translate([x0, washers_y])
|
||||||
|
washers();
|
||||||
|
|
||||||
|
translate([x0, screws_y])
|
||||||
|
screws();
|
||||||
|
|
||||||
|
translate([x0, o_rings_y])
|
||||||
|
o_rings();
|
||||||
|
|
||||||
|
translate([x0, springs_y])
|
||||||
|
springs();
|
||||||
|
|
||||||
|
translate([x0 + 50, sealing_strip_y])
|
||||||
|
sealing_strip_test();
|
||||||
|
|
||||||
|
translate([x0, tubings_y])
|
||||||
|
tubings();
|
||||||
|
|
||||||
|
translate([x0, pillars_y])
|
||||||
|
pillars();
|
||||||
|
|
||||||
|
translate([x0, leadnuts_y ])
|
||||||
|
leadnuts();
|
||||||
|
|
||||||
|
translate([x0 + 80, leadnuts_y])
|
||||||
|
ball_bearings();
|
||||||
|
|
||||||
|
translate([x0, pulleys_y])
|
||||||
|
pulleys();
|
||||||
|
|
||||||
|
translate([x0, linear_bearings_y]) {
|
||||||
|
linear_bearings();
|
||||||
|
rods();
|
||||||
|
}
|
||||||
|
|
||||||
|
translate([x0 + 10, hot_ends_y])
|
||||||
|
hot_ends();
|
||||||
|
|
||||||
|
translate([x0, sheets_y])
|
||||||
|
sheets();
|
||||||
|
|
||||||
|
translate([x0, pcbs_y])
|
||||||
|
pcbs();
|
||||||
|
|
||||||
|
translate([x0, displays_y])
|
||||||
|
displays();
|
||||||
|
|
||||||
|
translate([x0, fans_y]) {
|
||||||
|
fans();
|
||||||
|
|
||||||
|
translate_z(3)
|
||||||
|
fan_guards();
|
||||||
|
}
|
||||||
|
|
||||||
|
translate([x0, transformers_y])
|
||||||
|
variacs();
|
||||||
|
|
||||||
|
translate([x0, psus_y])
|
||||||
|
psus();
|
||||||
|
|
||||||
|
|
||||||
|
x1 = x0 + 100;
|
||||||
|
zipties_y = 0;
|
||||||
|
bulldogs_y = zipties_y + 40;
|
||||||
|
|
||||||
|
translate([x1, zipties_y])
|
||||||
|
zipties();
|
||||||
|
|
||||||
|
translate([x1, bulldogs_y])
|
||||||
|
bulldogs();
|
||||||
|
|
||||||
|
x2 = x1 + 90;
|
||||||
|
leds_y = 0;
|
||||||
|
carriers_y = leds_y + 40;
|
||||||
|
spades_y = carriers_y + 40;
|
||||||
|
buttons_y = spades_y + 40;
|
||||||
|
jacks_y = buttons_y + 40;
|
||||||
|
microswitches_y = jacks_y + 40;
|
||||||
|
rockers_y = microswitches_y + 40;
|
||||||
|
toggles_y = rockers_y + 40;
|
||||||
|
components_y = toggles_y + 40;
|
||||||
|
|
||||||
|
translate([x2, leds_y])
|
||||||
|
leds();
|
||||||
|
|
||||||
|
translate([x2 + 8, carriers_y])
|
||||||
|
carriers();
|
||||||
|
|
||||||
|
translate([x2+ 38, carriers_y])
|
||||||
|
meters();
|
||||||
|
|
||||||
|
translate([x2 + 68, carriers_y])
|
||||||
|
fuseholders();
|
||||||
|
|
||||||
|
translate([x2, spades_y])
|
||||||
|
spades();
|
||||||
|
|
||||||
|
translate([x2, buttons_y])
|
||||||
|
buttons();
|
||||||
|
|
||||||
|
translate([x2, jacks_y])
|
||||||
|
jacks();
|
||||||
|
|
||||||
|
translate([x2, microswitches_y])
|
||||||
|
microswitches();
|
||||||
|
|
||||||
|
translate([x2, rockers_y])
|
||||||
|
rockers();
|
||||||
|
|
||||||
|
translate([x2, toggles_y])
|
||||||
|
toggles();
|
||||||
|
|
||||||
|
translate([x2, components_y])
|
||||||
|
components();
|
||||||
|
|
||||||
|
|
||||||
|
x3 = x2 + 150;
|
||||||
|
veroboard_y = 0;
|
||||||
|
d_connectors_y = veroboard_y + 110;
|
||||||
|
iecs_y = d_connectors_y + 80;
|
||||||
|
modules_y = iecs_y + 60;
|
||||||
|
ssrs_y = modules_y + 80;
|
||||||
|
blowers_y = ssrs_y + 60;
|
||||||
|
batteries_y = blowers_y + 100;
|
||||||
|
steppers_y = batteries_y + 70;
|
||||||
|
|
||||||
|
translate([x3, veroboard_y])
|
||||||
|
veroboard_test();
|
||||||
|
|
||||||
|
translate([x3, d_connectors_y])
|
||||||
|
d_connectors();
|
||||||
|
|
||||||
|
translate([x3, iecs_y])
|
||||||
|
iecs();
|
||||||
|
|
||||||
|
translate([x3 + 15, modules_y])
|
||||||
|
microview();
|
||||||
|
|
||||||
|
translate([x3 + 40, modules_y])
|
||||||
|
modules();
|
||||||
|
|
||||||
|
translate([x3, ssrs_y])
|
||||||
|
ssrs();
|
||||||
|
|
||||||
|
translate([x3, blowers_y])
|
||||||
|
blowers();
|
||||||
|
|
||||||
|
translate([x3, batteries_y])
|
||||||
|
batteries();
|
||||||
|
|
||||||
|
translate([x2, steppers_y]) // interloper
|
||||||
|
stepper_motors();
|
||||||
|
|
||||||
|
translate([x3, transformers_y])
|
||||||
|
transformers();
|
||||||
|
|
||||||
|
|
||||||
|
x4 = x3 + 220;
|
||||||
|
belts_y = 0;
|
||||||
|
rails_y = belts_y + 200;
|
||||||
|
cable_strips_y = rails_y + 300;
|
||||||
|
|
||||||
|
translate([x4 + 112, belts_y + 58]) {
|
||||||
|
belt_test();
|
||||||
|
|
||||||
|
translate([0, 60])
|
||||||
|
opengrab_test();
|
||||||
|
}
|
||||||
|
|
||||||
|
translate([x4, rails_y + 130])
|
||||||
|
rails();
|
||||||
|
|
||||||
|
translate([x4, cable_strips_y])
|
||||||
|
cable_strips();
|
||||||
|
|
||||||
|
x6 = x5 + 150;
|
||||||
|
translate([x6, 125])
|
||||||
|
light_strips();
|
|
@ -0,0 +1,119 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
//! Clamp for ribbon cable and polypropylene strip.
|
||||||
|
//
|
||||||
|
include <core.scad>
|
||||||
|
include <vitamins/screws.scad>
|
||||||
|
include <vitamins/inserts.scad>
|
||||||
|
use <vitamins/cable_strip.scad>
|
||||||
|
|
||||||
|
wall = 2;
|
||||||
|
min_wall = 2 * extrusion_width;
|
||||||
|
screw = M3_cap_screw;
|
||||||
|
insert = screw_insert(screw);
|
||||||
|
screw_depth = insert_length(insert) + 1;
|
||||||
|
|
||||||
|
function ribbon_clamp_hole_pitch(ways) = ribbon_clamp_slot(ways) + 2 * min_wall + 2 * corrected_radius(insert_hole_radius(insert)); //! Hole pitch
|
||||||
|
function ribbon_clamp_width() = 2 * (insert_hole_radius(insert) + 2); //! Width
|
||||||
|
function ribbon_clamp_length(ways) = ribbon_clamp_hole_pitch(ways) + ribbon_clamp_width(); //! Length given ways
|
||||||
|
function ribbon_clamp_height() = screw_depth + 1; //! Height
|
||||||
|
|
||||||
|
module ribbon_clamp_hole_positions(ways, side = undef) //! Place children at hole positions
|
||||||
|
for(x = is_undef(side) ? [-1, 1] : side)
|
||||||
|
translate([x * ribbon_clamp_hole_pitch(ways) / 2, 0])
|
||||||
|
children();
|
||||||
|
|
||||||
|
module ribbon_clamp_holes(ways, h = 20) //! Drill screw holes
|
||||||
|
ribbon_clamp_hole_positions(ways)
|
||||||
|
drill(screw_clearance_radius(screw), h);
|
||||||
|
|
||||||
|
module ribbon_clamp(ways) { //! Generate STL for given number of ways
|
||||||
|
stl(str("ribbon_clamp_", ways));
|
||||||
|
|
||||||
|
pitch = ribbon_clamp_hole_pitch(ways);
|
||||||
|
d = ribbon_clamp_width();
|
||||||
|
h = ribbon_clamp_height();
|
||||||
|
t = h - ribbon_clamp_slot_depth() - wall;
|
||||||
|
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
hull() {
|
||||||
|
translate_z(h - t / 2)
|
||||||
|
cube([ribbon_clamp_hole_pitch(ways), d, t], center = true);
|
||||||
|
|
||||||
|
translate_z(1)
|
||||||
|
cube([pitch, max(wall, d - 2 * (h - t)), 2], center = true);
|
||||||
|
}
|
||||||
|
ribbon_clamp_hole_positions(ways, -1)
|
||||||
|
cylinder(d = d, h = h);
|
||||||
|
|
||||||
|
ribbon_clamp_hole_positions(ways, 1)
|
||||||
|
cylinder(d = d, h = h);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
translate_z(h)
|
||||||
|
cube([ribbon_clamp_slot(ways), d + 1, ribbon_clamp_slot_depth() * 2], center = true);
|
||||||
|
|
||||||
|
ribbon_clamp_hole_positions(ways)
|
||||||
|
translate_z(h)
|
||||||
|
rotate(22.5)
|
||||||
|
insert_hole(insert, screw_depth - insert_length(insert));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module ribbon_clamp_assembly(ways) pose([55, 180, 25]) //! Printed part with inserts in place
|
||||||
|
assembly(str("ribbon_clamp_", ways)) {
|
||||||
|
h = ribbon_clamp_height();
|
||||||
|
|
||||||
|
color(pp1_colour) render()
|
||||||
|
translate_z(h) vflip() ribbon_clamp(ways);
|
||||||
|
|
||||||
|
ribbon_clamp_hole_positions(ways)
|
||||||
|
vflip()
|
||||||
|
insert(insert);
|
||||||
|
}
|
||||||
|
|
||||||
|
module ribbon_clamp_fastened_assembly(ways, thickness, screw = screw) { //! Clamp with fasteners in place
|
||||||
|
tape_l = floor(ribbon_clamp_slot(ways));
|
||||||
|
tape_width = 25;
|
||||||
|
tape_thickness = 0.5;
|
||||||
|
|
||||||
|
vitamin(str(": Tape self amalgamating silicone ",tape_l," x 25mm"));
|
||||||
|
|
||||||
|
washer = screw_washer(screw);
|
||||||
|
screw_length = screw_shorter_than(2 * washer_thickness(washer) + thickness + screw_depth);
|
||||||
|
|
||||||
|
ribbon_clamp_assembly(ways);
|
||||||
|
|
||||||
|
color("red") translate_z(tape_thickness / 2)
|
||||||
|
cube([tape_l, tape_width, tape_thickness], center = true);
|
||||||
|
|
||||||
|
ribbon_clamp_hole_positions(ways)
|
||||||
|
vflip()
|
||||||
|
translate_z(thickness)
|
||||||
|
screw_and_washer(screw, screw_length, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
module ribbon_clamp_20_stl() ribbon_clamp(20);
|
||||||
|
|
||||||
|
//! * Place inserts into the holes and press home with a soldering iron with a conical bit heated to 200°C.
|
||||||
|
module ribbon_clamp_20_assembly() ribbon_clamp_assembly(20);
|
|
@ -0,0 +1,77 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
//! Knob with embedded hex head screw.
|
||||||
|
//
|
||||||
|
include <core.scad>
|
||||||
|
include <vitamins/screws.scad>
|
||||||
|
use <utils/hanging_hole.scad>
|
||||||
|
|
||||||
|
knob_wall = 2;
|
||||||
|
function knob_nut_trap_depth(screw) = round_to_layer(screw_head_height(screw));
|
||||||
|
knob_stem_h = 6;
|
||||||
|
knob_thickness = 4;
|
||||||
|
knob_r = 8;
|
||||||
|
knob_wave = 1;
|
||||||
|
knob_waves = 9;
|
||||||
|
knob_height = knob_stem_h + knob_thickness;
|
||||||
|
function knob_height() = knob_height;
|
||||||
|
|
||||||
|
module screw_knob(screw) { //! Generate the STL foe a knob to fit the specified hex screw
|
||||||
|
stl(str("screw_knob_M", screw_radius(screw) * 20));
|
||||||
|
|
||||||
|
knob_stem_r = nut_trap_radius(screw_nut(screw)) + knob_wall;
|
||||||
|
|
||||||
|
function wave(a) = knob_r + sin(a * knob_waves) * knob_wave;
|
||||||
|
|
||||||
|
union() {
|
||||||
|
render() difference() {
|
||||||
|
cylinder(r = knob_stem_r, h = knob_thickness + knob_stem_h);
|
||||||
|
|
||||||
|
hanging_hole(knob_nut_trap_depth(screw), screw_clearance_radius(screw))
|
||||||
|
rotate(45)
|
||||||
|
circle(r = nut_trap_radius(screw_nut(screw)), $fn = 6);
|
||||||
|
}
|
||||||
|
linear_extrude(height = knob_thickness, convexity = 3)
|
||||||
|
difference() {
|
||||||
|
polygon(points = [for(a = [0 : 359]) [wave(a) * sin(a), wave(a) * cos(a)]]);
|
||||||
|
|
||||||
|
circle(knob_stem_r - eps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Place the screw through the printed part
|
||||||
|
module screw_knob_assembly(screw, length) //! Assembly with the screw in place
|
||||||
|
assembly(str("screw_knob_M", 20 * screw_radius(screw), "_", length)) {
|
||||||
|
translate_z(knob_height)
|
||||||
|
vflip()
|
||||||
|
color(pp1_colour) screw_knob(screw);
|
||||||
|
|
||||||
|
translate_z(knob_height - knob_nut_trap_depth(screw))
|
||||||
|
rotate(-45)
|
||||||
|
screw(screw, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
module screw_knob_M30_stl() screw_knob(M3_hex_screw);
|
||||||
|
module screw_knob_M40_stl() screw_knob(M4_hex_screw);
|
||||||
|
|
||||||
|
module screw_knob_M30_16_assembly() screw_knob_assembly(M3_hex_screw, 16);
|
||||||
|
module screw_knob_M40_16_assembly() screw_knob_assembly(M4_hex_screw, 16);
|
|
@ -0,0 +1,80 @@
|
||||||
|
#
|
||||||
|
# NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
# 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/>.
|
||||||
|
#
|
||||||
|
"""
|
||||||
|
Capture Markup lines in OpenSCAD source code denoted by '//!'.
|
||||||
|
"""
|
||||||
|
import re
|
||||||
|
|
||||||
|
def parse_line(line):
|
||||||
|
""" process a line, add blurb to text and return true if got to a module or function """
|
||||||
|
if line[:3] == '//!':
|
||||||
|
line = line.replace('~\n', ' \n')
|
||||||
|
start = 4 if line[3] == ' ' else 3
|
||||||
|
return False, line[start :]
|
||||||
|
else:
|
||||||
|
words = line.split()
|
||||||
|
return len(words) and (words[0] == "module" or words[0] == "function"), ""
|
||||||
|
|
||||||
|
def _scrape_blurb(lines):
|
||||||
|
""" Find Markup lines before the first function or module given a list of lines."""
|
||||||
|
text = ""
|
||||||
|
for line in lines:
|
||||||
|
b, t = parse_line(line)
|
||||||
|
if b:
|
||||||
|
break
|
||||||
|
text += t
|
||||||
|
if len(text):
|
||||||
|
text += '\n'
|
||||||
|
return text
|
||||||
|
|
||||||
|
def scrape_blurb(scad_file):
|
||||||
|
""" Find Markup lines before the first function or module."""
|
||||||
|
with open(scad_file, "rt") as file:
|
||||||
|
lines = file.readlines()
|
||||||
|
return _scrape_blurb(lines)
|
||||||
|
|
||||||
|
def scrape_module_blurb(lines):
|
||||||
|
""" Find the Markup lines before the last function or module. """
|
||||||
|
text = ""
|
||||||
|
for line in lines:
|
||||||
|
b, t = parse_line(line)
|
||||||
|
text = "" if b else text + t
|
||||||
|
return text
|
||||||
|
|
||||||
|
def scrape_code(scad_file):
|
||||||
|
""" Find the Markup lines on the first line of functions and modules. """
|
||||||
|
with open(scad_file, "rt") as file:
|
||||||
|
lines = file.readlines()
|
||||||
|
blurb = _scrape_blurb(lines)
|
||||||
|
properties = {}
|
||||||
|
functions = {}
|
||||||
|
modules = {}
|
||||||
|
for line in lines:
|
||||||
|
match = re.match(r'^function (.*\(type\)|.*\(type ?= ?.*?\)) *= *type\[.*\].*?(?://! ?(.*))?$', line)
|
||||||
|
if match:
|
||||||
|
properties[match.group(1)] = match.group(2)
|
||||||
|
else:
|
||||||
|
match = re.match(r'^function (.*?\(.*?\)).*?(?://! ?(.*))$', line)
|
||||||
|
if match:
|
||||||
|
functions[match.group(1)] = match.group(2)
|
||||||
|
match = re.match(r'^module (.*?\(.*?\)).*?(?://! ?(.*))$', line)
|
||||||
|
if match:
|
||||||
|
modules[match.group(1)] = match.group(2)
|
||||||
|
|
||||||
|
return { "blurb" : blurb, "properties" : properties, "functions" : functions, "modules": modules}
|
|
@ -0,0 +1,248 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
#
|
||||||
|
# NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
# 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/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import shutil
|
||||||
|
import openscad
|
||||||
|
from time import *
|
||||||
|
from set_config import *
|
||||||
|
import json
|
||||||
|
|
||||||
|
def find_scad_file(mname):
|
||||||
|
for filename in os.listdir(source_dir):
|
||||||
|
if filename[-5:] == ".scad":
|
||||||
|
#
|
||||||
|
# look for module which makes the assembly
|
||||||
|
#
|
||||||
|
with open(source_dir + "/" + filename, "r") as f:
|
||||||
|
for line in f.readlines():
|
||||||
|
words = line.split()
|
||||||
|
if len(words) and words[0] == "module":
|
||||||
|
module = words[1].split('(')[0]
|
||||||
|
if module == mname:
|
||||||
|
return filename
|
||||||
|
return None
|
||||||
|
|
||||||
|
class BOM:
|
||||||
|
def __init__(self, name):
|
||||||
|
self.name = name
|
||||||
|
self.count = 1
|
||||||
|
self.vitamins = {}
|
||||||
|
self.printed = {}
|
||||||
|
self.routed = {}
|
||||||
|
self.assemblies = {}
|
||||||
|
|
||||||
|
def data(self, main):
|
||||||
|
return {
|
||||||
|
"name" : self.name,
|
||||||
|
"count" : self.count,
|
||||||
|
"assemblies" : [main.assemblies[ass].data(main) for ass in self.assemblies],
|
||||||
|
"vitamins" : self.vitamins,
|
||||||
|
"printed" : self.printed,
|
||||||
|
"routed" : self.routed
|
||||||
|
}
|
||||||
|
|
||||||
|
def flat_data(self):
|
||||||
|
assemblies = {}
|
||||||
|
for ass in self.assemblies:
|
||||||
|
assemblies[ass] = self.assemblies[ass].count
|
||||||
|
return {
|
||||||
|
"assemblies" : assemblies,
|
||||||
|
"vitamins" : self.vitamins,
|
||||||
|
"printed" : self.printed,
|
||||||
|
"routed" : self.routed
|
||||||
|
}
|
||||||
|
|
||||||
|
def add_part(self, s):
|
||||||
|
if s[-4:] == ".stl":
|
||||||
|
parts = self.printed
|
||||||
|
else:
|
||||||
|
if s[-4:] == ".dxf":
|
||||||
|
parts = self.routed
|
||||||
|
else:
|
||||||
|
parts = self.vitamins
|
||||||
|
if s in parts:
|
||||||
|
parts[s] += 1
|
||||||
|
else:
|
||||||
|
parts[s] = 1
|
||||||
|
|
||||||
|
def add_assembly(self, ass):
|
||||||
|
if ass in self.assemblies:
|
||||||
|
self.assemblies[ass].count += 1
|
||||||
|
else:
|
||||||
|
self.assemblies[ass] = BOM(ass)
|
||||||
|
|
||||||
|
def make_name(self, ass):
|
||||||
|
if self.count == 1:
|
||||||
|
return ass
|
||||||
|
return ass.replace("assembly", "assemblies")
|
||||||
|
|
||||||
|
def print_bom(self, breakdown, file = None):
|
||||||
|
if self.vitamins:
|
||||||
|
print("Vitamins:", file=file)
|
||||||
|
if breakdown:
|
||||||
|
longest = 0
|
||||||
|
for ass in self.assemblies:
|
||||||
|
name = ass.replace("_assembly","")
|
||||||
|
longest = max(longest, len(name))
|
||||||
|
for i in range(longest):
|
||||||
|
line = ""
|
||||||
|
for ass in sorted(self.assemblies):
|
||||||
|
name = ass.replace("_assembly","").replace("_"," ").capitalize()
|
||||||
|
index = i - (longest - len(name))
|
||||||
|
if index < 0:
|
||||||
|
line += " "
|
||||||
|
else:
|
||||||
|
line += (" %s " % name[index])
|
||||||
|
print(line[:-1], file=file)
|
||||||
|
|
||||||
|
for part in sorted(self.vitamins):
|
||||||
|
if ': ' in part:
|
||||||
|
part_no, description = part.split(': ')
|
||||||
|
else:
|
||||||
|
part_no, description = "", part
|
||||||
|
if breakdown:
|
||||||
|
for ass in sorted(self.assemblies):
|
||||||
|
bom = self.assemblies[ass]
|
||||||
|
if part in bom.vitamins:
|
||||||
|
file.write("%2d|" % bom.vitamins[part])
|
||||||
|
else:
|
||||||
|
file.write(" |")
|
||||||
|
print("%3d" % self.vitamins[part], description, file=file)
|
||||||
|
|
||||||
|
if self.printed:
|
||||||
|
if self.vitamins:
|
||||||
|
print(file=file)
|
||||||
|
print("Printed:", file=file)
|
||||||
|
for part in sorted(self.printed):
|
||||||
|
if breakdown:
|
||||||
|
for ass in sorted(self.assemblies):
|
||||||
|
bom = self.assemblies[ass]
|
||||||
|
if part in bom.printed:
|
||||||
|
file.write("%2d|" % bom.printed[part])
|
||||||
|
else:
|
||||||
|
file.write(" |")
|
||||||
|
print("%3d" % self.printed[part], part, file=file)
|
||||||
|
|
||||||
|
if self.routed:
|
||||||
|
print(file=file)
|
||||||
|
print("CNC cut:", file=file)
|
||||||
|
for part in sorted(self.routed):
|
||||||
|
if breakdown:
|
||||||
|
for ass in sorted(self.assemblies):
|
||||||
|
bom = self.assemblies[ass]
|
||||||
|
if part in bom.routed:
|
||||||
|
file.write("%2d|" % bom.routed[part])
|
||||||
|
else:
|
||||||
|
file.write(" |")
|
||||||
|
print("%3d" % self.routed[part], part, file=file)
|
||||||
|
|
||||||
|
if self.assemblies:
|
||||||
|
print(file=file)
|
||||||
|
print("Assemblies:", file=file)
|
||||||
|
for ass in sorted(self.assemblies):
|
||||||
|
print("%3d %s" % (self.assemblies[ass].count, self.assemblies[ass].make_name(ass)), file=file)
|
||||||
|
|
||||||
|
def parse_bom(file = "openscad.log", name = None):
|
||||||
|
main = BOM(name)
|
||||||
|
stack = []
|
||||||
|
|
||||||
|
for line in open(file):
|
||||||
|
pos = line.find('ECHO: "~')
|
||||||
|
if pos > -1:
|
||||||
|
s = line[pos + 8 : line.rfind('"')]
|
||||||
|
if s[-1] == '{':
|
||||||
|
ass = s[:-1]
|
||||||
|
if stack:
|
||||||
|
main.assemblies[stack[-1]].add_assembly(ass) #add to nested BOM
|
||||||
|
stack.append(ass)
|
||||||
|
main.add_assembly(ass) #add to flat BOM
|
||||||
|
else:
|
||||||
|
if s[0] == '}':
|
||||||
|
if s[1:] != stack[-1]:
|
||||||
|
raise Exception("Mismatched assembly " + s[1:] + str(stack))
|
||||||
|
stack.pop()
|
||||||
|
else:
|
||||||
|
main.add_part(s)
|
||||||
|
if stack:
|
||||||
|
main.assemblies[stack[-1]].add_part(s)
|
||||||
|
return main
|
||||||
|
|
||||||
|
def boms(target = None, assembly = None):
|
||||||
|
bom_dir = set_config(target) + "bom"
|
||||||
|
if assembly:
|
||||||
|
bom_dir += "/accessories"
|
||||||
|
if not os.path.isdir(bom_dir):
|
||||||
|
os.makedirs(bom_dir)
|
||||||
|
else:
|
||||||
|
assembly = "main_assembly"
|
||||||
|
if os.path.isdir(bom_dir):
|
||||||
|
shutil.rmtree(bom_dir)
|
||||||
|
sleep(0.1)
|
||||||
|
os.makedirs(bom_dir)
|
||||||
|
#
|
||||||
|
# Find the scad file that makes the module
|
||||||
|
#
|
||||||
|
scad_file = find_scad_file(assembly)
|
||||||
|
if not scad_file:
|
||||||
|
raise Exception("can't find source for " + assembly)
|
||||||
|
#
|
||||||
|
# make a file to use the module
|
||||||
|
#
|
||||||
|
bom_maker_name = source_dir + "/bom.scad"
|
||||||
|
with open(bom_maker_name, "w") as f:
|
||||||
|
f.write("use <%s>\n" % scad_file)
|
||||||
|
f.write("%s();\n" % assembly);
|
||||||
|
#
|
||||||
|
# Run openscad
|
||||||
|
#
|
||||||
|
openscad.run("-D","$bom=2","-D","$preview=true","-o", "openscad.echo", bom_maker_name)
|
||||||
|
os.remove(bom_maker_name)
|
||||||
|
print("Generating bom ...", end=" ")
|
||||||
|
|
||||||
|
main = parse_bom("openscad.echo", assembly)
|
||||||
|
|
||||||
|
if assembly == "main_assembly":
|
||||||
|
main.print_bom(True, open(bom_dir + "/bom.txt","wt"))
|
||||||
|
|
||||||
|
for ass in sorted(main.assemblies):
|
||||||
|
with open(bom_dir + "/" + ass + ".txt", "wt") as f:
|
||||||
|
bom = main.assemblies[ass]
|
||||||
|
print(bom.make_name(ass) + ":", file=f)
|
||||||
|
bom.print_bom(False, f)
|
||||||
|
|
||||||
|
with open(bom_dir + "/bom.json", 'w') as outfile:
|
||||||
|
json.dump(main.assemblies[assembly].data(main), outfile, indent = 4)
|
||||||
|
|
||||||
|
print("done")
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
args = len(sys.argv)
|
||||||
|
if args > 1:
|
||||||
|
if args > 2:
|
||||||
|
boms(sys.argv[1], sys.argv[2])
|
||||||
|
else:
|
||||||
|
boms(sys.argv[1])
|
||||||
|
else:
|
||||||
|
boms();
|
|
@ -0,0 +1,108 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
#
|
||||||
|
# NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
# 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/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# OpenSCAD produces randomly ordered STL files so source control like GIT can't tell if they have changed or not.
|
||||||
|
# This scrip orders each triangle to start with the lowest vertex first (comparing x, then y, then z)
|
||||||
|
# It then sorts the triangles to start with the one with the lowest vertices first (comparing first vertex, second, then third)
|
||||||
|
# This has no effect on the model but makes the STL consistent. I.e. it makes a canonical form.
|
||||||
|
#
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
def cmz(x):
|
||||||
|
''' Convert "-0" to "0". '''
|
||||||
|
return '0' if x == '-0' else x
|
||||||
|
|
||||||
|
class Vertex:
|
||||||
|
def __init__(self, x, y, z):
|
||||||
|
self.x, self.y, self.z = x, y, z
|
||||||
|
self.key = (float(x), float(y), float(z))
|
||||||
|
|
||||||
|
class Normal:
|
||||||
|
def __init__(self, dx, dy, dz):
|
||||||
|
self.dx, self.dy, self.dz = dx, dy, dz
|
||||||
|
|
||||||
|
class Facet:
|
||||||
|
def __init__(self, normal, v1, v2, v3):
|
||||||
|
self.normal = normal
|
||||||
|
if v1.key < v2.key:
|
||||||
|
if v1.key < v3.key:
|
||||||
|
self.vertices = (v1, v2, v3) #v1 is the smallest
|
||||||
|
else:
|
||||||
|
self.vertices = (v3, v1, v2) #v3 is the smallest
|
||||||
|
else:
|
||||||
|
if v2.key < v3.key:
|
||||||
|
self.vertices = (v2, v3, v1) #v2 is the smallest
|
||||||
|
else:
|
||||||
|
self.vertices = (v3, v1, v2) #v3 is the smallest
|
||||||
|
|
||||||
|
def key(self):
|
||||||
|
return (self.vertices[0].x, self.vertices[0].y, self.vertices[0].z,
|
||||||
|
self.vertices[1].x, self.vertices[1].y, self.vertices[1].z,
|
||||||
|
self.vertices[2].x, self.vertices[2].y, self.vertices[2].z)
|
||||||
|
|
||||||
|
class STL:
|
||||||
|
def __init__(self, fname):
|
||||||
|
self.facets = []
|
||||||
|
|
||||||
|
with open(fname) as f:
|
||||||
|
words = [cmz(s.strip()) for s in f.read().split()]
|
||||||
|
|
||||||
|
if words[0] == 'solid' and words[1] == 'OpenSCAD_Model':
|
||||||
|
i = 2
|
||||||
|
while words[i] == 'facet':
|
||||||
|
norm = Normal(words[i + 2], words[i + 3], words[i + 4])
|
||||||
|
v1 = Vertex(words[i + 8], words[i + 9], words[i + 10])
|
||||||
|
v2 = Vertex(words[i + 12], words[i + 13], words[i + 14])
|
||||||
|
v3 = Vertex(words[i + 16], words[i + 17], words[i + 18])
|
||||||
|
i += 21
|
||||||
|
self.facets.append(Facet(norm, v1, v2, v3))
|
||||||
|
|
||||||
|
self.facets.sort(key = Facet.key)
|
||||||
|
else:
|
||||||
|
print("Not an OpenSCAD ascii STL file")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
def write(self, fname):
|
||||||
|
with open(fname,"wt") as f:
|
||||||
|
print('solid OpenSCAD_Model', file=f)
|
||||||
|
for facet in self.facets:
|
||||||
|
print(' facet normal %s %s %s' % (facet.normal.dx, facet.normal.dy, facet.normal.dz), file=f)
|
||||||
|
print(' outer loop', file=f)
|
||||||
|
for vertex in facet.vertices:
|
||||||
|
print(' vertex %s %s %s' % (vertex.x, vertex.y, vertex.z), file=f)
|
||||||
|
print(' endloop', file=f)
|
||||||
|
print(' endfacet', file=f)
|
||||||
|
print('endsolid OpenSCAD_Model', file=f)
|
||||||
|
|
||||||
|
def canonicalise(fname):
|
||||||
|
stl = STL(fname)
|
||||||
|
stl.write(fname)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
if len(sys.argv) == 2:
|
||||||
|
canonicalise(sys.argv[1])
|
||||||
|
else:
|
||||||
|
print("usage: c14n_stl file")
|
||||||
|
sys.exit(1)
|
|
@ -0,0 +1,49 @@
|
||||||
|
#
|
||||||
|
# NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
# 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/>.
|
||||||
|
#
|
||||||
|
import os
|
||||||
|
|
||||||
|
def mtime(file):
|
||||||
|
if os.path.isfile(file):
|
||||||
|
return os.path.getmtime(file)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def deps_name(dir, scad_name):
|
||||||
|
return dir + '/' + scad_name[:-5] + '.deps'
|
||||||
|
|
||||||
|
def read_deps(dname):
|
||||||
|
with open(dname, "rt") as file:
|
||||||
|
lines = file.readlines()
|
||||||
|
deps = []
|
||||||
|
for line in lines:
|
||||||
|
if line.startswith('\t'):
|
||||||
|
dep = line[1 : -1].rstrip(' \\')
|
||||||
|
if not dep in ['stl.scad', 'dxf.scad', 'svf.scad', 'png.scad']:
|
||||||
|
deps.append(dep)
|
||||||
|
return deps
|
||||||
|
|
||||||
|
def check_deps(target_mtime, dname):
|
||||||
|
if not target_mtime:
|
||||||
|
return "target missing"
|
||||||
|
if not os.path.isfile(dname):
|
||||||
|
return "no deps"
|
||||||
|
deps = read_deps(dname)
|
||||||
|
for dep in deps:
|
||||||
|
if mtime(dep) > target_mtime:
|
||||||
|
return dep + ' changed'
|
||||||
|
return None
|
|
@ -0,0 +1,32 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
#
|
||||||
|
# NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
# 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/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from exports import make_parts
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
if len(sys.argv) > 1 and not '.' in sys.argv[1]:
|
||||||
|
target, parts = sys.argv[1], sys.argv[2:]
|
||||||
|
else:
|
||||||
|
target, parts = None, sys.argv[1:]
|
||||||
|
make_parts(target, 'dxf', parts)
|
|
@ -0,0 +1,133 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
#
|
||||||
|
# NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
# 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/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
import os
|
||||||
|
import openscad
|
||||||
|
import sys
|
||||||
|
import c14n_stl
|
||||||
|
from set_config import *
|
||||||
|
import time
|
||||||
|
import times
|
||||||
|
from deps import *
|
||||||
|
|
||||||
|
def bom_to_parts(target_dir, part_type, assembly = None):
|
||||||
|
#
|
||||||
|
# Make a list of all the parts in the BOM
|
||||||
|
#
|
||||||
|
part_files = []
|
||||||
|
bom = assembly + '.txt' if assembly else "bom.txt"
|
||||||
|
suffix = ".dxf" if part_type == 'svg' else '.' + part_type
|
||||||
|
with open(target_dir + "/../bom/" + bom, "rt") as f:
|
||||||
|
for line in f.readlines():
|
||||||
|
words = line.split()
|
||||||
|
if words:
|
||||||
|
last_word = words[-1]
|
||||||
|
if last_word.endswith(suffix):
|
||||||
|
part_files.append(last_word[:-4] + '.' + part_type)
|
||||||
|
return part_files
|
||||||
|
|
||||||
|
def make_parts(target, part_type, parts = None):
|
||||||
|
#
|
||||||
|
# Make the target directory
|
||||||
|
#
|
||||||
|
top_dir = set_config(target)
|
||||||
|
target_dir = top_dir + part_type + 's'
|
||||||
|
deps_dir = top_dir + "deps"
|
||||||
|
if not os.path.isdir(target_dir):
|
||||||
|
os.makedirs(target_dir)
|
||||||
|
if not os.path.isdir(deps_dir):
|
||||||
|
os.makedirs(deps_dir)
|
||||||
|
times.read_times(target_dir)
|
||||||
|
#
|
||||||
|
# Decide which files to make
|
||||||
|
#
|
||||||
|
if parts:
|
||||||
|
targets = list(parts) #copy the list so we dont modify the list passed in
|
||||||
|
else:
|
||||||
|
targets = bom_to_parts(target_dir, part_type)
|
||||||
|
for file in os.listdir(target_dir):
|
||||||
|
if file.endswith('.' + part_type):
|
||||||
|
if not file in targets:
|
||||||
|
print("Removing %s" % file)
|
||||||
|
os.remove(target_dir + '/' + file)
|
||||||
|
#
|
||||||
|
# Find all the scad files
|
||||||
|
#
|
||||||
|
lib_dir = os.environ['OPENSCADPATH'] + '/NopSCADlib'
|
||||||
|
used = []
|
||||||
|
module_suffix = '_dxf' if part_type == 'svg' else '_' + part_type
|
||||||
|
for dir in [source_dir, lib_dir]:
|
||||||
|
for filename in os.listdir(dir):
|
||||||
|
if filename[-5:] == ".scad":
|
||||||
|
#
|
||||||
|
# find any modules ending in _<part_type>
|
||||||
|
#
|
||||||
|
with open(dir + "/" + filename, "r") as f:
|
||||||
|
for line in f.readlines():
|
||||||
|
words = line.split()
|
||||||
|
if(len(words) and words[0] == "module"):
|
||||||
|
module = words[1].split('(')[0]
|
||||||
|
if module.endswith(module_suffix):
|
||||||
|
base_name = module[:-4]
|
||||||
|
part = base_name + '.' + part_type
|
||||||
|
if part in targets:
|
||||||
|
#
|
||||||
|
# make a file to use the module
|
||||||
|
#
|
||||||
|
part_maker_name = part_type + ".scad"
|
||||||
|
with open(part_maker_name, "w") as f:
|
||||||
|
f.write("use <%s/%s>\n" % (dir, filename))
|
||||||
|
f.write("%s();\n" % module);
|
||||||
|
#
|
||||||
|
# Run openscad on the created file
|
||||||
|
#
|
||||||
|
part_file = target_dir + "/" + part
|
||||||
|
dname = deps_name(deps_dir, filename)
|
||||||
|
changed = check_deps(mtime(part_file), dname)
|
||||||
|
changed = times.check_have_time(changed, part)
|
||||||
|
if changed:
|
||||||
|
print(changed)
|
||||||
|
t = time.time()
|
||||||
|
openscad.run("-D$bom=1", "-d", dname, "-o", part_file, part_maker_name)
|
||||||
|
times.add_time(part, t)
|
||||||
|
if part_type == 'stl':
|
||||||
|
c14n_stl.canonicalise(part_file)
|
||||||
|
targets.remove(part)
|
||||||
|
os.remove(part_maker_name)
|
||||||
|
#
|
||||||
|
# Add the files on the BOM to the used list for plates.py
|
||||||
|
#
|
||||||
|
for line in open("openscad.log"):
|
||||||
|
if line[:7] == 'ECHO: "' and line[-6:] == '.' + part_type + '"\n':
|
||||||
|
used.append(line[7:-2])
|
||||||
|
#
|
||||||
|
# List the ones we didn't find
|
||||||
|
#
|
||||||
|
if targets:
|
||||||
|
for part in targets:
|
||||||
|
if part[-4:] != '.' + part_type:
|
||||||
|
print(part, "is not a", part_type, "file")
|
||||||
|
else:
|
||||||
|
print("Could not find a module called", part[:-4] + module_suffix, "to make", part)
|
||||||
|
sys.exit(1)
|
||||||
|
times.print_times()
|
||||||
|
return used
|
|
@ -0,0 +1,68 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
#
|
||||||
|
# NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
# 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/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# Find projects and add them to the gallery
|
||||||
|
#
|
||||||
|
from __future__ import print_function
|
||||||
|
import os
|
||||||
|
from colorama import Fore, init
|
||||||
|
from tests import do_cmd
|
||||||
|
import re
|
||||||
|
from shutil import copyfile
|
||||||
|
|
||||||
|
project_dir = '../..'
|
||||||
|
target_dir = 'gallery'
|
||||||
|
output_name = target_dir + '/readme.md'
|
||||||
|
|
||||||
|
def gallery():
|
||||||
|
if not os.path.isdir(target_dir):
|
||||||
|
os.makedirs(target_dir)
|
||||||
|
|
||||||
|
projects = [i for i in os.listdir(project_dir) if os.path.isdir(project_dir + '/' + i + '/assemblies')]
|
||||||
|
with open(output_name, 'wt') as output_file:
|
||||||
|
for project in projects:
|
||||||
|
path = project_dir + '/' + project
|
||||||
|
print(project)
|
||||||
|
document = path + '/readme.md'
|
||||||
|
if os.path.isfile(document):
|
||||||
|
with open(document, 'rt') as readme:
|
||||||
|
for line in readme.readlines():
|
||||||
|
match = re.match(r"^.*!(\[.*\]\(.*\)).*$", line)
|
||||||
|
if match:
|
||||||
|
image = match.group(0)
|
||||||
|
if image.startswith('![Main Assembly](assemblies/'):
|
||||||
|
file = image[17 : -1]
|
||||||
|
line = line.replace(image, '![](%s.png)' % project)
|
||||||
|
copyfile(path + '/' + file, '%s/%s.png' %(target_dir, project))
|
||||||
|
else:
|
||||||
|
line = line.replace(image, '')
|
||||||
|
print(line[:-1], file = output_file)
|
||||||
|
if line == '---\n':
|
||||||
|
break;
|
||||||
|
else:
|
||||||
|
print(Fore.MAGENTA + "Can't find", document, Fore.WHITE);
|
||||||
|
with open(target_dir + "/readme.html", "wt") as html_file:
|
||||||
|
do_cmd(("python -m markdown -x tables " + output_name).split(), html_file)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
init()
|
||||||
|
gallery()
|
|
@ -0,0 +1,35 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
#
|
||||||
|
# NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
# 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/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from exports import make_parts
|
||||||
|
from bom import boms
|
||||||
|
from render import render
|
||||||
|
from views import views
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
target = None if len(sys.argv) == 1 else sys.argv[1]
|
||||||
|
boms(target)
|
||||||
|
for part in ['stl', 'dxf']:
|
||||||
|
make_parts(target, part)
|
||||||
|
render(target, part)
|
||||||
|
views(target)
|
|
@ -0,0 +1,38 @@
|
||||||
|
#
|
||||||
|
# NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
# 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/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# Run openscad
|
||||||
|
#
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import subprocess, sys
|
||||||
|
|
||||||
|
def run(*args):
|
||||||
|
cmd = ["openscad"] + list(args)
|
||||||
|
for arg in cmd:
|
||||||
|
print(arg, end=" ")
|
||||||
|
print()
|
||||||
|
with open("openscad.log", "w") as log:
|
||||||
|
rc = subprocess.call(cmd, stdout = log, stderr = log)
|
||||||
|
for line in open("openscad.log", "rt"):
|
||||||
|
if 'ERROR:' in line or 'WARNING:' in line:
|
||||||
|
print(line[:-1])
|
||||||
|
if rc:
|
||||||
|
sys.exit(rc)
|
|
@ -0,0 +1,69 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
#
|
||||||
|
# NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
# 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/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
from set_config import *
|
||||||
|
from exports import bom_to_parts
|
||||||
|
import os
|
||||||
|
import openscad
|
||||||
|
from tests import do_cmd
|
||||||
|
from deps import mtime
|
||||||
|
|
||||||
|
def render(target, type):
|
||||||
|
#
|
||||||
|
# Make the target directory
|
||||||
|
#
|
||||||
|
target_dir = set_config(target) + type + 's'
|
||||||
|
if not os.path.isdir(target_dir):
|
||||||
|
os.makedirs(target_dir)
|
||||||
|
#
|
||||||
|
# Find all the parts
|
||||||
|
#
|
||||||
|
parts = bom_to_parts(target_dir, type)
|
||||||
|
#
|
||||||
|
# Remove unused png files
|
||||||
|
#
|
||||||
|
for file in os.listdir(target_dir):
|
||||||
|
if file.endswith('.png'):
|
||||||
|
if not file[:-4] + '.' + type in parts:
|
||||||
|
print("Removing %s" % file)
|
||||||
|
os.remove(target_dir + '/' + file)
|
||||||
|
|
||||||
|
for part in parts:
|
||||||
|
part_file = target_dir + '/' + part
|
||||||
|
png_name = target_dir + '/' + part[:-4] + '.png'
|
||||||
|
#
|
||||||
|
# make a file to import the stl
|
||||||
|
#
|
||||||
|
if mtime(part_file) > mtime(png_name):
|
||||||
|
png_maker_name = "png.scad"
|
||||||
|
with open(png_maker_name, "w") as f:
|
||||||
|
f.write('color("lime") import("%s");\n' % part_file)
|
||||||
|
cam = "--camera=0,0,0,70,0,315,500" if type == 'stl' else "--camera=0,0,0,0,0,0,500"
|
||||||
|
render = "--preview" if type == 'stl' else "--render"
|
||||||
|
openscad.run("--projection=p", "--imgsize=4096,4096", cam, render, "--autocenter", "--viewall", "-o", png_name, png_maker_name);
|
||||||
|
do_cmd(("magick "+ png_name + " -trim -resize 280x280 -background #ffffe5 -gravity Center -extent 280x280 -bordercolor #ffffe5 -border 10 " + png_name).split())
|
||||||
|
os.remove(png_maker_name)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
target = sys.argv[1] if len(sys.argv) > 1 else None
|
||||||
|
render(target, 'stl')
|
||||||
|
render(target, 'dxf')
|
|
@ -0,0 +1,84 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
#
|
||||||
|
# NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
# 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/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# Set target configuration for multi-target projects that have variable configurations.
|
||||||
|
#
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
source_dir = 'scad'
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
def valid_targets():
|
||||||
|
return [i[7:-5] for i in os.listdir(source_dir) if i[0:7] == "config_" and i[-5:] == ".scad"]
|
||||||
|
|
||||||
|
def valid_targets_string():
|
||||||
|
result = ''
|
||||||
|
targets = valid_targets()
|
||||||
|
for t in targets:
|
||||||
|
if result:
|
||||||
|
if t == targets[-1]:
|
||||||
|
result += ' and '
|
||||||
|
else:
|
||||||
|
result += ', '
|
||||||
|
result += t
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def set_config(target):
|
||||||
|
targets = valid_targets()
|
||||||
|
if not target:
|
||||||
|
if not targets:
|
||||||
|
return ""
|
||||||
|
print("Must specify a configuration: " + valid_targets_string())
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if not targets:
|
||||||
|
print("Not a muli-configuration project (no config_<target>.scad files found)")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if not target in targets:
|
||||||
|
print(target + " is not a configuration, avaliable configurations are: " + valid_targets_string())
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
fname = source_dir + "/target.scad"
|
||||||
|
text = "include <config_%s.scad>\n" % target;
|
||||||
|
line = ""
|
||||||
|
try:
|
||||||
|
with open(fname,"rt") as f:
|
||||||
|
line = f.read()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if line != text:
|
||||||
|
with open(fname,"wt") as f:
|
||||||
|
f. write(text);
|
||||||
|
return target + "/"
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
args = len(sys.argv)
|
||||||
|
if args == 2:
|
||||||
|
set_config(sys.argv[1])
|
||||||
|
else:
|
||||||
|
print("usage: set_config config_name")
|
||||||
|
sys.exit(1)
|
|
@ -0,0 +1,32 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
#
|
||||||
|
# NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
# 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/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from exports import make_parts
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
if len(sys.argv) > 1 and not '.' in sys.argv[1]:
|
||||||
|
target, parts = sys.argv[1], sys.argv[2:]
|
||||||
|
else:
|
||||||
|
target, parts = None, sys.argv[1:]
|
||||||
|
make_parts(target, 'stl', parts)
|
|
@ -0,0 +1,32 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
#
|
||||||
|
# NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
# 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/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from exports import make_parts
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
if len(sys.argv) > 1 and not '.' in sys.argv[1]:
|
||||||
|
target, parts = sys.argv[1], sys.argv[2:]
|
||||||
|
else:
|
||||||
|
target, parts = None, sys.argv[1:]
|
||||||
|
make_parts(target, 'svg', parts)
|
|
@ -0,0 +1,230 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
#
|
||||||
|
# NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
# 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/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import openscad
|
||||||
|
import subprocess
|
||||||
|
import bom
|
||||||
|
import times
|
||||||
|
import time
|
||||||
|
import json
|
||||||
|
from deps import *
|
||||||
|
from blurb import *
|
||||||
|
|
||||||
|
w = 4096
|
||||||
|
h = w
|
||||||
|
|
||||||
|
def do_cmd(cmd, output = sys.stdout):
|
||||||
|
for arg in cmd:
|
||||||
|
print(arg, end = " ")
|
||||||
|
print()
|
||||||
|
subprocess.call(cmd, stdout = output)
|
||||||
|
|
||||||
|
def depluralise(name):
|
||||||
|
if name[-3:] == "ies" and name != "zipties":
|
||||||
|
return name[:-3] + 'y'
|
||||||
|
if name[-3:] == "hes":
|
||||||
|
return name[:-2]
|
||||||
|
if name[-1:] == 's':
|
||||||
|
return name[:-1]
|
||||||
|
return name
|
||||||
|
|
||||||
|
def is_plural(name):
|
||||||
|
return name != depluralise(name)
|
||||||
|
|
||||||
|
def tests(tests):
|
||||||
|
scad_dir = "tests"
|
||||||
|
deps_dir = scad_dir + "/deps"
|
||||||
|
png_dir = scad_dir + "/png"
|
||||||
|
bom_dir = scad_dir + "/bom"
|
||||||
|
for dir in [deps_dir, png_dir, bom_dir]:
|
||||||
|
if not os.path.isdir(dir):
|
||||||
|
os.makedirs(dir)
|
||||||
|
doc_name = "readme.md"
|
||||||
|
index = {}
|
||||||
|
bodies = {}
|
||||||
|
times.read_times()
|
||||||
|
#
|
||||||
|
# Make cover pic if does not exist as very slow. Delete it to force an update.
|
||||||
|
#
|
||||||
|
png_name = "libtest.png"
|
||||||
|
scad_name = "libtest.scad"
|
||||||
|
if not os.path.isfile(png_name):
|
||||||
|
openscad.run("--projection=p", "--imgsize=%d,%d" % (w, h), "--camera=0,0,0,50,0,340,500", "--autocenter", "--viewall", "-o", png_name, scad_name);
|
||||||
|
do_cmd(["magick", png_name, "-trim", "-resize", "1280", "-bordercolor", "#ffffe5", "-border", "10", png_name])
|
||||||
|
#
|
||||||
|
# List of individual part files
|
||||||
|
#
|
||||||
|
scads = [i for i in os.listdir(scad_dir) if i[-5:] == ".scad"]
|
||||||
|
|
||||||
|
for scad in scads:
|
||||||
|
base_name = scad[:-5]
|
||||||
|
if not tests or base_name in tests:
|
||||||
|
print(base_name)
|
||||||
|
cap_name = base_name[0].capitalize() + base_name[1:]
|
||||||
|
scad_name = scad_dir + '/' + scad
|
||||||
|
png_name = png_dir + '/' + base_name + '.png'
|
||||||
|
bom_name = bom_dir + '/' + base_name + '.json'
|
||||||
|
|
||||||
|
objects_name = None
|
||||||
|
vits_name = 'vitamins/' + base_name + '.scad'
|
||||||
|
if is_plural(base_name) and os.path.isfile(vits_name):
|
||||||
|
objects_name = vits_name
|
||||||
|
|
||||||
|
locations = [
|
||||||
|
('vitamins/' + depluralise(base_name) + '.scad', 'Vitamins'),
|
||||||
|
(base_name + '.scad', 'Printed'),
|
||||||
|
('utils/' + base_name + '.scad', 'Utilities'),
|
||||||
|
('utils/core/' + base_name + '.scad', 'Core Utilities'),
|
||||||
|
]
|
||||||
|
|
||||||
|
for name, type in locations:
|
||||||
|
if os.path.isfile(name):
|
||||||
|
impl_name = name
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
print("Can't find implementation!")
|
||||||
|
continue
|
||||||
|
|
||||||
|
vsplit = "N"
|
||||||
|
vtype = locations[0][1]
|
||||||
|
types = [vtype + ' A-' + vsplit[0], vtype + ' ' + chr(ord(vsplit) + 1) + '-Z'] + [loc[1] for loc in locations[1 :]]
|
||||||
|
if type == vtype:
|
||||||
|
type = types[0] if cap_name[0] <= vsplit else types[1]
|
||||||
|
|
||||||
|
if not type in bodies:
|
||||||
|
bodies[type] = []
|
||||||
|
index[type] = []
|
||||||
|
body = bodies[type]
|
||||||
|
|
||||||
|
index[type] += [cap_name]
|
||||||
|
body += ['<a name="%s"></a>' % cap_name]
|
||||||
|
body += ["## " + cap_name]
|
||||||
|
|
||||||
|
doc = None
|
||||||
|
if impl_name:
|
||||||
|
doc = scrape_code(impl_name)
|
||||||
|
blurb = doc["blurb"]
|
||||||
|
else:
|
||||||
|
blurb = scrape_blurb(scad_name)
|
||||||
|
|
||||||
|
if not len(blurb):
|
||||||
|
print("Blurb not found!")
|
||||||
|
else:
|
||||||
|
body += [ blurb ]
|
||||||
|
|
||||||
|
if objects_name:
|
||||||
|
body += ["[%s](%s) Object definitions.\n" % (objects_name, objects_name)]
|
||||||
|
|
||||||
|
if impl_name:
|
||||||
|
body += ["[%s](%s) Implementation.\n" % (impl_name, impl_name)]
|
||||||
|
|
||||||
|
body += ["[%s](%s) Code for this example.\n" % (scad_name.replace('\\','/'), scad_name)]
|
||||||
|
|
||||||
|
if doc:
|
||||||
|
for thing in ["properties", "functions", "modules"]:
|
||||||
|
things = doc[thing]
|
||||||
|
if things:
|
||||||
|
body += ['### %s\n| | |\n|:--- |:--- |' % thing.title()]
|
||||||
|
for item in sorted(things):
|
||||||
|
body += ['| ```%s``` | %s |' % (item, things[item])]
|
||||||
|
body += ['']
|
||||||
|
|
||||||
|
body += ["![%s](%s)\n" %(base_name, png_name)]
|
||||||
|
|
||||||
|
dname = deps_name(deps_dir, scad)
|
||||||
|
oldest = min(mtime(png_name), mtime(bom_name))
|
||||||
|
changed = check_deps(oldest, dname)
|
||||||
|
changed = times.check_have_time(changed, scad_name)
|
||||||
|
if changed:
|
||||||
|
print(changed)
|
||||||
|
t = time.time()
|
||||||
|
openscad.run("-D", "$bom=2", "--projection=p", "--imgsize=%d,%d" % (w, h), "--camera=0,0,0,70,0,315,500", "--autocenter", "--viewall", "-d", dname, "-o", png_name, scad_name);
|
||||||
|
times.add_time(scad_name, t)
|
||||||
|
do_cmd(["magick", png_name, "-trim", "-resize", "1000x600", "-bordercolor", "#ffffe5", "-border", "10", png_name])
|
||||||
|
BOM = bom.parse_bom()
|
||||||
|
with open(bom_name, 'wt') as outfile:
|
||||||
|
json.dump(BOM.flat_data(), outfile, indent = 4)
|
||||||
|
|
||||||
|
with open(bom_name, "rt") as bom_file:
|
||||||
|
BOM = json.load(bom_file)
|
||||||
|
for thing in ["vitamins", "printed", "routed", "assemblies"]:
|
||||||
|
things = BOM[thing]
|
||||||
|
if things:
|
||||||
|
body += ['### %s\n| | | |\n| ---:|:--- |:---|' % thing.title()]
|
||||||
|
for item in sorted(things, key = lambda s: s.split(":")[-1]):
|
||||||
|
name = item
|
||||||
|
desc = ''
|
||||||
|
if thing == "vitamins":
|
||||||
|
vit = item.split(':')
|
||||||
|
name = '```' + vit[0] + '```' if vit[0] else ''
|
||||||
|
while '[[' in name and ']]' in name:
|
||||||
|
i = name.find('[[')
|
||||||
|
j = name.find(']]') + 2
|
||||||
|
name = name.replace(name[i : j], '[ ... ]')
|
||||||
|
desc = vit[1]
|
||||||
|
body += ['| %3d | %s | %s |' % (things[item], name, desc)]
|
||||||
|
body += ['']
|
||||||
|
|
||||||
|
body += ['\n<a href="#top">Top</a>']
|
||||||
|
body += ["\n---"]
|
||||||
|
|
||||||
|
with open(doc_name, "wt") as doc_file:
|
||||||
|
print('# NopSCADlib', file = doc_file)
|
||||||
|
print('''\
|
||||||
|
An ever expanding library of parts modelled in OpenSCAD useful for 3D printers and enclosures for electronics, etc.
|
||||||
|
|
||||||
|
It contains lots of vitamins (the RepRap term for non-printed parts), some general purpose printed parts and
|
||||||
|
some utilities. There are also Python scripts to generate Bills of Materials (BOMs),
|
||||||
|
STL files for all the printed parts and DXF files for CNC routed parts in a project.
|
||||||
|
|
||||||
|
<img src="libtest.png" width="100%"/>\n
|
||||||
|
''', file = doc_file)
|
||||||
|
|
||||||
|
print('## Table of Contents<a name="top"/>', file = doc_file)
|
||||||
|
print('<table><tr>', file = doc_file)
|
||||||
|
n = 0
|
||||||
|
for type in types:
|
||||||
|
print('<th align="left"> %s </th>' % type, end = '', file = doc_file)
|
||||||
|
n = max(n, len(index[type]))
|
||||||
|
print('</tr>', file = doc_file)
|
||||||
|
for i in range(n):
|
||||||
|
print('<tr>', file = doc_file, end = '')
|
||||||
|
for type in types:
|
||||||
|
if i < len(index[type]):
|
||||||
|
name = index[type][i]
|
||||||
|
print('<td> <a href = "#' + name + '">' + name + '</a> </td>', file = doc_file, end = '')
|
||||||
|
else:
|
||||||
|
print('<td></td>', file = doc_file, end = '')
|
||||||
|
print('</tr>', file = doc_file)
|
||||||
|
print('</table>\n\n---', file = doc_file)
|
||||||
|
for type in types:
|
||||||
|
for line in bodies[type]:
|
||||||
|
print(line, file = doc_file)
|
||||||
|
with open("readme.html", "wt") as html_file:
|
||||||
|
do_cmd("python -m markdown -x tables readme.md".split(), html_file)
|
||||||
|
times.print_times()
|
||||||
|
do_cmd('codespell -L od readme.md'.split())
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
tests(sys.argv[1:])
|
|
@ -0,0 +1,71 @@
|
||||||
|
#
|
||||||
|
# NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
# 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/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
# show execution times and how they have changed.
|
||||||
|
|
||||||
|
import json
|
||||||
|
import time
|
||||||
|
from colorama import Fore, init
|
||||||
|
|
||||||
|
def read_times(dir = '.'):
|
||||||
|
global times, last_times, times_fname
|
||||||
|
times_fname = dir + '/times.txt'
|
||||||
|
init()
|
||||||
|
try:
|
||||||
|
with open(times_fname) as json_file:
|
||||||
|
times = json.load(json_file)
|
||||||
|
last_times = dict(times)
|
||||||
|
except:
|
||||||
|
times = {}
|
||||||
|
last_times = {}
|
||||||
|
|
||||||
|
def write_times():
|
||||||
|
with open(times_fname, 'w') as outfile:
|
||||||
|
json.dump(times, outfile, indent = 4)
|
||||||
|
|
||||||
|
def got_time(name):
|
||||||
|
return name in last_times
|
||||||
|
|
||||||
|
def check_have_time(changed, name):
|
||||||
|
if not changed and not got_time(name):
|
||||||
|
changed = "no previous time"
|
||||||
|
return changed
|
||||||
|
|
||||||
|
def add_time(name, start):
|
||||||
|
times[name] = round(time.time() - start, 3)
|
||||||
|
|
||||||
|
def print_times():
|
||||||
|
write_times()
|
||||||
|
sorted_times = sorted(times.items(), key=lambda kv: kv[1])
|
||||||
|
total = 0
|
||||||
|
for entry in sorted_times:
|
||||||
|
colour = Fore.WHITE
|
||||||
|
key = entry[0]
|
||||||
|
new = entry[1]
|
||||||
|
delta = 0
|
||||||
|
if key in last_times:
|
||||||
|
old = last_times[key]
|
||||||
|
delta = new - old
|
||||||
|
if delta > 0.3:
|
||||||
|
colour = Fore.RED
|
||||||
|
if delta < -0.3:
|
||||||
|
colour = Fore.GREEN
|
||||||
|
print(colour + "%5.1f %5.1f %s" % (new, delta, key))
|
||||||
|
total += new
|
||||||
|
print(Fore.WHITE + "%5.1f" % total)
|
|
@ -0,0 +1,345 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
#
|
||||||
|
# NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
# 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/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
#: Generate assembly views and intructions
|
||||||
|
#
|
||||||
|
from __future__ import print_function
|
||||||
|
from set_config import *
|
||||||
|
import openscad
|
||||||
|
from tests import do_cmd
|
||||||
|
import time
|
||||||
|
import times
|
||||||
|
from deps import *
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
import blurb
|
||||||
|
import bom
|
||||||
|
from colorama import Fore
|
||||||
|
|
||||||
|
def is_assembly(s):
|
||||||
|
return s[-9:] == '_assembly' or s[-11:] == '_assemblies'
|
||||||
|
|
||||||
|
def add_assembly(flat_bom, bom):
|
||||||
|
if not bom in flat_bom:
|
||||||
|
big = False
|
||||||
|
for ass in bom["assemblies"]:
|
||||||
|
add_assembly(flat_bom, ass)
|
||||||
|
if ass["routed"]:
|
||||||
|
big = True
|
||||||
|
bom["big"] = big or bom["routed"]
|
||||||
|
flat_bom.append(bom)
|
||||||
|
|
||||||
|
def bom_to_assemblies(bom_dir):
|
||||||
|
global flat_bom
|
||||||
|
#
|
||||||
|
# Make a list of all the parts in the BOM
|
||||||
|
#
|
||||||
|
bom = {}
|
||||||
|
bom_file = bom_dir + "/bom.json"
|
||||||
|
with open(bom_file) as json_file:
|
||||||
|
bom = json.load(json_file)
|
||||||
|
flat_bom = []
|
||||||
|
add_assembly(flat_bom, bom)
|
||||||
|
ass = flat_bom[-1]
|
||||||
|
if len(ass["assemblies"]) < 2 and not ass["vitamins"] and not ass["printed"] and not ass["routed"]:
|
||||||
|
flat_bom = flat_bom[:-1]
|
||||||
|
return [assembly["name"] for assembly in flat_bom]
|
||||||
|
|
||||||
|
def eop(print_mode, project, doc_file, last = False, first = False):
|
||||||
|
if print_mode:
|
||||||
|
print('\n<div style="page-break-after: always;"></div>', file = doc_file)
|
||||||
|
else:
|
||||||
|
if not first:
|
||||||
|
print('[Top](#%s)' % project.lower().replace(' ', '-'), file = doc_file)
|
||||||
|
if not last:
|
||||||
|
print("\n---", file = doc_file)
|
||||||
|
|
||||||
|
def pad(s, before, after = 0):
|
||||||
|
return ' ' * before + str(s) + ' ' * after
|
||||||
|
|
||||||
|
def views(target, do_assemblies = None):
|
||||||
|
done_assemblies = []
|
||||||
|
#
|
||||||
|
# Make the target directory
|
||||||
|
#
|
||||||
|
top_dir = set_config(target)
|
||||||
|
target_dir = top_dir + 'assemblies'
|
||||||
|
deps_dir = top_dir + "deps"
|
||||||
|
bom_dir = top_dir + "bom"
|
||||||
|
if not os.path.isdir(target_dir):
|
||||||
|
os.makedirs(target_dir)
|
||||||
|
if not os.path.isdir(deps_dir):
|
||||||
|
os.makedirs(deps_dir)
|
||||||
|
times.read_times(target_dir)
|
||||||
|
#
|
||||||
|
# Find all the assemblies
|
||||||
|
#
|
||||||
|
assemblies = bom_to_assemblies(bom_dir)
|
||||||
|
for file in os.listdir(target_dir):
|
||||||
|
if file.endswith('.png'):
|
||||||
|
assembly = file[:-4].replace('_assembled', '_assembly')
|
||||||
|
if assembly.endswith('_tn'):
|
||||||
|
assembly = assembly[:-3]
|
||||||
|
if not assembly in assemblies:
|
||||||
|
print("Removing %s" % file)
|
||||||
|
os.remove(target_dir + '/' + file)
|
||||||
|
#
|
||||||
|
# Find all the scad files
|
||||||
|
#
|
||||||
|
main_blurb = None
|
||||||
|
lib_dir = os.environ['OPENSCADPATH'] + '/NopSCADlib'
|
||||||
|
for dir in [source_dir, lib_dir]:
|
||||||
|
for filename in os.listdir(dir):
|
||||||
|
if filename.endswith('.scad'):
|
||||||
|
#
|
||||||
|
# find any modules with names ending in _assembly
|
||||||
|
#
|
||||||
|
with open(dir + "/" + filename, "r") as f:
|
||||||
|
lines = f.readlines()
|
||||||
|
line_no = 0
|
||||||
|
for line in lines:
|
||||||
|
words = line.split()
|
||||||
|
if len(words) and words[0] == "module":
|
||||||
|
module = words[1].split('(')[0]
|
||||||
|
if is_assembly(module):
|
||||||
|
if module in assemblies:
|
||||||
|
#
|
||||||
|
# Scrape the assembly instructions
|
||||||
|
#
|
||||||
|
for ass in flat_bom:
|
||||||
|
if ass["name"] == module:
|
||||||
|
if not "blurb" in ass:
|
||||||
|
ass["blurb"] = blurb.scrape_module_blurb(lines[:line_no])
|
||||||
|
break
|
||||||
|
if not do_assemblies or module in do_assemblies:
|
||||||
|
#
|
||||||
|
# make a file to use the module
|
||||||
|
#
|
||||||
|
png_maker_name = 'png.scad'
|
||||||
|
with open(png_maker_name, "w") as f:
|
||||||
|
f.write("use <%s/%s>\n" % (dir, filename))
|
||||||
|
f.write("%s();\n" % module);
|
||||||
|
#
|
||||||
|
# Run openscad on the created file
|
||||||
|
#
|
||||||
|
dname = deps_name(deps_dir, filename)
|
||||||
|
for explode in [0, 1]:
|
||||||
|
png_name = target_dir + '/' + module + '.png'
|
||||||
|
if not explode:
|
||||||
|
png_name = png_name.replace('_assembly', '_assembled')
|
||||||
|
changed = check_deps(mtime(png_name), dname)
|
||||||
|
changed = times.check_have_time(changed, png_name)
|
||||||
|
if changed:
|
||||||
|
print(changed)
|
||||||
|
t = time.time()
|
||||||
|
openscad.run("-D$pose=1", "-D$explode=%d" % explode, "--projection=p", "--imgsize=4096,4096", "--autocenter", "--viewall", "-d", dname, "-o", png_name, png_maker_name);
|
||||||
|
times.add_time(png_name, t)
|
||||||
|
do_cmd(["magick", png_name, "-trim", "-resize", "1004x1004", "-bordercolor", "#ffffe5", "-border", "10", png_name])
|
||||||
|
tn_name = png_name.replace('.png', '_tn.png')
|
||||||
|
if mtime(png_name) > mtime(tn_name):
|
||||||
|
do_cmd(("magick "+ png_name + " -trim -resize 280x280 -background #ffffe5 -gravity Center -extent 280x280 -bordercolor #ffffe5 -border 10 " + tn_name).split())
|
||||||
|
os.remove(png_maker_name)
|
||||||
|
done_assemblies.append(module)
|
||||||
|
else:
|
||||||
|
if module == 'main_assembly':
|
||||||
|
main_blurb = blurb.scrape_module_blurb(lines[:line_no])
|
||||||
|
line_no += 1
|
||||||
|
times.print_times()
|
||||||
|
#
|
||||||
|
# Build the document
|
||||||
|
#
|
||||||
|
for print_mode in [True, False]:
|
||||||
|
doc_name = top_dir + "readme.md"
|
||||||
|
with open(doc_name, "wt") as doc_file:
|
||||||
|
#
|
||||||
|
# Title, description and picture
|
||||||
|
#
|
||||||
|
project = ' '.join(word[0].upper() + word[1:] for word in os.path.basename(os.getcwd()).split('_'))
|
||||||
|
print('# %s' % project, file = doc_file)
|
||||||
|
main_file = bom.find_scad_file('main_assembly')
|
||||||
|
if not main_file:
|
||||||
|
raise Exception("can't find source for main_assembly")
|
||||||
|
text = blurb.scrape_blurb(source_dir + '/' + main_file)
|
||||||
|
if len(text):
|
||||||
|
print(text, file = doc_file, end = '')
|
||||||
|
else:
|
||||||
|
if print_mode:
|
||||||
|
print(Fore.MAGENTA + "Missing project description" + Fore.WHITE)
|
||||||
|
print('![Main Assembly](assemblies/%s.png)\n' % flat_bom[-1]["name"].replace('_assembly', '_assembled'), file = doc_file)
|
||||||
|
eop(print_mode, project, doc_file, first = True)
|
||||||
|
#
|
||||||
|
# Build TOC
|
||||||
|
#
|
||||||
|
print('## Table of Contents', file = doc_file)
|
||||||
|
print('[TOC]\n', file = doc_file)
|
||||||
|
eop(print_mode, project, doc_file)
|
||||||
|
#
|
||||||
|
# Global BOM
|
||||||
|
#
|
||||||
|
print('## Parts list', file = doc_file)
|
||||||
|
vitamins = {}
|
||||||
|
printed = {}
|
||||||
|
routed = {}
|
||||||
|
for ass in flat_bom:
|
||||||
|
for v in ass["vitamins"]:
|
||||||
|
if v in vitamins:
|
||||||
|
vitamins[v] += ass["vitamins"][v]
|
||||||
|
else:
|
||||||
|
vitamins[v] = ass["vitamins"][v]
|
||||||
|
for p in ass["printed"]:
|
||||||
|
if p in printed:
|
||||||
|
printed[p] += ass["printed"][p]
|
||||||
|
else:
|
||||||
|
printed[p] = ass["printed"][p]
|
||||||
|
for ass in flat_bom:
|
||||||
|
name = ass["name"][:-9].replace('_', ' ').title().replace(' ',' ')
|
||||||
|
print('| <span style="writing-mode: vertical-rl; text-orientation: mixed;">%s</span> ' % name, file = doc_file, end = '')
|
||||||
|
print('| <span style="writing-mode: vertical-rl; text-orientation: mixed;">TOTALS</span> | |', file = doc_file)
|
||||||
|
print(('|--:' * len(flat_bom) + '|--:|:--|'), file = doc_file)
|
||||||
|
for v in sorted(vitamins, key = lambda s: s.split(":")[-1]):
|
||||||
|
for ass in flat_bom:
|
||||||
|
count = ass["vitamins"][v] if v in ass["vitamins"] else '.'
|
||||||
|
print('| %s ' % pad(count, 2, 1), file = doc_file, end = '')
|
||||||
|
print('| %s | %s |' % (pad(vitamins[v], 2, 1), pad(v.split(":")[1], 2)), file = doc_file)
|
||||||
|
print(('| ' * len(flat_bom) + '| | **3D Printed parts** |'), file = doc_file)
|
||||||
|
for p in sorted(printed):
|
||||||
|
for ass in flat_bom:
|
||||||
|
count = ass["printed"][p] if p in ass["printed"] else '.'
|
||||||
|
print('| %s ' % pad(count, 2, 1), file = doc_file, end = '')
|
||||||
|
print('| %s | %s |' % (pad(printed[p], 2, 1), pad(p, 3)), file = doc_file)
|
||||||
|
eop(print_mode, project, doc_file)
|
||||||
|
#
|
||||||
|
# Assembly instructions
|
||||||
|
#
|
||||||
|
for ass in flat_bom:
|
||||||
|
name = ass["name"]
|
||||||
|
cap_name = name.replace('_', ' ').title()
|
||||||
|
if ass["count"] > 1:
|
||||||
|
print("## %d x %s" % (ass["count"], cap_name), file = doc_file)
|
||||||
|
else:
|
||||||
|
print("## %s" % cap_name, file = doc_file)
|
||||||
|
vitamins = ass["vitamins"]
|
||||||
|
if vitamins:
|
||||||
|
print("### Vitamins", file = doc_file)
|
||||||
|
print("|Qty|Description|", file = doc_file)
|
||||||
|
print("|--:|:----------|", file = doc_file)
|
||||||
|
for v in vitamins:
|
||||||
|
print("|%d|%s|" % (vitamins[v], v.split(":")[1]), file = doc_file)
|
||||||
|
print("\n", file = doc_file)
|
||||||
|
|
||||||
|
printed = ass["printed"]
|
||||||
|
if printed:
|
||||||
|
print('### 3D Printed parts', file = doc_file)
|
||||||
|
i = 0
|
||||||
|
for p in printed:
|
||||||
|
print('%s %d x %s |' % ('\n|' if not (i % 3) else '', printed[p], p), file = doc_file, end = '')
|
||||||
|
if (i % 3) == 2 or i == len(printed) - 1:
|
||||||
|
n = (i % 3) + 1
|
||||||
|
print('\n|%s' % ('--|' * n), file = doc_file)
|
||||||
|
for j in range(n):
|
||||||
|
part = list(printed.keys())[i - n + j + 1]
|
||||||
|
print('| ![%s](stls/%s) %s' % (part, part.replace('.stl','.png'), '|\n' if j == j - 1 else ''), end = '', file = doc_file)
|
||||||
|
print('\n', file = doc_file)
|
||||||
|
i += 1
|
||||||
|
print('\n', file = doc_file)
|
||||||
|
|
||||||
|
routed = ass["routed"]
|
||||||
|
if routed:
|
||||||
|
print("### CNC Routed parts", file = doc_file)
|
||||||
|
i = 0
|
||||||
|
for r in routed:
|
||||||
|
print('%s %d x %s |' % ('\n|' if not (i % 3) else '', routed[r], r), file = doc_file, end = '')
|
||||||
|
if (i % 3) == 2 or i == len(routed) - 1:
|
||||||
|
n = (i % 3) + 1
|
||||||
|
print('\n|%s' % ('--|' * n), file = doc_file)
|
||||||
|
for j in range(n):
|
||||||
|
part = list(routed.keys())[i - n + j + 1]
|
||||||
|
print('| ![%s](dxfs/%s) %s' % (part, part.replace('.dxf','.png'), '|\n' if j == j - 1 else ''), end = '', file = doc_file)
|
||||||
|
print('\n', file = doc_file)
|
||||||
|
i += 1
|
||||||
|
print('\n', file = doc_file)
|
||||||
|
|
||||||
|
sub_assemblies = ass["assemblies"]
|
||||||
|
if sub_assemblies:
|
||||||
|
print("### Sub-assemblies", file = doc_file)
|
||||||
|
i = 0
|
||||||
|
for a in sub_assemblies:
|
||||||
|
print('%s %d x %s |' % ('\n|' if not (i % 3) else '', a["count"], a["name"]), file = doc_file, end = '')
|
||||||
|
if (i % 3) == 2 or i == len(sub_assemblies) - 1:
|
||||||
|
n = (i % 3) + 1
|
||||||
|
print('\n|%s' % ('--|' * n), file = doc_file)
|
||||||
|
for j in range(n):
|
||||||
|
a = sub_assemblies[i - n + j + 1]["name"].replace('_assembly', '_assembled')
|
||||||
|
print('| ![%s](assemblies/%s) %s' % (a, a + '_tn.png', '|\n' if j == j - 1 else ''), end = '', file = doc_file)
|
||||||
|
print('\n', file = doc_file)
|
||||||
|
i += 1
|
||||||
|
print('\n', file = doc_file)
|
||||||
|
|
||||||
|
small = not ass["big"]
|
||||||
|
suffix = '_tn.png' if small else '.png'
|
||||||
|
print('### Assembly instructions', file = doc_file)
|
||||||
|
print('![%s](assemblies/%s)\n' % (name, name + suffix), file = doc_file)
|
||||||
|
|
||||||
|
if "blurb" in ass and ass["blurb"]:
|
||||||
|
print(ass["blurb"], file = doc_file)
|
||||||
|
else:
|
||||||
|
if print_mode:
|
||||||
|
print(Fore.MAGENTA + "Missing instructions for %s" % name, Fore.WHITE)
|
||||||
|
|
||||||
|
name = name.replace('_assembly', '_assembled')
|
||||||
|
print('![%s](assemblies/%s)\n' % (name, name + suffix), file = doc_file)
|
||||||
|
eop(print_mode, project, doc_file, last = ass == flat_bom[-1] and not main_blurb)
|
||||||
|
#
|
||||||
|
# If main module is suppressed print any blurb here
|
||||||
|
#
|
||||||
|
if main_blurb:
|
||||||
|
print(main_blurb, file = doc_file)
|
||||||
|
eop(print_mode, project, doc_file, last = True)
|
||||||
|
#
|
||||||
|
# Convert to HTML
|
||||||
|
#
|
||||||
|
html_name = "printme.html" if print_mode else "readme.html"
|
||||||
|
with open(top_dir + html_name, "wt") as html_file:
|
||||||
|
do_cmd(("python -m markdown -x tables -x toc -x sane_lists " + doc_name).split(), html_file)
|
||||||
|
#
|
||||||
|
# Spell check
|
||||||
|
#
|
||||||
|
do_cmd('codespell -L od readme.md'.split())
|
||||||
|
#
|
||||||
|
# List the ones we didn't find
|
||||||
|
#
|
||||||
|
missing = set()
|
||||||
|
for assembly in assemblies + (do_assemblies if do_assemblies else []):
|
||||||
|
if assembly not in done_assemblies:
|
||||||
|
missing.add(assembly)
|
||||||
|
if missing:
|
||||||
|
for assembly in missing:
|
||||||
|
print(Fore.MAGENTA + "Could not find a module called", assembly, Fore.WHITE)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
if len(sys.argv) > 1 and sys.argv[1][-9:] != "_assembly":
|
||||||
|
target, assemblies = sys.argv[1], sys.argv[2:]
|
||||||
|
else:
|
||||||
|
target, assemblies = None, sys.argv[1:]
|
||||||
|
|
||||||
|
views(target, assemblies)
|
|
@ -0,0 +1,127 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
//! UK 13A socket and printed backbox with earth terminal for the panel it is mounted on.
|
||||||
|
//
|
||||||
|
include <core.scad>
|
||||||
|
include <vitamins/mains_sockets.scad>
|
||||||
|
include <vitamins/screws.scad>
|
||||||
|
include <vitamins/inserts.scad>
|
||||||
|
include <vitamins/ring_terminals.scad>
|
||||||
|
|
||||||
|
box_height = 19;
|
||||||
|
base_thickness = 2;
|
||||||
|
wall = 3.5;
|
||||||
|
|
||||||
|
cable_d = 7;
|
||||||
|
cable_z = cable_d / 2 + base_thickness + 1;
|
||||||
|
function cable_y(type) = -mains_socket_depth(type) / 2;
|
||||||
|
cable_x = 0;
|
||||||
|
|
||||||
|
earth = M3_ringterm;
|
||||||
|
earth_screw = ringterm_screw(earth);
|
||||||
|
|
||||||
|
height = base_thickness + box_height;
|
||||||
|
function socket_box_depth() = height; //! Outside depth of the backbox
|
||||||
|
|
||||||
|
module socket_box(type) { //! Generate STL of the backbox for the specified socket
|
||||||
|
stl(str("socket_box_",type[0]));
|
||||||
|
|
||||||
|
screw = mains_socket_screw(type);
|
||||||
|
screw_clearance_radius = screw_clearance_radius(screw);
|
||||||
|
|
||||||
|
insert = screw_insert(screw);
|
||||||
|
insert_length = insert_length(insert);
|
||||||
|
insert_boss = mains_socket_insert_boss(type);
|
||||||
|
insert_hole_radius = insert_hole_radius(insert);
|
||||||
|
|
||||||
|
difference() {
|
||||||
|
linear_extrude(height = height, convexity = 5)
|
||||||
|
face_plate(type);
|
||||||
|
|
||||||
|
difference() {
|
||||||
|
translate_z(base_thickness)
|
||||||
|
linear_extrude(height = height, convexity = 5)
|
||||||
|
offset(-wall) offset(1) face_plate(type);
|
||||||
|
|
||||||
|
for(side = [-1, 1])
|
||||||
|
hull()
|
||||||
|
for(x = [1, 2])
|
||||||
|
translate([side * mains_socket_pitch(type) / x, 0])
|
||||||
|
cylinder(d = insert_boss, h = 100);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Socket holes
|
||||||
|
//
|
||||||
|
translate_z(height)
|
||||||
|
mains_socket_hole_positions(type) {
|
||||||
|
poly_cylinder(r = screw_clearance_radius, h = 2 * box_height, center = true);
|
||||||
|
|
||||||
|
poly_cylinder(r = insert_hole_radius, h = 2 * insert_length, center = true);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Cable hole
|
||||||
|
//
|
||||||
|
translate([cable_x, cable_y(type), cable_z])
|
||||||
|
rotate([90, 0, 0])
|
||||||
|
teardrop_plus(r = cable_d / 2, h = 30);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module socket_box_MKLOGIC_stl() socket_box(MKLOGIC);
|
||||||
|
module socket_box_Contactum_stl() socket_box(Contactum);
|
||||||
|
|
||||||
|
module socket_box_assembly(type) //! The box with inserts fitted
|
||||||
|
assembly(str("socket_box_", type[0])) {
|
||||||
|
screw = mains_socket_screw(type);
|
||||||
|
insert = screw_insert(screw);
|
||||||
|
|
||||||
|
color("lime") render() socket_box(type);
|
||||||
|
|
||||||
|
mains_socket_hole_positions(type)
|
||||||
|
translate_z(height)
|
||||||
|
insert(insert);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//! * Place two inserts into the holes in the lugs and press them home with a soldering iron with a tapered bit heated to 200°C.
|
||||||
|
module socket_box_MKLOGIC_assembly() socket_box_assembly(MKLOGIC);
|
||||||
|
|
||||||
|
module socket_box_fastened_assembly(type, thickness) { //! The socket and backbox on each side of the specified panel thickness
|
||||||
|
screw = mains_socket_screw(type);
|
||||||
|
insert = screw_insert(screw);
|
||||||
|
screw_length = screw_longer_than(mains_socket_height(type) + thickness + insert_length(insert));
|
||||||
|
|
||||||
|
explode(-50)
|
||||||
|
translate_z(-height - thickness)
|
||||||
|
socket_box_assembly(type);
|
||||||
|
|
||||||
|
explode(50, true) {
|
||||||
|
mains_socket(type);
|
||||||
|
|
||||||
|
mains_socket_hole_positions(type)
|
||||||
|
translate_z(mains_socket_height(type))
|
||||||
|
screw(screw, screw_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
mains_socket_earth_position(type)
|
||||||
|
rotate(-90)
|
||||||
|
ring_terminal_assembly(earth, thickness);
|
||||||
|
}
|
|
@ -0,0 +1,189 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
//! Retracting strap handle. Print the strap with flexible filament. Shown with default dimensions but can
|
||||||
|
//! be fully customised by passing a list of properties.
|
||||||
|
//
|
||||||
|
include <core.scad>
|
||||||
|
include <vitamins/screws.scad>
|
||||||
|
include <vitamins/inserts.scad>
|
||||||
|
|
||||||
|
strap = [18, 2, M3_pan_screw, 3, 25];
|
||||||
|
function strap() = strap;
|
||||||
|
|
||||||
|
wall = 2;
|
||||||
|
clearance = 0.5;
|
||||||
|
step = 0.3;
|
||||||
|
overlap = 3;
|
||||||
|
panel_clearance = 0.25;
|
||||||
|
counterbore = 1;
|
||||||
|
|
||||||
|
function strap_width(type = strap) = type[0]; //! Width of strap
|
||||||
|
function strap_thickness(type = strap) = type[1]; //! Thickness of strap
|
||||||
|
function strap_screw(type = strap) = type[2]; //! Screw type
|
||||||
|
function strap_panel(type = strap) = type[3]; //! Panel thickness
|
||||||
|
function strap_extension(type = strap) = type[4]; //! How much length of the strap that can pull out
|
||||||
|
|
||||||
|
function strap_insert(type) = screw_insert(strap_screw(type)); //! The insert type
|
||||||
|
function strap_key(type) = strap_panel(type) - panel_clearance;
|
||||||
|
function strap_height(type) = wall + max(insert_length(strap_insert(type)) - strap_key(type), strap_thickness(type) + clearance); //! Height of the ends
|
||||||
|
function strap_end_width(type = strap) = strap_width(type) + 2 * (wall + clearance); //! Width of the ends
|
||||||
|
function strap_boss_r(type) = wall + insert_hole_radius(strap_insert(type));
|
||||||
|
|
||||||
|
function strap_min_width(type) = (strap_width(type) - 2 * (strap_boss_r(type) + clearance)) / 2;
|
||||||
|
|
||||||
|
module strap_boss_shape(type)
|
||||||
|
hull() {
|
||||||
|
r = strap_boss_r(type);
|
||||||
|
|
||||||
|
circle4n(r);
|
||||||
|
|
||||||
|
translate([r / 2, 0])
|
||||||
|
rounded_square([r, 2 * r], r = 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
module strap_screw_positions(length, type = strap) //! Place children at the screw positions
|
||||||
|
for(end = [-1, 1])
|
||||||
|
translate([end * (length / 2 - wall - 2 * clearance - strap_min_width(type) - strap_boss_r(type) - strap_extension(type) / 2), 0])
|
||||||
|
rotate(end * 90 + 90)
|
||||||
|
children();
|
||||||
|
|
||||||
|
module strap_holes(length, type = strap, h = 100) //! The panel cut outs
|
||||||
|
extrude_if(h)
|
||||||
|
strap_screw_positions(length, type)
|
||||||
|
offset(cnc_bit_r + 0.05)
|
||||||
|
offset(-step - cnc_bit_r)
|
||||||
|
strap_boss_shape(type);
|
||||||
|
|
||||||
|
module strap(length, type = strap) { //! Generate the STL for the rubber strap
|
||||||
|
stl("strap");
|
||||||
|
|
||||||
|
len = length - 2 * (wall + clearance);
|
||||||
|
w = strap_width(type);
|
||||||
|
|
||||||
|
linear_extrude(height = strap_thickness(type), convexity = 3)
|
||||||
|
difference() {
|
||||||
|
rounded_square([len, w], w / 2 - eps);
|
||||||
|
|
||||||
|
for(end = [-1, 1])
|
||||||
|
translate([end * (len / 2 - strap_min_width(type) - strap_boss_r(type) - clearance), 0])
|
||||||
|
rotate(end * 90 + 90)
|
||||||
|
hull() {
|
||||||
|
offset(clearance)
|
||||||
|
strap_boss_shape(type);
|
||||||
|
|
||||||
|
translate([strap_extension(type) / 2, 0])
|
||||||
|
offset(clearance)
|
||||||
|
strap_boss_shape(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module strap_end(type = strap) { //! Generate the STL for end piece
|
||||||
|
stl("strap_end");
|
||||||
|
|
||||||
|
z1 = strap_height(type) - strap_thickness(type) - clearance;
|
||||||
|
z2 = strap_height(type) + strap_key(type);
|
||||||
|
r1 = strap_boss_r(type) - 1;
|
||||||
|
|
||||||
|
module outer()
|
||||||
|
hull() {
|
||||||
|
translate([0, -strap_end_width(type) / 2])
|
||||||
|
square([strap_boss_r(type) + overlap, strap_end_width(type)]);
|
||||||
|
|
||||||
|
translate([-strap_extension(type) / 2, 0])
|
||||||
|
circle(d = strap_end_width(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
module with_hole()
|
||||||
|
difference() {
|
||||||
|
children();
|
||||||
|
|
||||||
|
circle(r1);
|
||||||
|
}
|
||||||
|
|
||||||
|
union() {
|
||||||
|
linear_extrude(height = z1)
|
||||||
|
with_hole()
|
||||||
|
outer();
|
||||||
|
|
||||||
|
translate_z(z1)
|
||||||
|
linear_extrude(height = strap_height(type) - z1)
|
||||||
|
difference() {
|
||||||
|
outer();
|
||||||
|
|
||||||
|
hull() {
|
||||||
|
translate([0, -strap_width(type) / 2 - clearance])
|
||||||
|
square([strap_boss_r(type) + overlap, strap_width(type) + 2 * clearance]);
|
||||||
|
|
||||||
|
translate([-strap_extension(type) / 2, 0])
|
||||||
|
circle(d = strap_width(type) + 2 * clearance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
linear_extrude(height = strap_height(type) - layer_height)
|
||||||
|
with_hole()
|
||||||
|
strap_boss_shape(type);
|
||||||
|
|
||||||
|
linear_extrude(height = z2)
|
||||||
|
with_hole()
|
||||||
|
offset(cnc_bit_r)
|
||||||
|
offset(-step - cnc_bit_r)
|
||||||
|
strap_boss_shape(type);
|
||||||
|
|
||||||
|
render() difference() {
|
||||||
|
cylinder(r = r1 + eps, h = z2);
|
||||||
|
|
||||||
|
translate_z(z2)
|
||||||
|
insert_hole(strap_insert(type), counterbore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
//! * Place the insert into the hole and push home with a soldering iron with a tapered bit heated to 200°C.
|
||||||
|
//
|
||||||
|
module strap_end_assembly(type = strap)
|
||||||
|
assembly("strap_end") {
|
||||||
|
color(pp1_colour)
|
||||||
|
strap_end(type);
|
||||||
|
|
||||||
|
translate_z(strap_height(type) + strap_key(type))
|
||||||
|
insert(strap_insert(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
module strap_assembly(length, type = strap) { //! Assembly with screws in place
|
||||||
|
screw = strap_screw(type);
|
||||||
|
washer = screw_washer(screw);
|
||||||
|
penny = penny_washer(washer);
|
||||||
|
insert = strap_insert(type);
|
||||||
|
|
||||||
|
screw_length = screw_shorter_than(washer_thickness(washer) + washer_thickness(penny) + insert_length(insert) + panel_clearance + counterbore);
|
||||||
|
|
||||||
|
color(pp4_colour) strap(length, type);
|
||||||
|
|
||||||
|
strap_screw_positions(length, type)
|
||||||
|
translate_z(strap_height(type))
|
||||||
|
vflip() {
|
||||||
|
explode(-50) strap_end_assembly(type);
|
||||||
|
|
||||||
|
translate_z(strap_height(type) + strap_panel(type))
|
||||||
|
screw_and_washer(screw, screw_length, true, true);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../utils/annotation.scad>
|
||||||
|
|
||||||
|
module annotations() {
|
||||||
|
arrow();
|
||||||
|
|
||||||
|
translate_z(21)
|
||||||
|
label("Text", halign = "center", valign = "bottom");
|
||||||
|
}
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
annotations();
|
|
@ -0,0 +1,30 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
use <../utils/layout.scad>
|
||||||
|
|
||||||
|
include <../vitamins/ball_bearings.scad>
|
||||||
|
|
||||||
|
module ball_bearings()
|
||||||
|
layout([for(b = ball_bearings) bb_diameter(b)])
|
||||||
|
ball_bearing(ball_bearings[$i])
|
||||||
|
bearing_ball(3);
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
ball_bearings();
|
|
@ -0,0 +1,41 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../utils/layout.scad>
|
||||||
|
|
||||||
|
include <../vitamins/springs.scad>
|
||||||
|
include <../vitamins/batteries.scad>
|
||||||
|
|
||||||
|
module batteries()
|
||||||
|
layout([for(b = batteries) battery_diameter(b)], 5) let(battery=batteries[$i]) {
|
||||||
|
battery = batteries[$i];
|
||||||
|
rotate(-135) // To show Lumintop USB socket and LEDs
|
||||||
|
battery(battery);
|
||||||
|
|
||||||
|
contact = battery_contact(battery);
|
||||||
|
translate_z(battery_length(battery) / 2 + contact_pos(contact).x)
|
||||||
|
rotate([0, 180, 0])
|
||||||
|
battery_contact(contact);
|
||||||
|
|
||||||
|
translate_z(-battery_length(battery) / 2 - contact_neg(contact).x)
|
||||||
|
battery_contact(contact, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
batteries();
|
|
@ -0,0 +1,74 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
|
||||||
|
include <../vitamins/belts.scad>
|
||||||
|
include <../vitamins/screws.scad>
|
||||||
|
include <../vitamins/inserts.scad>
|
||||||
|
include <../vitamins/pulleys.scad>
|
||||||
|
use <../utils/layout.scad>
|
||||||
|
|
||||||
|
module belt_test() {
|
||||||
|
p1 = [75, -50];
|
||||||
|
p2 = [-75, -50];
|
||||||
|
p3 = [-75, 100];
|
||||||
|
p4 = [75, 100];
|
||||||
|
|
||||||
|
p5 = [75 - pulley_pr(GT2x20ob_pulley) - pulley_pr(GT2x16_plain_idler), -pulley_pr(GT2x16_plain_idler)];
|
||||||
|
p6 = [-75 + pulley_pr(GT2x20ob_pulley) + pulley_pr(GT2x16_plain_idler), -pulley_pr(GT2x16_plain_idler)];
|
||||||
|
|
||||||
|
translate(p1) pulley_assembly(GT2x20ob_pulley);
|
||||||
|
translate(p2) pulley_assembly(GT2x20ob_pulley);
|
||||||
|
translate(p3) pulley_assembly(GT2x20_toothed_idler);
|
||||||
|
translate(p4) pulley_assembly(GT2x20_toothed_idler);
|
||||||
|
|
||||||
|
translate(p5) {
|
||||||
|
pulley = GT2x16_plain_idler;
|
||||||
|
screw = find_screw(hs_cs_cap, pulley_bore(pulley));
|
||||||
|
insert = screw_insert(screw);
|
||||||
|
|
||||||
|
pulley_assembly(pulley);
|
||||||
|
translate_z(pulley_height(pulley) + pulley_offset(pulley) + screw_head_depth(screw, pulley_bore(pulley)))
|
||||||
|
screw(screw, 20);
|
||||||
|
|
||||||
|
translate_z(pulley_offset(pulley) - insert_length(insert))
|
||||||
|
vflip()
|
||||||
|
insert(insert);
|
||||||
|
|
||||||
|
}
|
||||||
|
translate(p6) pulley_assembly(GT2x16_plain_idler);
|
||||||
|
|
||||||
|
path = [ [p1.x, p1.y, pulley_pr(GT2x20ob_pulley)],
|
||||||
|
[p5.x, p5.y, -pulley_pr(GT2x16_plain_idler)],
|
||||||
|
[p6.x, p6.y, -pulley_pr(GT2x16_plain_idler)],
|
||||||
|
[p2.x, p2.y, pulley_pr(GT2x20ob_pulley)],
|
||||||
|
[p3.x, p3.y, pulley_pr(GT2x20ob_pulley)],
|
||||||
|
[p4.x, p4.y, pulley_pr(GT2x20ob_pulley)]
|
||||||
|
];
|
||||||
|
belt = GT2x6;
|
||||||
|
belt(belt, path, 80, [0, belt_pitch_height(belt) - belt_thickness(belt) / 2]);
|
||||||
|
|
||||||
|
translate([-25, 0])
|
||||||
|
layout([for(b = belts) belt_width(b)], 10)
|
||||||
|
rotate([0, 90, 0])
|
||||||
|
belt(belts[$i], [[0, 0, 20], [0, 1, 20]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
belt_test();
|
|
@ -0,0 +1,83 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../utils/bezier.scad>
|
||||||
|
use <../utils/sweep.scad>
|
||||||
|
use <../utils/annotation.scad>
|
||||||
|
|
||||||
|
function find_min_z(path, i = 1, best_i = 0) =
|
||||||
|
i >= len(path) ? best_i
|
||||||
|
: find_min_z(path, i + 1, path[i].z < path[best_i].z ? i : best_i);
|
||||||
|
|
||||||
|
module beziers() {
|
||||||
|
//
|
||||||
|
// Make Bezier control points to give specified length
|
||||||
|
//
|
||||||
|
control_points = adjust_bezier_length([[0, 0, 100], [0, 0, 0], [200, 0, 20], [100, -100, 50]], 250);
|
||||||
|
//
|
||||||
|
// Draw control points
|
||||||
|
//
|
||||||
|
color("green")
|
||||||
|
for(p = control_points)
|
||||||
|
translate(p)
|
||||||
|
sphere(1);
|
||||||
|
//
|
||||||
|
// Lines joining the control points
|
||||||
|
//
|
||||||
|
color("red")
|
||||||
|
sweep(control_points, circle_points(0.5, $fn = 64));
|
||||||
|
//
|
||||||
|
// Bezier curve path from control points
|
||||||
|
//
|
||||||
|
curve = bezier_path(control_points);
|
||||||
|
//
|
||||||
|
// Draw the curve
|
||||||
|
//
|
||||||
|
sweep(curve, circle_points(2, $fn = 64));
|
||||||
|
//
|
||||||
|
// Length computed from control points
|
||||||
|
//
|
||||||
|
length = bezier_length(control_points);
|
||||||
|
//
|
||||||
|
// Length computed from curve
|
||||||
|
//
|
||||||
|
length2 = path_length(curve);
|
||||||
|
assert(str(length) == str(length2), str(length, " ", length2));
|
||||||
|
//
|
||||||
|
// Minimum Z
|
||||||
|
//
|
||||||
|
min_z = bezier_min_z(control_points);
|
||||||
|
i = find_min_z(curve);
|
||||||
|
assert(str(min_z) == str(curve[i].z));
|
||||||
|
|
||||||
|
color("blue") {
|
||||||
|
translate(curve[i] + [0, 0, 2])
|
||||||
|
arrow();
|
||||||
|
|
||||||
|
translate(curve[i] - [0, 0, 2])
|
||||||
|
vflip()
|
||||||
|
arrow();
|
||||||
|
}
|
||||||
|
|
||||||
|
translate(control_points[1] - [0, 0, 2])
|
||||||
|
label(str("bezier_length = ", length, ", bezier_min_z = ", bezier_min_z(curve)), valign = "top");
|
||||||
|
}
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
beziers();
|
|
@ -0,0 +1,41 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../utils/layout.scad>
|
||||||
|
|
||||||
|
include <../vitamins/screws.scad>
|
||||||
|
include <../vitamins/blowers.scad>
|
||||||
|
|
||||||
|
module blowers()
|
||||||
|
layout([for(b = blowers) blower_width(b)], 10, true) let(b = blowers[$i]){
|
||||||
|
screw = blower_screw(b);
|
||||||
|
washer = screw_washer(screw);
|
||||||
|
h = blower_lug(b);
|
||||||
|
|
||||||
|
blower(b);
|
||||||
|
|
||||||
|
blower_hole_positions(b)
|
||||||
|
translate_z(h)
|
||||||
|
screw_and_washer(screw, screw_longer_than(h + washer_thickness(washer) + 5));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
blowers();
|
|
@ -0,0 +1,108 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
//! BOM and assembly demonstration
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
include <../vitamins/screws.scad>
|
||||||
|
include <../vitamins/inserts.scad>
|
||||||
|
include <../vitamins/sheets.scad>
|
||||||
|
$explode = 1; // Normally set on the command line when generating assembly views with views.py
|
||||||
|
|
||||||
|
screw = M3_cap_screw;
|
||||||
|
sheet = PMMA3;
|
||||||
|
height = 10;
|
||||||
|
|
||||||
|
insert = screw_insert(screw);
|
||||||
|
washer = screw_washer(screw);
|
||||||
|
|
||||||
|
module widget(thickness) {
|
||||||
|
vitamin(str("widget(", thickness, "): Rivit like thing for ", thickness, "mm sheets"));
|
||||||
|
t = 1;
|
||||||
|
color("silver") {
|
||||||
|
cylinder(d = 3, h = thickness + 2 * eps, center = true);
|
||||||
|
|
||||||
|
for(end = [-1, 1])
|
||||||
|
translate_z(end * (thickness / 2 + t / 2 + eps))
|
||||||
|
cylinder(d = 4, h = t, center = true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module widgit_stl() {
|
||||||
|
stl("widget");
|
||||||
|
|
||||||
|
union() {
|
||||||
|
rounded_rectangle([30, 30, 3], 2);
|
||||||
|
|
||||||
|
render() insert_boss(insert, height, 2.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module widgit_dxf() {
|
||||||
|
dxf("widget");
|
||||||
|
|
||||||
|
difference() {
|
||||||
|
sheet_2D(sheet, 20, 20, 1);
|
||||||
|
|
||||||
|
drill(screw_clearance_radius(screw), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! * Push the insert into the base with a soldering iron heated to 200°C
|
||||||
|
module widgit_base_assembly()
|
||||||
|
assembly("widgit_base") {
|
||||||
|
color(pp1_colour)
|
||||||
|
widgit_stl();
|
||||||
|
|
||||||
|
translate_z(height)
|
||||||
|
insert(insert);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! * Magically insert the widget into the acrylic sheet
|
||||||
|
module widget_top_assembly()
|
||||||
|
assembly("widget_top") {
|
||||||
|
translate([-5, 5])
|
||||||
|
widget(sheet_thickness(sheet));
|
||||||
|
|
||||||
|
render_2D_sheet(sheet) // Must be last because it is transparent
|
||||||
|
widgit_dxf();
|
||||||
|
}
|
||||||
|
|
||||||
|
//! * Screw the two assemblies together
|
||||||
|
module widgit_assembly()
|
||||||
|
assembly("wigdit") {
|
||||||
|
|
||||||
|
widgit_base_assembly(); // Note this is not exloded because it is sub-assembly
|
||||||
|
|
||||||
|
translate_z(height) {
|
||||||
|
translate_z(sheet_thickness(sheet))
|
||||||
|
screw_and_washer(screw, screw_longer_than(sheet_thickness(sheet) + 2 * washer_thickness(washer) + 3), true);
|
||||||
|
|
||||||
|
explode(5)
|
||||||
|
translate_z(sheet_thickness(sheet) / 2 + eps)
|
||||||
|
widget_top_assembly();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module boms() {
|
||||||
|
widgit_assembly();
|
||||||
|
}
|
||||||
|
|
||||||
|
boms();
|
|
@ -0,0 +1,54 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
|
||||||
|
include <../vitamins/screws.scad>
|
||||||
|
include <../vitamins/sheets.scad>
|
||||||
|
include <../vitamins/inserts.scad>
|
||||||
|
|
||||||
|
use <../box.scad>
|
||||||
|
|
||||||
|
box = [M3_dome_screw, 3, DiBond, PMMA3, DiBond6, true, 150, 100, 70];
|
||||||
|
|
||||||
|
include <../box_assembly.scad>
|
||||||
|
|
||||||
|
module box_assembly() _box_assembly(box);
|
||||||
|
|
||||||
|
module box_test() {
|
||||||
|
translate_z(box_height(box) / 2 + box_bezel_height(box, true))
|
||||||
|
box_assembly();
|
||||||
|
|
||||||
|
rows = 3;
|
||||||
|
cols = 3;
|
||||||
|
gap = 30;
|
||||||
|
|
||||||
|
x_pitch = (box_width(box) + 2 * box_outset(box)) / cols + gap;
|
||||||
|
y_pitch = (box_depth(box) + 2 * box_outset(box)) / rows + gap;
|
||||||
|
for(x = [0 : cols - 1], y = [0 : rows - 1])
|
||||||
|
translate([(x - cols / 2) * x_pitch + gap / 2, (y - rows / 2) * y_pitch + gap / 2])
|
||||||
|
color((x + y) % 2 ? pp1_colour : pp2_colour) box_bezel_section(box, true, rows, cols, x, y);
|
||||||
|
|
||||||
|
translate([-cols / 2 * x_pitch - 20, 0])
|
||||||
|
for(i = [0 : 2])
|
||||||
|
translate([0, (i - 1) * 20, 0])
|
||||||
|
color(i % 2 ? pp1_colour : pp2_colour) box_corner_profile_section(box, i, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
box_test();
|
|
@ -0,0 +1,29 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../utils/layout.scad>
|
||||||
|
|
||||||
|
include <../vitamins/bulldogs.scad>
|
||||||
|
|
||||||
|
module bulldogs()
|
||||||
|
layout([for(b = bulldogs) bulldog_depth(b)], 5, true)
|
||||||
|
bulldog(bulldogs[$i]);
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
bulldogs();
|
|
@ -0,0 +1,66 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
|
||||||
|
include <../vitamins/screws.scad>
|
||||||
|
include <../vitamins/sheets.scad>
|
||||||
|
include <../vitamins/inserts.scad>
|
||||||
|
|
||||||
|
include <../butt_box.scad>
|
||||||
|
|
||||||
|
$explode = 0;
|
||||||
|
|
||||||
|
box = [M3_dome_screw, DiBond, DiBond6, PMMA3, 250, 400, 300, 120];
|
||||||
|
|
||||||
|
module bbox_assembly() _bbox_assembly(box);
|
||||||
|
|
||||||
|
module bbox_test() {
|
||||||
|
translate_z(bbox_height(box) / 2)
|
||||||
|
bbox_assembly();
|
||||||
|
}
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
bbox_test();
|
||||||
|
else {
|
||||||
|
gap = 2;
|
||||||
|
bb = sheet_thickness(bbox_base_sheet(box));
|
||||||
|
bt = sheet_thickness(bbox_top_sheet(box));
|
||||||
|
h = bbox_height(box) + bb;
|
||||||
|
h2 = h + bt;
|
||||||
|
|
||||||
|
bbox_base_blank(box);
|
||||||
|
|
||||||
|
translate([bbox_width(box) / 2 + gap + h / 2 - bb / 2, 0])
|
||||||
|
rotate(90)
|
||||||
|
bbox_right_blank(box);
|
||||||
|
|
||||||
|
translate([-bbox_width(box) / 2 - gap - h / 2 + bb / 2, 0])
|
||||||
|
rotate(-90)
|
||||||
|
bbox_left_blank(box);
|
||||||
|
|
||||||
|
translate([0, bbox_depth(box) / 2 + gap + h / 2 - bb / 2])
|
||||||
|
rotate(180)
|
||||||
|
bbox_back_blank(box);
|
||||||
|
|
||||||
|
translate([0, -bbox_depth(box) / 2 - gap - h2 / 2 - (bt - bb) / 2])
|
||||||
|
bbox_front_blank(box);
|
||||||
|
|
||||||
|
translate([0, -bbox_depth(box) / 2 - gap - h2 - gap - bbox_depth(box) / 2 - sheet_thickness(bbox_sheets(box))])
|
||||||
|
bbox_top_blank(box);
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../utils/layout.scad>
|
||||||
|
|
||||||
|
include <../vitamins/buttons.scad>
|
||||||
|
|
||||||
|
module buttons()
|
||||||
|
layout([for(b = buttons) square_button_width(b)], 5)
|
||||||
|
square_button(buttons[$i]);
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
buttons();
|
|
@ -0,0 +1,36 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
|
||||||
|
use <../cable_grommets.scad>
|
||||||
|
|
||||||
|
module cable_grommets() {
|
||||||
|
rotate(90)
|
||||||
|
color(pp1_colour) ribbon_grommet(20, 3);
|
||||||
|
|
||||||
|
translate([20, 0])
|
||||||
|
round_grommet_assembly(6, 3);
|
||||||
|
|
||||||
|
translate([40, 0])
|
||||||
|
rotate(90)
|
||||||
|
color(pp1_colour) mouse_grommet(5, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
cable_grommets();
|
|
@ -0,0 +1,38 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
|
||||||
|
use <../vitamins/cable_strip.scad>
|
||||||
|
|
||||||
|
module cable_strips() {
|
||||||
|
depth = 50;
|
||||||
|
rotate(-90)
|
||||||
|
for(pos = [-100, 0, 100]) {
|
||||||
|
bezier_cable_strip(ways = 20, depth = depth, length = 150, travel = 100, pos = pos, below = 100, extra = 10);
|
||||||
|
|
||||||
|
translate([0, depth * 2])
|
||||||
|
rotate([0, -90, 0])
|
||||||
|
cable_strip(ways =20, depth = depth / 2, travel = 100, x = pos, extra = 30);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
cable_strips();
|
|
@ -0,0 +1,25 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../carriers.scad>
|
||||||
|
|
||||||
|
module carriers()
|
||||||
|
color(pp1_colour) ESP12F_carrier_stl();
|
||||||
|
|
||||||
|
carriers();
|
|
@ -0,0 +1,26 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
include <../core.scad>
|
||||||
|
|
||||||
|
module clips() {
|
||||||
|
clip(xmin = 0, ymin = 0, zmin = 0, zmax = 40) sphere(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
clips();
|
|
@ -0,0 +1,57 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../utils/layout.scad>
|
||||||
|
|
||||||
|
include <../vitamins/screws.scad>
|
||||||
|
include <../vitamins/components.scad>
|
||||||
|
|
||||||
|
module resistors()
|
||||||
|
layout([for(r = resistors) resistor_diameter(r)], 10)
|
||||||
|
resistor(resistors[$i]);
|
||||||
|
|
||||||
|
module al_clad_resistors()
|
||||||
|
layout([for(a = al_clad_resistors) al_clad_width(a)])
|
||||||
|
rotate(90)
|
||||||
|
al_clad_resistor_assembly(al_clad_resistors[$i], 4.7)
|
||||||
|
screw(al_clad_hole(al_clad_resistors[$i]) > 3 ? M3_pan_screw : M2p5_pan_screw, 16);
|
||||||
|
|
||||||
|
|
||||||
|
module thermal_cutouts()
|
||||||
|
layout([for(t = thermal_cutouts) tc_length(t)])
|
||||||
|
thermal_cutout(thermal_cutouts[$i]);
|
||||||
|
|
||||||
|
module components() {
|
||||||
|
resistors();
|
||||||
|
|
||||||
|
translate([0, 50])
|
||||||
|
TO220("Generic TO220 package");
|
||||||
|
|
||||||
|
translate([30, 50])
|
||||||
|
panel_USBA();
|
||||||
|
|
||||||
|
translate([0,80])
|
||||||
|
thermal_cutouts();
|
||||||
|
|
||||||
|
translate([0, 130])
|
||||||
|
al_clad_resistors();
|
||||||
|
}
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
components();
|
|
@ -0,0 +1,37 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../corner_block.scad>
|
||||||
|
|
||||||
|
include <../vitamins/screws.scad>
|
||||||
|
|
||||||
|
screws = [M2_cap_screw, M2p5_pan_screw, M3_dome_screw, M4_dome_screw];
|
||||||
|
|
||||||
|
module do_corner_block(screw)
|
||||||
|
if($preview)
|
||||||
|
fastened_corner_block_assembly(3, screw = screw);
|
||||||
|
else
|
||||||
|
corner_block(screw);
|
||||||
|
|
||||||
|
module corner_blocks()
|
||||||
|
for(i = [0 : len(screws) - 1])
|
||||||
|
translate([i * 30, 0])
|
||||||
|
do_corner_block(screws[i]);
|
||||||
|
|
||||||
|
corner_blocks();
|
|
@ -0,0 +1,38 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../utils/layout.scad>
|
||||||
|
|
||||||
|
include <../vitamins/d_connectors.scad>
|
||||||
|
|
||||||
|
module d_connectors()
|
||||||
|
for(socket = [false, true])
|
||||||
|
translate([socket ? len(d_connectors) * (d_flange_width(d_connectors[0]) + 10) : 0, 0])
|
||||||
|
layout([for(d = d_connectors) d_flange_width(d)], 10) let(d = d_connectors[$i])
|
||||||
|
rotate(90) {
|
||||||
|
d_plug(d, socket, pcb = $i == 2, idc = $i == 1);
|
||||||
|
|
||||||
|
if(socket)
|
||||||
|
translate_z(d_flange_thickness(d))
|
||||||
|
d_connector_holes(d)
|
||||||
|
d_pillar();
|
||||||
|
}
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
d_connectors();
|
|
@ -0,0 +1,29 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
use <../utils/layout.scad>
|
||||||
|
|
||||||
|
include <../vitamins/displays.scad>
|
||||||
|
use <../vitamins/pcb.scad>
|
||||||
|
|
||||||
|
module displays()
|
||||||
|
layout([for(d = displays) pcb_length(display_pcb(d))], 10)
|
||||||
|
display(displays[$i]);
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
displays();
|
|
@ -0,0 +1,34 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../global_defs.scad>
|
||||||
|
use <../utils/dogbones.scad>
|
||||||
|
|
||||||
|
module dogbones() {
|
||||||
|
#linear_extrude(height = eps)
|
||||||
|
dogbone_square([10, 20]);
|
||||||
|
|
||||||
|
#translate([15, 0])
|
||||||
|
dogbone_rectangle([10, 20, 5], center = false);
|
||||||
|
|
||||||
|
sq = 3;
|
||||||
|
translate([-5 + sq / 2 + eps, -10 + sq / 2 + eps])
|
||||||
|
%cube([sq, sq, 1], center = true);
|
||||||
|
}
|
||||||
|
|
||||||
|
dogbones();
|
|
@ -0,0 +1,57 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../door_hinge.scad>
|
||||||
|
|
||||||
|
include <../vitamins/sheets.scad>
|
||||||
|
use <../vitamins/screw.scad>
|
||||||
|
|
||||||
|
door_w = 50;
|
||||||
|
door_h = 50;
|
||||||
|
sheet = PMMA6;
|
||||||
|
|
||||||
|
module door_hinges() {
|
||||||
|
translate([door_hinge_stat_length() / 2 - door_hinge_pin_x(), 0])
|
||||||
|
if($preview) {
|
||||||
|
for(side = [-1, 1])
|
||||||
|
translate_z(side * door_h / 2) {
|
||||||
|
door_hinge_assembly(side > 0, sheet_thickness(sheet));
|
||||||
|
|
||||||
|
door_hinge_static_assembly(side > 0, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
translate([door_w / 2 + eps, door_hinge_pin_y() - eps])
|
||||||
|
rotate([90, 0, 0])
|
||||||
|
render_2D_sheet(sheet)
|
||||||
|
difference() {
|
||||||
|
sheet_2D(sheet, door_w, door_h, 3);
|
||||||
|
|
||||||
|
for(z =[-1, 1])
|
||||||
|
translate([-door_w / 2, z * door_h / 2])
|
||||||
|
door_hinge_hole_positions(z)
|
||||||
|
drill(screw_pilot_hole(door_hinge_screw()), 0);
|
||||||
|
}
|
||||||
|
translate([door_w, 0])
|
||||||
|
children();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
door_hinge_parts_stl();
|
||||||
|
}
|
||||||
|
|
||||||
|
door_hinges();
|
|
@ -0,0 +1,29 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../door_latch.scad>
|
||||||
|
|
||||||
|
module door_latches()
|
||||||
|
translate([door_latch_offset(), 0])
|
||||||
|
if($preview)
|
||||||
|
door_latch_assembly(3);
|
||||||
|
else
|
||||||
|
door_latch_stl();
|
||||||
|
|
||||||
|
door_latches();
|
|
@ -0,0 +1,29 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../utils/layout.scad>
|
||||||
|
|
||||||
|
include <../fan_guard.scad>
|
||||||
|
include <../vitamins/fans.scad>
|
||||||
|
|
||||||
|
module fan_guards()
|
||||||
|
layout([for(f = fans) fan_width(f)], 10)
|
||||||
|
color(pp1_colour) fan_guard(fans[$i], spokes = fan_width(fans[$i]) > 40 ? 8 : 4);
|
||||||
|
|
||||||
|
fan_guards();
|
|
@ -0,0 +1,31 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../utils/layout.scad>
|
||||||
|
|
||||||
|
include <../fan_guard.scad>
|
||||||
|
|
||||||
|
include <../vitamins/fans.scad>
|
||||||
|
|
||||||
|
module fans()
|
||||||
|
layout([for(f = fans) fan_width(f)], 10)
|
||||||
|
fan_assembly(fans[$i], 3 + fan_guard_thickness(), true);
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
fans();
|
|
@ -0,0 +1,26 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../global_defs.scad>
|
||||||
|
use <../utils/fillet.scad>
|
||||||
|
|
||||||
|
module fillets() {
|
||||||
|
fillet(3, 25);
|
||||||
|
}
|
||||||
|
|
||||||
|
fillets();
|
|
@ -0,0 +1,37 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../fixing_block.scad>
|
||||||
|
use <../utils/layout.scad>
|
||||||
|
|
||||||
|
include <../vitamins/screws.scad>
|
||||||
|
|
||||||
|
screws = [M2_cap_screw, M2p5_pan_screw, M3_dome_screw, M4_dome_screw];
|
||||||
|
|
||||||
|
module fixing_block_test(screw)
|
||||||
|
if($preview)
|
||||||
|
fastened_fixing_block_assembly(3, screw = screw);
|
||||||
|
else
|
||||||
|
fixing_block(screw);
|
||||||
|
|
||||||
|
module fixing_blocks()
|
||||||
|
layout([for(s = screws) fixing_block_width(s)], 5)
|
||||||
|
fixing_block_test(screws[$i]);
|
||||||
|
|
||||||
|
fixing_blocks();
|
|
@ -0,0 +1,37 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../foot.scad>
|
||||||
|
|
||||||
|
module feet()
|
||||||
|
if($preview) {
|
||||||
|
translate([50, 0])
|
||||||
|
foot_assembly(3);
|
||||||
|
|
||||||
|
translate([foot_diameter(insert_foot()) / 2, 0])
|
||||||
|
fastened_insert_foot_assembly(3);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
translate([50, 0])
|
||||||
|
foot();
|
||||||
|
|
||||||
|
insert_foot();
|
||||||
|
}
|
||||||
|
|
||||||
|
feet();
|
|
@ -0,0 +1,27 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
|
||||||
|
use <../vitamins/fuseholder.scad>
|
||||||
|
|
||||||
|
module fuseholders()
|
||||||
|
fuseholder(6);
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
fuseholders();
|
|
@ -0,0 +1,31 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
include <../core.scad>
|
||||||
|
|
||||||
|
module globals() {
|
||||||
|
linear_extrude(height = eps) {
|
||||||
|
semi_circle(r = 10);
|
||||||
|
|
||||||
|
translate([30, 0])
|
||||||
|
ellipse(15, 7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rotate([70, 0, 315]) globals();
|
|
@ -0,0 +1,29 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../handle.scad>
|
||||||
|
|
||||||
|
module handle()
|
||||||
|
translate([handle_length() / 2, 0])
|
||||||
|
if($preview)
|
||||||
|
handle_fastened_assembly(3);
|
||||||
|
else
|
||||||
|
handle_stl();
|
||||||
|
|
||||||
|
handle();
|
|
@ -0,0 +1,28 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../global_defs.scad>
|
||||||
|
use <../utils/hanging_hole.scad>
|
||||||
|
|
||||||
|
module hanging_holes() {
|
||||||
|
rotate(45)
|
||||||
|
#hanging_hole(z = 10, ir = 3, h = 30)
|
||||||
|
circle(r = 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
hanging_holes();
|
|
@ -0,0 +1,31 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../utils/layout.scad>
|
||||||
|
|
||||||
|
include <../vitamins/hot_ends.scad>
|
||||||
|
|
||||||
|
module hot_ends()
|
||||||
|
layout([for(h = hot_ends) 40])
|
||||||
|
translate([-20, 0])
|
||||||
|
rotate(90)
|
||||||
|
hot_end(hot_ends[$i], 3);
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
hot_ends();
|
|
@ -0,0 +1,30 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../utils/layout.scad>
|
||||||
|
|
||||||
|
include <../vitamins/iecs.scad>
|
||||||
|
|
||||||
|
module iecs()
|
||||||
|
layout([for(i = iecs) iec_flange_h(i)], 10)
|
||||||
|
rotate(90)
|
||||||
|
iec_assembly(iecs[$i], 3);
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
iecs();
|
|
@ -0,0 +1,30 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../utils/layout.scad>
|
||||||
|
|
||||||
|
include <../vitamins/inserts.scad>
|
||||||
|
|
||||||
|
module inserts()
|
||||||
|
for(i = [0: len(inserts) -1])
|
||||||
|
translate([10 * i, 0])
|
||||||
|
insert(inserts[i]);
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
inserts();
|
|
@ -0,0 +1,35 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
|
||||||
|
use <../vitamins/jack.scad>
|
||||||
|
|
||||||
|
module jacks() {
|
||||||
|
translate([0, 0])
|
||||||
|
jack_4mm("blue",3, "royalblue");
|
||||||
|
|
||||||
|
translate([20, 0])
|
||||||
|
jack_4mm_shielded("brown", 3, "sienna");
|
||||||
|
|
||||||
|
translate([40, 0])
|
||||||
|
post_4mm("red",3);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
jacks();
|
|
@ -0,0 +1,30 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../global_defs.scad>
|
||||||
|
use <../utils/layout.scad>
|
||||||
|
|
||||||
|
diams = [3, 7, 5, 11];
|
||||||
|
|
||||||
|
module layouts() {
|
||||||
|
linear_extrude(height = eps)
|
||||||
|
layout(diams, gap = 1)
|
||||||
|
circle(d = diams[$i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
rotate([70, 0, 315]) layouts();
|
|
@ -0,0 +1,30 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../utils/layout.scad>
|
||||||
|
|
||||||
|
include <../vitamins/screws.scad>
|
||||||
|
include <../vitamins/leadnuts.scad>
|
||||||
|
|
||||||
|
module leadnuts()
|
||||||
|
layout([for(n = leadnuts) leadnut_flange_dia(n)], 5)
|
||||||
|
leadnut(leadnuts[$i]);
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
leadnuts();
|
|
@ -0,0 +1,29 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../utils/layout.scad>
|
||||||
|
|
||||||
|
include <../vitamins/leds.scad>
|
||||||
|
|
||||||
|
module leds()
|
||||||
|
layout([for(l = LEDs) led_diameter(l)], 5)
|
||||||
|
led(LEDs[$i], ["green", "blue", "red"][$i % 3]);
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
leds();
|
|
@ -0,0 +1,38 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../utils/layout.scad>
|
||||||
|
|
||||||
|
include <../vitamins/light_strips.scad>
|
||||||
|
|
||||||
|
module light_strips()
|
||||||
|
layout([for(s = light_strips) light_strip_width(s)], 10)
|
||||||
|
rotate(90) let(light = light_strips[$i], segs = light_strip_segments(light, 260), d = light_strip_clip_depth(light)) {
|
||||||
|
light_strip(light, segs);
|
||||||
|
|
||||||
|
for(end = [-1, 1])
|
||||||
|
translate([end * (light_strip_cut_length(light, segs) / 2 - d / 2), 0])
|
||||||
|
rotate([90, 0, 90])
|
||||||
|
color("lime") render()
|
||||||
|
translate_z(-d / 2)
|
||||||
|
light_strip_clip(light);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
light_strips();
|
|
@ -0,0 +1,29 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../utils/layout.scad>
|
||||||
|
|
||||||
|
include <../vitamins/linear_bearings.scad>
|
||||||
|
|
||||||
|
module linear_bearings()
|
||||||
|
layout([for(b = linear_bearings) 2 * bearing_radius(b)])
|
||||||
|
linear_bearing(linear_bearings[$i]);
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
linear_bearings();
|
|
@ -0,0 +1,29 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../utils/layout.scad>
|
||||||
|
|
||||||
|
include <../vitamins/mains_sockets.scad>
|
||||||
|
|
||||||
|
module mains_sockets()
|
||||||
|
layout([for(s = mains_sockets) mains_socket_width(s)], 5)
|
||||||
|
mains_socket(mains_sockets[$i]);
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
mains_sockets();
|
|
@ -0,0 +1,70 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../utils/maths.scad>
|
||||||
|
use <../utils/annotation.scad>
|
||||||
|
|
||||||
|
tip = [0, 0, 20];
|
||||||
|
|
||||||
|
module shape() {
|
||||||
|
cylinder(d1 = 20, d2 = 0, h = tip.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
t = [10, 20, 30];
|
||||||
|
r = [45, 20, 70];
|
||||||
|
s = [1, 0.5, 0.75];
|
||||||
|
|
||||||
|
module maths() {
|
||||||
|
//
|
||||||
|
// Translate, rotate and scale the shape
|
||||||
|
//
|
||||||
|
translate(t)
|
||||||
|
rotate(r)
|
||||||
|
scale(s)
|
||||||
|
shape();
|
||||||
|
//
|
||||||
|
// Apply the same transformations to the vector position of the tip
|
||||||
|
//
|
||||||
|
p = transform(tip, translate(t) * rotate(r) * scale(s));
|
||||||
|
//
|
||||||
|
// Place an arrow where the tip ends up
|
||||||
|
//
|
||||||
|
translate(p)
|
||||||
|
arrow();
|
||||||
|
//
|
||||||
|
// Unit vector pointing at p
|
||||||
|
//
|
||||||
|
u = unit(p);
|
||||||
|
//
|
||||||
|
// Point arrow in same direction
|
||||||
|
//
|
||||||
|
z = [0, 0, 1];
|
||||||
|
v = cross(u, z);
|
||||||
|
a = acos(u * z);
|
||||||
|
|
||||||
|
|
||||||
|
l = 20;
|
||||||
|
rotate(-a, v)
|
||||||
|
translate_z(l)
|
||||||
|
vflip()
|
||||||
|
arrow(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
rotate(45)
|
||||||
|
maths();
|
|
@ -0,0 +1,39 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
|
||||||
|
use <../vitamins/meter.scad>
|
||||||
|
|
||||||
|
module meters()
|
||||||
|
if($preview) {
|
||||||
|
meter_assembly();
|
||||||
|
|
||||||
|
translate([0, meter_bezel_width() + 5])
|
||||||
|
vflip()
|
||||||
|
meter_assembly();
|
||||||
|
|
||||||
|
translate([0, -meter_bezel_width()])
|
||||||
|
rotate([0, 180, 0])
|
||||||
|
meter(colour = "blue", value = "123");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
meter_bezel();
|
||||||
|
|
||||||
|
|
||||||
|
meters();
|
|
@ -0,0 +1,29 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../utils/layout.scad>
|
||||||
|
|
||||||
|
include <../vitamins/microswitches.scad>
|
||||||
|
|
||||||
|
module microswitches()
|
||||||
|
layout([for(i = microswitches) microswitch_length(i)], 5)
|
||||||
|
microswitch(microswitches[$i]);
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
microswitches();
|
|
@ -0,0 +1,21 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
use <../vitamins/microview.scad>
|
||||||
|
|
||||||
|
microview(!$preview);
|
|
@ -0,0 +1,30 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../utils/layout.scad>
|
||||||
|
|
||||||
|
include <../vitamins/screws.scad>
|
||||||
|
include <../vitamins/modules.scad>
|
||||||
|
|
||||||
|
module modules()
|
||||||
|
layout([for(m = modules) mod_length(m)], 5)
|
||||||
|
module_assembly(modules[$i], 3);
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
modules();
|
|
@ -0,0 +1,51 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../utils/layout.scad>
|
||||||
|
|
||||||
|
include <../vitamins/screws.scad>
|
||||||
|
|
||||||
|
module nuts() {
|
||||||
|
for(nyloc = [false, true])
|
||||||
|
translate([0, nyloc ? 20 : 0])
|
||||||
|
layout([for(n = nuts) 2 * nut_radius(n)], 5)
|
||||||
|
nut(nuts[$i], nyloc);
|
||||||
|
|
||||||
|
translate([0, 40])
|
||||||
|
layout([for(n = nuts) 2 * nut_radius(n)], 5) let(n = nuts[$i]) {
|
||||||
|
if(n == M3_nut)
|
||||||
|
nut(n, brass = true);
|
||||||
|
|
||||||
|
if(n == M2p5_nut)
|
||||||
|
nut(n, nylon = true);
|
||||||
|
|
||||||
|
if(n == M4_nut)
|
||||||
|
rotate(-45)
|
||||||
|
wingnut(M4_wingnut);
|
||||||
|
|
||||||
|
if(n == M6_nut)
|
||||||
|
nut_and_washer(M6_half_nut, false);
|
||||||
|
|
||||||
|
if(n == M8_nut)
|
||||||
|
#nut_trap(M8_cap_screw, n, h = 30);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
nuts();
|
|
@ -0,0 +1,25 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
use <../vitamins/o_ring.scad>
|
||||||
|
|
||||||
|
module o_rings()
|
||||||
|
O_ring(2.5, 1.6, 3);
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
o_rings();
|
|
@ -0,0 +1,39 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
include <../core.scad>
|
||||||
|
use <../utils/offset.scad>
|
||||||
|
|
||||||
|
module shape()
|
||||||
|
difference() {
|
||||||
|
cube(40, center = true);
|
||||||
|
|
||||||
|
cube([20, 20, 41], center = true);
|
||||||
|
}
|
||||||
|
|
||||||
|
module offsets() {
|
||||||
|
$fn = 20;
|
||||||
|
|
||||||
|
for(x = [-1, 0, 1])
|
||||||
|
translate([50 * x, 0])
|
||||||
|
offset_3D(3 * x, chamfer_base = true)
|
||||||
|
shape();
|
||||||
|
}
|
||||||
|
|
||||||
|
offsets();
|
|
@ -0,0 +1,32 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
|
||||||
|
use <../vitamins/opengrab.scad>
|
||||||
|
|
||||||
|
module opengrab_test() {
|
||||||
|
opengrab_target();
|
||||||
|
|
||||||
|
rotate(45)
|
||||||
|
translate_z(opengrab_target_thickness())
|
||||||
|
opengrab();
|
||||||
|
}
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
opengrab_test();
|
|
@ -0,0 +1,32 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../utils/layout.scad>
|
||||||
|
|
||||||
|
include <../vitamins/d_connectors.scad>
|
||||||
|
include <../vitamins/pcbs.scad>
|
||||||
|
|
||||||
|
module pcbs()
|
||||||
|
layout([for(p = pcbs) pcb_width(p)], 15)
|
||||||
|
translate([0, pcb_length(pcbs[$i]) / 2])
|
||||||
|
rotate(90)
|
||||||
|
pcb_assembly(pcbs[$i], 5 + $i, 3);
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
pcbs();
|
|
@ -0,0 +1,29 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../utils/layout.scad>
|
||||||
|
|
||||||
|
include <../vitamins/pillars.scad>
|
||||||
|
|
||||||
|
module pillars()
|
||||||
|
layout([for(p = pillars) pillar_od(p)], 5)
|
||||||
|
pillar(pillars[$i]);
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
pillars();
|
|
@ -0,0 +1,77 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
include <../core.scad>
|
||||||
|
use <../vitamins/rod.scad>
|
||||||
|
include <../vitamins/sheets.scad>
|
||||||
|
|
||||||
|
module polyholes() {
|
||||||
|
module positions()
|
||||||
|
for(i = [1 : 10]) {
|
||||||
|
translate([(i * i + i) / 2 + 3 * i , 8])
|
||||||
|
let($r = i / 2)
|
||||||
|
children();
|
||||||
|
|
||||||
|
let(d = i + 0.5)
|
||||||
|
translate([(d * d + d) / 2 + 3 * d, 19])
|
||||||
|
let($r = d / 2)
|
||||||
|
children();
|
||||||
|
}
|
||||||
|
|
||||||
|
color(pp1_colour) linear_extrude(height = 3, center = true)
|
||||||
|
difference() {
|
||||||
|
square([100, 27]);
|
||||||
|
|
||||||
|
positions()
|
||||||
|
poly_circle(r = $r);
|
||||||
|
}
|
||||||
|
|
||||||
|
positions()
|
||||||
|
rod(d = 2 * $r, l = 8 * $r + 5);
|
||||||
|
//
|
||||||
|
// Poly rings
|
||||||
|
//
|
||||||
|
ir = 3 / 2;
|
||||||
|
cir = corrected_radius(ir);
|
||||||
|
sizes = [1.5, 2, 3, 4];
|
||||||
|
for(i = [0 : len(sizes) - 1])
|
||||||
|
translate([i * 10, -10]) {
|
||||||
|
color(pp1_colour) linear_extrude(height = 1)
|
||||||
|
poly_ring(ir = ir, or = cir + sizes[i] * extrusion_width);
|
||||||
|
|
||||||
|
rod(2 * ir, 3);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Drill and slot
|
||||||
|
//
|
||||||
|
sheet = Steel06;
|
||||||
|
translate([10, -30])
|
||||||
|
render_2D_sheet(sheet)
|
||||||
|
difference() {
|
||||||
|
sheet_2D(sheet, 20, 20, 1);
|
||||||
|
|
||||||
|
translate([0, 5])
|
||||||
|
slot(1.5, 6, 0);
|
||||||
|
|
||||||
|
translate([0, -5])
|
||||||
|
drill(2, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
polyholes();
|
|
@ -0,0 +1,36 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../utils/layout.scad>
|
||||||
|
|
||||||
|
include <../vitamins/screws.scad>
|
||||||
|
include <../vitamins/psus.scad>
|
||||||
|
|
||||||
|
module psus()
|
||||||
|
layout([for(p = psus) psu_width(p)], 10) let(p = psus[$i])
|
||||||
|
rotate(atx_psu(p) ? 0 : 90) {
|
||||||
|
psu(p);
|
||||||
|
|
||||||
|
psu_screw_positions(p)
|
||||||
|
translate_z(3)
|
||||||
|
screw_and_washer(psu_screw(p), 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
psus();
|
|
@ -0,0 +1,32 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../utils/layout.scad>
|
||||||
|
|
||||||
|
include <../vitamins/screws.scad>
|
||||||
|
include <../vitamins/belts.scad>
|
||||||
|
include <../vitamins/pulleys.scad>
|
||||||
|
|
||||||
|
module pulleys()
|
||||||
|
layout([for(p = pulleys) pulley_flange_dia(p)])
|
||||||
|
rotate(-45)
|
||||||
|
pulley_assembly(pulleys[$i]);
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
pulleys();
|
|
@ -0,0 +1,29 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
include <../global_defs.scad>
|
||||||
|
use <../utils/quadrant.scad>
|
||||||
|
|
||||||
|
|
||||||
|
module quadrants() {
|
||||||
|
linear_extrude(height = eps)
|
||||||
|
quadrant(10, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
rotate([70, 0, 315]) quadrants();
|
|
@ -0,0 +1,48 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../utils/layout.scad>
|
||||||
|
|
||||||
|
include <../vitamins/screws.scad>
|
||||||
|
include <../vitamins/rails.scad>
|
||||||
|
use <../vitamins/nut.scad>
|
||||||
|
|
||||||
|
sheet = 3;
|
||||||
|
|
||||||
|
module rails()
|
||||||
|
layout([for(l = rails) carriage_width(rail_carriage(l))], 25)
|
||||||
|
rotate(-90) {
|
||||||
|
rail = rails[$i];
|
||||||
|
length = rail == MGN15 ? 260 : 200;
|
||||||
|
screw = rail_screw(rail);
|
||||||
|
nut = screw_nut(screw);
|
||||||
|
washer = screw_washer(screw);
|
||||||
|
|
||||||
|
rail_assembly(rail, length, rail_travel(rail, length) / 2);
|
||||||
|
|
||||||
|
rail_screws(rail, length, sheet + nut_thickness(nut, true) + washer_thickness(washer));
|
||||||
|
|
||||||
|
rail_hole_positions(rail, length, 0)
|
||||||
|
translate_z(-sheet)
|
||||||
|
vflip()
|
||||||
|
nut_and_washer(nut, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
rails();
|
|
@ -0,0 +1,35 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../ribbon_clamp.scad>
|
||||||
|
use <../vitamins/wire.scad>
|
||||||
|
|
||||||
|
ways = 20;
|
||||||
|
|
||||||
|
module ribbon_clamps()
|
||||||
|
translate([ribbon_clamp_length(ways) / 2, 0])
|
||||||
|
if($preview) {
|
||||||
|
ribbon_clamp_fastened_assembly(ways, 3);
|
||||||
|
|
||||||
|
ribbon_cable(ways, 100);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ribbon_clamp(ways);
|
||||||
|
|
||||||
|
ribbon_clamps();
|
|
@ -0,0 +1,31 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../utils/layout.scad>
|
||||||
|
|
||||||
|
include <../vitamins/screws.scad>
|
||||||
|
include <../vitamins/ring_terminals.scad>
|
||||||
|
|
||||||
|
module ring_terminals()
|
||||||
|
layout([for(t = ring_terminals) ringterm_od(t)], 5)
|
||||||
|
rotate(90)
|
||||||
|
ring_terminal_assembly(ring_terminals[$i], 3);
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
ring_terminals();
|
|
@ -0,0 +1,29 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../utils/layout.scad>
|
||||||
|
|
||||||
|
include <../vitamins/rockers.scad>
|
||||||
|
|
||||||
|
module rockers()
|
||||||
|
layout([for(r = rockers) rocker_flange_w(r)], 5)
|
||||||
|
rocker(rockers[$i]);
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
rockers();
|
|
@ -0,0 +1,31 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
include <../core.scad>
|
||||||
|
use <../utils/layout.scad>
|
||||||
|
|
||||||
|
include <../vitamins/linear_bearings.scad>
|
||||||
|
|
||||||
|
use <../vitamins/rod.scad>
|
||||||
|
|
||||||
|
module rods()
|
||||||
|
layout([for(b = linear_bearings) 2 * bearing_radius(b)])
|
||||||
|
rod(bearing_rod_dia(linear_bearings[$i]), 80);
|
||||||
|
|
||||||
|
if($preview)
|
||||||
|
rods();
|
|
@ -0,0 +1,42 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
include <../core.scad>
|
||||||
|
use <../utils/round.scad>
|
||||||
|
|
||||||
|
module shape()
|
||||||
|
difference() {
|
||||||
|
square(40, center = true);
|
||||||
|
|
||||||
|
square([20, 20], center = true);
|
||||||
|
}
|
||||||
|
|
||||||
|
module rounds() {
|
||||||
|
linear_extrude(height = eps)
|
||||||
|
round(or = 4, ir = 2)
|
||||||
|
shape();
|
||||||
|
|
||||||
|
|
||||||
|
translate([50, 0])
|
||||||
|
round_3D(or = 4, ir = 2, chamfer_base = true, $fn = 16)
|
||||||
|
linear_extrude(height = 40, center = true)
|
||||||
|
shape();
|
||||||
|
}
|
||||||
|
|
||||||
|
rounds();
|
|
@ -0,0 +1,32 @@
|
||||||
|
//
|
||||||
|
// NopSCADlib Copyright Chris Palmer 2018
|
||||||
|
// 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/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
include <../global_defs.scad>
|
||||||
|
use <../utils/rounded_cylinder.scad>
|
||||||
|
|
||||||
|
|
||||||
|
module rounded_cylinders() {
|
||||||
|
linear_extrude(height = eps)
|
||||||
|
rounded_corner(10, 20, 3, 5);
|
||||||
|
|
||||||
|
translate([30, 10])
|
||||||
|
rounded_cylinder(10, 20, 3, 5, 270);
|
||||||
|
}
|
||||||
|
|
||||||
|
rounded_cylinders();
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue