1
0
mirror of https://github.com/nophead/NopSCADlib.git synced 2025-09-20 20:21:33 +02:00

Compare commits

..

21 Commits

Author SHA1 Message Date
Chris
f327df95a3 Merge pull request #162 from martinbudden/tests_py
Improved resilience of compare_images.
2021-03-06 15:58:38 +00:00
Martin Budden
09956b6219 Improved resilience of compare_images. 2021-03-06 15:36:49 +00:00
Chris
f8c9adca5a Merge pull request #161 from martinbudden/cmdline_reorder
Reordered openscad command line parameters to put output name first.
2021-03-06 15:06:03 +00:00
Martin Budden
b83e56713f Reordered openscad command line parameters. 2021-03-06 14:30:35 +00:00
Chris Palmer
da4f9fbdc3 Typo in changlog.py doc string. 2021-03-04 09:14:27 +00:00
Chris Palmer
614e5f3a72 Issues in the changelog now link to to the issue. 2021-03-03 19:27:25 +00:00
Chris Palmer
a7eae4f549 Neater changlog format. 2021-03-03 19:10:27 +00:00
Chris Palmer
3cd5769708 Merge branch 'martinbudden-cf_contrast' 2021-03-03 14:32:19 +00:00
Chris Palmer
7b770abe12 Udpated changelog 2021-03-03 14:31:38 +00:00
Chris Palmer
31ab8562a7 Updated images 2021-03-03 14:29:32 +00:00
Chris Palmer
db703379a3 Merge branch 'cf_contrast' of https://github.com/martinbudden/NopSCADlib into martinbudden-cf_contrast 2021-03-03 14:17:48 +00:00
Chris Palmer
cd925bc049 Added changelog link to readme. 2021-03-03 14:12:21 +00:00
Chris Palmer
4a2951e22f Fixed changelog.py for when HEAD doesn't have tag. 2021-03-03 13:51:22 +00:00
Chris Palmer
a93a8f99fb Added CHANGELOG.md for #154 2021-03-03 13:47:09 +00:00
Martin Budden
73c436ee15 Improved contrast of carbon fiber sheets. 2021-02-27 16:34:27 +00:00
Chris Palmer
c69100bd71 Added spring steel and silicone sheets. 2021-02-22 15:26:19 +00:00
Chris Palmer
e0b89359aa Fixed plateup using target dir when no panels or platters. 2021-02-21 14:18:41 +00:00
Chris Palmer
041d720c39 Updated example bom.json. 2021-02-21 14:17:09 +00:00
Chris Palmer
03a0c2fe98 Fixed typo. 2021-02-20 20:13:36 +00:00
Chris Palmer
7c2df8d36d The pose module can now specify the camera distance supressing viewall and
autocentre.
2021-02-20 19:28:52 +00:00
Chris Palmer
8474718884 Added printed pocket_handle(). 2021-02-17 13:20:39 +00:00
23 changed files with 2228 additions and 58 deletions

1705
CHANGELOG.md Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -3,6 +3,7 @@
"name": "base_assembly", "name": "base_assembly",
"big": null, "big": null,
"ngb": false, "ngb": false,
"zoomed": 0,
"count": 1, "count": 1,
"assemblies": {}, "assemblies": {},
"vitamins": { "vitamins": {
@@ -22,6 +23,7 @@
"name": "feet_assembly", "name": "feet_assembly",
"big": null, "big": null,
"ngb": false, "ngb": false,
"zoomed": 0,
"count": 1, "count": 1,
"assemblies": { "assemblies": {
"base_assembly": 1 "base_assembly": 1
@@ -49,6 +51,7 @@
"name": "mains_in_assembly", "name": "mains_in_assembly",
"big": null, "big": null,
"ngb": false, "ngb": false,
"zoomed": 0,
"count": 1, "count": 1,
"assemblies": { "assemblies": {
"feet_assembly": 1 "feet_assembly": 1
@@ -86,6 +89,7 @@
"name": "main_assembly", "name": "main_assembly",
"big": null, "big": null,
"ngb": false, "ngb": false,
"zoomed": 0,
"count": 1, "count": 1,
"assemblies": { "assemblies": {
"mains_in_assembly": 1 "mains_in_assembly": 1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 882 KiB

After

Width:  |  Height:  |  Size: 884 KiB

View File

@@ -33,6 +33,8 @@
//! //!
//! See [usage](docs/usage.md) for requirements, installation instructions and a usage guide. //! See [usage](docs/usage.md) for requirements, installation instructions and a usage guide.
//! //!
//! A list of changes classified as breaking, additions or fixes is maintained in [CHANGELOG.md](CHANGELOG.md).
//!
//! <img src="libtest.png" width="100%"/> //! <img src="libtest.png" width="100%"/>
// //
// This file shows all the parts in the library. // This file shows all the parts in the library.
@@ -117,6 +119,7 @@ use <tests/flat_hinge.scad>
use <tests/foot.scad> use <tests/foot.scad>
use <tests/handle.scad> use <tests/handle.scad>
use <tests/PCB_mount.scad> use <tests/PCB_mount.scad>
use <tests/pocket_handle.scad>
use <tests/printed_box.scad> use <tests/printed_box.scad>
use <tests/printed_pulleys.scad> use <tests/printed_pulleys.scad>
use <tests/ribbon_clamp.scad> use <tests/ribbon_clamp.scad>
@@ -180,7 +183,10 @@ translate([x5, cable_grommets_y + 250])
translate([950, 600]) translate([950, 600])
box_test(); box_test();
translate([890, 750]) translate([830, 770])
pocket_handles();
translate([950, 750])
printed_boxes(); printed_boxes();
translate([850, 1330]) translate([850, 1330])
@@ -201,8 +207,8 @@ ball_bearings_y = pillars_y + 40;
pulleys_y = ball_bearings_y +40; pulleys_y = ball_bearings_y +40;
hot_ends_y = pulleys_y + 60; hot_ends_y = pulleys_y + 60;
linear_bearings_y = hot_ends_y + 50; linear_bearings_y = hot_ends_y + 50;
sheets_y = linear_bearings_y + 100; sheets_y = linear_bearings_y + 90;
pcbs_y = sheets_y + 40; pcbs_y = sheets_y + 60;
displays_y = pcbs_y + 170; displays_y = pcbs_y + 170;
fans_y = displays_y + 80; fans_y = displays_y + 80;
transformers_y = fans_y + 120; transformers_y = fans_y + 120;

154
printed/pocket_handle.scad Normal file
View File

@@ -0,0 +1,154 @@
//
// NopSCADlib Copyright Chris Palmer 2021
// 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 pocket handle
//
include <../core.scad>
function pocket_handle(hand_size = [90, 40, 40], slant = 35, screw = M3_cs_cap_screw, panel_t = 3, wall = 4, rad = 4) = //! Construct a pocket_handle property list
[hand_size, slant, screw, panel_t, wall, rad];
function pocket_handle_hand_size(type) = type[0]; //! Size of the hole for the fingers
function pocket_handle_slant(type) = type[1]; //! Upward slant of the hand hole
function pocket_handle_screw(type) = type[2]; //! Screw type, can be countersunk or not
function pocket_handle_panel_t(type) = type[3]; //! Thickness of the panel it is mounted in
function pocket_handle_wall(type) = type[4]; //! Wall thickness
function pocket_handle_rad(type) = type[5]; //! Min corner rad
function pocket_handle_flange(type) = //! Size of the flange
let(w = pocket_handle_wall(type),
f = washer_diameter(screw_washer(pocket_handle_screw(type))) + 2 + w,
s = pocket_handle_hand_size(type))
[s.x + 2 * f, s.y + 2 * f, w];
module pocket_handle_hole_positions(type) { //! Place children at screw hole positions
f = pocket_handle_flange(type);
h = pocket_handle_hand_size(type);
x_pitch = (f.x + h.x) / 4;
y_pitch = (f.y + h.y) / 4;
for(x = [-1, 1], y = [-1, 1])
translate([x * x_pitch, y * y_pitch])
children();
}
module pocket_handle_holes(type, h = 0) { //! Panel cutout and screw holes
hand = pocket_handle_hand_size(type);
w = pocket_handle_wall(type);
slot = [hand.x + 2 * w, hand.y + 2 * w];
t = pocket_handle_panel_t(type);
clearance = norm([slot.y, t]) - slot.y + 0.2; // has to be enough clearance for the diagonal to swing it in
extrude_if(h) {
pocket_handle_hole_positions(type)
drill(screw_clearance_radius(pocket_handle_screw(type)), 0);
rounded_square([slot.x + clearance, slot.y + clearance], pocket_handle_rad(type) + w + clearance / 2);
}
}
module pocket_handle(type) { //! Generate STL for pocket_handle
f = pocket_handle_flange(type);
r = pocket_handle_rad(type);
s = pocket_handle_slant(type);
o = f.z * tan(s);
h = pocket_handle_hand_size(type);
t = pocket_handle_panel_t(type);
w = pocket_handle_wall(type);
screw = pocket_handle_screw(type) ;
stl("pocket_handle")
union() {
difference() {
hull() {
rounded_rectangle(f, r);
translate_z(f.z - eps)
rounded_rectangle([f.x + 2 * o, f.y + 2 * o, eps], r + o);
}
hull() {
rounded_rectangle([h.x, h.y, f.z + eps], r);
translate_z(-eps)
rounded_rectangle([h.x + 2 * o, h.y + 2 * o, eps], r + o);
}
pocket_handle_hole_positions(type) {
if(screw_head_height(screw))
translate_z(-eps)
poly_cylinder(r = screw_clearance_radius(screw), h = f.z + 2 * eps, center = false);
else
screw_polysink(screw, h = 2 * f.z + eps, alt = true);
}
}
translate_z(f.z)
linear_extrude(t)
difference() {
rounded_square([h.x + 2 * w, h.y + 2 * w], r + w);
rounded_square([h.x, h.y], r);
}
translate_z(f.z + t)
difference() {
height = h.z - f.z - t;
hull() {
rounded_rectangle([h.x + 2 * w, h.y + 2 * w, eps], r + w);
translate((height + w) * [0, sin(s), cos(s)])
rounded_rectangle([h.x + 2 * w, h.y + 2 * w, eps], r + w);
}
hull() {
translate_z(-eps)
rounded_rectangle([h.x, h.y, eps], r);
translate(height * [0, sin(s), cos(s)])
rounded_rectangle([h.x, h.y, eps], r);
}
}
}
}
module pocket_handle_assembly(type) { //! Assembly with fasteners in place
f = pocket_handle_flange(type);
screw = pocket_handle_screw(type);
nut = screw_nut(screw);
t = pocket_handle_panel_t(type);
washers = screw_head_height(screw) ? 2 : 1;
screw_length = screw_length(screw, f.z + t, washers, nyloc = true);
translate_z(f.z + t / 2) hflip() {
stl_colour(pp1_colour)
pocket_handle(type);
pocket_handle_hole_positions(type) {
translate_z(f.z + t)
explode(15, true)
nut_and_washer(nut, true);
vflip()
if(washers == 2)
screw_and_washer(screw, screw_length);
else
screw(screw, screw_length);
}
}
}

View File

@@ -14,6 +14,8 @@ The license is GNU General Public License v3.0, see [COPYING](COPYING).
See [usage](docs/usage.md) for requirements, installation instructions and a usage guide. See [usage](docs/usage.md) for requirements, installation instructions and a usage guide.
A list of changes classified as breaking, additions or fixes is maintained in [CHANGELOG.md](CHANGELOG.md).
<img src="libtest.png" width="100%"/> <img src="libtest.png" width="100%"/>
## Table of Contents<a name="top"/> ## Table of Contents<a name="top"/>
@@ -35,15 +37,15 @@ See [usage](docs/usage.md) for requirements, installation instructions and a usa
<tr><td> <a href = "#Displays">Displays</a> </td><td> <a href = "#Nuts">Nuts</a> </td><td> <a href = "#Spools">Spools</a> </td><td> <a href = "#Handle">Handle</a> </td><td> <a href = "#Rounded_cylinder">Rounded_cylinder</a> </td><td></td></tr> <tr><td> <a href = "#Displays">Displays</a> </td><td> <a href = "#Nuts">Nuts</a> </td><td> <a href = "#Spools">Spools</a> </td><td> <a href = "#Handle">Handle</a> </td><td> <a href = "#Rounded_cylinder">Rounded_cylinder</a> </td><td></td></tr>
<tr><td> <a href = "#Extrusion_brackets">Extrusion_brackets</a> </td><td> <a href = "#O_ring">O_ring</a> </td><td> <a href = "#Springs">Springs</a> </td><td> <a href = "#PCB_mount">PCB_mount</a> </td><td> <a href = "#Rounded_polygon">Rounded_polygon</a> </td><td></td></tr> <tr><td> <a href = "#Extrusion_brackets">Extrusion_brackets</a> </td><td> <a href = "#O_ring">O_ring</a> </td><td> <a href = "#Springs">Springs</a> </td><td> <a href = "#PCB_mount">PCB_mount</a> </td><td> <a href = "#Rounded_polygon">Rounded_polygon</a> </td><td></td></tr>
<tr><td> <a href = "#Extrusions">Extrusions</a> </td><td> <a href = "#Opengrab">Opengrab</a> </td><td> <a href = "#Stepper_motors">Stepper_motors</a> </td><td> <a href = "#PSU_shroud">PSU_shroud</a> </td><td> <a href = "#Rounded_right_triangle">Rounded_right_triangle</a> </td><td></td></tr> <tr><td> <a href = "#Extrusions">Extrusions</a> </td><td> <a href = "#Opengrab">Opengrab</a> </td><td> <a href = "#Stepper_motors">Stepper_motors</a> </td><td> <a href = "#PSU_shroud">PSU_shroud</a> </td><td> <a href = "#Rounded_right_triangle">Rounded_right_triangle</a> </td><td></td></tr>
<tr><td> <a href = "#Fans">Fans</a> </td><td> <a href = "#PCB">PCB</a> </td><td> <a href = "#Swiss_clips">Swiss_clips</a> </td><td> <a href = "#Press_fit">Press_fit</a> </td><td> <a href = "#Sector">Sector</a> </td><td></td></tr> <tr><td> <a href = "#Fans">Fans</a> </td><td> <a href = "#PCB">PCB</a> </td><td> <a href = "#Swiss_clips">Swiss_clips</a> </td><td> <a href = "#Pocket_handle">Pocket_handle</a> </td><td> <a href = "#Sector">Sector</a> </td><td></td></tr>
<tr><td> <a href = "#Fuseholder">Fuseholder</a> </td><td> <a href = "#PCBs">PCBs</a> </td><td> <a href = "#Toggles">Toggles</a> </td><td> <a href = "#Printed_box">Printed_box</a> </td><td> <a href = "#Sweep">Sweep</a> </td><td></td></tr> <tr><td> <a href = "#Fuseholder">Fuseholder</a> </td><td> <a href = "#PCBs">PCBs</a> </td><td> <a href = "#Toggles">Toggles</a> </td><td> <a href = "#Press_fit">Press_fit</a> </td><td> <a href = "#Sweep">Sweep</a> </td><td></td></tr>
<tr><td> <a href = "#Geared_steppers">Geared_steppers</a> </td><td> <a href = "#PSUs">PSUs</a> </td><td> <a href = "#Transformers">Transformers</a> </td><td> <a href = "#Printed_pulleys">Printed_pulleys</a> </td><td> <a href = "#Thread">Thread</a> </td><td></td></tr> <tr><td> <a href = "#Geared_steppers">Geared_steppers</a> </td><td> <a href = "#PSUs">PSUs</a> </td><td> <a href = "#Transformers">Transformers</a> </td><td> <a href = "#Printed_box">Printed_box</a> </td><td> <a href = "#Thread">Thread</a> </td><td></td></tr>
<tr><td> <a href = "#Green_terminals">Green_terminals</a> </td><td> <a href = "#Panel_meters">Panel_meters</a> </td><td> <a href = "#Tubings">Tubings</a> </td><td> <a href = "#Ribbon_clamp">Ribbon_clamp</a> </td><td> <a href = "#Tube">Tube</a> </td><td></td></tr> <tr><td> <a href = "#Green_terminals">Green_terminals</a> </td><td> <a href = "#Panel_meters">Panel_meters</a> </td><td> <a href = "#Tubings">Tubings</a> </td><td> <a href = "#Printed_pulleys">Printed_pulleys</a> </td><td> <a href = "#Tube">Tube</a> </td><td></td></tr>
<tr><td> <a href = "#Hot_ends">Hot_ends</a> </td><td> <a href = "#Pillars">Pillars</a> </td><td> <a href = "#Variacs">Variacs</a> </td><td> <a href = "#SSR_shroud">SSR_shroud</a> </td><td></td><td></td></tr> <tr><td> <a href = "#Hot_ends">Hot_ends</a> </td><td> <a href = "#Pillars">Pillars</a> </td><td> <a href = "#Variacs">Variacs</a> </td><td> <a href = "#Ribbon_clamp">Ribbon_clamp</a> </td><td></td><td></td></tr>
<tr><td> <a href = "#Hygrometer">Hygrometer</a> </td><td> <a href = "#Pin_headers">Pin_headers</a> </td><td> <a href = "#Veroboard">Veroboard</a> </td><td> <a href = "#Screw_knob">Screw_knob</a> </td><td></td><td></td></tr> <tr><td> <a href = "#Hygrometer">Hygrometer</a> </td><td> <a href = "#Pin_headers">Pin_headers</a> </td><td> <a href = "#Veroboard">Veroboard</a> </td><td> <a href = "#SSR_shroud">SSR_shroud</a> </td><td></td><td></td></tr>
<tr><td> <a href = "#IECs">IECs</a> </td><td> <a href = "#Pulleys">Pulleys</a> </td><td> <a href = "#Washers">Washers</a> </td><td> <a href = "#Socket_box">Socket_box</a> </td><td></td><td></td></tr> <tr><td> <a href = "#IECs">IECs</a> </td><td> <a href = "#Pulleys">Pulleys</a> </td><td> <a href = "#Washers">Washers</a> </td><td> <a href = "#Screw_knob">Screw_knob</a> </td><td></td><td></td></tr>
<tr><td> <a href = "#Inserts">Inserts</a> </td><td></td><td> <a href = "#Wire">Wire</a> </td><td> <a href = "#Strap_handle">Strap_handle</a> </td><td></td><td></td></tr> <tr><td> <a href = "#Inserts">Inserts</a> </td><td></td><td> <a href = "#Wire">Wire</a> </td><td> <a href = "#Socket_box">Socket_box</a> </td><td></td><td></td></tr>
<tr><td></td><td></td><td> <a href = "#Zipties">Zipties</a> </td><td></td><td></td><td></td></tr> <tr><td></td><td></td><td> <a href = "#Zipties">Zipties</a> </td><td> <a href = "#Strap_handle">Strap_handle</a> </td><td></td><td></td></tr>
</table> </table>
--- ---
@@ -3154,6 +3156,7 @@ When woven sheets (e.g. carbon fibre) are rendered it is necessary to specify th
| 1 | `sheet(FoilTape, 30, 30, 2)` | Aluminium foil tape 30mm x 30mm x 0.05mm | | 1 | `sheet(FoilTape, 30, 30, 2)` | Aluminium foil tape 30mm x 30mm x 0.05mm |
| 1 | `sheet(AL6, 30, 30, 2)` | Aluminium tooling plate 30mm x 30mm x 6mm | | 1 | `sheet(AL6, 30, 30, 2)` | Aluminium tooling plate 30mm x 30mm x 6mm |
| 1 | `sheet(AL8, 30, 30, 2)` | Aluminium tooling plate 30mm x 30mm x 8mm | | 1 | `sheet(AL8, 30, 30, 2)` | Aluminium tooling plate 30mm x 30mm x 8mm |
| 1 | `sheet(Spring05, 30, 30, 2)` | Bi-metal saw blade 30mm x 30mm x 0.5mm |
| 1 | `sheet(Cardboard, 30, 30, 2)` | Corrugated cardboard 30mm x 30mm x 5mm | | 1 | `sheet(Cardboard, 30, 30, 2)` | Corrugated cardboard 30mm x 30mm x 5mm |
| 1 | `sheet(Foam20, 30, 30, 2)` | Foam sponge 30mm x 30mm x 20mm | | 1 | `sheet(Foam20, 30, 30, 2)` | Foam sponge 30mm x 30mm x 20mm |
| 1 | `sheet(DiBond, 30, 30, 2)` | Sheet DiBond 30mm x 30mm x 3mm | | 1 | `sheet(DiBond, 30, 30, 2)` | Sheet DiBond 30mm x 30mm x 3mm |
@@ -3172,6 +3175,7 @@ When woven sheets (e.g. carbon fibre) are rendered it is necessary to specify th
| 1 | `sheet(CF3, 30, 30, 2)` | Sheet carbon fiber 30mm x 30mm x 3mm | | 1 | `sheet(CF3, 30, 30, 2)` | Sheet carbon fiber 30mm x 30mm x 3mm |
| 1 | `sheet(glass2, 30, 30, 2)` | Sheet glass 30mm x 30mm x 2mm | | 1 | `sheet(glass2, 30, 30, 2)` | Sheet glass 30mm x 30mm x 2mm |
| 1 | `sheet(Steel06, 30, 30, 2)` | Sheet mild steel 30mm x 30mm x 0.6mm | | 1 | `sheet(Steel06, 30, 30, 2)` | Sheet mild steel 30mm x 30mm x 0.6mm |
| 1 | `sheet(Silicone3, 30, 30, 2)` | Sheet silicone 30mm x 30mm x 3mm |
<a href="#top">Top</a> <a href="#top">Top</a>
@@ -4956,6 +4960,56 @@ The stl must be given a parameterless wrapper in the project that uses it.
| 1 | pcb_mount_PI_IO_5.stl | | 1 | pcb_mount_PI_IO_5.stl |
<a href="#top">Top</a>
---
<a name="Pocket_handle"></a>
## Pocket_handle
Customisable pocket handle
[printed/pocket_handle.scad](printed/pocket_handle.scad) Implementation.
[tests/pocket_handle.scad](tests/pocket_handle.scad) Code for this example.
### Properties
| Function | Description |
|:--- |:--- |
| `pocket_handle_hand_size(type)` | Size of the hole for the fingers |
| `pocket_handle_panel_t(type)` | Thickness of the panel it is mounted in |
| `pocket_handle_rad(type)` | Min corner rad |
| `pocket_handle_screw(type)` | Screw type, can be countersunk or not |
| `pocket_handle_slant(type)` | Upward slant of the hand hole |
| `pocket_handle_wall(type)` | Wall thickness |
### Functions
| Function | Description |
|:--- |:--- |
| `pocket_handle(hand_size = [90, 40, 40], slant = 35, screw = M3_cs_cap_screw, panel_t = 3, wall = 4, rad = 4)` | Construct a pocket_handle property list |
| `pocket_handle_flange(type)` | Size of the flange |
### Modules
| Module | Description |
|:--- |:--- |
| `pocket_handle(type)` | Generate STL for pocket_handle |
| `pocket_handle_assembly(type)` | Assembly with fasteners in place |
| `pocket_handle_hole_positions(type)` | Place children at screw hole positions |
| `pocket_handle_holes(type, h = 0)` | Panel cutout and screw holes |
![pocket_handle](tests/png/pocket_handle.png)
### Vitamins
| Qty | Module call | BOM entry |
| ---:|:--- |:---|
| 4 | `nut(M3_nut, nyloc = true)` | Nut M3 x 2.4mm nyloc |
| 4 | `screw(M3_cs_cap_screw, 12)` | Screw M3 cs cap x 12mm |
| 4 | `washer(M3_washer)` | Washer M3 x 7mm x 0.5mm |
### Printed
| Qty | Filename |
| ---:|:--- |
| 1 | pocket_handle.stl |
<a href="#top">Top</a> <a href="#top">Top</a>
--- ---
@@ -6016,6 +6070,13 @@ If the code to make an STL or DXF is made a child of the `stl()` or `dxf()` modu
it with code. it with code.
This can speed up the generation of the build instructions greatly but isn't compatible with STLs that include support structures. This can speed up the generation of the build instructions greatly but isn't compatible with STLs that include support structures.
The `pose()` module allows assembly views in the readme to be posed differently to the default view in the GUI:
* Setting the `exploded` parameter to `true` allows just the exploded version to be posed and setting to `false` allows just the assembled view to be posed, the default is both.
* If the `d` parameter is set to specify the camera distance then the normal `viewall` and `autocenter` options are suppressed allowing a small section to be zoomed in to fill the view.
* To get the parameter values make the GUI window square, pose the view with the mouse and then copy the viewport parameters from the Edit menu and paste them into the pose invocation.
* Two `pose()` modules can be chained to allow different poses for exploded and assembled views.
[utils/core/bom.scad](utils/core/bom.scad) Implementation. [utils/core/bom.scad](utils/core/bom.scad) Implementation.
[tests/BOM.scad](tests/BOM.scad) Code for this example. [tests/BOM.scad](tests/BOM.scad) Code for this example.
@@ -6039,7 +6100,7 @@ This can speed up the generation of the build instructions greatly but isn't com
| `no_explode()` | Prevent children being exploded | | `no_explode()` | Prevent children being exploded |
| `no_pose()` | Force children not to be posed even if parent is | | `no_pose()` | Force children not to be posed even if parent is |
| `not_on_bom(on = false)` | Specify the following child parts are not on the BOM, for example when they are on a PCB that comes assembled | | `not_on_bom(on = false)` | Specify the following child parts are not on the BOM, for example when they are on a PCB that comes assembled |
| `pose(a = [55, 0, 25], t = [0, 0, 0], exploded = undef)` | Pose an STL or assembly for rendering to png by specifying rotation `a` and translation `t`, `exploded = true for` just the exploded view or `false` for unexploded only. | | `pose(a = [55, 0, 25], t = [0, 0, 0], exploded = undef, d = undef)` | Pose an STL or assembly for rendering to png by specifying rotation `a`, translation `t` and optionally `d`, `exploded = true for` just the exploded view or `false` for unexploded only. |
| `pose_hflip(exploded = undef)` | Pose an STL or assembly for rendering to png by flipping around the Y axis, `exploded = true for` just the exploded view or `false` for unexploded only. | | `pose_hflip(exploded = undef)` | Pose an STL or assembly for rendering to png by flipping around the Y axis, `exploded = true for` just the exploded view or `false` for unexploded only. |
| `pose_vflip(exploded = undef)` | Pose an STL or assembly for rendering to png by flipping around the X axis, `exploded = true for` just the exploded view or `false` for unexploded only. | | `pose_vflip(exploded = undef)` | Pose an STL or assembly for rendering to png by flipping around the X axis, `exploded = true for` just the exploded view or `false` for unexploded only. |
| `stl(name)` | Name an stl that will appear on the BOM, there needs to a module named `<name>_stl` to make it | | `stl(name)` | Name an stl that will appear on the BOM, there needs to a module named `<name>_stl` to make it |

View File

@@ -61,6 +61,7 @@ class BOM:
self.name = name self.name = name
self.big = None self.big = None
self.ngb = False self.ngb = False
self.zoomed = 0
self.count = 1 self.count = 1
self.vitamins = {} self.vitamins = {}
self.printed = {} self.printed = {}
@@ -75,6 +76,7 @@ class BOM:
"name" : self.name, "name" : self.name,
"big" : self.big, "big" : self.big,
"ngb" : self.ngb, "ngb" : self.ngb,
"zoomed" : self.zoomed,
"count" : self.count, "count" : self.count,
"assemblies" : assemblies, "assemblies" : assemblies,
"vitamins" : {v : self.vitamins[v].data() for v in self.vitamins}, "vitamins" : {v : self.vitamins[v].data() for v in self.vitamins},

163
scripts/changelog.py Normal file
View File

@@ -0,0 +1,163 @@
#!/usr/bin/env python
#
# NopSCADlib Copyright Chris Palmer 2021
# 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/>.
#
#! Creates the changelog from the git log
from __future__ import print_function
import sys
import subprocess
import re
filename = 'CHANGELOG.md'
def tag_version(t):
""" Format a version tag """
return 'v%d.%d.%d' % t
def initials(name):
""" Convert full name to initials with a tooltip """
i = ''.join([n[0].upper() + '.' for n in name.split(' ')])
return '[%s](# "%s")' % (i, name)
def get_remote_url():
""" Get the git remote URL for the repository """
url = subprocess.check_output(["git", "config", "--get", "remote.origin.url"]).decode("utf-8").strip("\n")
if url.startswith("git@"):
url = url.replace(":", "/", 1).replace("git@", "https://", 1)
if url.endswith(".git"):
url = url[:-4]
return url
def iscode(word):
""" try to guess if the word is code """
endings = ['()', '*']
starts = ['$', '--']
anywhere = ['.', '_', '=', '[', '/']
words = ['center', 'false', 'true', 'ngb']
for w in words:
if word == w:
return True
for end in endings:
if word.endswith(end):
return True
for start in starts:
if word.startswith(start):
return True
for any in anywhere:
if word.find(any) >= 0:
return True
return False
def codify(word, url):
""" if a word is deemed code enclose it backticks """
if word:
if re.match(r'#[0-9]+', word):
return '[%s](%s "show issue")' % (word, url + '/issues/' + word[1:])
if iscode(word):
return '`' + word + '`'
return word
def fixup_comment(comment, url):
""" markup code words and fix new paragraphs """
result = ''
word = ''
code = False
for i, c in enumerate(comment):
if c == '`' or code: # Already a code block
result += c # Copy verbatim
if c == '`': code = not code # Keep track of state
else:
if c in ' \n' or (c == '.' and (i + 1 == len(comment) or comment[i + 1] in ' \n')): # if a word terminator
result += codify(word, url) + c # Add codified word before terminator
word = ''
else:
word += c # Accumulate next word
result += codify(word, url) # In case comment ends without a terminator
return result.replace('\n\n','\n\n * ') # Give new paragraphs a bullet point
class Commit(): # members dynamically added from commit_fields
pass
blurb = """
# %s Changelog
This changelog is generated by `changelog.py` using manually added semantic version tags to classify commits as breaking changes, additions or fixes.
"""
if __name__ == '__main__':
url = get_remote_url()
commit_fields = {
'hash': "%H|", # commit commit_hash
'tag': "%D|", # tag
'author': "%aN|", # author name
'date': " %as|", # author date short form
'comment': "%B~" # body
}
# Produce the git log
format = ''.join([v for k, v in commit_fields.items()])
text = subprocess.check_output(["git", "log", "--topo-order", "--format=" + format]).decode("utf-8")
# Process the log into a list of Commit objects
commits = []
for line in text.split('~'):
line = line.strip('\n')
if line:
fields = line.split('|')
commit = Commit()
for i, k in enumerate(commit_fields):
exec('commit.%s = """%s"""' % (k, fields[i]), locals())
# Convert version tag to tuple
if commit.tag:
match = re.match(r'.*tag: v([0-9]+)\.([0-9]+)\.([0-9]+).*', commit.tag)
commit.tag = (int(match.group(1)), int(match.group(2)), int(match.group(3))) if match else ''
commits.append(commit)
# Format the results from the Commit objects
with open(filename, "wt") as file:
print(blurb % url.split('/')[-1], file = file)
for i, c in enumerate(commits):
if c.tag:
ver = tag_version(c.tag)
level, type = (3, 'Fixes') if c.tag[2] else (2, 'Additions') if c.tag[1] else (1, 'Breaking Changes') if c.tag[0] else (1, 'First publicised version')
# Find the previous tagged commit
j = i + 1
diff = ''
while j < len(commits):
if commits[j].tag:
last_ver = tag_version(commits[j].tag)
diff = '[...](%s "diff with %s")' % (url + '/compare/' + last_ver + '...' + ver, last_ver)
break
j += 1
# Print verson info
print('%s [%s](%s "show release") %s %s' % ('#' * (level + 1), ver, url + '/releases/tag/' + ver, type, diff), file = file)
# Print commits excluding merges
if not c.comment.startswith('Merge branch') and not c.comment.startswith('Merge pull'):
print('* %s [`%s`](%s "show commit") %s %s\n' % (c.date, c.hash[:7], url + '/commit/' + c.hash, initials(c.author), fixup_comment(c.comment, url)), file = file)

View File

@@ -142,7 +142,7 @@ def make_parts(target, part_type, parts = None):
f.write("use <%s/%s>\n" % (reltmp(dir, target), filename)) f.write("use <%s/%s>\n" % (reltmp(dir, target), filename))
f.write("%s();\n" % module); f.write("%s();\n" % module);
t = time.time() t = time.time()
openscad.run("-D$bom=1", "-d", dname, "-o", part_file, part_maker_name) openscad.run("-o", part_file, part_maker_name, "-D$bom=1", "-d", dname)
times.add_time(part, t) times.add_time(part, t)
if part_type == 'stl': if part_type == 'stl':
bounds = c14n_stl.canonicalise(part_file) bounds = c14n_stl.canonicalise(part_file)

View File

@@ -25,7 +25,7 @@ from __future__ import print_function
import subprocess, sys import subprocess, sys
def run_list(args, silent = False, verbose = False): def run_list(args, silent = False, verbose = False):
cmd = ["openscad", "--hardwarnings"] + args cmd = ["openscad"] + args + ["--hardwarnings"]
if not silent: if not silent:
for arg in cmd: for arg in cmd:
print(arg, end=" ") print(arg, end=" ")

View File

@@ -44,18 +44,22 @@ def plateup(target, part_type, usage = None):
source_dir1 = source_dirs[part_type] source_dir1 = source_dirs[part_type]
source_dir2 = top_dir + source_dirs[part_type] source_dir2 = top_dir + source_dirs[part_type]
times.read_times(target_dir)
# #
# Loop through source directories # Loop through source directories
# #
all_used = [] all_used = []
all_sources = [] all_sources = []
all_parts = [] all_parts = []
read_times = False
for dir in [source_dir1, source_dir2]: for dir in [source_dir1, source_dir2]:
if not os.path.isdir(dir): if not os.path.isdir(dir):
continue continue
if not os.path.isdir(target_dir): if not os.path.isdir(target_dir):
os.makedirs(target_dir) os.makedirs(target_dir)
if not read_times:
times.read_times(target_dir)
read_times = True
# #
# Make the deps dir # Make the deps dir
# #
@@ -140,4 +144,4 @@ def plateup(target, part_type, usage = None):
print("Removing %s" % file) print("Removing %s" % file)
os.remove(deps_dir + '/' + file) os.remove(deps_dir + '/' + file)
times.print_times(all_parts) times.print_times(all_parts)

View File

@@ -8,6 +8,7 @@ They should work with both Python 2 and Python 3.
|:---|:---| |:---|:---|
| `bom.py` | Generates BOM files for the project. | | `bom.py` | Generates BOM files for the project. |
| `c14n_stl.py` | OpenSCAD produces randomly ordered STL files. This script re-orders them consistently so that GIT can tell if they have changed or not. | | `c14n_stl.py` | OpenSCAD produces randomly ordered STL files. This script re-orders them consistently so that GIT can tell if they have changed or not. |
| `changelog.py` | Creates the changelog from the git log |
| `doc_scripts.py` | Makes this document and doc/usage.md. | | `doc_scripts.py` | Makes this document and doc/usage.md. |
| `dxfs.py` | Generates DXF files for all the routed parts listed on the BOM or a specified list. | | `dxfs.py` | Generates DXF files for all the routed parts listed on the BOM or a specified list. |
| `gallery.py` | Finds projects and adds them to the gallery. | | `gallery.py` | Finds projects and adds them to the gallery. |

View File

@@ -94,7 +94,7 @@ def render(target, type):
cam = "--camera=0,0,0,70,0,315,500" if type == 'stl' else "--camera=0,0,0,0,0,0,500" 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' or colour != pp1 else "--render" render = "--preview" if type == 'stl' or colour != pp1 else "--render"
tmp_name = tmp_dir + '/' + part[:-4] + '.png' tmp_name = tmp_dir + '/' + part[:-4] + '.png'
openscad.run(colour_scheme, "--projection=p", "--imgsize=4096,4096", cam, render, "--autocenter", "--viewall", "-o", tmp_name, png_maker_name); openscad.run("-o", tmp_name, png_maker_name, colour_scheme, "--projection=p", "--imgsize=4096,4096", cam, render, "--autocenter", "--viewall");
do_cmd(("magick "+ tmp_name + " -trim -resize 280x280 -background %s -gravity Center -extent 280x280 -bordercolor %s -border 10 %s" do_cmd(("magick "+ tmp_name + " -trim -resize 280x280 -background %s -gravity Center -extent 280x280 -bordercolor %s -border 10 %s"
% (background, background, tmp_name)).split()) % (background, background, tmp_name)).split())
update_image(tmp_name, png_name) update_image(tmp_name, png_name)

View File

@@ -60,7 +60,8 @@ def compare_images(a, b, c):
with open(log_name, 'w') as output: with open(log_name, 'w') as output:
do_cmd(("magick compare -metric AE -fuzz %d%% %s %s %s" % (fuzz, a, b, c)).split(), output = output) do_cmd(("magick compare -metric AE -fuzz %d%% %s %s %s" % (fuzz, a, b, c)).split(), output = output)
with open(log_name, 'r') as f: with open(log_name, 'r') as f:
pixels = int(float(f.read().strip())) pixels = f.read().strip()
pixels = int(float(pixels if pixels.isnumeric() else -1))
os.remove(log_name) os.remove(log_name)
return pixels return pixels
@@ -116,7 +117,7 @@ def tests(tests):
libtest = True libtest = True
lib_blurb = scrape_blurb(scad_name) lib_blurb = scrape_blurb(scad_name)
if not os.path.isfile(png_name): if not os.path.isfile(png_name):
openscad.run(colour_scheme, "--projection=p", "--imgsize=%d,%d" % (w, h), "--camera=0,0,0,50,0,340,500", "--autocenter", "--viewall", "-o", png_name, scad_name); openscad.run(scad_name, "-o", png_name, colour_scheme, "--projection=p", "--imgsize=%d,%d" % (w, h), "--camera=0,0,0,50,0,340,500", "--autocenter", "--viewall");
do_cmd(["magick", png_name, "-trim", "-resize", "1280", "-bordercolor", background, "-border", "10", png_name]) do_cmd(["magick", png_name, "-trim", "-resize", "1280", "-bordercolor", background, "-border", "10", png_name])
else: else:
# #
@@ -237,7 +238,7 @@ def tests(tests):
print(changed) print(changed)
t = time.time() t = time.time()
tmp_name = tmp_dir + '/tmp.png' tmp_name = tmp_dir + '/tmp.png'
openscad.run_list(options.list() + ["-D$bom=2", colour_scheme, "--projection=p", "--imgsize=%d,%d" % (w, h), "--camera=0,0,0,70,0,315,500", "--autocenter", "--viewall", "-d", dname, "-o", tmp_name, scad_name]); openscad.run_list([scad_name, "-o", tmp_name] + options.list() + ["-D$bom=2", colour_scheme, "--projection=p", "--imgsize=%d,%d" % (w, h), "--camera=0,0,0,70,0,315,500", "--autocenter", "--viewall", "-d", dname]);
times.add_time(scad_name, t) times.add_time(scad_name, t)
do_cmd(["magick", tmp_name, "-trim", "-resize", "1000x600", "-bordercolor", background, "-border", "10", tmp_name]) do_cmd(["magick", tmp_name, "-trim", "-resize", "1000x600", "-bordercolor", background, "-border", "10", tmp_name])
update_image(tmp_name, png_name) update_image(tmp_name, png_name)

View File

@@ -185,6 +185,7 @@ def views(target, do_assemblies = None):
# #
for ass in flat_bom: for ass in flat_bom:
if ass["name"] == real_name: if ass["name"] == real_name:
zoomed = ass['zoomed']
if not "blurb" in ass: if not "blurb" in ass:
ass["blurb"] = blurb.scrape_module_blurb(lines[:line_no]) ass["blurb"] = blurb.scrape_module_blurb(lines[:line_no])
break break
@@ -219,7 +220,8 @@ def views(target, do_assemblies = None):
t = time.time() t = time.time()
target_def = ['-D$target="%s"' % target] if target else [] target_def = ['-D$target="%s"' % target] if target else []
cwd_def = ['-D$cwd="%s"' % os.getcwd().replace('\\', '/')] cwd_def = ['-D$cwd="%s"' % os.getcwd().replace('\\', '/')]
openscad.run_list(options.list() + target_def + cwd_def + ["-D$pose=1", "-D$explode=%d" % explode, colour_scheme, "--projection=p", "--imgsize=4096,4096", "--autocenter", "--viewall", "-d", dname, "-o", tmp_name, png_maker_name]); view_def = ['--viewall', '--autocenter'] if not (zoomed & (1 << explode)) else ['--camera=0,0,0,55,0,25,140']
openscad.run_list(["-o", tmp_name, png_maker_name] + options.list() + target_def + cwd_def + view_def + ["-D$pose=1", "-D$explode=%d" % explode, colour_scheme, "--projection=p", "--imgsize=4096,4096", "-d", dname]);
times.add_time(png_name, t) times.add_time(png_name, t)
do_cmd(["magick", tmp_name, "-trim", "-resize", "1004x1004", "-bordercolor", background, "-border", "10", tmp_name]) do_cmd(["magick", tmp_name, "-trim", "-resize", "1004x1004", "-bordercolor", background, "-border", "10", tmp_name])
update_image(tmp_name, png_name) update_image(tmp_name, png_name)

View File

@@ -29,7 +29,7 @@ module pcbs() {
rotate(90) rotate(90)
pcb_assembly(pcbs[$i], 5 + $i, 3); pcb_assembly(pcbs[$i], 5 + $i, 3);
translate([0, 120]) translate([0, 110])
layout([for(p = perfboards) pcb_length(p)], 10) layout([for(p = perfboards) pcb_length(p)], 10)
translate([0, -pcb_width(perfboards[$i]) / 2]) translate([0, -pcb_width(perfboards[$i]) / 2])
pcb_assembly(perfboards[$i], 5 + $i, 3); pcb_assembly(perfboards[$i], 5 + $i, 3);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 153 KiB

After

Width:  |  Height:  |  Size: 153 KiB

BIN
tests/png/pocket_handle.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 73 KiB

40
tests/pocket_handle.scad Normal file
View File

@@ -0,0 +1,40 @@
//
// NopSCADlib Copyright Chris Palmer 2021
// 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/sheets.scad>
use <../printed/pocket_handle.scad>
show_holes = false;
handle = pocket_handle();
module pocket_handles() {
if($preview) {
pocket_handle_assembly(handle);
if(show_holes)
#pocket_handle_holes(handle);
}
else
pocket_handle(handle);
}
pocket_handles();

View File

@@ -25,25 +25,30 @@ include <../vitamins/screws.scad>
width = 30; width = 30;
2d = true; 2d = true;
module sheets() module sheets() {
layout([for(s = sheets) width], 5) rows = 2;
let(sheet = sheets[$i], w = sheet_is_woven(sheet) ? width : undef) n = ceil(len(sheets) / rows);
if(2d) w = width + 5;
render_2D_sheet(sheet, w = w, d = w) for(y = [0 : rows - 1], x = [0 : n - 1], s = y * n + x)
difference() { if(s < len(sheets))
sheet_2D(sheet, width, width, 2); translate([width / 2 + x * w, y * w])
let(sheet = sheets[s], w = sheet_is_woven(sheet) ? width : undef)
if(2d)
render_2D_sheet(sheet, w = w, d = w)
difference() {
sheet_2D(sheet, width, width, 2);
circle(3); circle(3);
} }
else else
render_sheet(sheet, w = w, d = w) render_sheet(sheet, w = w, d = w)
difference() { difference() {
sheet(sheet, width, width, 2); sheet(sheet, width, width, 2);
translate_z(sheet_thickness(sheet) / 2)
screw_countersink(M3_cs_cap_screw);
}
translate_z(sheet_thickness(sheet) / 2)
screw_countersink(M3_cs_cap_screw);
}
}
if($preview) if($preview)
sheets(); sheets();

View File

@@ -34,14 +34,19 @@
//! If the code to make an STL or DXF is made a child of the `stl()` or `dxf()` module then the STL or DXF will be used in the assembly views generated by `views.py` instead of generating //! If the code to make an STL or DXF is made a child of the `stl()` or `dxf()` module then the STL or DXF will be used in the assembly views generated by `views.py` instead of generating
//! it with code. //! it with code.
//! This can speed up the generation of the build instructions greatly but isn't compatible with STLs that include support structures. //! This can speed up the generation of the build instructions greatly but isn't compatible with STLs that include support structures.
//!
//! The `pose()` module allows assembly views in the readme to be posed differently to the default view in the GUI:
//!
//! * Setting the `exploded` parameter to `true` allows just the exploded version to be posed and setting to `false` allows just the assembled view to be posed, the default is both.
//! * If the `d` parameter is set to specify the camera distance then the normal `viewall` and `autocenter` options are suppressed allowing a small section to be zoomed in to fill the view.
//! * To get the parameter values make the GUI window square, pose the view with the mouse and then copy the viewport parameters from the Edit menu and paste them into the pose invocation.
//! * Two `pose()` modules can be chained to allow different poses for exploded and assembled views.
// //
function bom_mode(n = 1) = $_bom >= n && (is_undef($on_bom) || $on_bom); //! Current BOM mode, 0 = none, 1 = printed and routed parts and assemblies, 2 includes vitamins as well function bom_mode(n = 1) = $_bom >= n && (is_undef($on_bom) || $on_bom); //! Current BOM mode, 0 = none, 1 = printed and routed parts and assemblies, 2 includes vitamins as well
function exploded() = is_undef($exploded_parent) ? $exploded : 0; //! Returns the value of `$exploded` if it is defined, else `0` function exploded() = is_undef($exploded_parent) ? $exploded : 0; //! Returns the value of `$exploded` if it is defined, else `0`
function show_supports() = !$preview || exploded(); //! True if printed support material should be shown function show_supports() = !$preview || exploded(); //! True if printed support material should be shown
module no_explode() let($exploded_parent = true) children(); //! Prevent children being exploded module no_explode() let($exploded_parent = true) children(); //! Prevent children being exploded
module no_pose() let($posed = true) children(); //! Force children not to be posed even if parent is
module explode(d, explode_children = false, offset = [0,0,0]) { //! Explode children by specified Z distance or vector `d`, option to explode grand children module explode(d, explode_children = false, offset = [0,0,0]) { //! Explode children by specified Z distance or vector `d`, option to explode grand children
v = is_list(d) ? d : [0, 0, d]; v = is_list(d) ? d : [0, 0, d];
o = is_list(offset) ? offset : [0, 0, offset]; o = is_list(offset) ? offset : [0, 0, offset];
@@ -62,17 +67,29 @@ module explode(d, explode_children = false, offset = [0,0,0]) { //! Explode
children(); children();
} }
module pose(a = [55, 0, 25], t = [0, 0, 0], exploded = undef) //! Pose an STL or assembly for rendering to png by specifying rotation `a` and translation `t`, `exploded = true for` just the exploded view or `false` for unexploded only. module no_pose() let($posed = true, $zoomed = undef) children(); //! Force children not to be posed even if parent is
if(is_undef($pose) || !is_undef($posed) || (!is_undef(exploded) && exploded != !!exploded()))
children(); module pose(a = [55, 0, 25], t = [0, 0, 0], exploded = undef, d = undef) //! Pose an STL or assembly for rendering to png by specifying rotation `a`, translation `t` and optionally `d`, `exploded = true for` just the exploded view or `false` for unexploded only.
else let($zoomed = is_undef(d)
let($posed = true) // only pose the top level ? is_undef($zoomed)
rotate([55, 0, 25]) ? undef
rotate([-a.x, 0, 0]) : $zoomed
rotate([0, -a.y, 0]) : is_undef(exploded)
rotate([0, 0, -a.z]) ? 3
translate(-t) : exploded
children(); ? 2
: 1)
if(is_undef($pose) || !is_undef($posed) || (!is_undef(exploded) && exploded != !!exploded()))
children();
else
let($posed = true) // only pose the top level
rotate([55, 0, 25])
translate_z(is_undef(d) ? 0 : 140 - d)
rotate([-a.x, 0, 0])
rotate([0, -a.y, 0])
rotate([0, 0, -a.z])
translate(-t)
children();
module pose_hflip(exploded = undef) //! Pose an STL or assembly for rendering to png by flipping around the Y axis, `exploded = true for` just the exploded view or `false` for unexploded only. module pose_hflip(exploded = undef) //! Pose an STL or assembly for rendering to png by flipping around the Y axis, `exploded = true for` just the exploded view or `false` for unexploded only.
if(is_undef($pose) || !is_undef($posed) || (!is_undef(exploded) && exploded != !!exploded())) if(is_undef($pose) || !is_undef($posed) || (!is_undef(exploded) && exploded != !!exploded()))
@@ -93,7 +110,9 @@ module pose_vflip(exploded = undef) //! Pose an STL or assembly for render
module assembly(name, big = undef, ngb = false) { //! Name an assembly that will appear on the BOM, there needs to a module named `<name>_assembly` to make it. `big` can force big or small assembly diagrams. module assembly(name, big = undef, ngb = false) { //! Name an assembly that will appear on the BOM, there needs to a module named `<name>_assembly` to make it. `big` can force big or small assembly diagrams.
if(bom_mode()) { if(bom_mode()) {
args = is_undef(big) && !ngb ? "" : str("(big=", big, ", ngb=", ngb, ")"); zoom = is_undef($zoomed) ? 0 : $zoomed;
arglist = str(arg(big, undef, "big"), arg(ngb, false, "ngb"), arg(zoom, 0, "zoomed"));
args = len(arglist) ? str("(", slice(arglist, 2), ")") : "";
echo(str("~", name, "_assembly", args, "{")); echo(str("~", name, "_assembly", args, "{"));
} }
no_pose() no_pose()

View File

@@ -45,11 +45,14 @@ Foam20 = [ "Foam20", "Foam sponge", 20,[0.3, 0.3, 0.3, 1 ],
AL6 = [ "AL6", "Aluminium tooling plate", 6, [0.9, 0.9, 0.9, 1 ], false]; AL6 = [ "AL6", "Aluminium tooling plate", 6, [0.9, 0.9, 0.9, 1 ], false];
AL8 = [ "AL8", "Aluminium tooling plate", 8, [0.9, 0.9, 0.9, 1 ], false]; AL8 = [ "AL8", "Aluminium tooling plate", 8, [0.9, 0.9, 0.9, 1 ], false];
Steel06 = [ "Steel06", "Sheet mild steel", 0.6,"silver" , false]; Steel06 = [ "Steel06", "Sheet mild steel", 0.6,"silver" , false];
CF1 = [ "CF1", "Sheet carbon fiber", 1, grey(30), false, 2, 2, grey(25)]; Spring05 = [ "Spring05", "Bi-metal saw blade", 0.5,"#FBC300", false];
CF2 = [ "CF2", "Sheet carbon fiber", 2, grey(30), false, 2, 2, grey(25)]; Silicone3 = [ "Silicone3", "Sheet silicone", 3, [0.9, 0.9, 0.9, 0.95 ], false];
CF3 = [ "CF3", "Sheet carbon fiber", 3, grey(30), false, 2, 2, grey(25)]; CF1 = [ "CF1", "Sheet carbon fiber", 1, grey(35), false, 2, 2, grey(20)];
CF2 = [ "CF2", "Sheet carbon fiber", 2, grey(35), false, 2, 2, grey(20)];
CF3 = [ "CF3", "Sheet carbon fiber", 3, grey(35), false, 2, 2, grey(20)];
sheets = [CF1, CF2, CF3, MDF6, MDF10, MDF12, MDF19, PMMA2, PMMA3, PMMA6, PMMA8, PMMA10, glass2, DiBond, DiBond6, Cardboard, FoilTape, Foam20, AL6, AL8, Steel06]; sheets = [CF1, CF2, CF3, MDF6, MDF10, MDF12, MDF19, PMMA2, PMMA3, PMMA6, PMMA8, PMMA10,
glass2, DiBond, DiBond6, Cardboard, FoilTape, AL6, AL8, Steel06, Spring05, Silicone3, Foam20];
use <sheet.scad> use <sheet.scad>