diff --git a/readme.md b/readme.md index c23ab3f..f456ed6 100644 --- a/readme.md +++ b/readme.md @@ -7436,7 +7436,7 @@ This is to prevent the global BOM page becoming too wide in large projects by ha The example below shows how to define a vitamin and incorporate it into an assembly with sub-assemblies and make an exploded view. The resulting flat BOM is shown but hierarchical BOMs are also generated for real projects. -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, DXF or SVG is made a child of the `stl()`, `dxf()` or `svg()` module then the STL, DXF or SVG will be used in the assembly views generated by `views.py` instead of generating it with code. This can speed up the generation of the build instructions greatly but isn't compatible with STLs that include support structures. @@ -7475,8 +7475,10 @@ The `pose()` module allows assembly views in the readme to be posed differently | `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 `_stl` to make it | | `stl_colour(colour = pp1_colour, alpha = 1)` | Colour an stl where it is placed in an assembly. `alpha` can be used to make it appear transparent. | +| `svg(name)` | Name an svg that will appear on the BOM, there needs to a module named `_svg` to make it | | `use_dxf(name)` | Import a DXF to make a build panel | | `use_stl(name)` | Import an STL to make a build platter | +| `use_svg(name)` | Import an SVG to make a build panel | | `vitamin(description)` | Describe a vitamin for the BOM entry and precede it with a module call that creates it, eg. "widget(42): Widget size 42" | ![bom](tests/png/bom.png) @@ -7487,6 +7489,8 @@ The `pose()` module allows assembly views in the readme to be posed differently | 1 | `insert(F1BM3)` | Heatfit insert M3 x 5.8mm | | 1 | `widget(3)` | Rivet like thing for 3mm sheets | | 1 | `screw(M3_cap_screw, 8)` | Screw M3 cap x 8mm | +| 4 | `screw(M3_cap_screw, 10)` | Screw M3 cap x 10mm | +| 1 | `sheet(MDF6, 40, 40)` | Sheet MDF 40mm x 40mm x 6mm | | 1 | `sheet(PMMA3, 20, 20, 1)` | Sheet acrylic 20mm x 20mm x 3mm | | 1 | `washer(M3_washer)` | Washer M3 x 7mm x 0.5mm | | 1 | `star_washer(M3_washer)` | Washer star M3 x 0.5mm | @@ -7499,6 +7503,7 @@ The `pose()` module allows assembly views in the readme to be posed differently ### Routed | Qty | Filename | | ---:|:--- | +| 1 | mdf.svg | | 1 | widget.dxf | ### Assemblies diff --git a/scripts/bom.py b/scripts/bom.py index 192cd21..a3b22df 100755 --- a/scripts/bom.py +++ b/scripts/bom.py @@ -104,14 +104,14 @@ class BOM: def add_part(self, s): args = [] - match = re.match(r'^(.*?\.stl|.*?\.dxf)\((.*)\)$', s) #look for name.stl(...) or name.dxf(...) + match = re.match(r'^(.*?\.stl|.*?\.dxf|.*?\.svg)\((.*)\)$', s) #look for name.stl(...), name.dxf(...) or name.svg(...) if match: s = match.group(1) args = [match.group(2)] if s[-4:] == ".stl": parts = self.printed else: - if s[-4:] == ".dxf": + if s[-4:] == ".dxf" or s[-4:] == ".svg": parts = self.routed else: parts = self.vitamins diff --git a/scripts/deps.py b/scripts/deps.py index 87b0464..9f40dba 100644 --- a/scripts/deps.py +++ b/scripts/deps.py @@ -35,7 +35,7 @@ def read_deps(dname): for line in lines: if line.startswith('\t'): dep = line[1 : -1].rstrip(' \\').replace('\\ ', ' ') - if not os.path.basename(dep) in ['stl.scad', 'dxf.scad', 'svf.scad', 'png.scad', 'target.scad']: + if not os.path.basename(dep) in ['stl.scad', 'dxf.scad', 'svg.scad', 'png.scad', 'target.scad']: deps.append(dep) return deps diff --git a/scripts/exports.py b/scripts/exports.py index 49df256..1896d0a 100644 --- a/scripts/exports.py +++ b/scripts/exports.py @@ -39,7 +39,7 @@ def bom_to_parts(bom_dir, part_type, assembly = None): # part_files = [] bom = assembly + '.txt' if assembly else "bom.txt" - suffix = ".dxf" if part_type == 'svg' else '.' + part_type + suffix = '.' + part_type with open(bom_dir + '/' + bom, "rt") as f: for line in f.readlines(): words = line.split() @@ -106,7 +106,7 @@ def make_parts(target, part_type, parts = None): # # Find all the scad files # - module_suffix = '_dxf' if part_type == 'svg' else '_' + part_type + module_suffix = '_' + part_type for dir in source_dirs(bom_dir): if targets and os.path.isdir(dir): for filename in os.listdir(dir): diff --git a/scripts/make_all.py b/scripts/make_all.py index 53f8a40..a79edad 100755 --- a/scripts/make_all.py +++ b/scripts/make_all.py @@ -39,7 +39,7 @@ if __name__ == '__main__': target = None if len(sys.argv) == 1 else sys.argv[1] set_config(target, usage) boms(target) - for part in ['stl', 'dxf']: + for part in ['stl', 'dxf', 'svg']: make_parts(target, part) render(target, part) plateup(target, part) diff --git a/scripts/plateup.py b/scripts/plateup.py index 06dbe30..cf70ad0 100644 --- a/scripts/plateup.py +++ b/scripts/plateup.py @@ -31,8 +31,8 @@ import re import time import times -source_dirs = { "stl" : "platters", "dxf" : "panels" } -target_dirs = { "stl" : "printed", "dxf" : "routed" } +source_dirs = { "stl" : "platters", "dxf" : "panels", "svg" : "panels" } +target_dirs = { "stl" : "printed", "dxf" : "routed", "svg" : "routed" } def plateup(target, part_type, usage = None): # diff --git a/scripts/render.py b/scripts/render.py index a7907b3..d8638d7 100755 --- a/scripts/render.py +++ b/scripts/render.py @@ -33,7 +33,7 @@ import json from tmpdir import * def usage(): - print("\nusage:\n\trender [target_config] - Render images of the stl and dxf files."); + print("\nusage:\n\trender [target_config] - Render images of the stl, dxf and svg files."); sys.exit(1) def render(target, type): @@ -57,7 +57,7 @@ def render(target, type): with open(bom_file) as json_file: flat_bom = json.load(json_file) - things = { 'stl' : 'printed', 'dxf' : 'routed' }[type] + things = { 'stl' : 'printed', 'dxf' : 'routed', 'svg' : 'routed' }[type] colours = {} for ass in flat_bom: for part in ass[things]: @@ -112,3 +112,4 @@ if __name__ == '__main__': target = sys.argv[1] if len(sys.argv) > 1 else None render(target, 'stl') render(target, 'dxf') + render(target, 'svg') diff --git a/scripts/views.py b/scripts/views.py index bfa0926..56af36d 100755 --- a/scripts/views.py +++ b/scripts/views.py @@ -374,7 +374,12 @@ def views(target, do_assemblies = None): print('\n|%s' % ('---|' * n), file = doc_file) for j in range(n): part = 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) + if (part[-4:] == ".dxf"): + print('| ![%s](dxfs/%s) %s' % (part, part.replace('.dxf','.png'), '|\n' if j == j - 1 else ''), end = '', file = doc_file) + elif (part[-4:] == ".svg"): + print('| ![%s](svgs/%s) %s' % (part, part.replace('.svg','.png'), '|\n' if j == j - 1 else ''), end = '', file = doc_file) + else: + print("Unkown file type ", part[-4:], " for file ", part) print('\n', file = doc_file) print('\n', file = doc_file) diff --git a/tests/BOM.scad b/tests/BOM.scad index f9a65e5..8d3c96b 100644 --- a/tests/BOM.scad +++ b/tests/BOM.scad @@ -25,11 +25,11 @@ include <../core.scad> include <../vitamins/sheets.scad> use <../vitamins/insert.scad> -screw = M3_cap_screw; +screwM3 = M3_cap_screw; sheet = PMMA3; height = 10; -insert = screw_insert(screw); +insert = screw_insert(screwM3); module widget(thickness) { vitamin(str("widget(", thickness, "): Rivet like thing for ", thickness, "mm sheets")); @@ -46,7 +46,13 @@ module widget(thickness) { module widget_stl() { stl("widget") union() { - rounded_rectangle([30, 30, 3], 2, true); + difference() { + rounded_rectangle([30, 30, 3], 2, true); + for(x = [-10,10]) + for (y=[-10,10]) + translate([x,y,-1.5]) + cylinder(r=2, h=3.5); + } render() insert_boss(insert, height, 2.2); } @@ -57,7 +63,18 @@ module widget_dxf() { difference() { sheet_2D(sheet, 20, 20, 1); - drill(screw_clearance_radius(screw), 0); + drill(screw_clearance_radius(screwM3), 0); + } +} + +module mdf_svg() { + svg("mdf") + difference() { + sheet_2D(MDF6, 40,40); + for(x = [-10,10]) + for (y=[-10,10]) + translate([x,y,0]) + drill(screw_clearance_radius(screwM3), 0); } } @@ -85,11 +102,23 @@ assembly("widget_top") { module widget_assembly() assembly("widget") { - widget_base_assembly(); // Note this is not exploded because it is sub-assembly + translate_z(-6) { + render_2D_sheet(MDF6) + mdf_svg(); + + explode(0) + for(x = [-10,10]) + for (y=[-10,10]) + translate([x,y,-10]) + screw(screwM3, 10); + } + + explode(3) + widget_base_assembly(); // Note this is not exploded because it is sub-assembly translate_z(height) { translate_z(sheet_thickness(sheet)) - screw_and_washer(screw, screw_length(screw, sheet_thickness(sheet) + 3, 2, longer = true), true); + screw_and_washer(screwM3, screw_length(screwM3, sheet_thickness(sheet) + 3, 2, longer = true), true); explode(5) translate_z(sheet_thickness(sheet) / 2 + eps) diff --git a/tests/png/bom.png b/tests/png/bom.png index 442918f..8b2b347 100644 Binary files a/tests/png/bom.png and b/tests/png/bom.png differ diff --git a/utils/core/bom.scad b/utils/core/bom.scad index 31bfeb4..9d33706 100644 --- a/utils/core/bom.scad +++ b/utils/core/bom.scad @@ -31,7 +31,7 @@ //! The example below shows how to define a vitamin and incorporate it into an assembly with sub-assemblies and make an exploded view. //! The resulting flat BOM is shown but hierarchical BOMs are also generated for real projects. //! -//! 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, DXF or SVG is made a child of the `stl()`, `dxf()` or `svg()` module then the STL, DXF or SVG will be used in the assembly views generated by `views.py` instead of generating //! it with code. //! This can speed up the generation of the build instructions greatly but isn't compatible with STLs that include support structures. //! @@ -168,12 +168,32 @@ module dxf(name) { //! Name a dxf that will appear on the B } } +module svg(name) { //! Name an svg that will appear on the BOM, there needs to a module named `_svg` to make it + if(bom_mode() && is_undef($in_svg)) { + if(is_undef($dxf_colour)) + echo(str("~", name, ".svg")); + else + echo(str("~", name, ".svg(colour='", $dxf_colour, "')")); + } + if($children) + if(is_undef($pose)) + let($in_svg = true) + children(); + else { + path = is_undef($target) ? "/svgs/" : str("/", $target, "/svgs/"); + import(str($cwd, path, name, ".svg")); + } +} + module use_stl(name) //! Import an STL to make a build platter assert(false); // Here for documentation only, real version in core.scad module use_dxf(name) //! Import a DXF to make a build panel assert(false); // Here for documentation only, real version in core.scad +module use_svg(name) //! Import an SVG to make a build panel + assert(false); // Here for documentation only, real version in core.scad + function value_string(value) = is_string(value) ? str("\"", value, "\"") : str(value); //! Convert `value` to a string or quote it if it is already a string function arg(value, default, name = "") = //! Create string for arg if not default, helper for `vitamin()` diff --git a/utils/core/core.scad b/utils/core/core.scad index 21b38f3..4ee94c1 100644 --- a/utils/core/core.scad +++ b/utils/core/core.scad @@ -37,3 +37,9 @@ module use_dxf(name) { //! Import a DXF to make a build panel path = is_undef($target) ? "../dxfs/" : str($cwd, "/", $target, "/dxfs/"); import(str(path, name, ".dxf")); } + +module use_svg(name) { //! Import an SVG to make a build panel + svg(name); + path = is_undef($target) ? "../svgs/" : str($cwd, "/", $target, "/svgs/"); + import(str(path, name, ".svg")); +}