mirror of
https://github.com/nophead/NopSCADlib.git
synced 2025-09-03 12:22:46 +02:00
Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
fd8712d6bf | ||
|
b6a32b6b41 | ||
|
0738893510 | ||
|
849bc479cc | ||
|
86d7e0f124 | ||
|
c897060726 | ||
|
b2c2fc668b | ||
|
4914f90994 | ||
|
2210396234 | ||
|
2eef050f60 | ||
|
23a64f238d | ||
|
a8422a6aa6 | ||
|
b56ddea1e3 |
@@ -233,3 +233,20 @@ Vitamins are only ever previewed, so they are optimised to draw quickly in F5 an
|
||||
In OpenCSG 3D difference and intersection are relatively slow and the negative volumes interfere with nearby objects when they are composed into assemblies. For this reason as much
|
||||
as possible is done by unioning primitives and extruded 2D shapes. Any 3D differences or intersections are wrapped in ```render()``` so that CGAL will compute a polyhedron
|
||||
that is cached and reused. This will be very slow the first time it renders but very fast afterwards.
|
||||
|
||||
### Multiple configurations
|
||||
|
||||
Some parametric designs might have several configurations, for example a 3D printer with different size options. If several configurations need to be supported at the
|
||||
same time multiple sets of BOMS, STLS and DXFs need to be generated in separate diectories. NopSCADlib supports this by having multiple configuration files named
|
||||
```config_<target_name>.scad```. All the scripts take an optional first parameter that selects one of these config files by specifying ```target_name```.
|
||||
|
||||
The target config file is selected by generating ```target.scad``` that includes ```config_<target_name>.scad```.
|
||||
The rest of the project includes ```target.scad``` to use the configuration.
|
||||
Additionally all the generated file directories (assemblies, bom, stls, dxfs, etc.) are placed in a sub-directory called ```<target_name>```.
|
||||
|
||||
### Other libraries
|
||||
|
||||
The build scripts need to be able to locate the source files where the modules to generate the STL files and assemblies reside. They will search all the scad files
|
||||
in the project plus any ```printed``` directories outside the project. This covers the printed parts in NopSCADlib but also allows other libraries of printed parts.
|
||||
|
||||
Other libraries of vitamins and utilities can be used provided they follow the same convensions of NopSCADlib. The build scripts don't need to search those.
|
||||
|
BIN
libtest.png
BIN
libtest.png
Binary file not shown.
Before Width: | Height: | Size: 784 KiB After Width: | Height: | Size: 786 KiB |
@@ -151,13 +151,13 @@ translate([890, 730])
|
||||
printed_boxes();
|
||||
|
||||
|
||||
translate([850, 1260])
|
||||
translate([850, 1300])
|
||||
bbox_test();
|
||||
|
||||
|
||||
inserts_y = 0;
|
||||
nuts_y = inserts_y + 20;
|
||||
washers_y = nuts_y + 100;
|
||||
washers_y = nuts_y + 120;
|
||||
screws_y = washers_y + 120;
|
||||
o_rings_y = screws_y + 130;
|
||||
springs_y = o_rings_y + 20;
|
||||
|
17
readme.md
17
readme.md
@@ -1689,6 +1689,9 @@ If a nut is given a child then it gets placed on its top surface.
|
||||
|:--- |:--- |
|
||||
| ```nut_radius(type)``` | Radius across the corners |
|
||||
| ```nut_size(type)``` | Diameter of the corresponding screw |
|
||||
| ```nut_square_size(type)``` | Diameter of the corresponding screw |
|
||||
| ```nut_square_thickness(type)``` | Thickness of the square nut |
|
||||
| ```nut_square_width(type)``` | Width of the square nut |
|
||||
| ```nut_trap_depth(type)``` | Depth of nut trap |
|
||||
| ```nut_washer(type)``` | Corresponding washer |
|
||||
|
||||
@@ -1705,6 +1708,7 @@ If a nut is given a child then it gets placed on its top surface.
|
||||
|:--- |:--- |
|
||||
| ```nut(type, nyloc = false, brass = false, nylon = false)``` | Draw specified nut |
|
||||
| ```nut_and_washer(type, nyloc)``` | Draw nut with corresponding washer |
|
||||
| ```nut_square(type, brass = false, nylon = false)``` | Draw specified square nut |
|
||||
| ```nut_trap(screw, nut, depth = 0, horizontal = false, supported = false, h = 200)``` | Make a nut trap |
|
||||
| ```wingnut(type)``` | Draw a wingnut |
|
||||
|
||||
@@ -1723,18 +1727,23 @@ If a nut is given a child then it gets placed on its top surface.
|
||||
| 1 | ```nut(M3_nut)``` | Nut M3 x 2.4mm |
|
||||
| 1 | ```nut(M3_nut, brass = true)``` | Nut M3 x 2.4mm brass |
|
||||
| 1 | ```nut(M3_nut, nyloc = true)``` | Nut M3 x 2.4mm nyloc |
|
||||
| 1 | ```nut(M3nS_thin_nut)``` | Nut M3nS 5.5 x 1.8mm |
|
||||
| 1 | ```sliding_t_nut(M4_hammer_nut)``` | Nut M4 hammer |
|
||||
| 1 | ```sliding_t_nut(M4_sliding_t_nut)``` | Nut M4 sliding T |
|
||||
| 1 | ```nut(M4_nut)``` | Nut M4 x 3.2mm |
|
||||
| 1 | ```nut(M4_nut, nyloc = true)``` | Nut M4 x 3.2mm nyloc |
|
||||
| 1 | ```nut(M4nS_thin_nut)``` | Nut M4nS 7 x 2.2mm |
|
||||
| 1 | ```sliding_t_nut(M5_sliding_t_nut)``` | Nut M5 sliding T |
|
||||
| 1 | ```nut(M5_nut)``` | Nut M5 x 4mm |
|
||||
| 1 | ```nut(M5_nut, nyloc = true)``` | Nut M5 x 4mm nyloc |
|
||||
| 1 | ```nut(M5nS_thin_nut)``` | Nut M5nS 8 x 2.7mm |
|
||||
| 1 | ```nut(M6_half_nut)``` | Nut M6 x 3mm |
|
||||
| 1 | ```nut(M6_nut)``` | Nut M6 x 5mm |
|
||||
| 1 | ```nut(M6_nut, nyloc = true)``` | Nut M6 x 5mm nyloc |
|
||||
| 1 | ```nut(M6nS_thin_nut)``` | Nut M6nS 10 x 3.2mm |
|
||||
| 1 | ```nut(M8_nut)``` | Nut M8 x 6.5mm |
|
||||
| 1 | ```nut(M8_nut, nyloc = true)``` | Nut M8 x 6.5mm nyloc |
|
||||
| 1 | ```nut(M8nS_thin_nut)``` | Nut M8nS 13 x 4mm |
|
||||
| 1 | ```washer(M6_washer)``` | Washer M6 x 12.5mm x 1.5mm |
|
||||
| 1 | ```wingnut(M4_wingnut)``` | Wingnut M4 |
|
||||
|
||||
@@ -1982,7 +1991,7 @@ PCBs and perfboard with optional components. The shape can be a rectangle with o
|
||||
| 1 | ```molex_254(2)``` | Molex KK header 2 way |
|
||||
| 1 | ```molex_254(3)``` | Molex KK header 3 way |
|
||||
| 16 | ```nut(M2_nut, nyloc = true)``` | Nut M2 x 1.6mm nyloc |
|
||||
| 32 | ```nut(M2p5_nut, nyloc = true)``` | Nut M2.5 x 2.2mm nyloc |
|
||||
| 30 | ```nut(M2p5_nut, nyloc = true)``` | Nut M2.5 x 2.2mm nyloc |
|
||||
| 12 | ```nut(M3_nut, nyloc = true)``` | Nut M3 x 2.4mm nyloc |
|
||||
| 12 | ```nut(M4_nut, nyloc = true)``` | Nut M4 x 3.2mm nyloc |
|
||||
| 1 | ```pcb(PI_IO)``` | PI_IO V2 |
|
||||
@@ -1997,7 +2006,7 @@ PCBs and perfboard with optional components. The shape can be a rectangle with o
|
||||
| 1 | ```pcb(RPI3)``` | Raspberry Pi 3 |
|
||||
| 1 | ```pcb(RPI0)``` | Raspberry Pi Zero |
|
||||
| 16 | ```screw(M2_cap_screw, 25)``` | Screw M2 cap x 25mm |
|
||||
| 4 | ```screw(M2p5_cap_screw, 16)``` | Screw M2.5 cap x 16mm |
|
||||
| 2 | ```screw(M2p5_cap_screw, 16)``` | Screw M2.5 cap x 16mm |
|
||||
| 12 | ```screw(M2p5_cap_screw, 20)``` | Screw M2.5 cap x 20mm |
|
||||
| 4 | ```screw(M2p5_pan_screw, 20)``` | Screw M2.5 pan x 20mm |
|
||||
| 8 | ```screw(M2p5_pan_screw, 25)``` | Screw M2.5 pan x 25mm |
|
||||
@@ -2009,7 +2018,7 @@ PCBs and perfboard with optional components. The shape can be a rectangle with o
|
||||
| 2 | ```green_terminal(gt_2p54, 4)``` | Terminal block 4 way 0.1" |
|
||||
| 1 | | USB A to Mini B lead |
|
||||
| 16 | ```washer(M2_washer)``` | Washer M2 x 5mm x 0.3mm |
|
||||
| 32 | ```washer(M2p5_washer)``` | Washer M2.5 x 5.9mm x 0.5mm |
|
||||
| 30 | ```washer(M2p5_washer)``` | Washer M2.5 x 5.9mm x 0.5mm |
|
||||
| 12 | ```washer(M3_washer)``` | Washer M3 x 7mm x 0.5mm |
|
||||
| 12 | ```washer(M4_washer)``` | Washer M4 x 9mm x 0.8mm |
|
||||
| 1 | ```pcb(ZC_A0591)``` | ZC-A0591 ULN2003 driver PCB |
|
||||
@@ -2026,7 +2035,7 @@ PCBs and perfboard with optional components. The shape can be a rectangle with o
|
||||
| 4 | pcb_spacer25120_2.stl |
|
||||
| 4 | pcb_spacer25130_2.stl |
|
||||
| 4 | pcb_spacer25240.stl |
|
||||
| 4 | pcb_spacer2550.stl |
|
||||
| 2 | pcb_spacer2550.stl |
|
||||
| 4 | pcb_spacer2580.stl |
|
||||
| 4 | pcb_spacer2590.stl |
|
||||
| 4 | pcb_spacer30180.stl |
|
||||
|
@@ -189,8 +189,12 @@ def parse_bom(file = "openscad.log", name = None):
|
||||
print(line[:-1])
|
||||
return main
|
||||
|
||||
def usage():
|
||||
print("\nusage:\n\tbom [target_config] [<accessory_name>_assembly] - Generate BOMs for a project or an accessory to a project.")
|
||||
sys.exit(1)
|
||||
|
||||
def boms(target = None, assembly = None):
|
||||
bom_dir = set_config(target) + "bom"
|
||||
bom_dir = set_config(target, usage) + "bom"
|
||||
if assembly:
|
||||
bom_dir += "/accessories"
|
||||
if not os.path.isdir(bom_dir):
|
||||
@@ -217,7 +221,7 @@ def boms(target = None, assembly = None):
|
||||
#
|
||||
# Run openscad
|
||||
#
|
||||
openscad.run("-D","$bom=2","-D","$preview=true","-o", "openscad.echo", bom_maker_name)
|
||||
openscad.run("-D","$bom=2","-D","$preview=true","-o", "openscad.echo", "-d", bom_dir + "/bom.deps", bom_maker_name)
|
||||
os.remove(bom_maker_name)
|
||||
print("Generating bom ...", end=" ")
|
||||
|
||||
@@ -239,11 +243,24 @@ def boms(target = None, assembly = None):
|
||||
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])
|
||||
if len(sys.argv) > 3: usage()
|
||||
|
||||
if len(sys.argv) == 3:
|
||||
target, assembly = sys.argv[1], sys.argv[2]
|
||||
else:
|
||||
boms();
|
||||
if len(sys.argv) == 2:
|
||||
if sys.argv[1][-9:] == "_assembly":
|
||||
target, assembly = None, sys.argv[1]
|
||||
else:
|
||||
target, assembly = sys.argv[1], None
|
||||
else:
|
||||
target, assembly = None, None
|
||||
|
||||
if assembly:
|
||||
if assembly[-9:] != "_assembly": usage()
|
||||
|
||||
try:
|
||||
boms(target, assembly)
|
||||
except Exception as e:
|
||||
print(str(e))
|
||||
sys.exit(1)
|
||||
|
@@ -113,5 +113,5 @@ if __name__ == '__main__':
|
||||
if len(sys.argv) == 2:
|
||||
canonicalise(sys.argv[1])
|
||||
else:
|
||||
print("usage: c14n_stl file")
|
||||
print("\nusage:\n\t c14n_stl file - Canonicalise an STL file created by OpenSCAD.")
|
||||
sys.exit(1)
|
||||
|
@@ -17,6 +17,7 @@
|
||||
# If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
import os
|
||||
from set_config import source_dir
|
||||
|
||||
def mtime(file):
|
||||
if os.path.isfile(file):
|
||||
@@ -32,7 +33,7 @@ def read_deps(dname):
|
||||
deps = []
|
||||
for line in lines:
|
||||
if line.startswith('\t'):
|
||||
dep = line[1 : -1].rstrip(' \\')
|
||||
dep = line[1 : -1].rstrip(' \\').replace('\\ ', ' ')
|
||||
if not os.path.basename(dep) in ['stl.scad', 'dxf.scad', 'svf.scad', 'png.scad', 'target.scad']:
|
||||
deps.append(dep)
|
||||
return deps
|
||||
@@ -48,3 +49,18 @@ def check_deps(target, dname):
|
||||
if mtime(dep) > target_mtime:
|
||||
return dep + ' changed'
|
||||
return None
|
||||
|
||||
def source_dirs(bom_dir):
|
||||
dirs = set()
|
||||
lib_dirs = set()
|
||||
deps = read_deps(bom_dir + '/bom.deps')
|
||||
cwd = os.getcwd().replace('\\', '/')
|
||||
for dep in deps:
|
||||
dir = os.path.dirname(dep)
|
||||
if dir.startswith(cwd):
|
||||
dirs.add(dir[len(cwd) + 1:])
|
||||
else:
|
||||
if dir.endswith('/printed'):
|
||||
lib_dirs.add(dir)
|
||||
dirs.remove(source_dir)
|
||||
return [source_dir] + sorted(dirs) + sorted(lib_dirs)
|
||||
|
@@ -26,6 +26,7 @@ from __future__ import print_function
|
||||
|
||||
import os
|
||||
from tests import do_cmd
|
||||
import argparse
|
||||
|
||||
dir = 'scripts'
|
||||
|
||||
@@ -74,4 +75,5 @@ They should work with both Python 2 and Python 3.
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
argparse.ArgumentParser(description='Generate scripts/readme.md and make html versions of that and doc/usage.md').parse_args()
|
||||
doc_scripts()
|
||||
|
@@ -30,14 +30,14 @@ import times
|
||||
from deps import *
|
||||
import json
|
||||
|
||||
def bom_to_parts(target_dir, part_type, assembly = None):
|
||||
def bom_to_parts(bom_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:
|
||||
with open(bom_dir + '/' + bom, "rt") as f:
|
||||
for line in f.readlines():
|
||||
words = line.split()
|
||||
if words:
|
||||
@@ -46,13 +46,24 @@ def bom_to_parts(target_dir, part_type, assembly = None):
|
||||
part_files.append(last_word[:-4] + '.' + part_type)
|
||||
return part_files
|
||||
|
||||
def usage(t):
|
||||
print("\nusage:\n\t%ss [target_config] [<name1>.%s] ... [<nameN>.%s] - Generate specified %s files or all if none specified." % ( t, t, t, t.upper()))
|
||||
sys.exit(1)
|
||||
|
||||
def make_parts(target, part_type, parts = None):
|
||||
#
|
||||
# Check list of parts is the correct type
|
||||
#
|
||||
if parts:
|
||||
for p in parts:
|
||||
if not p.endswith('.' + part_type): usage(part_type)
|
||||
#
|
||||
# Make the target directory
|
||||
#
|
||||
top_dir = set_config(target)
|
||||
top_dir = set_config(target, lambda: usage(part_type))
|
||||
target_dir = top_dir + part_type + 's'
|
||||
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):
|
||||
@@ -64,7 +75,7 @@ def make_parts(target, part_type, parts = None):
|
||||
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)
|
||||
targets = bom_to_parts(bom_dir, part_type)
|
||||
for file in os.listdir(target_dir):
|
||||
if file.endswith('.' + part_type):
|
||||
if not file in targets:
|
||||
@@ -83,12 +94,11 @@ def make_parts(target, part_type, parts = None):
|
||||
#
|
||||
# Find all the scad files
|
||||
#
|
||||
lib_dirs = [path + '/' + lib + '/printed' for path in os.environ['OPENSCADPATH'].split(os.pathsep) for lib in sorted(os.listdir(path))]
|
||||
module_suffix = '_dxf' if part_type == 'svg' else '_' + part_type
|
||||
for dir in [source_dir, source_dir + '/printed'] + lib_dirs:
|
||||
if os.path.isdir(dir):
|
||||
for dir in source_dirs(bom_dir):
|
||||
if targets and os.path.isdir(dir):
|
||||
for filename in os.listdir(dir):
|
||||
if filename[-5:] == ".scad":
|
||||
if targets and filename[-5:] == ".scad":
|
||||
#
|
||||
# find any modules ending in _<part_type>
|
||||
#
|
||||
@@ -138,9 +148,6 @@ def make_parts(target, part_type, parts = None):
|
||||
#
|
||||
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)
|
||||
print("Could not find a module called", part[:-4] + module_suffix, "to make", part)
|
||||
usage(part_type)
|
||||
times.print_times()
|
||||
|
@@ -30,6 +30,7 @@ import re
|
||||
from shutil import copyfile
|
||||
from tests import update_image
|
||||
import sys
|
||||
import argparse
|
||||
|
||||
project_dirs = ['../..', 'examples']
|
||||
target_dir = 'gallery'
|
||||
@@ -39,7 +40,6 @@ def gallery(force):
|
||||
if not os.path.isdir(target_dir):
|
||||
os.makedirs(target_dir)
|
||||
|
||||
|
||||
paths = sorted([pdir + '/' + i for pdir in project_dirs for i in os.listdir(pdir) if os.path.isdir(pdir + '/' + i + '/assemblies')], key = lambda s: os.path.basename(s))
|
||||
with open(output_name, 'wt') as output_file:
|
||||
print("# A gallery of projects made with NopSCADlib", file = output_file)
|
||||
@@ -78,4 +78,8 @@ def gallery(force):
|
||||
|
||||
if __name__ == '__main__':
|
||||
init()
|
||||
gallery(force = len(sys.argv) > 1 and sys.argv[1] == '-f')
|
||||
parser = argparse.ArgumentParser(description='Creates a galley of projects by copying the top level image and description to gallery/readme.md.')
|
||||
parser.add_argument("-f", help = "run make_all in each project to force update", action="store_true")
|
||||
args = parser.parse_args()
|
||||
|
||||
gallery(force = args.f)
|
||||
|
@@ -27,9 +27,17 @@ from bom import boms
|
||||
from render import render
|
||||
from views import views
|
||||
from plateup import plateup
|
||||
from set_config import set_config
|
||||
|
||||
|
||||
def usage():
|
||||
print("\nusage:\n\tmake_all [target_config] - Make all the manufacturing files and readme for a project.")
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) > 2: usage()
|
||||
target = None if len(sys.argv) == 1 else sys.argv[1]
|
||||
set_config(target, usage)
|
||||
boms(target)
|
||||
for part in ['stl', 'dxf']:
|
||||
make_parts(target, part)
|
||||
|
@@ -25,9 +25,15 @@ import sys
|
||||
|
||||
from plateup import plateup
|
||||
|
||||
def usage():
|
||||
print("\nusage:\n\tpanels [target_config] - Aggregate DXF files for routing together.")
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) > 2: usage()
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
target = sys.argv[1]
|
||||
else:
|
||||
target = None
|
||||
plateup(target, 'dxf')
|
||||
plateup(target, 'dxf', usage)
|
||||
|
@@ -31,11 +31,11 @@ from shutil import copyfile
|
||||
source_dirs = { "stl" : "platters", "dxf" : "panels" }
|
||||
target_dirs = { "stl" : "printed", "dxf" : "routed" }
|
||||
|
||||
def plateup(target, part_type):
|
||||
def plateup(target, part_type, usage = None):
|
||||
#
|
||||
# Make the target directory
|
||||
#
|
||||
top_dir = set_config(target)
|
||||
top_dir = set_config(target, usage)
|
||||
parts_dir = top_dir + part_type + 's'
|
||||
target_dir = parts_dir + '/' + target_dirs[part_type]
|
||||
source_dir = top_dir + source_dirs[part_type]
|
||||
|
@@ -25,9 +25,15 @@ import sys
|
||||
|
||||
from plateup import plateup
|
||||
|
||||
def usage():
|
||||
print("\nusage:\n\tplatters [target_config] - Aggregate STL files for printing together.")
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) > 2: usage()
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
target = sys.argv[1]
|
||||
else:
|
||||
target = None
|
||||
plateup(target, 'stl')
|
||||
plateup(target, 'stl', usage)
|
||||
|
@@ -30,17 +30,23 @@ from tests import do_cmd, update_image, colour_scheme, background
|
||||
from deps import mtime
|
||||
from colorama import init
|
||||
|
||||
def usage():
|
||||
print("\nusage:\n\trender [target_config] - Render images of the stl and dxf files.");
|
||||
sys.exit(1)
|
||||
|
||||
def render(target, type):
|
||||
#
|
||||
# Make the target directory
|
||||
#
|
||||
target_dir = set_config(target) + type + 's'
|
||||
top_dir = set_config(target, usage)
|
||||
target_dir = top_dir + type + 's'
|
||||
bom_dir = top_dir + 'bom'
|
||||
if not os.path.isdir(target_dir):
|
||||
os.makedirs(target_dir)
|
||||
#
|
||||
# Find all the parts
|
||||
#
|
||||
parts = bom_to_parts(target_dir, type)
|
||||
parts = bom_to_parts(bom_dir, type)
|
||||
#
|
||||
# Remove unused png files
|
||||
#
|
||||
@@ -71,6 +77,7 @@ def render(target, type):
|
||||
|
||||
if __name__ == '__main__':
|
||||
init()
|
||||
if len(sys.argv) > 2: usage()
|
||||
target = sys.argv[1] if len(sys.argv) > 1 else None
|
||||
render(target, 'stl')
|
||||
render(target, 'dxf')
|
||||
|
@@ -45,20 +45,27 @@ def valid_targets_string():
|
||||
return result
|
||||
|
||||
|
||||
def set_config(target):
|
||||
def set_config(target, usage = None):
|
||||
if target and target[:1] == '-' and usage: usage()
|
||||
targets = valid_targets()
|
||||
if not target:
|
||||
if not targets:
|
||||
return ""
|
||||
print("Must specify a configuration: " + valid_targets_string())
|
||||
if usage:
|
||||
usage()
|
||||
sys.exit(1)
|
||||
|
||||
if not targets:
|
||||
print("Not a muli-configuration project (no config_<target>.scad files found)")
|
||||
if usage:
|
||||
usage()
|
||||
sys.exit(1)
|
||||
|
||||
if not target in targets:
|
||||
print(target + " is not a configuration, avaliable configurations are: " + valid_targets_string())
|
||||
if usage:
|
||||
usage()
|
||||
sys.exit(1)
|
||||
|
||||
fname = source_dir + "/target.scad"
|
||||
@@ -75,10 +82,13 @@ def set_config(target):
|
||||
f. write(text);
|
||||
return target + "/"
|
||||
|
||||
def usage():
|
||||
print("\nusage:\n\tset_config config_name")
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
args = len(sys.argv)
|
||||
if args == 2:
|
||||
set_config(sys.argv[1])
|
||||
set_config(sys.argv[1], usage)
|
||||
else:
|
||||
print("usage: set_config config_name")
|
||||
sys.exit(1)
|
||||
usage()
|
||||
|
@@ -85,6 +85,10 @@ def depluralise(name):
|
||||
def is_plural(name):
|
||||
return name != depluralise(name)
|
||||
|
||||
def usage():
|
||||
print("\nusage:\n\ttests [test_name1] ... [test_nameN] - Run specified tests or all tests in none specified.");
|
||||
sys.exit(1)
|
||||
|
||||
def tests(tests):
|
||||
scad_dir = "tests"
|
||||
deps_dir = scad_dir + "/deps"
|
||||
@@ -96,6 +100,7 @@ def tests(tests):
|
||||
doc_name = "readme.md"
|
||||
index = {}
|
||||
bodies = {}
|
||||
done = []
|
||||
times.read_times()
|
||||
options.check_options(deps_dir)
|
||||
#
|
||||
@@ -114,6 +119,7 @@ def tests(tests):
|
||||
for scad in scads:
|
||||
base_name = scad[:-5]
|
||||
if not tests or base_name in tests:
|
||||
done.append(base_name)
|
||||
print(base_name)
|
||||
cap_name = base_name[0].capitalize() + base_name[1:]
|
||||
base_name = base_name.lower()
|
||||
@@ -234,6 +240,14 @@ def tests(tests):
|
||||
body += ['\n<a href="#top">Top</a>']
|
||||
body += ["\n---"]
|
||||
|
||||
for test in done:
|
||||
if test in tests:
|
||||
tests.remove(test)
|
||||
if tests:
|
||||
for test in tests:
|
||||
print(Fore.MAGENTA + "Could not find a test called", test, Fore.WHITE)
|
||||
usage()
|
||||
|
||||
with open(doc_name, "wt") as doc_file:
|
||||
print('# NopSCADlib', file = doc_file)
|
||||
print('''\
|
||||
@@ -279,4 +293,6 @@ See [usage](docs/usage.md) for requirements, installation instructions and a usa
|
||||
do_cmd('codespell -L od readme.md'.split())
|
||||
|
||||
if __name__ == '__main__':
|
||||
for arg in sys.argv[1:]:
|
||||
if arg[:1] == '-': usage()
|
||||
tests(sys.argv[1:])
|
||||
|
@@ -97,12 +97,16 @@ def titalise(name):
|
||||
cap_next = c == ' '
|
||||
return result
|
||||
|
||||
def usage():
|
||||
print("\nusage:\n\t views [target_config] [<name1>_assembly] ... [<nameN>_assembly] - Create assembly images and readme.")
|
||||
sys.exit(1)
|
||||
|
||||
def views(target, do_assemblies = None):
|
||||
done_assemblies = []
|
||||
#
|
||||
# Make the target directory
|
||||
#
|
||||
top_dir = set_config(target)
|
||||
top_dir = set_config(target, usage)
|
||||
target_dir = top_dir + 'assemblies'
|
||||
deps_dir = top_dir + "deps"
|
||||
bom_dir = top_dir + "bom"
|
||||
@@ -133,8 +137,7 @@ def views(target, do_assemblies = None):
|
||||
# Find all the scad files
|
||||
#
|
||||
main_blurb = None
|
||||
lib_dirs = [path + '/' + lib + '/printed' for path in os.environ['OPENSCADPATH'].split(os.pathsep) for lib in sorted(os.listdir(path))]
|
||||
for dir in [source_dir, source_dir + '/printed'] + lib_dirs:
|
||||
for dir in source_dirs(bom_dir):
|
||||
if os.path.isdir(dir):
|
||||
for filename in os.listdir(dir):
|
||||
if filename.endswith('.scad'):
|
||||
@@ -396,4 +399,7 @@ if __name__ == '__main__':
|
||||
else:
|
||||
target, assemblies = None, sys.argv[1:]
|
||||
|
||||
for a in assemblies:
|
||||
if a[-9:] != "_assembly": usage()
|
||||
|
||||
views(target, assemblies)
|
||||
|
@@ -61,6 +61,19 @@ module nuts() {
|
||||
if(n == M4_nut)
|
||||
sliding_t_nut(M4_hammer_nut);
|
||||
}
|
||||
|
||||
translate([0, 100]) {
|
||||
if(n == M3_nut)
|
||||
nut_square(M3nS_thin_nut);
|
||||
if(n == M4_nut)
|
||||
nut_square(M4nS_thin_nut);
|
||||
if(n == M5_nut)
|
||||
nut_square(M5nS_thin_nut);
|
||||
if(n == M6_nut)
|
||||
nut_square(M6nS_thin_nut);
|
||||
if(n == M8_nut)
|
||||
nut_square(M8nS_thin_nut);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 111 KiB |
Binary file not shown.
Before Width: | Height: | Size: 144 KiB After Width: | Height: | Size: 143 KiB |
@@ -39,6 +39,10 @@ function nut_trap_depth(type) = type[6]; //! Depth of nut trap
|
||||
|
||||
function nut_flat_radius(type) = nut_radius(type) * cos(30); //! Radius across the flats
|
||||
|
||||
function nut_square_size(type) = type[1]; //! Diameter of the corresponding screw
|
||||
function nut_square_width(type) = type[2]; //! Width of the square nut
|
||||
function nut_square_thickness(type) = type[3]; //! Thickness of the square nut
|
||||
|
||||
module nut(type, nyloc = false, brass = false, nylon = false) { //! Draw specified nut
|
||||
thread_d = nut_size(type);
|
||||
hole_rad = thread_d / 2;
|
||||
@@ -189,6 +193,31 @@ module extrusionSlidingNut(size, tabSizeY1, tabSizeY2, tabSizeZ, holeRadius, hol
|
||||
}
|
||||
}
|
||||
|
||||
module nut_square(type, brass = false, nylon = false) { //! Draw specified square nut
|
||||
thread_d = nut_size(type);
|
||||
hole_rad = thread_d / 2;
|
||||
width = nut_square_width(type);
|
||||
thickness = nut_square_thickness(type);
|
||||
desc = brass ? "brass" : nylon ? "nylon" : "";
|
||||
vitamin(str("nut(", type[0], arg(brass, false, "brass"), arg(nylon, false, "nylon"),
|
||||
"): Nut M", nut_size(type), "nS ", width, " x ", thickness, "mm ", desc));
|
||||
|
||||
colour = brass ? brass_colour : nylon ? grey30 : grey70;
|
||||
color(colour)
|
||||
difference() {
|
||||
linear_extrude(height = thickness) {
|
||||
difference() {
|
||||
square([width, width], center = true);
|
||||
|
||||
circle(hole_rad);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if(show_threads)
|
||||
female_metric_thread(thread_d, metric_coarse_pitch(thread_d), thickness, center = false, colour = colour);
|
||||
}
|
||||
|
||||
function nut_trap_radius(nut, horizontal = false) = nut_radius(nut) + (horizontal ? layer_height / 4 : 0); //! Radius across the corners of a nut trap
|
||||
function nut_trap_flat_radius(nut, horizontal = false) = nut_trap_radius(nut, horizontal) * cos(30); //! Radius across the flats of a nut trap
|
||||
|
||||
|
@@ -51,6 +51,20 @@ toggle_nut = ["toggle_nut", 6.1, 9.2, 1.5, 1.5, M6_washer, 1.5]
|
||||
|
||||
M4_wingnut = ["M4_wingnut", 4, 10, 3.75,8, M4_washer, 0, 22, 10, 6, 3];
|
||||
|
||||
// DIN 562 (thin) square nuts
|
||||
// s w h
|
||||
// c i e
|
||||
// r d i
|
||||
// e t g
|
||||
// w h h
|
||||
// t
|
||||
//
|
||||
M3nS_thin_nut = ["M3nS_thin_nut", 3, 5.5, 1.8];
|
||||
M4nS_thin_nut = ["M4nS_thin_nut", 4, 7, 2.2];
|
||||
M5nS_thin_nut = ["M5nS_thin_nut", 5, 8, 2.7];
|
||||
M6nS_thin_nut = ["M6nS_thin_nut", 6, 10, 3.2];
|
||||
M8nS_thin_nut = ["M8nS_thin_nut", 8, 13, 4];
|
||||
|
||||
// sx ty1 ty2 hammer
|
||||
M3_sliding_t_nut = ["M3_sliding_t_nut", 3, 6, 3.0, 4.0, false, 0, 10, 10, 6, false];
|
||||
M4_sliding_t_nut = ["M4_sliding_t_nut", 4, 6, 3.25,4.5, false, 0, 11, 10, 6, false];
|
||||
|
@@ -63,17 +63,20 @@ function pcb_coord(type, p) = let(l = pcb_length(type), w = pcb_width(type)) //!
|
||||
[(p.x >= 0 ? p.x : l + p.x) - l / 2,
|
||||
(p.y >= 0 ? p.y : w + p.y) - w / 2];
|
||||
|
||||
module pcb_screw_positions(type) { //! Positions children at the mounting hole positions
|
||||
module pcb_hole_positions(type, all = true) { // Positition children at the hole positions, including holes not used for screws
|
||||
holes = pcb_holes(type);
|
||||
|
||||
if(len(holes))
|
||||
for($i = [0 : len(holes) - 1]) {
|
||||
p = pcb_coord(type, holes[$i]);
|
||||
translate([p.x, p.y, 0])
|
||||
for($i = [0 : 1 : len(holes) - 1]) {
|
||||
hole = holes[$i];
|
||||
if(len(hole) == 2 || all)
|
||||
translate(pcb_coord(type, hole))
|
||||
children();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module pcb_screw_positions(type) //! Positions children at the mounting hole positions
|
||||
pcb_hole_positions(type, false) children();
|
||||
|
||||
module chip(length, width, thickness, colour, cutout = false) //! Draw a coloured cube to represent a chip, or other rectangular component
|
||||
if(!cutout)
|
||||
color(colour)
|
||||
@@ -837,7 +840,7 @@ module pcb(type) { //! Draw specified PCB
|
||||
else
|
||||
rounded_square([pcb_length(type), pcb_width(type)], r = pcb_radius(type));
|
||||
|
||||
pcb_screw_positions(type)
|
||||
pcb_hole_positions(type)
|
||||
circle(d = pcb_hole_d(type) + eps);
|
||||
|
||||
if(Len(grid))
|
||||
@@ -847,7 +850,7 @@ module pcb(type) { //! Draw specified PCB
|
||||
|
||||
color("silver")
|
||||
translate_z(t / 2)
|
||||
pcb_screw_positions(type)
|
||||
pcb_hole_positions(type)
|
||||
tube(or = max(pcb_land_d(type), 1) / 2, ir = pcb_hole_d(type) / 2, h = t + 2 * eps);
|
||||
|
||||
fr4 = pcb_colour(type) != "sienna";
|
||||
|
@@ -342,7 +342,7 @@ PSU12V1A = ["PSU12V1A", "PSU 12V 1A", 67, 31, 1.7, 0, 3.9, 0, "green", true, [[3
|
||||
RAMPSEndstop = ["RAMPSEndstop", "RAMPS Endstop Switch",
|
||||
40.0, 16.0, 1.6, 0.5, 2.54, 0, "red", false,
|
||||
[
|
||||
[2, 2], [2, 13.5], [17, 13.5], [36, 13.5]
|
||||
[2, 2, false], [2, 13.5, false], [17, 13.5], [36, 13.5]
|
||||
],
|
||||
[
|
||||
[ 12, 8, -90, "jst_xh", 3, true, "white", "silver"],
|
||||
|
Reference in New Issue
Block a user